用线性规划解决《戴森球计划》中的生产规划问题

李辰剑 2023-6-16 定稿

一、问题引入

《戴森球计划》相信大家都很熟悉啦,它是一款科幻主题的模拟经营游戏。在《戴森球计划》中,玩家需要在宇宙中采集材料、解锁科技、进行工业生产,最终建造出一个包裹恒星的戴森球,通过戴森球大量收割恒星的太阳能。然而,《戴森球计划》中科技产品的生产和建造极其复杂(配方很复杂,供应链更复杂);而建造整个戴森球(包裹整个恒星,物资消耗能不大吗)又需要大量物资,对生产的规模和效率提出了很高的要求。因此,玩家常常需要花费大量时间来设计、建造、调整各种科技产品的生产线,非常痛苦。这也是《戴森球计划》被许多玩家诟病“费肝”的原因。

于是我就想,能否用计算机科学中一些成熟的优化算法来帮忙设计生产线呢?我初步筛选出了三个可以用计算机算法优化的任务:

(1) 用线性规划求解最优的资源、产品分配。《戴森球计划》中的产业链很长,一些产品的生产配方较为复杂,需要经过多道生产步骤。例如,以下是低阶科技产品电动马达的生产线路图:


如何合理分配资源(例如,以合适的比例将铁矿分配到铁块和磁铁的生产中)以最大化目标产出(例如,最大化马达的生产速率)是一个麻烦的问题。但这一步骤恰好可以用线性规划(Linear Programming)模型求解。

(2) 用集成芯片设计算法优化工厂和物流的布局布线。 《戴森球计划》中的工厂输入输出和布局可以非常复杂… 其实这和集成芯片物理设计中的元件布局和布线有许多相似之处。

(3) 用非线性模型优化工厂位置和物流。这个我懂,区位条件嘛!哪颗星球铁矿多、就着重生产钢铁、马达;哪颗星球石油多,就着重搞能源工业和石油化工。如果有市场经济,每个工厂的厂长就会自己搬去离原料最近的工厂,从而最小化物流开销。——可惜《戴森球计划》中的所有生产都由玩家一人负责,因此需要玩家自己优化所有工厂的位置,相当繁琐。如果能写出一个目标函数,以工厂选址为输入变量变量、以物流成本为函数值、再对该函数进行最优化,就可以得到最优的工厂选址,从而将玩家从繁琐的工厂规划中解放出来。

虽然三个想法都很诱人,但是布局布线和非线性优化都过于复杂…… 于是我决定先尝试基于线性规划的想法(1)。也许以后可以试试另两个想法 :-)


《戴森球计划》游戏内截图。上:《戴森球计划》中的生产线;下:正在建造中的戴森球。

二、问题建模

1. 《戴森球计划》中的产品分配问题

《戴森球计划》中的产业链很长,一些产品的生产需要经过多道生产步骤。例如,以下是低阶科技产品电动马达的生产线路图:


在生产马达时,给定铁矿和铜矿生产速度,玩家会面临这样一个问题:如何确定铁块和磁铁的生产比例?如果铁块生产过多、磁线圈就会生产不足,导致铁块积压;相反,如果铁块生产过少、磁铁生产过多,就会导致磁线圈积压。因此,只有合理地分配原料和中间产品,才能达到目标产品的最大产量。合理分配单一资源并非难事。但在《戴森球计划》的实际生产中,往往需要同时平衡十几种原料和产品的供应链,完美平衡所有产物并非易事。

在实际搭建高阶科技产品生产线的时候,常常由于原料生产力不匹配遇到顾此失彼的情况。由于生产线不均衡、无法完美匹配原料生产,从而导致某种材料堆积或缺乏,这会使某一步生产成为瓶颈,无法充分利用星球上的资源禀赋快速生产高级产品。但由于生产链很复杂,手工优化调整很繁琐。

《戴森球计划》中高阶科技产品「能量矩阵」和「结构矩阵」的生产过程。从原材料到成品,构成了一个复杂的有向无环图 (DAG) 结构。图片来自 https://steamah.com/dyson-sphere-program-matrix-production-guide/

