如何在Pymoo中从我的代码中选择第一个种群

How select a first population from my code in Pymoo

提问人:Rafael Henrique 提问时间:11/17/2023 更新时间:11/17/2023 访问量:40

问:

我需要帮助。

我的代码是最大化利润和最小化面积,这是 X 的总和。X 是 áreas,其中 4 个是免费使用的,另外 4 个是有成本使用的,并且与前 7 个相比,生产力较低。

我有 8 个 X 的输出变量。但是,我需要我的代码在 Pymoo 中创建一个首先检查前 4 个的群体。该代码是:

pip install -U pymoo==0.5.0
#importando algumas bibliotecas iniciais do Pymoo

import numpy as np

from pymoo.factory import get_problem
from pymoo.optimize import minimize
#valores iniciais (em R$/t)

S_preco = 2300

#Área (em ha)
#MA - 1
#TO - 2
#PI - 3
#BA - 4
#Nova terra MA - 5
#Nova terra TO - 6
#Nova terra PI - 7
#Nova terra BA - 8

AreaMAX = [600000, 650000, 500000, 1500000, 309853, 930190, 14197, 55525]

#produtividade das terras (em t/ha)

Produtividade = [3.206, 3.322, 3.377, 3.779, 3, 3.12, 3, 3.3]

#custos

#custo do plantio da soja (em R$/t)
S_custo = [983, 966.5, 1051.5, 1040.167, 983, 966.5, 1051.5, 1040.167]

#custo do uso da terra (em R$/t)

Custo_terra = [0, 0, 0, 0, 7500, 9000, 10000, 20500]

#demanda de soja a ser atendida (em t)

S_demanda = 5056921 + 2332769 - (5056921/117887685 + 2332769/117887685)*18344777

#demais preços e custos (valores constantes)

S_preco = 2500
F_preco = 2500
O_preco = 3500
B_preco = 3500

F_custo = 60
O_custo = 100
B_custo = 500

#demanda de farelo, óleo bruto e biodiesel (em t)

F_demanda = 1510028
O_demanda = 378913
B_demanda = 244031.02

#Valores iniciais da porcentagem de soja a ser vendida e da porcentagem de óleo a ser vendido

#S_per = 0
#O_per = 0

#modelo matemático:

#f1 é a equação de maximização do lucro da soja e dos subprodutos
#f2 é a equação de minimização das quatro áreas
#g1 a g8 são as restrições relacionadas a área máxima
  #g1 é a restrição da área máxima de MA
  #g2 é a restrição da área máxima de TO
  #g3 é a restrição da área máxima de PI
  #g4 é a restrição da área máxima da BA
  #g5 é a restrição da área máxima da área de aptidão do MA (Nova MA)
  #g6 é a restrição da área máxima da área de aptidão do TO (Nova TO)
  #g7 é a restrição da área máxima da área de aptidão do PI (Nova PI)
  #g8 é a restrição da área máxima da área de aptidão da BA (Nova BA)
#g9 a g12 são as restrições relacionadas a demanda de cada subproduto
  #g9 é a restrição de demanda mínima da soja
  #g10 é a restrição de demanda mínima do farelo
  #g11 é a restrição de demanda mínima do óleo bruto
  #g12 é a restrição de demanda mínima do biodiesel

import numpy as np
from pymoo.core.problem import ElementwiseProblem

