我正在制作幻灯片来解释整数线性规划 (ILP)。我想要做的是展示如何以图形方式解决二维问题。
例如我有以下问题:
Decision variables:
\begin{description}
\item[$x_{1}$]
\item[$x_{2}$]
\end{description}
Maximaize
\[ 3 x_{1} + 4 x_{2} \]
Restrictions
\begin{equation*}
\begin{cases}
2x_1 + 1x_2 \leq 120 \\
1x_1 + 3x_2 \leq 180 \\
1x_1 + 1x_2 \leq 80 \\
x_1 \geq 0, x_2 \geq 0
\end{cases}
\label{eq:restricties}
\end{equation*}
我能画出最大值的线。功能和限制,但我没有成功完成以下操作:
- 填充限制的表面(较大的然后和较小的然后)(制作交叉点)
- 显示不等式的标签。等式
$2x_1 + 1x_2 \leq 120$
位于线旁边 - 填充解决方案空间的表面
有人能幫助我嗎?
这是我目前拥有的代码。
\begin{tikzpicture}
\begin{axis}[
domain=0:150,
xmin=-10, xmax=150,
ymin=-5, ymax=150,
samples=400,
axis y line=center,
axis x line=middle,
]
\addplot+[mark=none,blue] {120-x} node[pin=180:{$4x^2-5$}]{};
\addplot+[mark=none,black] {(1/3)*(180-x)};
\addplot+[mark=none,purple] {80-x};
\addplot+[mark=none,red] {(1/8)*12*x};
\addplot+[mark=none,green] {(1/4)*(290-3*x)};
\addplot+[mark=none,style=dashed,green] {(1/4)*(100-3*x)};
\addplot+[mark=none,style=dashed,green] {(1/4)*(350-3*x)};
\end{axis}
\end{tikzpicture}
亲切的问候
詹斯·比斯
答案1
对于那些感兴趣的人,这里有一个 MetaPost 解决方案(插入 LuaLaTeX 程序中),解决了 OP 的第 2 点和第 3 点(尽管我更喜欢用等式来标记线条,这是个人选择)。我认为第 1 点太难在一张图中恰当地表示。这个程序在某些地方使用了 MetaPost 隐式求解线性方程组的能力。它还在图上指示点解和最优值。编码本身肯定可以改进,例如通过引入特定的宏。我稍后会处理这个问题!
\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
\mplibtextextlabel{enable}
\begin{document}
\begin{mplibcode}
u := .075cm; xmax := 140; ymax := 140;
path constraint[], objective, max_objective; pair loc[], loc_eqmax;
beginfig(1);
% 2x_1 + x_2 \le 120
z11 = (0, 120);
z12 = (60, 0);
constraint1 = (z11 -- z12) scaled u; loc1 = u*.2[z11, z12];
% x_1 + 3x_2 \le 180
z21 = (0, 60);
z22 = (120, 20);
constraint2 = (z21 -- z22) scaled u; loc2 = u*.7[z21, z22];
% x_1 + 1x_2 \leq 80
z31 = (0, 80);
z32 = (80, 0);
constraint3 = (z31 -- z32) scaled u; loc3 = u*.2[z31, z32];
% x1 \geq 0
constraint4 = origin -- (0, ymax*u);
% x2 \geq 0
constraint5 = origin -- (xmax*u, 0);
fill buildcycle(constraint1, constraint3, constraint2, constraint4, constraint5)
withcolor .8white;
draw constraint1;
draw thelabel.top("$2x_1 + x_2 = 120$", loc1) rotatedaround(loc1, angle(z12-z11));
draw constraint2;
draw thelabel.top("$x_1 + 3x_2 = 180$", loc2) rotatedaround(loc2, angle(z22-z21));
draw constraint3;
draw thelabel.top("$x_1 + x_2 = 80$", loc3) rotatedaround(loc3, angle(z32-z31));
drawarrow constraint4;
label.lft("$x_1 = 0$", .5u*z21); label.lft("$x_2$", (0, u*ymax));
label.bot("$x_2 = 0$", .5u*z12); label.bot("$x_1$", (xmax*u, 0));
drawarrow constraint5;
% max 3x_1 + 4x2
3x01 + 4y01 = 0; x01 = -50;
3x02 + 4y02 = 0; y02 = -60;
objective = (z01 -- z02) scaled u;
drawoptions(withcolor red);
draw objective scaled .5 dashed evenly;
draw thelabel.bot("$3x_1+4x_2 = 0$", origin) rotatedaround(origin, angle(z02-z01));
% point solution z
x + y = 80; x + 3y = 180;
draw z*u withpen pencircle scaled 3;
label.llft("$(" & decimal x & "," & decimal y & ")$", z*u);
% Maximum
max_objective = objective shifted (z*u);
draw max_objective;
loc_eqmax = point .7 of max_objective;
draw thelabel.top("$3x_1 + 4x_2 =" & decimal(3x+4y) & "$", loc_eqmax)
rotatedaround(loc_eqmax, angle(loc_eqmax-z*u));
endfig;
\end{mplibcode}
\end{document}
输出:
编辑这是一个版本不是包含在 LuaLaTeX 程序中,只有 MetaPost 编码。在这个程序中,我定义了一个宏来简化旋转标签的处理:
vardef rotatedlabel@#(expr str, loc, angl) =
draw thelabel@#(str, loc) rotatedaround(loc, angl)
enddef;
事实证明,该luamplib
软件包无法正确处理此宏的井号 (#),因此我这次恢复了独立的 MetaPost。(与此同时,该luamplib
软件包的维护者 Kim Dohyun 已修复了该问题,但新版本尚未在 CTAN 中找到)。输出与上面相同。
input latexmp; setupLaTeXMP(textextlabel=enable, mode=rerun);
vardef rotatedlabel@#(expr str, loc, angl) =
draw thelabel@#(str, loc) rotatedaround(loc, angl)
enddef;
u := .075cm; xmax := 140; ymax := 140;
path constraint[], objective, max_objective; pair loc[], loc_eqmax;
beginfig(1);
% 2x_1 + x_2 \le 120
z11 = (0, 120); z12 = (60, 0);
constraint1 = (z11 -- z12) scaled u; loc1 = u*.2[z11, z12];
% x_1 + 3x_2 \le 180
z21 = (0, 60); z22 = (120, 20);
constraint2 = (z21 -- z22) scaled u; loc2 = u*.7[z21, z22];
% x_1 + 1x_2 \leq 80
z31 = (0, 80); z32 = (80, 0);
constraint3 = (z31 -- z32) scaled u; loc3 = u*.2[z31, z32];
% x1 \geq 0
constraint4 = origin -- (0, ymax*u);
% x2 \geq 0
constraint5 = origin -- (xmax*u, 0);
fill buildcycle(constraint1, constraint3, constraint2, constraint4, constraint5)
withcolor .8white;
draw constraint1;
rotatedlabel.top("$2x_1 + x_2 = 120$", loc1, angle(z12-z11));
draw constraint2;
rotatedlabel.top("$x_1 + 3x_2 = 180$", loc2, angle(z22-z21));
draw constraint3;
rotatedlabel.top("$x_1 + x_2 = 80$", loc3, angle(z32-z31));
drawarrow constraint4;
label.lft("$x_1 = 0$", .5u*z21); label.lft("$x_2$", (0, u*ymax));
drawarrow constraint5;
label.bot("$x_2 = 0$", .5u*z12); label.bot("$x_1$", (xmax*u, 0));
% max 3x_1 + 4x2
3x01 + 4y01 = 0; x01 = -50;
3x02 + 4y02 = 0; y02 = -60;
objective = (z01 -- z02) scaled u;
drawoptions(withcolor red);
draw objective scaled .5 dashed evenly;
rotatedlabel.bot("$3x_1+4x_2 = 0$", origin, angle(z02-z01));
% point solution z
x + y = 80; x + 3y = 180;
draw z*u withpen pencircle scaled 3;
label.llft("$(" & decimal x & "," & decimal y & ")$", z*u);
% Maximum
max_objective = objective shifted (z*u);
draw max_objective;
loc_eqmax = point .7 of max_objective;
rotatedlabel.top("$3x_1 + 4x_2 =" & decimal(3x+4y) & "$", loc_eqmax, angle(loc_eqmax-z*u));
endfig;
end.
答案2
像这样吗?给每行都贴上标签会很麻烦,用图例会更好,但这不是你想要的。如果你满足了这些限制,你最终只会得到两个彩色块。这是你想要的吗?
\documentclass{article}
\usepackage{pgfplots}
\usepackage{amsmath}
\pgfplotsset{compat=newest}
\usepgfplotslibrary{fillbetween}
\begin{document}
Decision variables:
\begin{description}
\item[$x_{1}$]
\item[$x_{2}$]
\end{description}
Maximaize
\[ 3 x_{1} + 4 x_{2} \]
Restrictions
\begin{equation*}
\begin{cases}
2x_1 + 1x_2 \leq 120 \\
1x_1 + 3x_2 \leq 180 \\
1x_1 + 1x_2 \leq 80 \\
x_1 \geq 0, x_2 \geq 0
\end{cases}
\label{eq:restricties}
\end{equation*}
\begin{tikzpicture}
\begin{axis}[
domain=0:180,
xmin=0, xmax=180,
ymin=0, ymax=150,
samples=200,
axis y line=center,
axis x line=middle,
]
%First line blue with a label
\addplot+[mark=none,blue] {120-x} node[pin=180:{$4x^2-5$}]{} node[pos=0](blue){};
\node [right] at (blue) {\footnotesize{$2x_1 + 1x_2 \leq 120$}};
%Second line black with a label
\addplot+[mark=none,black] {(1/3)*(180-x)} node[pos=0.6](black){};
\node [right] at (black) {\footnotesize{$ 1x_1 + 3x_2 \leq 180$}};
%Third line purple with a label
\addplot+[mark=none,purple] {80-x} node[pos=0](purple){};
\node [right] at (purple) {\footnotesize{$ 1x_1 + 1x_2 \leq 80$}};
%Fourth line red with a label
\addplot+[mark=none,red] {(1/8)*12*x} node[pos=0.02](red){};
\node [right] at (red) {\footnotesize{red}};
%Fifth line green with a label
\addplot+[mark=none,green] {(1/4)*(290-3*x)} node[pos=0.5](green){};
\node [right] at (green) {\footnotesize{Inequality}};
%Min and max lines with labels
\addplot+[name path=A, mark=none,style=dashed,green] {(1/4)*(100-3*x)} node[pos=0](min){};
\node [right] at (min) {\footnotesize{$\min$}};
\addplot+[name path=B, mark=none,style=dashed,green] {(1/4)*(350-3*x)}node[pos=0](max){};
\node [right] at (max) {\footnotesize{$\max$}};
% Colouring between the two dashed green lines aka min and max
\addplot[green!20] fill between[of=A and B];
\end{axis}
\end{tikzpicture}
\end{document}