考虑到《戴森球计划》中的生产配方都是「线性的」,即,一份原料一份收获,我们可以将原料分配问题建模为线性规划问题。一旦将问题建模为线性规划问题,就可以调用成熟的线性规划求解器自动求解,从而将玩家从繁琐的手动优化中解放出来。

2. 假设与变量

《戴森球计划》中的自动化生产是一个非常复杂的问题。除了原料之外,还要考虑物流、工厂占地、生产速率等等问题。为了将问题规约为简单的线性规划模型,我们做一些简化:

  1. 假设星球上的资源总量无限,但每分钟采集的资源数量(即资源采集速率)受到矿脉数量限制。
  2. 假设星球上总是有足够的地方修建工厂。
  3. 假设有充足的能源供应(依靠正在建造的戴森球)和便捷的物流系统(不用考虑物流运输问题)。

在这些假设下,能源、工厂占地、物流都不成为问题,资源采集速率是对生产的唯一约束。

因此,这一模型求解得到的结果不提供工厂和物流的布局方案,只提供原料和各个工业品的分配方案QAQ

接下来,我们将『每种工业品的每分钟生产量』(即生产速率)建模为线性规划中的变量。例如,铁矿,铁块,齿轮的每分钟生产数量分别对应线性规划中的 $\sharp铁矿$,$\sharp铁块$,$\sharp 齿轮$ 变量。其中,「$\sharp$」表示「数量」之意。

以钢铁生产线为例。在《戴森球计划》中,一单位铁矿可以冶炼出一单位铁块,一单位铁块又可以生产一单位齿轮。假设每分钟最多采集 2500 单位铁矿,就可以得到如下约束:

3. 将原料生产模型转化为线性规划问题

假设 $原料_i$ 供应了产品 $产品_1,产品_2,…,产品_{m_i}$的生产,其中生产每份 $产品_j$ 需要 $a_{ji}$ 份 $原料_i$。那线性规划模型中的约束可以写为:

若一种产品的生产配方同时需要多种原料,则需要同时出现在多个原料的约束式里。例如,如果考虑电动马达生产线、忽略其它产品,可以得到以下的模型:

在《戴森球计划》中,大多数物品都由单一配方生产,但少部分物品有多种生产渠道,我们需要为此调整生成的公式。例如,游戏中的石墨烯既可以由可燃冰得到,也可以由化工工艺生产。于是,需要将产品分为两部分写入模型,再用一个式子加起来。例如,对石墨烯可以得到下式(下式中省略了系数和一些原料):

三、求解器选择,以及代码实现

线性规划是一个非常成熟的数学模型,市面上有许多求解器可供选择。例如,大名鼎鼎的 MATLAB 便提供了线性规划求解函数。然而,最终我选择了 MiniZinc。MiniZinc 是一款通用的求解器,它可以求解的问题范畴比线性规划大得多。更重要的是,MiniZinc 有自己的约束表示语言,可以通过类似高级语言的方式指定复杂的约束。相比之下,MATLAB 只支持求解矩阵输入形式的线性规划。将复杂的生产配方转换为矩阵形式是一件非常麻烦的事,因此我最终选择了 MiniZinc。

MiniZinc 的核心是一个命令行工具,负责求解由 .mzn 后缀文件指定的约束问题。不过除了命令行交互, MiniZinc 官方还提供了具有图形界面的 IDE 来编辑和运行代码,这也是我采用的交互方式。

1
2
# 在命令行使用 MiniZinc 求解器
$ minizinc --solver gecode problem.mzn
MiniZinc IDE 截图

Remark

  1. 严格来说 MiniZinc 是一款约束描述语言,真正求解时可以选择不同的求解器。
  2. 求解过程中出现了奇怪的现象:若将模型设置为整数线性规划问题,大多数求解器都可以求解;但如果将数据类型设为实数、将模型设置为实数线性规划模型,一些求解器反而无法求解。按理说,实数规划比整数规划更简单才对。

最后,完整的代码如下。其中,矿物资源的生产速度取自我的存档,使用时请修改为自己的存档数据;有一些极少使用的配方没有包含在内。求解结果见第四部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
% % DSP.mzn % %