class MyProblem(ElementwiseProblem):

    def __init__(self):
        super().__init__(n_var=10,
                         n_obj=2,
                         n_constr=12,
                         xl=np.array([0,0,0,0,0,0,0,0,0,0]),
                         xu=np.array([AreaMAX[0],AreaMAX[1],AreaMAX[2],AreaMAX[3],AreaMAX[4],AreaMAX[5],AreaMAX[6],AreaMAX[7],1,1]))

    def _evaluate(self, X, out, *args, **kwargs):
        f1 = -1*((X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*X[8]*S_preco + (X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*(1 - X[8])*(F_preco*0.4 + 0.2*(X[9]*O_preco + (1 - X[9])*B_preco)) - (X[0]*(Produtividade[0]*S_custo[0] + Custo_terra[0]) + X[1]*(Produtividade[1]*S_custo[1] + Custo_terra[1]) + X[2]*(Produtividade[2]*S_custo[2] + Custo_terra[2]) + X[3]*(Produtividade[3]*S_custo[3] + Custo_terra[3]) + X[4]*(Produtividade[4]*S_custo[4] + Custo_terra[4]) + X[5]*(Produtividade[5]*S_custo[5] + Custo_terra[5]) + X[6]*(Produtividade[6]*S_custo[6] + Custo_terra[6]) + X[7]*(Produtividade[7]*S_custo[7] + Custo_terra[7])) - (X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*(1 - X[8])*(F_custo + O_custo + 0.2*(1 - X[9])*(B_custo)))/1e10
        f2 = (X[0] + X[1] + X[2] + X[3] + X[4] + X[5] + X[6] + X[7])/1e7

        g1 = X[0] - AreaMAX[0]
        g2 = X[1] - AreaMAX[1]
        g3 = X[2] - AreaMAX[2]
        g4 = X[3] - AreaMAX[3]
        g5 = X[4] - AreaMAX[4]
        g6 = X[5] - AreaMAX[5]
        g7 = X[6] - AreaMAX[6]
        g8 = X[7] - AreaMAX[7]
        g9 = -1*((X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*X[8] - S_demanda)
        g10 = -1*((X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*(1 - X[8])*0.4 - F_demanda)
        g11 = -1*((X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*(1 - X[8])*0.2*X[9] - O_demanda)
        g12 = -1*((X[0]*Produtividade[0] + X[1]*Produtividade[1] + X[2]*Produtividade[2] + X[3]*Produtividade[3] + X[4]*Produtividade[4] + X[5]*Produtividade[5] + X[6]*Produtividade[6] + X[7]*Produtividade[7])*(1 - X[8])*0.2*(1 - X[9]) - B_demanda)

        out["F"] = [f1, f2]
        out["G"] = [g1, g2, g3, g4, g5 ,g6, g7, g8, g9, g10, g11, g12]

problem = MyProblem()

#X[0] - Área de soja da região do MA
#X[1] - Área de soja da região do TO
#X[2] - Área de soja da região do PI
#X[3] - Área de soja da região da BA
#X[4] - Área de soja da região da Nova MA
#X[5] - Área de soja da região da Nova TO
#X[6] - Área de soja da região da Nova PI
#X[7] - Área de soja da região da Nova BA
#X[8] - S_Per (porcentagem de soja vendido)
#X[9] - O_Per (porcentagem de oleo vendido)

problem = MyProblem()

#importando as bibliotecas do NSGA-II

from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.factory import get_sampling, get_crossover, get_mutation

algorithm = NSGA2(
    pop_size=1100,
    n_offsprings=10,
    sampling=get_sampling("real_random"),
    crossover=get_crossover("real_sbx", prob=0.9, eta=15),
    mutation=get_mutation("real_pm", eta=20),
    eliminate_duplicates=True
)

#definindo o número de gerações

from pymoo.factory import get_termination

termination = get_termination("n_gen", 1000)

#rodando o NSGA-II

from pymoo.optimize import minimize

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

X = res.X
F = res.F

res.F[:,0] *= -1

#plotando a fronteira de Pareto do NSGA-II

from pymoo.visualization.scatter import Scatter

plot = Scatter(title = "Espaço Objetivo")
plot.add(res.F, color="red")
plot.show()

#gerando o arquivo em csv das variaveis do NSGA-II

X = res.pop.get("X")
np.savetxt("NSGApop.csv", X, delimiter=",",)

#gerando o arquivo em csv dos resultados de f1 e f2 do NSGA-II

F = res.pop.get("F")
np.savetxt("NSGAResult.csv", F, delimiter=",")

So, what changes in population (and in the code) I have to do, to ensure that code will priorize the first X0 to X3, and use the other 4 after (X4 to X7). Also, how the choice of individuals of population works in Pymoo. Anyone can help?

I think I have doubts about how population works in Pymoo, related to code also.

I just wanted to learn how to write the first population of my code. And how I can write the population code to priorize the first X(0 to 3).

python 优化 genetic-algorithm population pymoo

评论

0赞 Pieter-Jan 11/17/2023
What do you mean with "priorize the first X0 to X3"? Prioritize what?
0赞 Rafael Henrique 11/17/2023
I need to change the code to fill the values of X0 to X3 first, and after try to fill the values of X4 to X7 (just see the code). That is why I needed assistance to change population method in NSGA-II, NSGA-III and C-TAEA
0赞 Pieter-Jan 11/17/2023
Your question is not clear to me. A MOO like NSGA-II will try to find an optimal combination of ALL your design variables (10 in your case) to minimize the objective function. Why doe you first want to fill in the first four variables and only after the last four? MOO will do it all simultaneously.
0赞 Rafael Henrique 11/17/2023
Actually the first function I have to maximize (that is why I put a negative multiplier), and the second I have to minimize. So, MOO like NSGA-II, NSGA-III and even a classic algorithm will try to fill all with all restrictions. I asked this because the last four variables have a cost value to be associated, which is Custo_Terra. [0 (X0), 0(X1), 0(X2), 0(X3), 7500(X4), 9000(X5), 10000(X6), 20500(X7)]. So, If I wanted to maximize profit (first equation), in a logical way, is better to the first four variables to be used, and after jump to the last four (X5 to X7). Continue in the next paragraph
0赞 Rafael Henrique 11/17/2023
So, in the MOO way, maybe can be justified. However, there is not a way to change my code to fill X0 to X3 first, and after X5 to X7, and also in the same way that defines X8 and X9 (not related to areas)? To see if NSGA can follow the logic. I am not trying to buying new fields, since I wanted to maximize profit and minimize area. If I use X5 to X7 first, it affects the profit more that if I using X0 to X3. Clear now?

答:

0赞 Pieter-Jan 11/17/2023 #1

You can set a first population as a starting point by using initialization. Here is an example: https://pymoo.org/customization/initialization.html

评论

0赞 Rafael Henrique 11/17/2023
I tried this link, but I do not understand how use it in my code. Also, I got a error any time that my code is running with trying to select a population.