from abc import ABCMeta
from desdeo.problem.Problem import PythonProblem
[docs]class Objective(object):
[docs] def __init__(self, name, maximized=False, ideal=None, nadir=None):
self.name = name
self.maximized = maximized
self.ideal = ideal
self.nadir = nadir
[docs] def __call__(self, inner):
self.inner = inner
return self
[docs]class Constraint(object):
[docs] def __init__(self, name):
self.name = name
[docs] def __call__(self, inner):
self.inner = inner
return self
[docs]class Variable(object):
[docs] def __init__(self, low, high, start, name):
self.low = low
self.high = high
self.start = start
self.name = name
# Inheritance from ABC is compulsary to interoperate with it
[docs]class PorcelainProblem(PythonProblem, metaclass=PorcelainProblemMeta):
[docs] def __init__(self):
from desdeo.optimization import SciPyDE
from desdeo.problem import Variable as ProblemVariable
from desdeo.problem.RangeEstimators import default_estimate
super().__init__(
nobj=len(self._porc_objs),
nconst=len(self._porc_constrs),
maximized=[obj.maximized for _, obj in self._porc_objs],
objectives=[obj.name for _, obj in self._porc_objs],
name=self._porc_name, # Optional
)
for _, var in self._porc_vars:
self.add_variables(
ProblemVariable(
[var.low, var.high], starting_point=var.start, name=var.name
)
)
# TODO: Use user defined ideal/nadir override for relevant dimensions
ideal, nadir = default_estimate(SciPyDE, self)
self.ideal = ideal
self.nadir = nadir
[docs] def evaluate(self, population):
objectives = []
for values in population:
vals_dict = dict(zip((k for k, _ in self._porc_vars), values))
obj_vals = []
for _, obj in self._porc_objs:
val = obj.inner(**vals_dict)
obj_vals.append(-val if obj.maximized else val)
objectives.append(obj_vals)
return objectives