% % 变量定义 % %
% 原矿
var int: iron_ore; constraint iron_ore >= 0;
var int: copper_ore; constraint copper_ore >= 0;
var int: coal_ore; constraint coal_ore >= 0;

% 初级产品
var int: iron; constraint iron >= 0;
var int: magnet; constraint magnet >= 0;
var int: copper; constraint copper >= 0;
var int: coal; constraint coal >= 0;

% 次级产品
var int: magnet_coil; constraint magnet_coil >= 0;
var int: gear; constraint gear >= 0;

% 电磁产品生产线
var int: EM_turbine; constraint EM_turbine >= 0;
var int: motor; constraint motor >= 0;

% 电路板
var int: PCB; constraint PCB >=0;
var int: IC; constraint IC >= 0; % 当前资源禀赋下(硅矿=2250),IC最多每分钟生产250左右
var int: micro_unit; constraint micro_unit >= 0;

% 硅产线
var int: silicon_ore; constraint silicon_ore >= 0;
var int: silicon; constraint silicon >= 0;
var int: lattice_silicon; constraint lattice_silicon >= 0;

% 光学产线
var int: raw_stone; constraint raw_stone >= 0;
var int: glass; constraint glass >= 0;
var int: prism; constraint prism >= 0;
var int: plasma_generator; constraint plasma_generator >= 0;
var int: photon_merger; constraint photon_merger >= 0;

% 结构产线
var int: titanium_ore; constraint titanium_ore >= 0;
var int: titanium; constraint titanium >= 0;
var int: titan_alloy; constraint titan_alloy >= 0;
var int: titan_glass; constraint titan_glass >= 0;
var int: titan_diamond; constraint titan_diamond >= 0;
var int: diamond; constraint diamond >= 0;
var int: graphene; constraint graphene >= 0;
var int: graphene_tube; constraint graphene_tube >= 0;
var int: steel; constraint steel >= 0;

% 能源
var int: HE_graphite; constraint HE_graphite >= 0;
var int: mined_HE_graphite; constraint mined_HE_graphite >= 0;
var int: splitted_HE_graphite; constraint splitted_HE_graphite >= 0;
HE_graphite = splitted_HE_graphite + mined_HE_graphite;
% HE = High Energy, HE_graphite:高能石墨
var int: crude_oil; constraint crude_oil >= 0;
var int: gasoline; constraint gasoline >= 0;
var int: combustible_ice; constraint combustible_ice >= 0;
var int: hydrogen; constraint hydrogen >= 0;
% 从气态巨行星提取的氢
var int: extracted_hydrogen; constraint extracted_hydrogen >= 0;
% 裂解得到的氢
var int: splitted_hydrogen; constraint splitted_hydrogen >= 0;
% 原油分馏得到的氢
var int: fractioned_hydrogen; constraint fractioned_hydrogen >= 0;
constraint hydrogen = extracted_hydrogen + fractioned_hydrogen + splitted_hydrogen;
var int: deuterium; constraint deuterium >= 0;
var int: deuterium_unit; constraint deuterium_unit >= 0;

% 化工
var int: sulfuric_acid; constraint sulfuric_acid >= 0;
var int: organic_crystal; constraint organic_crystal >= 0;
var int: plastic; constraint plastic >= 0;

% quantum/advanced
var int: super_magnet_coil; constraint super_magnet_coil >= 0; % 当前资源,极限=85/分钟
var int: QIC; constraint QIC >= 0;
var int: particle_broadband; constraint particle_broadband >= 0;
var int: Casmir_crystal; constraint Casmir_crystal >= 0;
var int: subspace_selector; constraint subspace_selector >= 0;
% subspace_selector: 位面过滤器

% DSP component
var int: solar_sail; constraint solar_sail >= 0;
var int: DSP_unit; constraint DSP_unit >= 0;

% rocket
var int: framework_mat; constraint framework_mat >= 0;
var int: rocket; constraint rocket >= 0;

