为什么glpk将线性规划公式视为非线性规划?

huangapple go评论124阅读模式
英文:

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.

  1. from pyomo.environ import *
  2. m = AbstractModel()
  3. m.techs = Set()
  4. m.products = Set()
  5. m.suppliers = Set()
  6. m.demands = Set()
  7. m.years = Set()
  8. m.initial_demands = Param(m.demands,m.products)
  9. m.growths = Param(m.demands,m.products)
  10. m.yields = Param(m.techs,m.products,m.suppliers)
  11. m.CO2emissions = Param(m.techs,m.suppliers)
  12. m.TAC = Param(m.techs,m.suppliers)
  13. m.max_installed = Param(m.techs,m.suppliers)
  14. m.installed_techs = Var(m.techs, m.suppliers, m.years, within=Binary)
  15. m.number_installed_techs= Var(m.techs, m.suppliers, m.years, bounds=(0,None))
  16. m.totalTAC = Var(bounds=(None,None))
  17. m.totalCO2 = Var(bounds=(None,None))
  18. m.totalTACperyear = Var(m.years, bounds=(None, None))
  19. m.totalCO2peryear = Var(m.years, bounds=(None, None))
  20. def total_TAC(m):
  21. return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  22. m.cost = Objective(rule=total_TAC, sense=minimize)
  23. def total_CO2(m):
  24. return m.totalCO2 == sum(m.totalCO2peryear[year] for year in m.years)
  25. m.totalCO2_cons = Constraint(rule=total_CO2)
  26. def total_TACperyear(m,year):
  27. 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)
  28. m.TACperyear_cons = Constraint(m.years, rule=total_TACperyear)
  29. def total_CO2peryear(m,year):
  30. 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)
  31. m.CO2peryear_cons = Constraint(m.years, rule=total_CO2peryear)
  32. def demandperyear(m,demand,product,year):
  33. if year == 1:
  34. expression = m.initial_demands[demand,product]
  35. return expression
  36. expression = m.initial_demands[demand,product]*(1 + m.growths[demand,product]*year)
  37. return expression
  38. m.demandsperyear = Param(m.demands, m.products,m.years, initialize=demandperyear)
  39. def fulfill_demands(m,supplier,demand,product,year):
  40. if supplier == demand:
  41. expression = sum(m.number_installed_techs[tech,supplier,year]*m.yields[tech,product,supplier] for tech in m.techs) >= m.demandsperyear[demand,product,year]
  42. return expression
  43. return Constraint.Skip
  44. m.fulfill_demands_cons = Constraint(m.suppliers,m.demands,m.products,m.years, rule=fulfill_demands)
  45. def max_installed(m,tech,supplier):
  46. expression = sum(m.number_installed_techs[tech,supplier,year] for year in m.years) <= m.max_installed[tech,supplier]
  47. return expression
  48. m.max_installed_cons = Constraint(m.techs,m.suppliers, rule=max_installed)
  49. def accum_installed(m,tech,supplier,year):
  50. if year == 1:
  51. expression = m.number_installed_techs[tech,supplier,year] == m.installed_techs[tech,supplier,year]
  52. return expression
  53. expression = m.number_installed_techs[tech,supplier,year] == m.number_installed_techs[tech,supplier,year-1] + m.installed_techs[tech,supplier,year]
  54. return expression
  55. m.accum_cons = Constraint(m.techs,m.suppliers,m.years, rule=accum_installed)
  56. # parameter
  57. data = {None: {
  58. 'techs' : {None: ['tek_A', 'tek_B', 'tek_C']},
  59. 'products' : {None: ['prod_A', 'prod_B', 'prod_C']},
  60. 'suppliers' : {None: ['daerah_A', 'daerah_B', 'daerah_C']},
  61. 'demands' : {None: ['daerah_A', 'daerah_B', 'daerah_C']},
  62. 'years' : {None: [1, 2, 3, 4, 5,6,7,8,9,10]},
  63. 'initial_demands': {('daerah_A','prod_A'): 10.0, ('daerah_A','prod_B'): 10.0, ('daerah_A','prod_C'): 10.0,
  64. ('daerah_B','prod_A'): 20.0, ('daerah_B','prod_B'): 20.0, ('daerah_B','prod_C'): 20.0,
  65. ('daerah_C','prod_A'): 12.0, ('daerah_C','prod_B'): 12.0, ('daerah_C','prod_C'): 12.0},
  66. 'growths': {('daerah_A','prod_A'): 0.02, ('daerah_A','prod_B'): 0.02, ('daerah_A','prod_C'): 0.02,
  67. ('daerah_B','prod_A'):
  68. <details>
  69. <summary>英文:</summary>
  70. I&#39;m new to both Python and Pyomo. Nonetheless, I&#39;ve made the below code following my previous question. However, if I run it using glpk solver, it says
  71. &gt; RuntimeError: Cannot write legal LP file. Objective &#39;cost&#39; has nonlinear terms that are not quadratic.
  72. I think the formulation is an LP. I&#39;m guessing it is the calculation of parameter &quot;demandsperyear&quot;? But, it shouldn&#39;t be the cause as it is a parameter, not a variable, right?
  73. If i use cbc, I&#39;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())

  1. If I have to calculate the &quot;demandsperyear&quot; outside of the Pyomo, how should i do that?
  2. Thanks
  3. </details>
  4. # 答案1
  5. **得分**: 0
  6. Here is the translation of the code portions you provided:
  7. ```python
  8. 要获得某些东西,如@user2357112建议的,我需要解决`total_TAC`上的问题:
  9. def total_TAC(m):
  10. # return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  11. return sum(m.totalTACperyear[year] for year in m.years)
  12. 然后,在创建实例之前,我计算了`demandsperyear`:
  13. def demandperyear_outside(demand, product, year, initial_demands, growths):
  14. if year == 1:
  15. return initial_demands[demand, product]
  16. # 我假设接下来的年份采用复利增长,也许您想要更改这个
  17. return initial_demands[demand, product] * (1 + growths[demand, product] * year)
  18. demandsperyear_data = {
  19. (demand, product, year): demandperyear_outside(
  20. demand, product, year, data[None]['initial_demands'], data[None]['growths'])
  21. for demand in data[None]['demands'][None]
  22. for product in data[None]['products'][None]
  23. for year in data[None]['years'][None]
  24. }
  25. 然后,我将其添加到`data`中:
  26. data[None]['demandsperyear'] = demandsperyear_data
  27. 通过这个操作,我将您的`m.demandsperyear`更改为:
  28. m.demandsperyear = Param(m.demands, m.products, m.years, initialize=data[None]['demandsperyear'])
  29. 我得到了一个**总CO2**(1400),但很遗憾**总TAC**是`None`。
  30. **更新我的第二次尝试**:我添加了一个`totalTAC`的约束条件,如下所示:
  31. def total_TAC_constraint(m):
  32. return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  33. m.totalTAC_cons = Constraint(rule=total_TAC_constraint)
  34. 现在我得到了结果:
  35. 总TAC 7000.0
  36. 总CO2 1400.0
英文:

To get something I had to solve, as @user2357112 suggested, the problem on total_TAC:

  1. def total_TAC(m):
  2. # return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  3. return sum(m.totalTACperyear[year] for year in m.years)

Then I calculated demandsperyear before creating the instance:

  1. def demandperyear_outside(demand, product, year, initial_demands, growths):
  2. if year == 1:
  3. return initial_demands[demand, product]
  4. # I assume compound growth for the next years, maybe you want to change this
  5. return initial_demands[demand, product] * (1 + growths[demand, product] * year)
  6. demandsperyear_data = {
  7. (demand, product, year): demandperyear_outside(
  8. demand, product, year, data[None][&#39;initial_demands&#39;], data[None][&#39;growths&#39;])
  9. for demand in data[None][&#39;demands&#39;][None]
  10. for product in data[None][&#39;products&#39;][None]
  11. for year in data[None][&#39;years&#39;][None]
  12. }

which I add to the data:

  1. data[None][&#39;demandsperyear&#39;] = demandsperyear_data

With this I change your m.demandsperyear to:

  1. m.demandsperyear = Param(m.demands, m.products, m.years, initialize=data[None][&#39;demandsperyear&#39;])

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:

  1. def total_TAC_constraint(m):
  2. return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  3. m.totalTAC_cons = Constraint(rule=total_TAC_constraint)

and I'm now getting results:

  1. Total TAC 7000.0
  2. 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.

你的问题与你发布的代码无关于线性/非线性。问题在于你的目标函数。你的目标函数(如下)被写成了一个等式,就像在一个约束中一样。

  1. def total_TAC(m):
  2. return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  3. 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.

目标函数应该是一个表达变量的表达式,它应该是可变的。如果你用以下方式替换,一切都能正常工作。当然,我不知道这是否是你在模型中寻找的数学表达方式,这取决于你。这只是将总和最小化作为目标。

  1. def total_TAC(m):
  2. return sum(m.totalTACperyear[year] for year in m.years)
  3. 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.

  1. def total_TAC(m):
  2. return m.totalTAC == sum(m.totalTACperyear[year] for year in m.years)
  3. 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.

  1. def total_TAC(m):
  2. return sum(m.totalTACperyear[year] for year in m.years)
  3. m.cost = Objective(rule=total_TAC, sense=minimize)

huangapple
  • 本文由 发表于 2023年5月7日 17:08:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193018.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定