Project-Platypus / Platypus

A Free and Open Source Python Library for Multiobjective Optimization
GNU General Public License v3.0
565 stars 153 forks source link

Integers and Multi-Objective with Particle Swarm #89

Closed infinity77 closed 1 year ago

infinity77 commented 5 years ago

Trying to run the following problem with two objectives, three variables, no constraints and Integer variables with SMPSO:

from platypus import *

def my_function(x):
    """ Some objective function"""
    return [-x[0] ** 2 - x[2] ** 2, x[1] - x[0]]

def AsInteger():

    problem = Problem(3, 2)  # define 3 inputs and 1 objective (and no constraints)
    problem.directions[:] = Problem.MAXIMIZE
    int1 = Integer(-50, 50)
    int2 = Integer(-50, 50)
    int3 = Integer(-50, 50)
    problem.types[:] = [int1, int2, int3]
    problem.function = my_function
    algorithm = SMPSO(problem)
    algorithm.run(10000)

I get:

Traceback (most recent call last): File "D:\MyProjects\Drilling\test_platypus.py", line 62, in AsInteger() File "D:\MyProjects\Drilling\test_platypus.py", line 19, in AsInteger algorithm.run(10000) File "build\bdist.win-amd64\egg\platypus\core.py", line 405, in run File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 820, in step File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 838, in iterate File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 1008, in _update_velocities TypeError: unsupported operand type(s) for -: 'list' and 'list'

With OMOPSO:

Traceback (most recent call last): File "D:\MyProjects\Drilling\test_platypus.py", line 62, in AsInteger() File "D:\MyProjects\Drilling\test_platypus.py", line 19, in AsInteger algorithm.run(10000) File "build\bdist.win-amd64\egg\platypus\core.py", line 405, in run File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 941, in step File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 949, in initialize File "build\bdist.win-amd64\egg\platypus\core.py", line 818, in iadd File "build\bdist.win-amd64\egg\platypus\core.py", line 785, in add File "build\bdist.win-amd64\egg\platypus\core.py", line 707, in compare KeyError: 0

With CMAES:

Traceback (most recent call last): File "D:\MyProjects\Drilling\test_platypus.py", line 62, in AsInteger() File "D:\MyProjects\Drilling\test_platypus.py", line 19, in AsInteger algorithm.run(10000) File "build\bdist.win-amd64\egg\platypus\core.py", line 405, in run File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 1074, in step File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 1134, in initialize File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 1298, in iterate File "build\bdist.win-amd64\egg\platypus\core.py", line 378, in evaluate_all File "build\bdist.win-amd64\egg\platypus\evaluator.py", line 88, in evaluate_all File "build\bdist.win-amd64\egg\platypus\evaluator.py", line 55, in run_job File "build\bdist.win-amd64\egg\platypus\core.py", line 345, in run File "build\bdist.win-amd64\egg\platypus\core.py", line 518, in evaluate File "build\bdist.win-amd64\egg\platypus\core.py", line 160, in call File "build\bdist.win-amd64\egg\platypus\types.py", line 147, in decode

File "build\bdist.win-amd64\egg\platypus\tools.py", line 521, in gray2bin TypeError: 'float' object has no attribute 'getitem'

With GDE3:

Traceback (most recent call last): File "D:\MyProjects\Drilling\test_platypus.py", line 62, in AsInteger() File "D:\MyProjects\Drilling\test_platypus.py", line 19, in AsInteger algorithm.run(10000) File "build\bdist.win-amd64\egg\platypus\core.py", line 405, in run File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 67, in step File "build\bdist.win-amd64\egg\platypus\algorithms.py", line 323, in iterate File "build\bdist.win-amd64\egg\platypus\operators.py", line 258, in evolve TypeError: float() argument must be a string or a number

It works fine with NSGAII, for example. Am I missing something fundamental? My apologies if this limitation is mentioned somewhere, I wasn't able to find it anywhere.

Thank you.

Andrea.

dhadka commented 5 years ago

Hi, the underlying issue is that those algorithms require real-valued decision variables. Integer is encoded as a binary array, so it's not compatible. If you want to use integer values with these algorithms, you'd need to use the Real encoding and cast/round to an int.

Having said that, the software needs to provide a better message indicating it was given an incompatible type.

PastelBelem8 commented 5 years ago

@dhadka why can't you simply convert the encodings of binary arrays back to integers values? You only need them to make the sum! I was thinking of making a call to decode, since you have access to the problem and, thus, the types.

PastelBelem8 commented 5 years ago

I have written a few lines of code to apply integer variables in this situation using the decode and encode methods of the different types. I'll make a push request of this later on. I recognize there might any reason why this has not been done in this way. Please let me know, what is your reasoning @dhadka

dhadka commented 5 years ago

The only real concern I have with using an integer variable with PSO is rounding. Suppose a particle's position is p0 = 0.0 and velocity is v = 0.5. I would expect the position after the first iteration to be p1 = 0.5 and after the second iteration be p2 = 1.0. However, with an integer representation that rounds down, the particle would be stationary...p1 = 0 and p2 = 0.

The better option, in my opinion, is to use a real-valued encoding and round the value to an integer in the evaluation function.

PastelBelem8 commented 5 years ago

Well, my concern with that is that the particles might spend evaluations with solutions that I am not interested at. This is especially concerning when dealing with expensive evaluation functions and, therefore, I cannot afford to spend those iterations.

In what conditions will the velocity be 0.5? As an alternative we could instead round the velocity when dealing with integer variables. Instead of taking two iterations to reach p2 = 1.0, we would take one. I must study a bit more this algorithm to provide other valuable feedback. I'll get back to you in a few days..

dhadka commented 5 years ago

I see your concern about the expensive evaluations. One option is to use a cache to avoid re-evaluating solutions (e.g., lru-dict).

The velocities are updated here: https://github.com/Project-Platypus/Platypus/blob/723ad6763abff99b4f31305191b754c2c26867b0/platypus/algorithms.py#L847

You may also consider modifying the code that updates the positions so that it only marks a solution as "unevaluated" when at least one of the integer variables has changed: https://github.com/Project-Platypus/Platypus/blob/723ad6763abff99b4f31305191b754c2c26867b0/platypus/algorithms.py#L895

wzbernstein commented 5 years ago

Hi there. Is there any additional documentation on dealing with discrete decision variables? I would like to limit the variable steps quite a bit for my application. Also, where can I find information about setting the termination conditions of the search? Appreciate your hard work. Cheers, Bill

whhxp commented 4 years ago

In my opinion, PSO is not suitable for binary-encoded problem.

github-actions[bot] commented 1 year ago

This issue is stale and will be closed soon. If you feel this issue is still relevant, please comment to keep it active. Please also consider working on a fix and submitting a PR.