I am trying to follow this method to solve an optimization problem. I have a bag of N=100 vehicles which have certain properties. For example cost, rank, and mpg. I am looking to find k=5 subsets of vehicles that have higher mpg and rank than others. N and k can take any values.
Following the pymoo, the evaluation function looks like this:
def _evaluate(self, x, out, *args, **kwargs):
out["F"] = np.array([x["rank"], x["mpg"]], dtype=float)
Here, x has as many dimensions as many columns for vehicles. In this case, I am using rank and mpg as I want to maximize these.
The guide says to create methods including:
Sampling Crossover Mutation
I want to know how can I formulate the above problem in these functions.
- Sampling: refer the link above, should I create a method that takes 5 random vehicles from bag and return these?
- Crossover: I am blind to this. What should I be doing in my case?
- Mutation: I don't know what to implement here.
If somebody has used pymoo, give me some hints on the above so that I can do my implementation.
Many Thanks
*** Here is the updated code for now. I am getting an error (attached).Error
from pymoo.algorithms.soo.nonconvex.ga import GA
from pymoo.optimize import minimize
from pymoo.core.crossover import Crossover
from pymoo.core.mutation import Mutation
from pymoo.core.sampling import Sampling
import numpy as np
from pymoo.core.problem import ElementwiseProblem
class SubsetProblem(ElementwiseProblem):
def __init__(self,L,n_max):
super().__init__(n_var=len(L), n_obj=2, n_ieq_constr=0)
self.L = L
self.n_max = n_max
def _evaluate(self, x, out, *args, **kwargs):
out["F"] = np.array([self.L[x][0], self.L[x][1]], dtype=float)
#out["G"] = (self.n_max - np.sum(x)) ** 2
class MySampling(Sampling):
def _do(self, problem, n_samples, **kwargs):
X = np.full((n_samples, problem.n_var), False, dtype=bool)
for k in range(n_samples):
I = np.random.permutation(problem.n_var)[:problem.n_max]
X[k, I] = True
return X
class BinaryCrossover(Crossover):
def __init__(self):
super().__init__(2, 1)
def _do(self, problem, X, **kwargs):
n_parents, n_matings, n_var = X.shape
_X = np.full((self.n_offsprings, n_matings, problem.n_var), False)
for k in range(n_matings):
p1, p2 = X[0, k], X[1, k]
both_are_true = np.logical_and(p1, p2)
_X[0, k, both_are_true] = True
n_remaining = problem.n_max - np.sum(both_are_true)
I = np.where(np.logical_xor(p1, p2))[0]
S = I[np.random.permutation(len(I))][:n_remaining]
_X[0, k, S] = True
return _X
class MyMutation(Mutation):
def _do(self, problem, X, **kwargs):
for i in range(X.shape[0]):
X[i, :] = X[i, :]
is_false = np.where(np.logical_not(X[i, :]))[0]
is_true = np.where(X[i, :])[0]
X[i, np.random.choice(is_false)] = True
X[i, np.random.choice(is_true)] = False
return X
# create the actual problem to be solved
np.random.seed(1)
L = np.array([[9,13],[9,14],[7,15],[6,12],[8,16],[8,14],[6,12],[3,18],[4,14],[5,14],[8,11],[8,18]])
n_max = 3
problem = SubsetProblem(L, n_max)
algorithm = GA(
pop_size=12,
sampling=MySampling(),
crossover=BinaryCrossover(),
mutation=MyMutation(),
eliminate_duplicates=True)
res = minimize(problem,
algorithm,
('n_gen', 60),
seed=1,
verbose=True)
print("Function value: %s" % res.F[0])
print("Subset:", np.where(res.X)[0])