我想知道如何画这些树:
我真的不知道。我看过了,但没有找到任何可以帮助我的东西(特别是画这些树)。所以我希望你能帮助我。
\documentclass[a4paper]{article}
\usepackage{amsmath}
\begin{document}
\end{document}
答案1
例如,这是使用强大forest
包的第二棵树的示意图。
\documentclass[tikz, border=5pt]{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
for tree={
shape=circle,
fill=black,
minimum width=5pt,
inner sep=1pt,
parent anchor=south,
child anchor=north,
anchor=center,
line width=1pt
}
[, label={right:some label A}
[, label={right:some label B}
[, label={right:some label C}
[, label={below:F}]
[, label={right:some label D}
[, label={below:E}]
]
]
]
]
\end{forest}
\end{document}
编辑
这里有两棵树及其公式。
如果您正在学习在逻辑中使用证明树,请不要将其用作示例。
这些不是逻辑证明中使用的标准树!
\documentclass[tikz, border=5pt, multi, varwidth]{standalone}
\usepackage{forest}
\standaloneenv{forest}
\begin{document}
\forestset{
my tree/.style={
for tree={
shape=circle,
fill=black,
minimum width=5pt,
inner sep=1pt,
anchor=center,
line width=1pt,
s sep+=25pt,
},
},
}
\begin{forest}
my tree
[, label={right:$(p_1 \rightarrow (\bot \vee (\lnot p_3)))$}
[, label={below:$p_1$}]
[, label={right:$(\bot \vee (\lnot p_3))$}
[, label={below:$\bot$}]
[, label={right:$(\lnot p_3)$}
[, label={below:$p_3$}]
]
]
]
\end{forest}
\begin{forest}
my tree
[, label={right:$(\lnot(\lnot(p_1 \wedge (\lnot p_1))))$}
[, label={right:$(\lnot(p_1 \wedge (\lnot p_1)))$}
[, label={right:$(p_1 \wedge (\lnot p_1))$}
[, label={below:$p_1$}]
[, label={right:$(\lnot p_1)$}
[, label={below:$p_1$}]
]
]
]
]
\end{forest}
\end{document}
答案2
pst-tree
这两棵树的路径如下:
\documentclass[12pt, a4paper, pdf]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{fourier}
\usepackage{pst-node, pst-tree}
\renewcommand\psedge{\ncline[arrows =-]}
\begin{document}
\psset{levelsep=1.5cm, treesep=3cm, dotsize =5pt}
\pstree
{\Tdot[dotsize =5pt] \nput{45}{\pssucc}{$ (p_1\to(\bot ∨ (\neg p_3)))$}}%
{%
\Tdot\nput{-90}{\pssucc}{$p_1$}
\pstree{\Tdot\nput{45}{\pssucc}{$(\bot ∨ (\neg p_3)) $}}%
{\Tdot\nput{-90}{\pssucc}{$\bot $}%
\pstree{\Tdot\nput{45}{\pssucc}{$(\neg p_3)$}}
{\Tdot\nput{-90}{\pssucc}{$p_3$}}
}
}
\hfill
\raisebox{-1.5cm}{%
\pstree%
{\Tdot[dotsize =5pt] \nput{45}{\pssucc}{$ (\neg(\neg(p_1 ∧ (\neg p_1))))$}}%
{\pstree%
{\Tdot \nput{45}{\pssucc}{$ (\neg(p_1 ∧ (\neg p_1)))$}}%
{\pstree%
{\Tdot \nput{45}{\pssucc}{$ (p_1 ∧ (\neg p_1)) $}}%
{\Tdot\nput{-90}{\pssucc}{$p_1$}%
\pstree%
{\Tdot \nput{45}{\pssucc}{$(\neg p_1)$}}%
{\Tdot\nput{-90}{\pssucc}{$p_1$}}
}
}
}
}%
\end{document}
答案3
也可以使用 MetaPost 来完成,例如借助元对象包裹。
树是 MetaObj 处理的“对象”之一,并且以递归方式定义,就像本程序中的树一样:
t := _T(TCs)(TCs, _T(TCs)(TCs, _T(TCs)(TCs)));
...
t := _T(TCs)(_T(TCs)(_T(TCs)(TCs, _T(TCs)(TCs))));
_T
new_Tree
是创建(子)树的命令的快捷方式,也是TCs
在当前节点放置实心圆的另一个快捷方式。
\documentclass{article}
\usepackage{luamplib}
\everymplib{verbatimtex \leavevmode etex;
input metaobj
setCurveDefaultOption("arrows")("draw");
setObjectDefaultOption("Tree")("treenodehsize")(0);
setObjectDefaultOption("Tree")("hbsep")(1.6cm);
setObjectDefaultOption("Tree")("vsep")(.7cm);
labeloffset := 2bp;
beginfig(1);}
\everyendmplib{endfig;}
\begin{document}
\emph{Examples.}
\begin{minipage}[t]{0.36\linewidth}
\centering
$T\big((p_1 \to (\perp \vee \neg (p_3)))\big)$;
\par\bigskip
\begin{mplibcode}
t := _T(TCs)(TCs, _T(TCs)(TCs, _T(TCs)(TCs)));
Obj(t).n = origin;
ObjLabel.treeroot(Obj(t))(1)(btex $p_1$ etex) "labdir(bot)";
ObjLabel.treeroot(Obj(t))(2,1)(btex $\perp$ etex) "labdir(bot)";
ObjLabel.treeroot(Obj(t))(2,2,1)(btex $p_3$ etex) "labdir(bot)";
ObjLabel.treeroot(Obj(t))(2,2)(btex $(\neg p_3)$ etex) "labdir(urt)";
ObjLabel.treeroot(Obj(t))(2)(btex $(\perp \vee (\neg p_3))$ etex) "labdir(urt)";
label.urt(btex $(p_1 \to (\perp \vee (\neg p_3)))$ etex, origin);
draw_Obj(t);
\end{mplibcode}
\end{minipage}
%
\begin{minipage}[t]{0.36\linewidth}
\centering
$T\big(\neg(\neg(p_1 \wedge (\neg p_1))) \big)$
\par\bigskip
\begin{mplibcode}
t := _T(TCs)(_T(TCs)(_T(TCs)(TCs, _T(TCs)(TCs))));
Obj(t).n = origin shifted (5cm, 0);
label.urt(btex $(\neg(\neg(p_1 \wedge (\neg p_1))))$ etex, Obj(t).n);
ObjLabel.treeroot(Obj(t))(1)(btex $(\neg(p_1 \wedge (\neg p_1)))$ etex) "labdir(urt)";
ObjLabel.treeroot(Obj(t))(1,1)(btex $(p_1 \wedge (\neg p_1))$ etex) "labdir(urt)";
ObjLabel.treeroot(Obj(t))(1,1,1)(btex $p_1$ etex) "labdir(bot)";
ObjLabel.treeroot(Obj(t))(1,1,2)(btex $(\neg p_1)$ etex) "labdir(urt)";
ObjLabel.treeroot(Obj(t))(1,1,2,1)(btex $p_1$ etex) "labdir(bot)";
draw_Obj(t);
\end{mplibcode}
\end{minipage}
\end{document}
使用 LuaLaTeX 排版。输出:
答案4
这是原始MWE
的Asymptote
:
这些树看起来像某种逻辑表达式的句法树,其中运算符 $\to$、$\vee$、$\wedge$、$\neg$ 和操作数 $p_1$、$p_3$ 和 $\perp$。
在示例文件中,testoptree.asy
树是通过手动分析表达式和分离运算符(作为字符串)及其左子表达式和右子表达式(子树)来递归定义的。非终端节点处的字符串标签是自动形成的。
//
// testoptree.asy
//
import optree;
real w=9cm, h=0.618w; size(w,h);
string p1="p_1", p3="p_3", to="\to", perp="\perp", vee="\vee", neg="\neg", wedge="\wedge";
opTree T1=
opTree(
opTree(p1),to,
opTree(
opTree(perp), vee,
opTree(
neg, opTree(p3)
)
)
);
opTree T2=
opTree(
neg,
opTree(
neg,
opTree(
opTree(p1), wedge,
opTree(
neg, opTree(p1)
)
)
)
);
void drawNode(pair c){
fill(circle(c,0.07),white);
fill(circle(c,0.06),orange);
}
draw(T1,darkblue+1.2bp,drawNode);
draw(shift(4,0)*T2,darkblue+1.2bp,drawNode);
这MWE
使用下面显示的模块optree.asy
。
struct opTree{
string sr;
opTree left, right;
pair root;
void operator init(opTree left=null, string sr, opTree right=null){
this.left=left;
this.sr=sr;
this.right=right;
}
}
string operator cast(opTree T){
if(T==null)return "";
if(T.left==null && T.right==null){
return " "+T.sr+" ";
}else{
return "("+T.left+T.sr+T.right+")";
}
}
opTree operator*(transform t,opTree T){
if(T!=null){
T.root=t*T.root;
T.left=t*T.left;
T.right=t*T.right;
}
return T;
}
typedef void DrawFunc(pair);
void draw(opTree T,pen linepen=currentpen, DrawFunc drawNode=null){
real dx=0.5, dy=sqrt(3)/2;
if(T!=null){
if(T.left!=null && T.right!=null){
T.left.root =T.root+(-dx,-dy);
T.right.root=T.root+( dx,-dy);
draw(T.right.root--T.root--T.left.root,linepen);
}
if(T.left==null && T.right!=null ){
T.right.root=T.root+(0,-dy);
draw(T.root--T.right.root,linepen);
}
if(T.left!=null && T.right==null ){
T.left.root =T.root+(0,-dy);
draw(T.root--T.left.root,linepen);
}
if(drawNode!=null) drawNode(T.root);
if(T.left==null && T.right==null){
label("$"+T.sr+"$",T.root,plain.S);
}else{
label("$"+T+"$",T.root,plain.NE);
}
draw(T.left ,linepen,drawNode);
draw(T.right,linepen,drawNode);
}
}
要获取独立的testoptree.pdf
,请运行:
asy -f pdf testoptree.asy
只要它在同一个文件夹中(或者是正在寻找文件的optree.asy
一些标准文件夹)。asy