stackexchange 成员,我尝试过这样做,但不幸的是我做不到。这真的很简单。我找到了一些代码并尝试获得与我的类似的图片。
第二张图片是
非常感谢您的帮助,很抱歉占用了您的时间。问候。
答案1
一种选择是使用强大的forest
包裹:
代码(带解释性注释):
\documentclass[varwidth=30cm,border=4pt]{standalone}
\usepackage{forest}
\usetikzlibrary{calc}
% The width of the [0,1] Intervals
\newlength\IntervalWd
\setlength\IntervalWd{5cm}
% Style for the upper labels in the intervals
\tikzset{
numlabel/.style={above,pos=#1,font=\scriptsize,text=magenta}
}
% Command to draw the intervals
% Syntax
% \DrawInterval[base]{divisions}{lables}{position}
\newcommand\DrawInterval[4][2]{
\draw[|-|]
(#4) node[below=3pt] {$0$} --
++(\IntervalWd,0pt) node[below=3pt] {$1$};
\ifnum#2=1\relax
\node[above,text=magenta,font=\scriptsize] at ([xshift=0.5\IntervalWd]#4) {1};
\else
\foreach \Valor in {1,...,#2}
{
\draw
([xshift=\Valor*(1/#2)*\IntervalWd] $ (#4) + (0,-2pt) $ ) --
++(0,4pt);
\node[xshift=\Valor*(1/#2)*\IntervalWd,above,text=magenta,font=\scriptsize]
at ([xshift=-0.5\Valor*(1/#2)*\IntervalWd]#4)
{\pgfmathprint{int(mod(\Valor-1,#1))}};
}
\foreach \Texto [count=\xi] in {#3}
{
\node[xshift=\xi*(1/#2)*\IntervalWd,anchor=base,yshift=-10pt,font=\scriptsize]
at (#4)
{$\Texto$};
}
\fi
}
\begin{document}
\begin{forest}
for tree={
circle,
fill,
inner sep=1.5pt,
parent anchor=south,
s sep=20pt
},
delay={
for tree={
if n=1
{edge label={node[midway,left,text=magenta,font=\scriptsize] {$0$}}}
{if n'=1
{edge label={node[midway,right,text=magenta,font=\scriptsize] {$1$}}}
{}
}
},
}
[$\emptyset$,fill=none,name=level0
[
[ [,name=level3l] [] ]
[ [] [] ]
]
[,name=level1
[ [] [] ]
[,name=level2 [] [,name=level3] ]
]
]
% Auxiliary coordinates
\coordinate (aux1) at ([xshift=20pt]level3|-level0);
\coordinate (aux2) at ([xshift=2cm]level3|-level0);
\coordinate (aux3) at ([xshift=2cm+20pt]level3|-level0);
\coordinate (aux4) at ([xshift=-20pt]level3l|-level0);
% The level number
\foreach \Valor in {0,...,3}
{
\node at (aux4|-level\Valor) {\Valor};
}
% The arrows
\foreach \Valor in {0,...,3}
{
\draw[<->,>=latex]
(aux1|-level\Valor) -- (aux2|-level\Valor);
}
% The [0,1] intervals
%level0
\DrawInterval{1}{}{aux3|-level0}
%level1
\DrawInterval{2}{1/2}{aux3|-level1}
%level2
\DrawInterval{4}{1/4,1/2,3/4}{aux3|-level2}
%level2
\DrawInterval{8}{1/8,1/4,3/8,1/2,5/8,3/4,7/8}{aux3|-level3}
\end{forest}\par\bigskip
\begin{forest}
for tree={
circle,
fill,
inner sep=1.5pt,
parent anchor=south,
s sep=15pt,
l sep=30pt,
if level=1{s sep=27pt}{}
},
delay={
for tree={
if n=1
{edge label={node[midway,left,text=magenta,font=\scriptsize] {$0$}}}
{if n'=1
{edge label={node[midway,right,text=magenta,font=\scriptsize] {$2$}}}
{edge label={node[midway,left,text=magenta,font=\scriptsize] {$1$}}}
}
},
}
[$\emptyset$,fill=none,name=level0
[,edge={magenta}
[,name=level2] [] [,edge={magenta}]
]
[
[] [] []
]
[
[] [] []
]
]
% Auxiliary coordinates
\coordinate (aux1) at ([xshift=-20pt] $ (level2|-level0)!0.5!(level2) $ );
\coordinate (aux2) at ([xshift=-2cm]aux1);
\coordinate (aux3) at ([xshift=-20pt]aux2);
\coordinate (aux4) at ([xshift=-\IntervalWd]aux3);
\draw[<->,>=latex]
(aux1) -- (aux2);
\DrawInterval[3]{9}{,,1/3,,,2/3,,}{aux4}
\end{forest}
\end{document}
答案2
此版本使用实验性prooftrees
软件包,该软件包已稍作更新以实现。
代码需要 0.08prooftrees
或更高版本(包括在下面)。这需要forest
因为包建立在 之上forest
。它主要用于轻松排版逻辑树证明。其中一个关键问题是将行号对齐在左侧,将对齐方式对齐在右侧。在这里,右侧的空格用于绘制数字线,并使用添加到 的几个东西来调整行号,prooftrees
以便轻松匹配问题中显示的样式。
第一张图
代码
\documentclass[tikz,border=10pt]{standalone}
\usepackage{prooftrees}% v 0.08
\usetikzlibrary{arrows.meta, positioning}
\begin{document}
\renewcommand\linenumberstyle[1]{#1}% default uses dots after the number
\forestset{
my label/.style n args=2{
edge label={node [midway, text=red, font=\scriptsize, #1] {$#2$}}
},
}
\begin{prooftree}{
zero start,% default starts numbering with 1
line justifications,% justifications must be explicitly enabled as their content is not specified directly
just format/.style={% this is used to draw the arrows and number lines on the right (where the justifications for inferences would go in a tree proof in logic)
before drawing tree={
tikz/.wrap 2 pgfmath args={
[font=\scriptsize]
\draw [{Stealth[]}-{Stealth[]}] (!<.base east) +(1.5mm,0) -- (.base) -- ++(10mm,0) coordinate (c);
\draw [font=\small]
[{Bar[width=10pt]}-{Bar[width=10pt]}] (c) ++(5pt,0) node (n1) [below=5pt] {$0$} -- ++(50mm,0) node (n2) [below=5pt] {$1$};
\ifnum##2>1
\path (n1 |- c) -- (n2 |- c) node [pos=.5/##2, above, text=red] {0} foreach \i [evaluate=\i as \ieval using {int(mod(\i,2))}] in {1,...,##1} { node [pos={(\i+.5)/##2}, above, text=red] {\ieval} node (nn\i) [pos=\i/##2, below=2.5pt] {$\frac{\i}{##2}$}};
\foreach \i in {1,...,##1} \draw (c -| nn\i) +(0,2.5pt) -- +(0,-2.5pt);
\fi
}{int((2^(level()-1))-1)}{int(2^(level()-1))},
}
},
for tree={% this sets up the main tree, rooted at the empty set symbol
math content,
if level=1{}{
circle,
fill,
minimum size=2.5pt,
inner sep=0pt,
outer sep=0pt,
if n=1{% add the red labels on the sides automatically
if level=2{
my label={above left}{0}
}{
my label={left}{0}
},
}{
if n'=1{
if level=2{
my label={above right}{1}
}{
my label={right}{1}
},
}{}
}
},
if level=0{% increase the separation a bit - necessary to stop squishing with the additional level added here for demonstration purposes
for descendants={s sep+=5pt},
}{},
}
},
[\emptyset% this is the root of the main tree
[[[[][]][[][]]][[[][]][[][]]]]% main left branch
[[[[][]][[][]]][[[][]][[][]]]]% main right branch
]
\end{prooftree}
\end{document}
请注意,在第一个可见级别之上还有一个额外的不可见级别。这些都是自动创建的。如果您想要使用级别信息执行操作,则只需知道这一点。例如,在下面的代码中,我使用此信息来创建数字线。因此,空集符号在级别 1 很重要,forest
即使就图表而言它处于级别 0。
包裹
将以下内容保存为prooftrees.sty
并将其粘贴在与文件相同的目录中.tex
:
%% Copyright 2015 cfr
%%
\ProvidesPackage{prooftrees}[2015/07/20 v0.08 prooftrees]
\RequirePackage{forest}
\newcounter{prooftree@countlevels}% count the levels in the proof tree
\setcounter{prooftree@countlevels}{0}
\newcount\prooftree@lcount% count the line numbers (on the left)
\newcount\prooftree@jcount% count the justifications (on the right)
\newcount\prooftree@linenoshift% adjustment for line numbering
\newcommand*\linenumberstyle[1]{#1.}
\forestset{
declare boolean={numbers}{0},% line numbering
declare boolean={justifiers}{0},% line justifications
declare boolean={verticals}{0},% single branches
grouped/.style={% this adjusts the alignment of line numbers and justifications when some levels of the tree are grouped together either whenever the number of children is only 1 or by applying the grouped style to particular nodes when specifying the tree
before computing xy={
l=\baselineskip,
if={\forestove{numbers}==1}{
if={\forestove{justifiers}==1}{
node walk={
every step/.style={l=\baselineskip},
after walk/.style={l=\baselineskip},
name/.wrap pgfmath arg={just ##1}{level()},
name/.wrap pgfmath arg={line no ##1}{level()},
},
}{
node walk={
after walk/.style={l=\baselineskip},
name/.wrap pgfmath arg={line no ##1}{level()},
},
},
}{
if={\forestove{justifiers}==1}{
node walk={
after walk/.style={l=\baselineskip},
name/.wrap pgfmath arg={just ##1}{level()}
},
}{},
},
},
no edge,
},
close/.style={
label={[yshift=2.5pt]below:$\otimes$},
},
line no/.style={% creates the line numbers on the left
no edge,
before typesetting nodes={% page 51
TeX={\advance\prooftree@lcount1},
content/.expanded/.wrap pgfmath arg={\linenumberstyle{##1}}{int(\linecounter+\the\prooftree@linenoshift)},% content i.e. the line number
name/.expanded={line no \the\prooftree@lcount},% name them so they can be moved later
if={\the\prooftree@lcount>2}{% the initial location of most line numbers is incorrect and they must be moved
for previous={% move the line number below the previous line number
append/.expanded={line no \the\prooftree@lcount}
},
}{},
},
},
line justification/.style={% creates the justifications on the right but does not yet specify any content
anchor=base west,
no edge,
before typesetting nodes={% page 51
TeX={\advance\prooftree@jcount1},
name/.expanded={just \the\prooftree@jcount},% name them so they can be moved
if={\the\prooftree@jcount>2}{% correct the location as for the line numbers (cf. line no style)
for previous={
append/.expanded={just \the\prooftree@jcount}
},
}{},
},
},
line numbering/.style={
for tree={numbers},
},
no line numbering/.style={
for tree={not numbers},
},
line numbering shift/.style={
TeX={\advance\prooftree@linenoshift#1},
},
zero start/.style={
line numbering shift=-1,
},
line justifications/.style={
for tree={justifiers},
},
no line justifications/.style={
for tree={not justifiers},
},
single branches/.style={
for tree={verticals},
},
no single branches/.style={
for tree={not verticals},
},
to prove/.style={
before typesetting nodes={
if level=0{
content={#1},
phantom=false,
}{}
}
},
proof tree/.style={
for tree={
parent anchor=south,
line numbering,
delay={
where content={}{
shape=coordinate,
}{}
},
},
where level=0{
for children={
no edge,
},
delay={
if content={}{phantom}{},
if={(\forestove{numbers}==1) || (\forestove{justifiers}==1)}{% count the levels if necessary
for descendants={
if={level()>\value{prooftree@countlevels}}{
TeX={
\stepcounter{prooftree@countlevels}
},
}{},
},
}{},
if={(\forestove{numbers}==1)}{% create the line numbers if appropriate
prepend={
[,
line no,
line no format,
repeat={\value{prooftree@countlevels}-1}{% most are created in the wrong place but line no moves them later
delay n={\the\prooftree@lcount}{
append={[, line no, line no format]}
},
}
]
},
}{},
if={(\forestove{justifiers}==1}{% create the nodes which will hold the justifications, if required
append={
[,
fit=rectangle,
just format,
line justification,
repeat={\value{prooftree@countlevels}-1}{% most are created in the wrong place but line justification moves them later
delay n={\the\prooftree@jcount}{
append={[, line justification, just format]}
},
}
]
}
}{},
},
}{
delay={
if={(\forestove{verticals}==0}{% automatically group lines if not using single branches
if n children=1{
for children={
if ={(\forestove{verticals}==0}{
grouped
}{},
}
}{},
}{},
}
},
before packing={
for tree={
tier/.wrap pgfmath arg={tier ##1}{level()},
},
},
},
just/.style={
if={\forestove{justifiers}==0}{
for root={
line justifications,
},
}{},
before packing={% puts the content of the justifications into the empty justification nodes on the right; because this is done late, the nodes need to be typeset again
for={name/.wrap pgfmath arg={just ##1}{level()}}{
content={#1},
typeset node
},
}
},
toing/.style={% this is here so I can easily override no edge when to line={} is used
edge path={
\noexpand\path [draw, \forestoption{edge}] (!u.parent anchor) -- (.child anchor)\forestoption{edge label};
},
},
to line/.style={% this option is intended for use with justifications and, although it should not give an error, it will have no effect in other cases (There is simply no reason to typeset a proof with this if not giving justifications, that I can think of)
if={#1>\value{prooftree@countlevels}}{% ensure that we get enough lines in the tree since #1 may well specify a line which would not otherwise exist
TeX={
\setcounter{prooftree@countlevels}{#1}
},
}{},
if={#1>level()}{% only try to move the node if the target line number exceeds the current level
if={\forestove{justifiers}==0}{% don't do anything if there are no justifications - there is no point in moving things in such a case
}{
if={\forestove{verticals}==0}{% if no single branches, get the vertical alignment from the correctly aligned line justification
before drawing tree={
y/.wrap pgfmath arg={##1}{y("!name={just #1}")},
toing
},
}{
before packing={% if single branches, a simple tier alignment suffices
tier=tier #1,
},
},
},
}{},
},
just to line/.style n args=2{
if={\forestove{justifiers}==0}{
for root={
line justifications,
},
}{},
if={#1>\value{prooftree@countlevels}}{% make sure the tree contains enough lines since #1 may exceed the total line count otherwise
TeX={
\setcounter{prooftree@countlevels}{#1}
},
}{},
if={#1>level()}{% only if the target line number exceeds the current level
before packing={
for={name={just #1}}{% specify the content of the target line justification and, because this is done late, typeset the node again
content={#2},
typeset node
},
}
}{% do nothing if the target line number is less than the current level
if={#1==level()}{% only if the target line number equals the current level
just=#2,
}{},
},
},
just format/.style={},
line no format/.style={},
}
\newcommand*\linecounter{\linecountformat{\the\prooftree@lcount}}
\newcommand*\linecountformat[1]{#1.}
\environbodyname\prooftreebody
\bracketset{action character=@}
\NewEnviron{prooftree}[1]{% \forest/\endforest from egreg's answer at http://tex.stackexchange.com/a/229608/
\forest
proof tree,
#1,
[@\prooftreebody]
\endforest}
\endinput
%% end prooftrees.sty