% 科技矩阵
var int: EM_matrix; constraint EM_matrix >= 0;
var int: structure_matrix; constraint structure_matrix >= 0;
var int: energy_matrix; constraint energy_matrix >= 0;
var int: information_matrix; constraint information_matrix >= 0;
var int: gravity_matrix; constraint gravity_matrix >= 0;
var int: universe_matrix; constraint universe_matrix >= 0;
var int: gravity_len; constraint gravity_len >= 0;
var int: particle_container; constraint particle_container >= 0;
var int: strange_matter; constraint strange_matter >= 0;

% % 原料生产速度 % %
% 请根据存档资源分布调整数值 %
constraint iron_ore <= 2500;
constraint copper_ore <= 2000;
constraint coal_ore <= 1300;
constraint raw_stone <= 3000;
constraint silicon_ore <= 2250;
constraint titanium_ore <= 2500;
constraint combustible_ice <= 192.04*45;
constraint extracted_hydrogen <= 87.1*45; %~3920
constraint crude_oil <= 29.28*60; %~1780;

% % 生产公式约束 % %
% 初级产品
constraint iron + magnet <= iron_ore;
constraint copper <= copper_ore;
constraint 2*silicon <= silicon_ore;
constraint 2*titanium <= titanium_ore;
constraint 2*mined_HE_graphite <= coal_ore;
constraint 2*glass + 2*sulfuric_acid <= raw_stone;
constraint 2*splitted_hydrogen <= crude_oil;
constraint gasoline = 2*splitted_hydrogen;
constraint 2*extracted_hydrogen <= combustible_ice;
constraint graphene = 2*extracted_hydrogen;
% 第一行(生产面板中的第一行产品,下同)
constraint gear + 3*steel + 2*motor + 2*PCB + 2*strange_matter <= iron;
constraint magnet_coil + micro_unit + PCB <= copper;
constraint lattice_silicon + 2*micro_unit + framework_mat <= silicon;
constraint 2*titan_alloy + 2*titan_glass + 6*titan_diamond + graphene_tube <= 2*titanium;
constraint plastic + diamond + super_magnet_coil + 2*energy_matrix <= HE_graphite;
constraint 2*splitted_HE_graphite + 4*plastic + 2*organic_crystal + 3*sulfuric_acid <= 2*gasoline;
constraint 3*graphene_tube + 4*Casmir_crystal + solar_sail <= 2*graphene;
constraint 2*organic_crystal + particle_broadband <= plastic;
% 第二行
constraint 2*magnet_coil + super_magnet_coil <= magnet;
constraint motor + 2*EM_turbine + EM_matrix + 4*plasma_generator <= magnet_coil;
constraint 2*particle_broadband <= lattice_silicon;
constraint deuterium_unit + 2*framework_mat <= 2*titan_alloy;
constraint 2*titan_glass + 3*prism <= 2*glass;
constraint 4*gravity_len + structure_matrix <= diamond;
constraint splitted_hydrogen = 3*splitted_HE_graphite; % 裂解公式
constraint organic_crystal <= organic_crystal;
constraint 2*splitted_HE_graphite + 2*deuterium + 12*Casmir_crystal + 2*energy_matrix <= hydrogen;
constraint 20*deuterium_unit + 10*strange_matter <= deuterium;
constraint 4*rocket <= deuterium_unit;
% 第三行
constraint titan_alloy <= steel;
constraint 2*EM_turbine <= motor;
constraint 2*subspace_selector <= titan_glass;
constraint 2*plasma_generator + 2*photon_merger <= prism;
constraint Casmir_crystal + structure_matrix <= titan_diamond;
constraint gravity_len <= strange_matter;
% 第四行
constraint motor <= gear;
constraint 2*super_magnet_coil <= EM_turbine;
constraint 2*IC + EM_matrix + photon_merger <= PCB;
constraint gravity_matrix <= gravity_len;
constraint 2*titan_alloy <= sulfuric_acid;
constraint 2*particle_broadband + 4*framework_mat <= graphene_tube;
% 第五行
constraint 0 <= plasma_generator;
constraint deuterium_unit <= 2*super_magnet_coil;
constraint information_matrix <= particle_broadband;
constraint 3*DSP_unit + 2*QIC + 2*information_matrix <= IC;
constraint subspace_selector <= Casmir_crystal;
constraint 2*strange_matter <= particle_container;
constraint 2*QIC <= subspace_selector;
constraint 3*DSP_unit <= solar_sail;
constraint 3*DSP_unit <= framework_mat;
constraint 2*rocket <= DSP_unit;
% 第六行
constraint solar_sail <= 2*photon_merger;
constraint 2*IC <= micro_unit;
constraint 2*rocket + gravity_matrix <= QIC;
% 第七行
constraint universe_matrix <= EM_matrix; % 电磁矩阵瓶颈:铁矿 #=625
constraint universe_matrix <= energy_matrix; % 瓶颈:煤矿 #=379
constraint universe_matrix <= structure_matrix; % 瓶颈:钛矿 #=416
constraint universe_matrix <= information_matrix; % 瓶颈:硅矿 #=112
constraint universe_matrix <= gravity_matrix; % 瓶颈:氢和钛矿 #=125
%宇宙矩阵还缺一个反物质约束
% universe_matrix #=62

