英文:
Why glpk sees a linear programming formulation as a nonlinear programming?
问题
I'm new to both Python and Pyomo. Nonetheless, I've made the below code following my previous question. However, if I run it using glpk solver, it says
> RuntimeError: Cannot write legal LP file. Objective 'cost' has nonlinear terms that are not quadratic.
I think the formulation is an LP. I'm guessing it is the calculation of parameter "demandsperyear"? But, it shouldn't be the cause as it is a parameter, not a variable, right?
If i use cbc, I've got errors that I cannot understand.
from pyomo.environ import *
m = AbstractModel()
m.techs = Set()
m.products = Set()
m.suppliers = Set()
m.demands = Set()
m.years = Set()
m.initial_demands = Param(m.demands,m.products)
m.growths = Param(m.demands,m.products)
m.yields = Param(m.techs,m.products,m.suppliers)
m.CO2emissions = Param(m.techs,m.suppliers)
m.TAC = Param(m.techs,m.suppliers)
m.max_installed = Param(m.techs,m.suppliers)
m.installed_techs = Var(m.techs, m.suppliers, m.years, within=Binary)
m.number_installed_techs= Var(m.techs, m.suppliers, m.years, bounds=(0,None))
m.totalTAC = Var(bounds=(None,None))
m.totalCO2 = Var(bounds=(None,None))
m.totalTACperyear = Var(m.years, bounds=(None, None))
m.totalCO2peryear = Var(m.years, bounds=(None, None))
def total_TAC(m):
return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
m.cost = Objective(rule=total_TAC, sense=minimize)
def total_CO2(m):
return m.totalCO2 == sum(m.totalCO2peryear[year] for year in m.years)
m.totalCO2_cons = Constraint(rule=total_CO2)
def total_TACperyear(m,year):
return m.totalTACperyear[year] == sum(m.number_installed_techs[tech,supplier,year]*m.TAC[tech,supplier] for tech in m.techs for supplier in m.suppliers)
m.TACperyear_cons = Constraint(m.years, rule=total_TACperyear)
def total_CO2peryear(m,year):
return m.totalCO2peryear[year] == sum(m.number_installed_techs[tech,supplier,year]*m.CO2emissions[tech,supplier] for tech in m.techs for supplier in m.suppliers)
m.CO2peryear_cons = Constraint(m.years, rule=total_CO2peryear)
def demandperyear(m,demand,product,year):
if year == 1:
expression = m.initial_demands[demand,product]
return expression
expression = m.initial_demands[demand,product]*(1 + m.growths[demand,product]*year)
return expression
m.demandsperyear = Param(m.demands, m.products,m.years, initialize=demandperyear)
def fulfill_demands(m,supplier,demand,product,year):
if supplier == demand:
expression = sum(m.number_installed_techs[tech,supplier,year]*m.yields[tech,product,supplier] for tech in m.techs) >= m.demandsperyear[demand,product,year]
return expression
return Constraint.Skip
m.fulfill_demands_cons = Constraint(m.suppliers,m.demands,m.products,m.years, rule=fulfill_demands)
def max_installed(m,tech,supplier):
expression = sum(m.number_installed_techs[tech,supplier,year] for year in m.years) <= m.max_installed[tech,supplier]
return expression
m.max_installed_cons = Constraint(m.techs,m.suppliers, rule=max_installed)
def accum_installed(m,tech,supplier,year):
if year == 1:
expression = m.number_installed_techs[tech,supplier,year] == m.installed_techs[tech,supplier,year]
return expression
expression = m.number_installed_techs[tech,supplier,year] == m.number_installed_techs[tech,supplier,year-1] + m.installed_techs[tech,supplier,year]
return expression
m.accum_cons = Constraint(m.techs,m.suppliers,m.years, rule=accum_installed)
# parameter
data = {None: {
'techs' : {None: ['tek_A', 'tek_B', 'tek_C']},
'products' : {None: ['prod_A', 'prod_B', 'prod_C']},
'suppliers' : {None: ['daerah_A', 'daerah_B', 'daerah_C']},
'demands' : {None: ['daerah_A', 'daerah_B', 'daerah_C']},
'years' : {None: [1, 2, 3, 4, 5,6,7,8,9,10]},
'initial_demands': {('daerah_A','prod_A'): 10.0, ('daerah_A','prod_B'): 10.0, ('daerah_A','prod_C'): 10.0,
('daerah_B','prod_A'): 20.0, ('daerah_B','prod_B'): 20.0, ('daerah_B','prod_C'): 20.0,
('daerah_C','prod_A'): 12.0, ('daerah_C','prod_B'): 12.0, ('daerah_C','prod_C'): 12.0},
'growths': {('daerah_A','prod_A'): 0.02, ('daerah_A','prod_B'): 0.02, ('daerah_A','prod_C'): 0.02,
('daerah_B','prod_A'):
<details>
<summary>英文:</summary>
I'm new to both Python and Pyomo. Nonetheless, I've made the below code following my previous question. However, if I run it using glpk solver, it says
> RuntimeError: Cannot write legal LP file. Objective 'cost' has nonlinear terms that are not quadratic.
I think the formulation is an LP. I'm guessing it is the calculation of parameter "demandsperyear"? But, it shouldn't be the cause as it is a parameter, not a variable, right?
If i use cbc, I've got errors that I cannot understand.
from pyomo.environ import *
m = AbstractModel()
m.techs = Set()
m.products = Set()
m.suppliers = Set()
m.demands = Set()
m.years = Set()
m.initial_demands = Param(m.demands,m.products)
m.growths = Param(m.demands,m.products)
m.yields = Param(m.techs,m.products,m.suppliers)
m.CO2emissions = Param(m.techs,m.suppliers)
m.TAC = Param(m.techs,m.suppliers)
m.max_installed = Param(m.techs,m.suppliers)
m.installed_techs = Var(m.techs, m.suppliers, m.years, within=Binary)
m.number_installed_techs= Var(m.techs, m.suppliers, m.years, bounds=(0,None))
m.totalTAC = Var(bounds=(None,None))
m.totalCO2 = Var(bounds=(None,None))
m.totalTACperyear = Var(m.years, bounds=(None, None))
m.totalCO2peryear = Var(m.years, bounds=(None, None))
def total_TAC(m):
return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
m.cost = Objective(rule=total_TAC, sense=minimize)
def total_CO2(m):
return m.totalCO2 == sum(m.totalCO2peryear[year] for year in m.years)
m.totalCO2_cons = Constraint(rule=total_CO2)
def total_TACperyear(m,year):
return m.totalTACperyear[year] == sum(m.number_installed_techs[tech,supplier,year]*m.TAC[tech,supplier] for tech in m.techs for supplier in m.suppliers)
m.TACperyear_cons = Constraint(m.years, rule=total_TACperyear)
def total_CO2peryear(m,year):
return m.totalCO2peryear[year] == sum(m.number_installed_techs[tech,supplier,year]*m.CO2emissions[tech,supplier] for tech in m.techs for supplier in m.suppliers)
m.CO2peryear_cons = Constraint(m.years, rule=total_CO2peryear)
def demandperyear(m,demand,product,year):
if year == 1:
expression = m.initial_demands[demand,product]
return expression
expression = m.initial_demands[demand,product]*(1 + m.growths[demand,product]*year)
return expression
m.demandsperyear = Param(m.demands, m.products,m.years, initialize=demandperyear)
def fulfill_demands(m,supplier,demand,product,year):
if supplier == demand:
expression = sum(m.number_installed_techs[tech,supplier,year]*m.yields[tech,product,supplier] for tech in m.techs) >= m.demandsperyear[demand,product,year]
return expression
return Constraint.Skip
m.fulfill_demands_cons = Constraint(m.suppliers,m.demands,m.products,m.years, rule=fulfill_demands)
def max_installed(m,tech,supplier):
expression = sum(m.number_installed_techs[tech,supplier,year] for year in m.years) <= m.max_installed[tech,supplier]
return expression
m.max_installed_cons = Constraint(m.techs,m.suppliers, rule=max_installed)
def accum_installed(m,tech,supplier,year):
if year == 1:
expression = m.number_installed_techs[tech,supplier,year] == m.installed_techs[tech,supplier,year]
return expression
expression = m.number_installed_techs[tech,supplier,year] == m.number_installed_techs[tech,supplier,year-1] + m.installed_techs[tech,supplier,year]
return expression
m.accum_cons = Constraint(m.techs,m.suppliers,m.years, rule=accum_installed)
parameter
data = {None: {
'techs' : {None: ['tek_A', 'tek_B', 'tek_C']},
'products' : {None: ['prod_A', 'prod_B', 'prod_C']},
'suppliers' : {None: ['daerah_A', 'daerah_B', 'daerah_C']},
'demands' : {None: ['daerah_A', 'daerah_B', 'daerah_C']},
'years' : {None: [1, 2, 3, 4, 5,6,7,8,9,10]},
'initial_demands': {('daerah_A','prod_A'): 10.0, ('daerah_A','prod_B'): 10.0, ('daerah_A','prod_C'): 10.0,
('daerah_B','prod_A'): 20.0, ('daerah_B','prod_B'): 20.0, ('daerah_B','prod_C'): 20.0,
('daerah_C','prod_A'): 12.0, ('daerah_C','prod_B'): 12.0, ('daerah_C','prod_C'): 12.0},
'growths': {('daerah_A','prod_A'): 0.02, ('daerah_A','prod_B'): 0.02, ('daerah_A','prod_C'): 0.02,
('daerah_B','prod_A'): 0.02, ('daerah_B','prod_B'): 0.02, ('daerah_B','prod_C'): 0.02,
('daerah_C','prod_A'): 0.02, ('daerah_C','prod_B'): 0.02, ('daerah_C','prod_C'): 0.02},
'max_installed' : {('tek_A','daerah_A'): 100.0, ('tek_A','daerah_B'): 100.0, ('tek_A','daerah_C'): 100.0,
('tek_B','daerah_A'): 100.0, ('tek_B','daerah_B'): 100.0, ('tek_B','daerah_C'): 100.0,
('tek_C','daerah_A'): 100.0, ('tek_C','daerah_B'): 100.0, ('tek_C','daerah_C'): 100.0},
'TAC' : {('tek_A','daerah_A'): 100.0, ('tek_A','daerah_B'): 100.0, ('tek_A','daerah_C'): 100.0,
('tek_B','daerah_A'): 100.0, ('tek_B','daerah_B'): 100.0, ('tek_B','daerah_C'): 100.0,
('tek_C','daerah_A'): 100.0, ('tek_C','daerah_B'): 100.0, ('tek_C','daerah_C'): 100.0},
'CO2emissions' : {('tek_A','daerah_A'): 20.0, ('tek_A','daerah_B'): 20.0, ('tek_A','daerah_C'): 20.0,
('tek_B','daerah_A'): 20.0, ('tek_B','daerah_B'): 20.0, ('tek_B','daerah_C'): 20.0,
('tek_C','daerah_A'): 20.0, ('tek_C','daerah_B'): 20.0, ('tek_C','daerah_C'): 20.0},
'yields': {('tek_A','prod_A','daerah_A'):8.0, ('tek_A','prod_A','daerah_B'):8.0, ('tek_A','prod_A','daerah_C'):8.0,
('tek_A','prod_B','daerah_A'):8.0, ('tek_A','prod_B','daerah_B'):8.0, ('tek_A','prod_B','daerah_C'):8.0,
('tek_A','prod_C','daerah_A'):8.0, ('tek_A','prod_C','daerah_B'):8.0, ('tek_A','prod_C','daerah_C'):8.0,
('tek_B','prod_A','daerah_A'):8.0, ('tek_B','prod_A','daerah_B'):8.0, ('tek_B','prod_A','daerah_C'):8.0,
('tek_B','prod_B','daerah_A'):8.0, ('tek_B','prod_B','daerah_B'):8.0, ('tek_B','prod_B','daerah_C'):8.0,
('tek_B','prod_C','daerah_A'):8.0, ('tek_B','prod_C','daerah_B'):8.0, ('tek_B','prod_C','daerah_C'):8.0,
('tek_C','prod_A','daerah_A'):8.0, ('tek_C','prod_A','daerah_B'):8.0, ('tek_C','prod_A','daerah_C'):8.0,
('tek_C','prod_B','daerah_A'):8.0, ('tek_C','prod_B','daerah_B'):8.0, ('tek_C','prod_B','daerah_C'):8.0,
('tek_C','prod_C','daerah_A'):8.0, ('tek_C','prod_C','daerah_B'):8.0, ('tek_C','prod_C','daerah_C'):8.0}
}}
instance = m.create_instance(data)
instance.pprint()
solver = SolverFactory('glpk')
hasil = solver.solve(instance)
for tech in instance.installed_techs.values():
print(tech.value)
for number_of_techs_installed in instance.number_installed_techs.values():
print(number_of_techs_installed.value)
for TACperyear in instance.totalTACperyear.values():
print(TACperyear.value)
for CO2peryear in instance.totalCO2peryear.values():
print(CO2peryear.value)
print('Total TAC', instance.totalTAC())
print('Total CO2', instance.totalCO2())
If I have to calculate the "demandsperyear" outside of the Pyomo, how should i do that?
Thanks
</details>
# 答案1
**得分**: 0
Here is the translation of the code portions you provided:
```python
要获得某些东西,如@user2357112建议的,我需要解决`total_TAC`上的问题:
def total_TAC(m):
# return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
return sum(m.totalTACperyear[year] for year in m.years)
然后,在创建实例之前,我计算了`demandsperyear`:
def demandperyear_outside(demand, product, year, initial_demands, growths):
if year == 1:
return initial_demands[demand, product]
# 我假设接下来的年份采用复利增长,也许您想要更改这个
return initial_demands[demand, product] * (1 + growths[demand, product] * year)
demandsperyear_data = {
(demand, product, year): demandperyear_outside(
demand, product, year, data[None]['initial_demands'], data[None]['growths'])
for demand in data[None]['demands'][None]
for product in data[None]['products'][None]
for year in data[None]['years'][None]
}
然后,我将其添加到`data`中:
data[None]['demandsperyear'] = demandsperyear_data
通过这个操作,我将您的`m.demandsperyear`更改为:
m.demandsperyear = Param(m.demands, m.products, m.years, initialize=data[None]['demandsperyear'])
我得到了一个**总CO2**(1400),但很遗憾**总TAC**是`None`。
**更新我的第二次尝试**:我添加了一个`totalTAC`的约束条件,如下所示:
def total_TAC_constraint(m):
return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
m.totalTAC_cons = Constraint(rule=total_TAC_constraint)
现在我得到了结果:
总TAC 7000.0
总CO2 1400.0
英文:
To get something I had to solve, as @user2357112 suggested, the problem on total_TAC
:
def total_TAC(m):
# return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
return sum(m.totalTACperyear[year] for year in m.years)
Then I calculated demandsperyear
before creating the instance:
def demandperyear_outside(demand, product, year, initial_demands, growths):
if year == 1:
return initial_demands[demand, product]
# I assume compound growth for the next years, maybe you want to change this
return initial_demands[demand, product] * (1 + growths[demand, product] * year)
demandsperyear_data = {
(demand, product, year): demandperyear_outside(
demand, product, year, data[None]['initial_demands'], data[None]['growths'])
for demand in data[None]['demands'][None]
for product in data[None]['products'][None]
for year in data[None]['years'][None]
}
which I add to the data
:
data[None]['demandsperyear'] = demandsperyear_data
With this I change your m.demandsperyear
to:
m.demandsperyear = Param(m.demands, m.products, m.years, initialize=data[None]['demandsperyear'])
I'm getting a Total CO2 (1400) but sadly a None
for Total TAC.
Update for my second attempt: I added a constraint for totalTAC
as follows:
def total_TAC_constraint(m):
return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
m.totalTAC_cons = Constraint(rule=total_TAC_constraint)
and I'm now getting results:
Total TAC 7000.0
Total CO2 1400.0
答案2
得分: 0
The problem with your code as posted has nothing to do with linear/nonlinear. The problem is in your objective function. Your objective function (below) is written as an equality, as you would in a constraint.
你的问题与你发布的代码无关于线性/非线性。问题在于你的目标函数。你的目标函数(如下)被写成了一个等式,就像在一个约束中一样。
def total_TAC(m):
return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
m.cost = Objective(rule=total_TAC, sense=minimize)
The objective function should be an expression of the variables that is, well, variable. If you substitute in this, all works. Of course, I don't know if this is the mathematical formulation you are looking for in your model, over to you on that. This just minimizes the sum as the objective.
目标函数应该是一个表达变量的表达式,它应该是可变的。如果你用以下方式替换,一切都能正常工作。当然,我不知道这是否是你在模型中寻找的数学表达方式,这取决于你。这只是将总和最小化作为目标。
def total_TAC(m):
return sum(m.totalTACperyear[year] for year in m.years)
m.cost = Objective(rule=total_TAC, sense=minimize)
英文:
The problem with your code as posted has nothing to do with linear/nonlinear. The problem is in your objective function. Your objective function (below) is written as an equality, as you would in a constraint.
def total_TAC(m):
return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
m.cost = Objective(rule=total_TAC, sense=minimize)
The objective function should be an expression of the variables that is, well, variable. If you substitute in this, all works. Of course, I don't know if this is the mathematical formulation you are looking for in your model, over to you on that. This just minimizes the sum as the objective.
def total_TAC(m):
return sum(m.totalTACperyear[year] for year in m.years)
m.cost = Objective(rule=total_TAC, sense=minimize)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论