使用 tikz 绘制马尔可夫链,其中状态仅部分着色

使用 tikz 绘制马尔可夫链,其中状态仅部分着色

我想画一个马尔可夫链,来展示 CTMC 随时间的抽象演变过程中瞬态和稳态之间的差异,就像图中这样:CTMC 随时间变化

我搜索了部分填充颜色,但没有得到任何线索,如能提供任何帮助我将非常感激。

答案1

定义部分高度很有趣:如果A是圆的面积,你必须解x = t - sin(t) / 2pi找到中心角由面积为一个。我无法在 TikZ 中做到这一点,但这是元帖子。我画出了你的第三张图:

在此处输入图片描述

这是源代码。用 进行编译lualatex

\documentclass[border=5mm]{standalone}
\usepackage{luatex85}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
    numeric node_diameter;
    node_diameter = 21;

    interim ahangle := 30;
    interim ahlength := 6;

    vardef connection(expr a, b, bend) = 
        a {(b-a) rotated bend} .. b
            cutbefore fullcircle scaled node_diameter shifted a
            cutafter fullcircle scaled (node_diameter+2) shifted b
    enddef;

    vardef loop(expr a, m) = 
        fullcircle scaled abs (m - a) shifted 5/8[a, m]
            cutbefore halfcircle scaled node_diameter shifted a
            cutafter  halfcircle scaled node_diameter rotated 180 shifted a
    enddef;

    vardef find(expr p) =
        lo_ := 0; hi_ := 360;
        forever:
            x_ := 1/2[lo_, hi_];
            exitif abs (hi_ - lo_) <= tolerance;
            if (0.017453292519943295 x_ - sind(x_)) < 6.283185307179586 p: lo_ else: hi_ fi := x_;
        endfor
        x_ / 90
    enddef;

    vardef partial_node(expr p) = 
        if p <= 0:
            fullcircle scaled eps
        elseif p < 1:
            numeric x; x = find(p);
            subpath (6-x, 6+x) of fullcircle scaled node_diameter -- cycle
        else:
            fullcircle scaled node_diameter
        fi
    enddef;

    x1 = x4 = 0; x2 = x5 = 120; x3 = x6 = 240;
    y1 = y2 = y3 = 0; y4 = y5 = y6 = -100;

    path c[]; 
    c12 = connection(z1, z2, 30);
    c21 = connection(z2, z1, 30);
    c23 = connection(z2, z3, 0);

    c14 = connection(z1, z4, 0);
    c44 = loop(z4, z4 shifted 28 left);
    c25 = connection(z2, z5, 0);
    c36 = connection(z3, z6, 36);
    c63 = connection(z6, z3, 36);

    forsuffixes $ = 12, 21, 23, 14, 44, 25, 36, 63:
        drawarrow c$;
    endfor

    label.top("$21$", point 1/2 of c12);
    label.lft("$21$", point 1/2 of c14);

    label.bot("$8$", point 1/2 of c21);
    label.top("$4$", point 1/2 of c23);
    label.rt ("$4$", point 1/2 of c25);

    label.lft("$10$", point 4 of c44);

    drawoptions(withcolor 1/2[red, white]);

    fill partial_node(1/3) shifted z1;

    fill partial_node(1/4) shifted z3;
    fill partial_node(1/2) shifted z4;
    fill partial_node(1/4) shifted z5;

    drawoptions();

    forsuffixes $ = 1, 2, 3, 4, 5, 6:
        draw fullcircle scaled node_diameter shifted z$;
    endfor

endfig;
\end{mplibcode}
\end{document}

笔记

  • 该参数node_diameter控制要绘制/填充的节点的大小

  • ahangleahlength控制普通 MP 中箭头的形状

  • 宏返回从到的connection可选弯曲连接路径ab

  • loop返回一个循环,a通过m

  • find宏改编自标准solve宏,用于解决上述方程。将答案除以 90,即可得到圆周上的相应“点”

  • partial_node宏返回一个循环路径,表示要填充的数量

我尽力让一切变得尽可能简单和“朴素”。

答案2

翻译 Thruston 对 Asymptote 的回答。

import plain_boxesExtra; // https://github.com/justonly011298/plain_boxesExtra

unitsize(1cm);
size(300);
real margin=3mm;
defaultpen(fontsize(10pt));
pair A[]={(0,0),(0,-1),(1,0),(1,-1),(2,0),(2,-1)};
object O[];
for (int i=0; i<A.length; ++i){ O.push(draw("",pscircle,A[i],margin,invisible)); }
add(new void(frame f, transform t) {
pen Pen=red+opacity(.5);
fill(f,arc(point(O[0],(S+N)/2,t),point(O[0],dir(-160),t),point(O[0],dir(-20),t))--cycle,Pen);
fill(f,arc(point(O[1],(S+N)/2,t),point(O[1],dir(-180),t),point(O[1],dir(0),t))--cycle,Pen);
fill(f,arc(point(O[3],(S+N)/2,t),point(O[3],dir(-150),t),point(O[3],dir(-30),t))--cycle,Pen);
fill(f,arc(point(O[4],(S+N)/2,t),point(O[4],dir(-150),t),point(O[4],dir(-30),t))--cycle,Pen);
for (int i=0; i<A.length; ++i) 
draw(f,circle(point(O[i],(S+N)/2,t),abs(point(O[i],(S+N)/2,t)-point(O[i],S,t))));
picture pic;
draw(pic,"$20$",point(O[0],S,t)--point(O[1],N,t),Arrow);
draw(pic,"$10$",arc(point(O[1],W,t)-2mm,point(O[1],dir(135),t),point(O[1],dir(-135),t)),Arrow);
draw(pic,"$21$",point(O[0],dir(30),t){dir(30)}..{dir(-30)}point(O[2],dir(150),t),LeftSide,Arrow);
draw(pic,"$8$",point(O[2],dir(-150),t){dir(-150)}..{dir(150)}point(O[0],dir(-30),t),LeftSide,Arrow);
draw(pic,"$4$",point(O[2],E,t)--point(O[4],W,t),LeftSide,Arrow);
draw(pic,"$4$",point(O[2],S,t)--point(O[3],N,t),LeftSide,Arrow);
draw(pic,point(O[4],dir(-45),t){dir(-60)}..{dir(-120)}point(O[5],dir(45),t),Arrow);
draw(pic,point(O[5],dir(135),t){dir(120)}..{dir(60)}point(O[4],dir(-135),t),Arrow);
add(f,pic.fit());
});

在此处输入图片描述

相关内容