% % 目标 % %
%constraint EM_turbine >= 100;
%constraint IC >= 100;

%solve maximize EM_matrix;
%solve maximize energy_matrix;
%solve maximize structure_matrix;
%solve maximize information_matrix;
%solve maximize gravity_matrix;
%solve maximize universe_matrix;
solve maximize rocket;

四、求解结果与分析

在这一节中,我将以一些终端科技产品为目标,运行优化器,得到有限资源条件下的最优解。有了线性规划求解器的帮助,我们就可以从纷繁复杂的生产线中找到关键的限速路径,并进一步分析其生产瓶颈。

在《戴森球计划》计划中,除去建筑,生产复杂、需求量大的终端科技产品有七种:

  • 电磁矩阵(蓝色矩阵):需要磁线圈和电磁涡轮生产,象征着电磁学科技。可以看作电磁科技和电磁产品生产力的抽象。
  • 能量矩阵(红色矩阵):需要高能石墨和氢元素生产,象征着能源工业。可以看作能源的抽象。
  • 结构矩阵(黄色矩阵):需要金刚石和钛晶石生产,象征着高强度材料科技。可以看作高阶材料科技和高强度材料产能的抽象。
  • 信息矩阵(紫色矩阵):需要集成芯片(游戏中的“处理器”)和粒子宽带生产,象征着成熟的信息科技。可以看作信息科技和信息产品产能的抽象。
  • 引力矩阵(绿色矩阵):需要量子芯片和引力透镜进行生产,象征着量子力学和广义相对论的统一(这两个理论之间有矛盾,现实世界中还没做到相互统一),代表了最高阶的科技和最先进的科技产品。
  • 宇宙矩阵(白色矩阵):一份宇宙矩阵由一份电磁矩阵、一份能量矩阵、一份结构矩阵、一份信息矩阵、一份引力矩阵生产,是消耗资源最多、最综合的产品。象征着最前沿且全面的科技水平。
  • 小型运载火箭:需要戴森球组件、量子芯片和氘核燃料棒生产。小型运载火箭负责将戴森球组件运送到恒星附近并组装,是戴森球的前体。在建造戴森球的过程中,大规模、稳定地量产运载火箭是必不可少的。然而,小型运载火箭的产业链非常长,生产难度高,需求量也非常大,因此设计火箭生产线绝非易事。

接下来,我们分别以前述的七种产品产量为目标,进行最优化,然后对结果进行分析。

六种矩阵的生产步骤和每一步的配方。
图片来自https://imgur.com/

1. 电磁矩阵

DSP.mzn 中将最优化目标设为 solve maximize EM_matrix;(即最大化电磁矩阵产量),然后调用求解器,得到以下结果:

为便于观察理解,求解器结果经过了筛选和重排,下同

1
2
3
4
5
6
7
8
9
iron_ore = 2500; % 达到矿物生产速度上限(上限=2500)
copper_ore = 1250; % 未达到矿物生产速度上限(上限=2000)
iron = 1250;
magnet = 1250;
copper = 1250;
PCB = 625;

EM_matrix = 625;
...(值为0的变量已忽略)...

线性规划的求解结果给出了电磁矩阵的最大生产速率(最后一行),以及产率最大化时对其它产品的需求(前六行)。在不同玩家的不同存档中,资源条件常常存在差异;而在同一存档中,前期和后期的资源开发利用程度也会有所不同。因此,电磁矩阵最大生产速率的绝对值意义不大;相比之下,更加重要的是分析产品的相对生产比例以及整体的生产规律和特点

可以看到,电磁矩阵的生产强烈依赖于铁矿和铜矿以及随后的铜铁产业。最后一行告诉我们,(在我的存档条件下,下同)电磁矩阵的最大生产速率为每分钟 625 单位。结合矿物资源上限可以发现,限制电磁矩阵生产的资源是铁矿,铜矿并没有被完全利用起来。

2. 能量矩阵

DSP.mzn 中将最优化目标设为 solve maximize energy_matrix;,然后调用求解器,得到以下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
coal_ore = 1300; % 达到矿物生产速度上限(上限=1780)
mined_HE_graphite = 650;
splitted_HE_graphite = 292;
HE_graphite = 942;
crude_oil = 1752; % 基本达到矿物生产速度上限(上限=1780)
gasoline = 1752;
combustible_ice = 0;
hydrogen = 1526;
extracted_hydrogen = 0; % 未开采巨型气态行星,氢元素生产仍有潜力
splitted_hydrogen = 876;
fractioned_hydrogen = 650;

energy_matrix = 471;
...(一些值为0的变量已忽略)...

可以看到,能量矩阵的生产强烈依赖于原油生产和煤矿采掘,这很符合大众对能源工业的印象 :-) 能量矩阵的最大生产速率为每分钟 471 单位,低于电磁矩阵,说明能量矩阵的生产难度更高;从数据可以看出,限制能量矩阵生产的关键资源是煤矿。

3. 结构矩阵

DSP.mzn 中将最优化目标设为 solve maximize structure_matrix;,然后调用求解器,得到以下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
coal_ore = 832; % 未达到矿物生产速度上限(上限=1300)
titanium_ore = 2496; % 达到矿物生产速度上限(上限=2500)
titanium = 1248;
titan_alloy = 0;
titan_glass = 0;
titan_diamond = 416;
diamond = 416;
steel = 0;
mined_HE_graphite = 416;
splitted_HE_graphite = 0;
HE_graphite = 416;

structure_matrix = 416;
...(一些值为0的变量已忽略)...

可以看到,结构矩阵的生产主要依赖于钛材料和金刚石。能量矩阵的最大生产速率为每分钟 416 单位,生产难度与能量矩阵基本持平;从数据可以看出,限制结构矩阵生产的关键资源是钛矿——这非常符合大众对钛“高强度材料元素”印象。

4. 信息矩阵

DSP.mzn 中将最优化目标设为 solve maximize information_matrix;,然后调用求解器,得到以下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
iron_ore = 896; % 未达到矿物生产速度上限(上限=2500)
copper_ore = 896; % 未达到矿物生产速度上限(上限=2200)
coal_ore = 134; % 远未达到矿物生产速度上限(上限=1300)
iron = 896;
copper = 896;
PCB = 448;
IC = 224;
micro_unit = 448;
silicon_ore = 2240; % 达到矿物生产速度上限(上限=2250)
silicon = 1120;
lattice_silicon = 224;
titanium_ore = 224;
titanium = 112;
graphene = 336;
graphene_tube = 224;
mined_HE_graphite = 67;
splitted_HE_graphite = 45;
HE_graphite = 112;
crude_oil = 270; % 远未达到矿物生产速度上限(上限=1780)
gasoline = 270;
combustible_ice = 336; % 远未达到矿物生产速度上限(上限=1300)
hydrogen = 303;
extracted_hydrogen = 168;
splitted_hydrogen = 135;
fractioned_hydrogen = 0;
plastic = 112;
particle_broadband = 112;

information_matrix = 112;
...(一些值为0的变量已忽略)...

可以看到,信息矩阵的生产比前几种矩阵要困难得多,每分钟最多只能生产 112 单位;而且产业链更复杂,涉及到能源、钛和铁。不过,在所有消耗的资源中,硅的消耗量最大,硅元素产量也直接成为了信息矩阵的生产瓶颈——这非常符合大众对硅元素“信息时代关键原料”的印象。

5. 引力矩阵

DSP.mzn 中将最优化目标设为 solve maximize gravity_matrix;,然后调用求解器,得到以下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
iron_ore = 1250; % 未达到矿物生产速度上限(上限=2500)
copper_ore = 1000; % 未达到矿物生产速度上限(上限=2000)
coal_ore = 1000; % 达到矿物生产速度上限(上限=1300)
iron = 1250;
magnet = 0;
copper = 1000;
coal = 0;
magnet_coil = 0;
gear = 0;
EM_turbine = 0;
motor = 0;
PCB = 500;
IC = 250;
micro_unit = 500;
silicon_ore = 2000; % 未达到矿物生产速度上限(上限=2250)
silicon = 1000;
lattice_silicon = 0;
raw_stone = 1000; % 未达到矿物生产速度上限(上限=3000)
glass = 500;
prism = 0;
plasma_generator = 0;
photon_merger = 0;
titanium_ore = 2500; % 达到矿物生产速度上限(上限=2500)
titanium = 1250;
titan_alloy = 0;
titan_glass = 500;
titan_diamond = 250;
diamond = 500;
graphene = 500;
mined_HE_graphite = 500;
splitted_HE_graphite = 0;
HE_graphite = 500;
combustible_ice = 500;
hydrogen = 5500;
extracted_hydrogen = 250;
splitted_hydrogen = 0;
fractioned_hydrogen = 5250;
deuterium = 1250;
QIC = 125;
Casmir_crystal = 250;
subspace_selector = 250;
gravity_len = 125;
particle_container = 250;
strange_matter = 125;

gravity_matrix = 125; % 引力矩阵最大产量
...(一些值为0的变量已忽略)...

可以看到,引力矩阵也是一种生产难度较高的资源,最大生产速率只有每分钟 125 单位,且需要「奇异物质」。在所有消耗的资源中,钛的消耗量最大,这是因为生产过程中需要大量高强度材料来囚禁高能物质。于是,钛元素产量也成为了引力矩阵的生产瓶颈。

实际上,在现实世界中,往往通过超导材料产生的强磁场来囚禁高能物质,而不是传统的高强度材料(钛合金、纳米材料等等)。

5. 宇宙矩阵

DSP.mzn 中将最优化目标设为 solve maximize universe_matrix;,然后调用求解器,得到以下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
iron_ore = 1364; % 上限=2500
copper_ore = 1116; % 上限=2000
coal_ore = 942; % 上限=1300
iron = 1240;
magnet = 124;
copper = 1116;
magnet_coil = 62;
PCB = 558;
IC = 248;
micro_unit = 496;
silicon_ore = 2232; % 上限=2250
silicon = 1116;
lattice_silicon = 124;
raw_stone = 496; % 上限=3000
glass = 248;
titanium_ore = 1736; % 上限=2250
titanium = 868;
titan_alloy = 0;
titan_glass = 248;
titan_diamond = 186;
diamond = 310;
graphene = 434;
graphene_tube = 124;
mined_HE_graphite = 471;
splitted_HE_graphite = 25;
HE_graphite = 496;
crude_oil = 150; % 上限=1780
gasoline = 150;
combustible_ice = 434;
hydrogen = 2902;
extracted_hydrogen = 217;
splitted_hydrogen = 75;
fractioned_hydrogen = 2610;
deuterium = 620;
deuterium_unit = 0;
sulfuric_acid = 0;
organic_crystal = 0;
plastic = 62;
QIC = 62;
particle_broadband = 62;
Casmir_crystal = 124;
subspace_selector = 124;
EM_matrix = 62;
structure_matrix = 62;
energy_matrix = 62;
information_matrix = 62;
gravity_matrix = 62;
universe_matrix = 62;
gravity_len = 62;
particle_container = 124;
strange_matter = 62;

宇宙矩阵是最究极的科技产品,需要五种矩阵(电磁、能量、结构、信息、引力)各一份才能生产一单位的宇宙矩阵。可以看到,宇宙矩阵的产业链最长、也需要最多种类的原料。值得注意的是,虽然只要五种矩阵各一份就能生产一单位宇宙矩阵,但宇宙矩阵的最大产量小于任意一个矩阵的最大产量,即:

