Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOEA-D with mixed Variables #674

Open
nico-ehlers opened this issue Dec 22, 2024 · 0 comments
Open

MOEA-D with mixed Variables #674

nico-ehlers opened this issue Dec 22, 2024 · 0 comments

Comments

@nico-ehlers
Copy link

Hello, somehow there is always a error message when I try to use the MOEA-D algorithm with mixed variables (example provided below). Is it possible to use MOEA-D with mixed variables?
Greetings
Nico

Error

` 100 # iterate for each member of the population in random order
101 for k in np.random.permutation(len(pop)):
102 # get the parents using the neighborhood selection
--> 103 P = self.selection.do(self.problem, pop, 1, self.mating.crossover.n_parents, neighbors=[self.neighbors[k]])
105 # perform a mating using the default operators - if more than one offspring just pick the first
106 off = np.random.choice(self.mating.do(self.problem, pop, 1, parents=P, n_max_iterations=1))

AttributeError: 'dict' object has no attribute 'n_parents'`

Example

`
from LCcalc.master import LCcalc
import sys
import os
import warnings
import pickle
import pandas as pd
import numpy as np
warnings.filterwarnings("ignore", category=UserWarning)
warnings.filterwarnings("ignore", category=pd.errors.DtypeWarning)
warnings.filterwarnings("ignore", category=pd.errors.PerformanceWarning)
warnings.filterwarnings("ignore", category=pd.errors.SettingWithCopyWarning)
warnings.filterwarnings("ignore", category=FutureWarning)

from pymoo.operators.sampling.rnd import FloatRandomSampling
from pymoo.algorithms.moo.moead import MOEAD
from pymoo.core.problem import (
Problem, # Vectorized - since most MO algorithms work with populations, this class evaluates a set of solutons at once
ElementwiseProblem # Inherits from the Problem Class, works with a single solution at a time
)
from pymoo.problems.functional import FunctionalProblem
from pymoo.operators.crossover.sbx import SBX
from pymoo.operators.mutation.pm import PM
from pymoo.termination import get_termination
from pymoo.core.variable import Integer, Choice #, Real
from pymoo.optimize import minimize
from pymoo.util.ref_dirs import get_reference_directions

mixed_variables = {
"renovation_2_1_perc" : Integer(bounds=(0,10)),
"densification_2_2_perc" : Integer(bounds=(0,10)),
"deconstruction_nb_timber_3_1_perc" : Integer(bounds=(0,10)),
"deconstruction_nb_solid_3_2_perc" : Integer(bounds=(0,10)),
"anzahl_stockwerke" : Integer(bounds=(1,2)),
"perc_BoilerGasHeating": Integer(bounds=(0, 100)),
"perc_BoilerOilHeating": Integer(bounds=(0, 100)),
"perc_HeatPumpsHeatingAirWater": Integer(bounds=(0, 100)),
"perc_HeatPumpsHeatingSoleWaterCollector": Integer(bounds=(0, 100)),
"perc_HeatPumpsHeatingSoleWaterSonde": Integer(bounds=(0, 100)),
"perc_HeatPumpsHeatingWaterWater": Integer(bounds=(0, 100)),
"perc_ElectricHeatersHeating": Integer(bounds=(0, 100)),
"perc_DistrictHeatingHeatingNonRenewable": Integer(bounds=(0, 100)),
"perc_BiomassHeating": Integer(bounds=(0, 100)),
"energyCostIncrease": Choice(options=[0, 1])#['high', 'norm']
}

class ProblemLCcalc(ElementwiseProblem):
def init(self, **kwargs):
super().init(vars = mixed_variables, # Anzahl der Designspace Variablen
n_obj=5, # nr of objectives
#n_eq_constr=1, # nr of equality constraints
#n_ieq_constr=1, # nr of inequality constraints
**kwargs) # upper bounds

def _evaluate(self,X,out, *args, **kwargs):
    
        # function replacement
        district_mean_gwp,district_mean_penrt,district_mean_pet,\
        district_mean_cost, Residents, Reuse_Score, Recycle_Score = \
        1,1,1,1,1,1,1
        out["F"] = np.column_stack([district_mean_gwp,district_mean_penrt,district_mean_cost,Residents*(-1),Recycle_Score*(-1)])

from pymoo.core.repair import Repair

class MyRepair(Repair):

def _do(self, problem, X, **kwargs):

    keys = list(mixed_variables.keys())[0:4]
    target_sum = 10
    
    for individual in X:
        # Normalize heating group
        renovation_sum = sum(individual[key] for key in keys)
        if renovation_sum != 0:
            for key in keys:
                individual[key] = round(individual[key] * (target_sum / renovation_sum))
            rounding_error = target_sum - sum(individual[key] for key in keys)
            if rounding_error > 0:
                min_key = min(keys, key=lambda key: individual[key])
                individual[min_key] += rounding_error
            if rounding_error < 0:
                max_key = max(keys, key=lambda key: individual[key])
                individual[max_key] += rounding_error
        if individual['densification_2_2_perc'] == 0:
            individual['anzahl_stockwerke'] = 0 
    
    heating_keys = [
        'perc_BoilerGasHeating', 'perc_BoilerOilHeating', 'perc_HeatPumpsHeatingAirWater',
        'perc_HeatPumpsHeatingSoleWaterCollector', 'perc_HeatPumpsHeatingSoleWaterSonde',
        'perc_HeatPumpsHeatingWaterWater', 'perc_ElectricHeatersHeating',
        'perc_DistrictHeatingHeatingNonRenewable', 'perc_BiomassHeating'
    ]

    # Target sum for each group
    heating_target_sum = 100  # Set desired target for the heating group
    # Process each dictionary (individual) in the list
    for individual in X:
        # Normalize heating group
        heating_sum = sum(individual[key] for key in heating_keys)
        if heating_sum != 0:
            for key in heating_keys:
                individual[key] = round(individual[key] * (heating_target_sum / heating_sum))

    return X

from pymoo.core.callback import Callback

class MyCallback(Callback):

def __init__(self) -> None:
    super().__init__()
    self.n_evals = []
    self.opt = []

def notify(self, algorithm):
    self.n_evals.append(algorithm.evaluator.n_eval)
    self.opt.append(algorithm.opt[0].F)

from pymoo.core.mixed import MixedVariableMating, MixedVariableSampling, MixedVariableDuplicateElimination
from pymoo.optimize import minimize
from pymoo.core.population import Population
from pymoo.util.ref_dirs import get_reference_directions

def MaOO(nr_objectives = 5,
n_gen=2,
n_neighbors=15,
prob_neighbor_mating=0.7,
seed=1,
crossover_prob=0.9,
crossover_eta=15,
mutation_eta=20):

ref_dirs = get_reference_directions("das-dennis", nr_objectives, n_partitions=round(nr_objectives))

# Define the problem
problem = ProblemLCcalc()

algorithm = MOEAD(
                ref_dirs = ref_dirs,
                n_neighbors=n_neighbors,
                prob_neighbor_mating=prob_neighbor_mating,

                crossover=SBX(prob=crossover_prob, eta=crossover_eta),
                mutation=PM(eta=mutation_eta),
                
                sampling = MixedVariableSampling(),
                mating=MixedVariableMating(eliminate_duplicates=MixedVariableDuplicateElimination(), repair=MyRepair()),
                repair=MyRepair()
                )

callback = MyCallback()

termination = get_termination("n_gen", n_gen) 

res = minimize(problem,
            algorithm,
            termination,
            callback=callback,
            seed=seed,
            save_history=True,
            verbose=True)

return

if name == 'main':
MaOO(nr_objectives = 5,
n_gen=2,
n_neighbors=15,
prob_neighbor_mating=0.7,
seed=1,
crossover_prob=0.9,
crossover_eta=15,
mutation_eta=20)`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant