
~ 안에이 답변, 사용자 cfr은 다음 이미지와 같은 출력을 제공하는 다음 코드를 제공합니다.
\documentclass[border=11pt]{standalone}
\usepackage[linguistics]{forest}
\usepackage{amsmath,amssymb}
\forestset{
declare toks={from}{},
declare toks register={claim},
claim=,
ll proof/.style={
for tree={math content},
before typesetting nodes={
if claim={}{}{
replace by/.process={Rw{claim}{[##1, math content, append]}},
no edge,
before computing xy={l'=2\baselineskip},
},
tempcounta'=0,
for tree breadth-first={
tempcounta'+=1,
content/.process={ OR OSl+tt= ? w w3 {content}{tempcounta}{from}{}{}{(##1)}{##2.\quad ##1\quad ##3} }
}
},
where n children=1{!1.no edge, before computing xy={!1.l'=\baselineskip}}{},
close/.style={label=below:\textsf{x}},
},
}
\begin{document}
\begin{forest}
ll proof,
claim=\vdash ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ \lnot ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ (p\lor (q\land r)) , from=1
[ \lnot ((p\lor q)\land (p\lor r)) , from=1
[ p , from=2
[ \lnot (p\lor q) , from=3
[ \lnot p , from=6
[ \lnot q , from=6, close
]]]
[ \lnot (p\lor r) , from=3
[1 \lnot p , from=7
[1 \lnot r , from=7, close
]]]]
[ (q\land r) , from=2
[1 q , from=5
[1 r , from=5
[1 \lnot (p\lor q) , from=3
[1 \lnot p , from=14
[1 \lnot q , from=14, close
]]]
[1 \lnot (p\lor r) , from=3
[1 \lnot p , from=15
[1 \lnot r , from=15, close
]]]]]]]]]
\end{forest}
\end{document}
다음 이미지와 같이 출력을 생성하기 위해 코드를 수정하는 방법을 아는 사람이 있는지 궁금합니다.
내가 생각할 수 있는 한 가지 접근 방식은 각 분기를 따라 가장 넓은 줄 번호, 수식 및 양쪽 정렬 각각의 너비를 저장한 다음 분기의 각 노드 내용을 열 너비가 고정된 3열 테이블 형식으로 래핑하는 것입니다. 이 최대 너비. 그런 다음 노드의 앵커 위치가 공식 열의 북쪽으로 설정되어 가지 사이의 선이 공식의 중심에 그려집니다.
훨씬 덜 우아하지만 훨씬 더 쉬운 접근 방식은 가지의 모든 공식을 포함하는 여러 줄의 표를 갖는 것입니다(예: 1, 2, 3 번호의 공식에 대한 하나, 4에 대한 하나, 5, 8, 11에 대한 또 다른 등). ). 그러나 나는 트리의 스타일보다는 트리 자체에 상당한 변경이 필요한 이와 같은 접근 방식을 피하고 싶습니다.
불행하게도 저는 현재 더 우아한 솔루션을 실제로 구현하기 위해 어디서부터 시작해야 할지 알 수 있는 기술적 전문 지식이 없으므로 어떤 도움이라도 주시면 감사하겠습니다.
업데이트
다음은 내용을 3개의 열(줄 번호용 열, wff용 열, 정당화용 열)이 있는 한 줄짜리 표로 처리하는 것과 관련된 부분 답변입니다.
\documentclass[border=11pt]{standalone}
\usepackage[linguistics]{forest}
\usepackage{amsmath,amssymb}
\usepackage{array}
\forestset{
declare toks={from}{},
declare toks register={claim},
claim=,
ll proof/.style={
before typesetting nodes={
if claim={}{}{
replace by/.process={Rw{claim}{[##1, math content, append]}},
no edge,
before computing xy={l'=2\baselineskip},
},
tempcounta'=0,
for tree breadth-first={
tempcounta'+=1,
content/.process={ OR OSl+tt= ? w w3 {content}{tempcounta}{from}{}{}{(##1)}{\begin{tabular}{>{\raggedleft}p{1em}cp{1em}}##2. & \ensuremath{##1} & \ensuremath{##3}\\\end{tabular}} }
}
},
where n children=1{!1.no edge, before computing xy={!1.l'=\baselineskip}}{},
close/.style={label=below:\textsf{x}},
},
}
\begin{document}
\begin{forest}
ll proof,
claim=\vdash ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ \lnot ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ (p\lor (q\land r)) , from=1
[ \lnot ((p\lor q)\land (p\lor r)) , from=1
[ p , from=2
[ \lnot (p\lor q) , from=3
[ \lnot p , from=6
[ \lnot q , from=6, close
]]]
[ \lnot (p\lor r) , from=3
[1 \lnot p , from=7
[1 \lnot r , from=7, close
]]]]
[ (q\land r) , from=2
[1 q , from=5
[1 r , from=5
[1 \lnot (p\lor q) , from=3
[1 \lnot p , from=14
[1 \lnot q , from=14, close
]]]
[1 \lnot (p\lor r) , from=3
[1 \lnot p , from=15
[1 \lnot r , from=1500, close
]]]]]]]]]
\end{forest}
\end{document}
위의 내용은 수식의 중심이 수평으로 정렬되도록 만듭니다. 따라서 우리는 얻는다
대신에
원래 코드와 마찬가지로. 이는 이미 가독성과 미적 측면을 향상시킵니다.
퍼즐에서 누락된 조각은 17.과 19.의 수식 열 너비가 15.의 수식 열 너비로 설정되어 줄 번호와 양쪽 맞춤도 수평으로 정렬되도록 구성하는 것입니다. (그리고 트리 전체에서도 마찬가지입니다.)
내 생각에는cfr의 답변각 수식의 너비를 계산하는 방법에 대한 힌트를 제공합니다. 하지만 너비를 저장한 다음 각 수식 세트에 가장 적합한 너비를 선택하는 방법을 모르겠습니다.
또 다른 업데이트
fwidth
수식 열의 너비에 전달되는 톡을 만들었습니다 . 이제 모든 것이 잘 정렬되었지만 사용자가 트리의 모든 노드에 대해 이 키를 설정해야 한다는 단점이 있습니다. 무엇으로 설정해야 하는지 알아내는 가장 좋은 방법은 분기의 가장 넓은 공식을 코드에 연결하는 것입니다.
\newlength{\myl}
\settowidth{\myl}{formula goes here}
\the\myl
그런 다음 fwidth
분기의 모든 수식에 대해 해당 길이를 설정합니다. 아래 예제 코드를 참조하세요.
\documentclass[border=11pt]{standalone}
\usepackage[linguistics]{forest}
\usepackage{amsmath,amssymb}
\usepackage{array}
\forestset{
declare toks={from}{},
declare toks={fwidth}{},
declare toks register={claim},
claim=,
ll proof/.style={
before typesetting nodes={
if claim={}{}{
replace by/.process={Rw{claim}{[##1, math content, append]}},
no edge,
before computing xy={l'=2\baselineskip},
},
tempcounta'=0,
for tree breadth-first={
tempcounta'+=1,
content/.process={ OR OSl+tt= ? w Ow4 {content}{tempcounta}{from}{}{}{(##1)}{fwidth}{\begin{tabular}{p{1em}>{\centering\arraybackslash}p{##4}p{1em}}##2. & \ensuremath{##1} & \ensuremath{##3}\\\end{tabular}} }
}
},
where n children=1{!1.no edge, before computing xy={!1.l'=\baselineskip}}{},
close/.style={label=below:\textsf{x}},
},
}
\begin{document}
\begin{forest}
ll proof,
claim=\vdash ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ \lnot ((p\lor (q\land r))\to((p\lor q)\land (p\lor r))), fwidth=158.8pt
[ (p\lor (q\land r)) , from=1, fwidth=158.8pt
[ \lnot ((p\lor q)\land (p\lor r)) , from=1, fwidth=158.8pt
[ p , from=2, fwidth=5.1pt
[ \lnot (p\lor q) , from=3, fwidth=35.5pt
[ \lnot p , from=6, fwidth=35.5pt
[ \lnot q , from=6, close, fwidth=35.5pt
]]]
[ \lnot (p\lor r) , from=3, fwidth=35.5pt
[1 \lnot p , from=7, fwidth=35.5pt
[1 \lnot r , from=7, close, fwidth=35.5pt
]]]]
[ (q\land r) , from=2, fwidth=28.6pt
[1 q , from=5, fwidth=28.6pt
[1 r , from=5, fwidth=28.6pt
[1 \lnot (p\lor q) , from=3, fwidth=40.5pt
[1 \lnot p , from=14, fwidth=40.5pt
[1 \lnot q , from=14, close, fwidth=40.5pt
]]]
[1 \lnot (p\lor r) , from=3, fwidth=40.5pt
[1 \lnot p , from=15, fwidth=40.5pt
[1 \lnot r , from=1500, close, fwidth=40.5pt
]]]]]]]]]
\end{forest}
\end{document}
fwidth
지금은 상황이 정말 좋아 보이지만 자동으로 계산하고 설정할 수 있다면 훨씬 더 편리할 것입니다 . (줄 번호와 정렬 열을 작은 고정 너비로 설정하여 발생하는 과도한 경고를 숨기는 것도 좋을 것입니다.) TikZ에 대한 더 깊은 지식을 갖고 forest
방법을 보여 주실 분을 기다립니다.
답변1
다음은 중앙 열의 너비를 자동으로 결정하는 tabular
/ 아이디어 의 변형입니다 (wff의 경우).align
% ref.: https://tex.stackexchange.com/q/570449/
\documentclass[border=11pt]{standalone}
\usepackage[linguistics]{forest}
\usepackage{amsmath,amssymb,array}
\newcolumntype{C}[1]{>{\centering $}p{#1}<{$}}
\forestset{
declare toks={from}{},
declare toks register={claim},
declare boolean={align me}{0},
declare dimen={my width}{0pt},
declare dimen register={lmeas},
lmeas/.pgfmath=width("99."),
declare dimen register={rmeas},
rmeas/.pgfmath=width("(99)"),
claim=,
ll proof/.style={
for tree={
math content,
},
for root=align me,
before typesetting nodes={
if claim={}{}{
replace by/.process={Rw{claim}{[##1, math content, append]}},
no edge,
before computing xy={l'=2\baselineskip},
},
},
where n children=1{!1.no edge, before computing xy={!1.l'=\baselineskip},}{},
for root={align me},
where n children>=2{
for children={align me}}{},
before packing={
tempcountb'=0,
where align me={%
tempcountb'+=1,
tempdima/.max={>{OOw2+d}{max x}{min x}{##1-##2}}{%
walk and save={temptoksa}{current,
until={> O_=!{n children}{1}}{first,typeset node}}%
},
for nodewalk={load=temptoksa}{my width/.register=tempdima, typeset node},
}{},
tempcounta'=0,
for tree breadth-first={
tempcounta'+=1,
align=p{\foresteregister{lmeas}}C{\foresteoption{my width}}p{\foresteregister{rmeas}},
content/.process={ OR OSl+tt= ? w w3 {content}{tempcounta}{from}{}{}{(##1)}{##2.\quad & ##1\quad & ##3} },
typeset node,
}
},
close/.style={label=below:\textsf{x}},
},
}
\begin{document}
\begin{forest}
ll proof,
claim=\vdash ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ \lnot ((p\lor (q\land r))\to((p\lor q)\land (p\lor r)))
[ (p\lor (q\land r)) , from=1
[ \lnot ((p\lor q)\land (p\lor r)) , from=1
[ p , from=2
[ \lnot (p\lor q) , from=3
[ \lnot p , from=6
[ \lnot q , from=6, close
]]]
[ \lnot (p\lor r) , from=3
[1 \lnot p , from=7
[1 \lnot r , from=7, close
]]]]
[ (q\land r) , from=2
[1 q , from=5
[1 r , from=5
[1 \lnot (p\lor q) , from=3
[1 \lnot p , from=14
[1 \lnot q , from=14, close
]]]
[1 \lnot (p\lor r) , from=3
[1 \lnot p , from=15
[1 \lnot r , from=15, close
]]]]]]]]]
\end{forest}
\end{document}
Sašo는 어떤 경우든 이 작업을 더 빠르게 할 수 있지만 저는 연습이 부족하므로 다른 사람도 더 잘할 수 있습니다. 멋진 열 지정자가 forest
의 파서와 얽힌 것 같습니다. 따라서 다소 투박한 접근 방식입니다. 내가 말했듯이, 다른 누군가가 의심할 바 없이 그 행동을 좀 더 정중하게 행동하게 만들 것입니다.