其中,“$(\rm alone)$”表示每种矩阵单独生产时对应的最大产量。各种初级矩阵需要的材料相互冲突、相互制约,导致宇宙矩阵的最大产量比各个矩阵产量的最小值还要小,只有每分钟 62 单位。

6. 小型运载火箭

最后,我们来查看小型运载火箭的最优生产速度。小型运载火箭是戴森球组件的运载工具,运载火箭的生产速度直接关系到戴森球的建造速度。在《戴森球计划》游戏中,一个戴森球往往需要上万个节点组成,需要数万~数十万艘运载火箭才能建造完成。小型火箭生产越快,戴森球建造得也越快。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
iron_ore = 2432; % 几乎达到矿物生产速度上限(上限=2500)
copper_ore = 1121; % 未达到矿物生产速度上限(上限=2000)
iron = 1786;
magnet = 646;
copper = 1121;
magnet_coil = 304;
gear = 152;
EM_turbine = 76;
motor = 152;
PCB = 437;
IC = 190;
micro_unit = 380;
silicon_ore = 1748; % 达到矿物生产速度上限(上限=2250)
silicon = 874;
raw_stone = 1254; % 达到矿物生产速度上限(上限=3000)
glass = 323;
prism = 114;
photon_merger = 57;
titanium_ore = 1520; % 达到矿物生产速度上限(上限=2500)
titanium = 760;
titan_alloy = 152;
titan_glass = 152;
titan_diamond = 76;
graphene = 894;
graphene_tube = 456;
steel = 152;
splitted_HE_graphite = 92;
HE_graphite = 92;
crude_oil = 552;
gasoline = 552;
combustible_ice = 894;
hydrogen = 4136; % 大量消耗氢能,但仍未达到上限
extracted_hydrogen = 447;
splitted_hydrogen = 276;
fractioned_hydrogen = 3413;
deuterium = 1520; % 需要大量氘元素用作火箭聚变引擎的燃料
deuterium_unit = 76;
sulfuric_acid = 304;
super_magnet_coil = 38;
QIC = 38;
Casmir_crystal = 76;
subspace_selector = 76;
solar_sail = 114;
DSP_unit = 38;
framework_mat = 114;
rocket = 19;

可以看到,运载火箭的生产非常困难,每分钟最多只能生产 19 艘运载火箭,不到 20 艘!这意味着,即使集中当前存档中的所有可用资源(我的存档开发了大约一个恒星系的资源)、建立最完善的产业链,也需要大约

才能建成一个戴森球(注意,这是现实世界中的时间!)。因此,玩家要么集中多个恒星系的资源,要么长时间挂机,才能完成戴森球的建造。这也是《戴森球计划》被诟病“太肝”的原因之一。

通过对生产火箭所需原料进行分析,我们发现铁矿、钛矿、硅矿和氢元素的需求量都非常大。因此,要提高运载火箭的产量并不是一件容易的事情。需要同时提高这四种原料及其下游产业链的产量,才能有效提升运载火箭的整体产能。否则,很可能某种原料的产量形成瓶颈,出现“短板效应”。

五、总结

在本文中,我们将《戴森球计划》中的工业品生产建模为线性规划问题,求解了给定资源禀赋下(以我的存档的资源情况作为参考)一些配方复杂的终端产品的最优生产方案。从结果来看,求解器给出的结果准确而丰富,优化速度远远快于玩家手动分析。

具体而言,我们使用了 MiniZinc 约束描述语言及其自带的求解器进行建模和求解。使用求解器提供的详细数值结果,我们能够从复杂的产业链中找出工业品生产的关键原料、识别产品生产速度的瓶颈,帮助玩家更好地规划生产策略。

尽管取得了一些结果,但我的模型中仍有很多不完善之处。例如,能源物流、工厂布局、区位条件都被忽略掉了,也不能在不同工艺(生产同一工业品的不同配方)间自由选择。这些都是日后可以改进的方向。

感谢

感谢 ChatGPT 帮助我做了一些文字工作 :-)

作者

IcyChlorine

发布于

2023-06-16

更新于

2024-03-20

许可协议

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.