Pyomo DataPortal 不适用于多个索引(抽象模型,CSV 导入)
Pyomo DataPortal Not Working with Multiple Indices (Abstract Model, CSV Import)
我正在尝试使用 Pyomo 中的 DataPortal 设置为抽象模型导入 CSV 数据。
from pyomo.environ import *
model = AbstractModel()
model.t = Set() # year index
model.a = Set() # type of resource index
model.q = Set() # zone index
model.EERF = Param(model.a, model.q, model.t) # feedstock production
data = DataPortal()
data.load(filename='EERBiomassProd.csv', param=model.EERF, index=(model.t, model.q, model.a))
instance = model.create_instance(data)
我从中导入的 CSV 有四列和很多行。
year
zone
source
tons
2020
california
herbaceous
2
2020
california
waste
4
...
...
...
...
2050
utah/nevada
woody
900
一共有4年的数值,10个区域,3个来源。我希望这些都是我的参数的索引,参数的值设置为“tons”列。
当我 运行 我的代码时,我从 Python 收到以下错误。
RuntimeError: Failed to set value for param=EERF, index=(2020, 'california', 'herbaceous'), value=2.
source error message=unsupported operand type(s) for +: 'int' and 'type'
建议?我可以尝试以其他方式导入数据,比如使用 Pandas 数据框吗?我是否应该手动写出每个索引是什么,而不是尝试使用 DataPortal(例如 model.t = Set(initialize=[2020, 2030, 2040, 2050])
)从 CSV 中读取它们?
我觉得你是在找麻烦...:)
你 运行 通过读取这样的数据遇到的问题是从多维集到单个集的推理。我不认为 pyomo
可以自然地做到这一点。您或许可以从 3-dim 索引中折磨出各个集合,但可能不值得。您将遇到 pyomo
必须解决的重复问题等。指数中可能有很多重复项(2020 年将出现多次,加利福尼亚等地也一样)。
下面的第一个示例读取您的数据(使用下面发布的类似 .csv),但仅捕获 3-dim 索引。也许这“足够好”但不太可能。
如果你想留在“抽象领域”,你应该将你的集合分解成单独的数据 fields/files 等等,也许在文档中使用 JSON 或 YAML 结构。
选项 2 是使用 csv reader
或 pandas
或自行开发的东西来读取 pyomo
之外的数据,然后根据结果制作一个 ConcreteModel。这是示例中的 m2
。我认为这是最简单的?取决于您模型的其余部分...
data.csv:
year,zone,source,tons
2020,ca,herb,2
2020,ca,waste,3
2020,nv,waste,4
2019,az,herb,5
脚本:
from pyomo.environ import *
model = AbstractModel()
# model.t = Set() # year index
# model.a = Set() # type of resource index
# model.q = Set() # zone index
model.tqa = Set(dimen=3)
model.EERF = Param(model.tqa) # feedstock production
data = DataPortal()
data.load(filename='data.csv', param=model.EERF, index=model.tqa)
instance = model.create_instance(data)
instance.pprint()
### Option 2 ###
import pandas as pd
df = pd.read_csv('data.csv').set_index(['year', 'zone', 'source'])
model_data = df.to_dict('index')
m2 = ConcreteModel('pandas_based')
### SETS
# note: sorted lists from sets is required to (1) avoid dupes,
# and (2) provide lists to initializer for consistent
# (deterministic) results. Failure to do either will gen warnings...
m2.t = Set(initialize=sorted({t[0] for t in model_data.keys()}))
m2.q = Set(initialize=sorted({t[1] for t in model_data.keys()}))
m2.a = Set(initialize=sorted({t[2] for t in model_data.keys()}))
# a convenience for later use...
m2.tqa_idx = Set(within=m2.t*m2.q*m2.a, initialize=model_data.keys())
### PARAMS
m2.EERF = Param(m2.t, m2.q, m2.a, initialize=
{t[0]:t[1]['tons'] for t in model_data.items()})
print(' *** Concrete Model *** ')
m2.pprint()
输出:
1 Set Declarations
tqa : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 3 : Any : 4 : {(2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'waste'), (2019, 'az', 'herb')}
1 Param Declarations
EERF : Size=4, Index=tqa, Domain=Any, Default=None, Mutable=False
Key : Value
(2019, 'az', 'herb') : 5
(2020, 'ca', 'herb') : 2
(2020, 'ca', 'waste') : 3
(2020, 'nv', 'waste') : 4
2 Declarations: tqa EERF
*** Concrete Model ***
7 Set Declarations
EERF_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 3 : t*q*a : 12 : {(2019, 'az', 'herb'), (2019, 'az', 'waste'), (2019, 'ca', 'herb'), (2019, 'ca', 'waste'), (2019, 'nv', 'herb'), (2019, 'nv', 'waste'), (2020, 'az', 'herb'), (2020, 'az', 'waste'), (2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'herb'), (2020, 'nv', 'waste')}
a : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {'herb', 'waste'}
q : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {'az', 'ca', 'nv'}
t : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {2019, 2020}
tqa_idx : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 3 : tqa_idx_domain : 4 : {(2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'waste'), (2019, 'az', 'herb')}
tqa_idx_domain : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 3 : tqa_idx_domain_index_0*a : 12 : {(2019, 'az', 'herb'), (2019, 'az', 'waste'), (2019, 'ca', 'herb'), (2019, 'ca', 'waste'), (2019, 'nv', 'herb'), (2019, 'nv', 'waste'), (2020, 'az', 'herb'), (2020, 'az', 'waste'), (2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'herb'), (2020, 'nv', 'waste')}
tqa_idx_domain_index_0 : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : t*q : 6 : {(2019, 'az'), (2019, 'ca'), (2019, 'nv'), (2020, 'az'), (2020, 'ca'), (2020, 'nv')}
1 Param Declarations
EERF : Size=4, Index=EERF_index, Domain=Any, Default=None, Mutable=False
Key : Value
(2019, 'az', 'herb') : 5
(2020, 'ca', 'herb') : 2
(2020, 'ca', 'waste') : 3
(2020, 'nv', 'waste') : 4
我正在尝试使用 Pyomo 中的 DataPortal 设置为抽象模型导入 CSV 数据。
from pyomo.environ import *
model = AbstractModel()
model.t = Set() # year index
model.a = Set() # type of resource index
model.q = Set() # zone index
model.EERF = Param(model.a, model.q, model.t) # feedstock production
data = DataPortal()
data.load(filename='EERBiomassProd.csv', param=model.EERF, index=(model.t, model.q, model.a))
instance = model.create_instance(data)
我从中导入的 CSV 有四列和很多行。
year | zone | source | tons |
---|---|---|---|
2020 | california | herbaceous | 2 |
2020 | california | waste | 4 |
... | ... | ... | ... |
2050 | utah/nevada | woody | 900 |
一共有4年的数值,10个区域,3个来源。我希望这些都是我的参数的索引,参数的值设置为“tons”列。
当我 运行 我的代码时,我从 Python 收到以下错误。
RuntimeError: Failed to set value for param=EERF, index=(2020, 'california', 'herbaceous'), value=2.
source error message=unsupported operand type(s) for +: 'int' and 'type'
建议?我可以尝试以其他方式导入数据,比如使用 Pandas 数据框吗?我是否应该手动写出每个索引是什么,而不是尝试使用 DataPortal(例如 model.t = Set(initialize=[2020, 2030, 2040, 2050])
)从 CSV 中读取它们?
我觉得你是在找麻烦...:)
你 运行 通过读取这样的数据遇到的问题是从多维集到单个集的推理。我不认为 pyomo
可以自然地做到这一点。您或许可以从 3-dim 索引中折磨出各个集合,但可能不值得。您将遇到 pyomo
必须解决的重复问题等。指数中可能有很多重复项(2020 年将出现多次,加利福尼亚等地也一样)。
下面的第一个示例读取您的数据(使用下面发布的类似 .csv),但仅捕获 3-dim 索引。也许这“足够好”但不太可能。
如果你想留在“抽象领域”,你应该将你的集合分解成单独的数据 fields/files 等等,也许在文档中使用 JSON 或 YAML 结构。
选项 2 是使用 csv reader
或 pandas
或自行开发的东西来读取 pyomo
之外的数据,然后根据结果制作一个 ConcreteModel。这是示例中的 m2
。我认为这是最简单的?取决于您模型的其余部分...
data.csv:
year,zone,source,tons
2020,ca,herb,2
2020,ca,waste,3
2020,nv,waste,4
2019,az,herb,5
脚本:
from pyomo.environ import *
model = AbstractModel()
# model.t = Set() # year index
# model.a = Set() # type of resource index
# model.q = Set() # zone index
model.tqa = Set(dimen=3)
model.EERF = Param(model.tqa) # feedstock production
data = DataPortal()
data.load(filename='data.csv', param=model.EERF, index=model.tqa)
instance = model.create_instance(data)
instance.pprint()
### Option 2 ###
import pandas as pd
df = pd.read_csv('data.csv').set_index(['year', 'zone', 'source'])
model_data = df.to_dict('index')
m2 = ConcreteModel('pandas_based')
### SETS
# note: sorted lists from sets is required to (1) avoid dupes,
# and (2) provide lists to initializer for consistent
# (deterministic) results. Failure to do either will gen warnings...
m2.t = Set(initialize=sorted({t[0] for t in model_data.keys()}))
m2.q = Set(initialize=sorted({t[1] for t in model_data.keys()}))
m2.a = Set(initialize=sorted({t[2] for t in model_data.keys()}))
# a convenience for later use...
m2.tqa_idx = Set(within=m2.t*m2.q*m2.a, initialize=model_data.keys())
### PARAMS
m2.EERF = Param(m2.t, m2.q, m2.a, initialize=
{t[0]:t[1]['tons'] for t in model_data.items()})
print(' *** Concrete Model *** ')
m2.pprint()
输出:
1 Set Declarations
tqa : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 3 : Any : 4 : {(2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'waste'), (2019, 'az', 'herb')}
1 Param Declarations
EERF : Size=4, Index=tqa, Domain=Any, Default=None, Mutable=False
Key : Value
(2019, 'az', 'herb') : 5
(2020, 'ca', 'herb') : 2
(2020, 'ca', 'waste') : 3
(2020, 'nv', 'waste') : 4
2 Declarations: tqa EERF
*** Concrete Model ***
7 Set Declarations
EERF_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 3 : t*q*a : 12 : {(2019, 'az', 'herb'), (2019, 'az', 'waste'), (2019, 'ca', 'herb'), (2019, 'ca', 'waste'), (2019, 'nv', 'herb'), (2019, 'nv', 'waste'), (2020, 'az', 'herb'), (2020, 'az', 'waste'), (2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'herb'), (2020, 'nv', 'waste')}
a : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {'herb', 'waste'}
q : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {'az', 'ca', 'nv'}
t : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {2019, 2020}
tqa_idx : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 3 : tqa_idx_domain : 4 : {(2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'waste'), (2019, 'az', 'herb')}
tqa_idx_domain : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 3 : tqa_idx_domain_index_0*a : 12 : {(2019, 'az', 'herb'), (2019, 'az', 'waste'), (2019, 'ca', 'herb'), (2019, 'ca', 'waste'), (2019, 'nv', 'herb'), (2019, 'nv', 'waste'), (2020, 'az', 'herb'), (2020, 'az', 'waste'), (2020, 'ca', 'herb'), (2020, 'ca', 'waste'), (2020, 'nv', 'herb'), (2020, 'nv', 'waste')}
tqa_idx_domain_index_0 : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : t*q : 6 : {(2019, 'az'), (2019, 'ca'), (2019, 'nv'), (2020, 'az'), (2020, 'ca'), (2020, 'nv')}
1 Param Declarations
EERF : Size=4, Index=EERF_index, Domain=Any, Default=None, Mutable=False
Key : Value
(2019, 'az', 'herb') : 5
(2020, 'ca', 'herb') : 2
(2020, 'ca', 'waste') : 3
(2020, 'nv', 'waste') : 4