포리스트로 조판된 논리 증명 트리의 노드 간 멋진 정렬

포리스트로 조판된 논리 증명 트리의 노드 간 멋진 정렬

~ 안에이 답변, 사용자 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}

tableau-분할선-nos-정렬 포함

Sašo는 어떤 경우든 이 작업을 더 빠르게 할 수 있지만 저는 연습이 부족하므로 다른 사람도 더 잘할 수 있습니다. 멋진 열 지정자가 forest의 파서와 얽힌 것 같습니다. 따라서 다소 투박한 접근 방식입니다. 내가 말했듯이, 다른 누군가가 의심할 바 없이 그 행동을 좀 더 정중하게 행동하게 만들 것입니다.

관련 정보