Closed mronda closed 4 years ago
@mronda Hi! CompoundOperator isn't very smart. It wants the number of offspring from one operator to match the number of parents required by the next operator. For example, SSX produces 2 offspring, but SPX requires 4 parents. It wouldn't allow that. I believe you can work around this by putting SPX first:
operators = CompoundOperator(SPX(nparents=4,noffspring=2), SSX(probability=0.1), Replace(probability=0.01), PM(probability=0.01))
Hi @dhadka
Tried that and getting:
508 # compute center of mass
--> 509 G = [sum([x[i][j] for i in range(n)]) / n for j in range(m)]
510
511 # compute expanded simplex vertices
TypeError: unsupported operand type(s) for +: 'int' and 'list'
SBX() has a check for type before entering, should this operator also be doing that?
hi @dhadka any ideas on this? Thanks!
Hmm...yeah, it looks like SPX doesn't filter by the decision variable type, so it can currently only work on real-valued decision variables. Have you tried SBX instead (simulated binary crossover)? That should work.
Hi @dhadka yes, I have. But for the constrained problem I am working on, I saw huge benefits of multi-parent crossover as SBX wasn't exploring the space as well. Would filtering the variables work? something like this :
k = len(parents)
n = parents[0].problem.nvars
x = []
problem = parents[0].problem
for i in range(k):
variables = []
for v in range(n):
if isinstance(problem.types[v], Real):
variables.append(parents[i].variables[v])
x.append(variables)
And then SSX() would handle the Subsets...
Yes, filtering the variables is another option :)
Just thought I'd update this. I re wrote a bit of that operator to work when using the CompoundOperator() and mix types. This is the code I am using for SPX() . Thanks!
class _SPX(Variator):
def __init__(self, nparents=10, noffspring=2, expansion=None):
super(_SPX, self).__init__(nparents)
self.nparents = nparents
self.noffspring = noffspring
if expansion is None:
self.expansion = math.sqrt(nparents + 1)
else:
self.expansion = expansion
def evolve(self, parents):
n = len(parents)
nvars = parents[0].problem.nvars
problem = parents[0].problem
x = []
# get continous indices
con_ix = []
for i in range(nvars):
if isinstance(problem.types[i], Real):
con_ix.append(i)
m = len(con_ix)
# append only continous variables
for i in range(n):
variables = []
for v in con_ix:
if isinstance(problem.types[v], Real):
variables.append(parents[i].variables[v])
x.append(variables)
# compute center of mass
G = [sum([x[i][j] for i in range(n)]) / n for j in range(m)]
# compute expanded simplex vertices
for i in range(n):
x[i] = add(G, multiply(self.expansion, subtract(x[i], G)))
# generate offspring
result = []
for _ in range(self.noffspring):
child = copy.deepcopy(parents[n - 1])
r = [
math.pow(random.uniform(0.0, 1.0), 1.0 / (i + 1.0))
for i in range(n - 1)
]
C = zeros(n, m)
for i in range(n):
for j in range(m):
if i == 0:
C[i][j] = 0.0
else:
C[i][j] = r[i - 1] * (x[i - 1][j] - x[i][j] + C[i - 1][j])
for j in range(0, len(con_ix)):
type = child.problem.types[con_ix[j]]
child.variables[con_ix[j]] = clip(
x[n - 1][j] + C[n - 1][j], type.min_value, type.max_value
)
child.evaluated = False
result.append(child)
return result
Hi,
So I have a problem setup with multiple types, Real and Subset. I was wondering if I can use the Multiparent Variator for the Reals ? I tried the line below :
operators = CompoundOperator(SSX(probability=0.1), SPX(nparents=4,noffspring=2), Replace(probability=0.01), PM(probability=0.01))
And got an error like
unexpected number of offspring, expected 2, received 3
.Is it even possible to combine these operators or I would have to stick to SBX() for Reals?
Thanks!