具有线性不等式、曲面和标签的 Tikz 图形(以图形方式 ILP)

具有线性不等式、曲面和标签的 Tikz 图形(以图形方式 ILP)

我正在制作幻灯片来解释整数线性规划 (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*}

我能画出最大值的线。功能和限制,但我没有成功完成以下操作:

  1. 填充限制的表面(较大的然后和较小的然后)(制作交叉点)
  2. 显示不等式的标签。等式$2x_1 + 1x_2 \leq 120$位于线旁边
  3. 填充解决方案空间的表面

有人能幫助我嗎?

这是我目前拥有的代码。

    \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}

相关内容