EDITAR

EDITAR

Eu tenho que digitar alguns quadros semânticos em meu documento, parecidos com o exemplo abaixo.

Quadro semântico

Minha primeira ideia foi usar tikzpara isso, então criei o seguinte monstro:

Árvore feia

\documentclass[convert]{standalone}
\usepackage{tikz,amssymb}
\usetikzlibrary{positioning}
\newcommand{\lnec}{\Box}
\begin{document}
  \begin{tikzpicture}[scale=2]
    \node[label=right:$(\lnec p\to\lnec q)\to\lnec(p\to q)$] (n1) {$\circ_1$};
    \node[label=left:$\lnec p\to\lnec q$, label=right:$\lnec(p\to q)$, below=of n1] (n2) {$\circ_1$};
    \node[label=left:$\lnec q$, label=right:$\lnec(p\to q)$, below left=of n2] (n3) {$\circ_1$};
    \node[label=right:{$\lnec p, \lnec(p\to q)$}, below right=of n2] (n4) {$\circ_1$};
    \node[label=left:$q$, label=right:$\lnec(p\to q)$, below=of n3] (n5) {$\circ_2$};
    \node[label=right:$p$, below left=of n4] (n6) {$\circ_3$};
    \node[label=right:$p\to q$, below right=of n4] (n7) {$\circ_4$};
    \node[label=left:$p$, label=right:$q$, below=of n7] (n8) {$\circ_4$};

    \draw[-] (n1) to (n2);
    \draw[-] (n2) to (n3);
    \draw[-] (n2) to (n4);
    \draw[-, dotted] (n3) to (n5);
    \draw[-, dotted] (n4) to (n6);
    \draw[-, dotted] (n4) to (n7);
    \draw[-] (n7) to (n8); 
  \end{tikzpicture}
\end{document}

É claro que este não é o resultado desejado. As bordas devem começar abaixo e terminar acima do \circs, e devem ter ângulos retos, de modo que o diagrama possa ser um pouco comprimido.

Desenhar esse tipo de diagrama é completamente novo para mim, então você pode me dar algumas orientações úteis? Você tem alguma dica ou truque para produzir esses quadros semânticos em geral? As embalagens semelhantes forestou qtreeproduzidas são mais fáceis de usar para esse tipo de árvore?


Editar: A resposta de @cfr abaixo é promissora, então gostaria de trabalhar foreste ajustar seu estilo tableaux. Eu tentei fazer isso sozinho nos últimos dois dias, mas entender todas forestas opções avançadas da documentação acabou sendo impossível para um iniciante como eu. Portanto, gostaria de conceder uma recompensa à pessoa que puder fazer o ajuste fino para mim. Que significa

  • o espaço entre os wffs e o \circseparador deve ser diminuído,
  • as bordas devem estar alinhadas com o centro dos \circseparadores, ignorando os possíveis subscritos,
  • o procedimento acima também deve funcionar quando nenhum subscrito para o \circseparador for fornecido.

Responder1

Esta resposta usa uma abordagem completamente diferente, pois infelizmente o código da versão original da pergunta foi perdido. Pode ser menos útil, pois não é baseado nesse código, mas vou deixá-lo aqui, pois pode ser útil para alguém em algum momento.

Aqui está um estilo Forest básico, tableauxque pode ser usado para esse tipo de diagrama.

O problema de usar labelé que ele não é levado em consideração ao posicionar os nós em relação uns aos outros. tableauxcria nós adicionais para este conteúdo, que são especificados junto com o nó 'principal'. Isto torna possível alinhar as coisas corretamente com o círculo “principal”, deixando espaço suficiente para as wffs.

A única desvantagem real disso é que é necessário criar um phantomnó raiz adicional, caso contrário, teríamos 2 ou 3 raízes (o nó principal no nível superior e wffs em cada lado). Isso não é possível. Daí o nó raiz fantasma.

Se você estiver fazendo muitas dessas coisas, é possível evitar ter que adicionar a raiz fantasma criando um novo ambiente que faça isso automaticamente. (O environpacote pode ser usado para isso com um nome personalizado para o corpo do ambiente.)

A biblioteca de Forest edgesé usada para fornecer o forked edgesestilo.

O ajuste fino fica como exercício para o leitor. Por exemplo, pode parecer melhor ajustar as distâncias entre irmãos para aproximar os wffs.

\documentclass[tikz,multi,border=10pt]{standalone}
\usepackage[edges]{forest}
\usepackage{amssymb}
\begin{document}
\forestset{%
  declare toks={F}{},
  declare toks={T}{},
  tableaux/.style={%
    forked edges,
    for tree={
      math content,
      parent anchor=children,
      child anchor=parent,
    },
    where level=0{%
      for children={no edge},
      phantom,
    }{%
      delay={%
        content/.wrap value={\circ_{##1}},
        insert before/.wrap pgfmath arg={%
          [{##1}, no edge, math content]
        }{T()},
        insert after/.wrap pgfmath arg={%
          [{##1}, no edge, math content]
        }{F()},
      },
      if={n_children("!u")==1}{%
        before packing={calign with current edge},
      }{}
    },
  }
}
\newcommand*{\necc}{\ensuremath{\mathbin{\Box}}}
\newcommand*{\lif}{\ensuremath{\mathbin{\rightarrow}}}
\begin{forest}
  tableaux
  [
    [1, F=(\necc p \lif \necc q) \lif \necc (p \lif q)
      [1, T=\necc p \lif \necc q, F=\necc (p \lif q)
        [1, T=\necc q, F=\necc (p \lif q)
          [2, T=q, F=p \lif q, edge=densely dotted
            [2, T={p, q}, F=q, label=below:$\otimes$]
          ]
        ]
        [1, F={\necc p, \necc(p \lif q)}
          [3, F=p, edge=densely dotted]
          [4, F=p \lif q, edge=densely dotted
            [4, F=q, T=p]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

quadros

EDITAR

Isso aborda os 3 desejos adicionados à questão. Evitamos o efeito dos subscritos no alinhamento, renderizando-os como rótulos em vez de parte dos nós. Ajustamos a distância aos wffs antes de desenhar a árvore, pois não queremos reduzir as distâncias entre irmãos em geral, mas apenas a distância entre os círculos e os wffs associados. Tudo bem com e sem os subscritos.

Dependendo do seu uso real, família e tamanho da fonte, etc., você pode querer ajustar as dimensões específicas usadas nos ajustes. Estes são -3.5pte 3.5ptpara os subscritos e 7.5pte -7.5ptpara as wffs no MWE abaixo.

\documentclass[tikz,multi,border=10pt]{standalone}
\usepackage[edges]{forest}
\usepackage{amssymb}
\begin{document}
\forestset{%
  declare toks={T}{},
  declare toks={F}{},
  tableaux/.style={%
    forked edges,
    for tree={
      math content,
      parent anchor=children,
      child anchor=parent,
    },
    where level=0{%
      for children={no edge},
      phantom,
    }{%
      before typesetting nodes={%
        content/.wrap value={\circ},
      },
      delay={%
        my label/.wrap pgfmath arg={{[inner sep=0pt, xshift=-3.5pt, yshift=3.5pt, anchor=north west, font=\scriptsize]-45:$##1$}}{content()},
        insert before/.wrap pgfmath arg={%
          [{##1}, no edge, math content, before drawing tree={x'+=7.5pt}]
        }{T()},
        insert after/.wrap pgfmath arg={%
          [{##1}, no edge, math content, before drawing tree={x'-=7.5pt}]
        }{F()},
      },
      if={n_children("!u")==1}{%
        before packing={calign with current edge},
      }{}
    },
  }
}
\newcommand*{\necc}{\ensuremath{\mathbin{\Box}}}
\newcommand*{\lif}{\ensuremath{\mathbin{\rightarrow}}}
\begin{forest}
  tableaux
  [
    [1, F=(\necc p \lif \necc q) \lif \necc (p \lif q)
      [1, T=\necc p \lif \necc q, F=\necc (p \lif q)
        [1, T=\necc q, F=\necc (p \lif q)
          [2, T=q, F=p \lif q, edge=densely dotted
            [2, T={p, q}, F=q, label=below:$\otimes$]
          ]
        ]
        [1, F={\necc p, \necc(p \lif q)}
          [3, F=p, edge=densely dotted]
          [4, F=p \lif q, edge=densely dotted
            [4, F=q, T=p
              [99, F=X!, T=XX!!
                [, F=XXX!!!, T=XXXX!!!!]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

versão ajustada

EDITAR EDITAR

Conforme apontado em um comentário, minha edição fez com que os fechamentos desaparecessem. Isso ocorre porque eles são criados usando labele os números no canto superior direito dos nós também foram adicionados usando label. Embora os rótulos sejam solicitados em locais diferentes e seriam adequados no código TikZ usual, Forest define labelde forma que apenas um seja permitido por nó. Além disso,label tambémsubstitui quaisquer anotações anteriores especificadas usando tikzou pin. De forest.sty:

 label/.style={tikz={\path[late options={%
        name=\forestoption{name},label={#1}}];}},
 pin/.style={tikz={\path[late options={%
        name=\forestoption{name},pin={#1}}];}},

Cada chamada tikzsubstitui qualquer configuração anterior. Conseqüentemente, o código não se acumula, mas substitui o código existente.

Não tenho certeza do motivo que o autor teve para essa escolha, por isso não tenho certeza da melhor forma de abordá-la. Uma opção seria usar afterthoughtpara os números, o que deveria permitir o uso labelna própria árvore. Nesse caso, entretanto, não poderíamos especificar os números como TikZ labels sem essencialmente reproduzir o código que Forest usa labelem primeiro lugar. Como não parece haver nenhuma vantagem em fazer isso, é tentador redefinir labeladicionando o seguinte código ao preâmbulo do documento:

\forestset{% Sašo Živanović won't like this ...
  label/.style={%
    tikz+={%
      \path[late options={%
        name=\forestoption{name},label={#1}}
      ];
    }
  },
}

O +aqui é o que faz a diferença. Agora labels serão acumulados em vez de se sobrescreverem e/ou quaisquer usos anteriores de pin, tikzou tikz+. Conforme indicado, não consigo imaginar que esse seja o tipo de coisa que devo fazer, por isso não estou recomendando, embora funcione:

restaurar fechamentos com hack

Uma alternativa mais complexa é usar isto:

\forestset{%
  my label/.style={%
    tikz+={%
      \path[late options={%
        name=\forestoption{name},label={#1}}
      ];
    }
  }
}

Então a colocação dos números simplesmente é usada my labelno lugar de label. Configuração completa:

\forestset{%
  declare toks={T}{},
  declare toks={F}{},
  my label/.style={%
    tikz+={%
      \path[late options={%
        name=\forestoption{name},label={#1}}
      ];
    }
  },
  tableaux/.style={%
    forked edges,
    for tree={
      math content,
      parent anchor=children,
      child anchor=parent,
    },
    where level=0{%
      for children={no edge},
      phantom,
    }{%
      before typesetting nodes={%
        content/.wrap value={\circ},
      },
      delay={%
        my label/.wrap pgfmath arg={{[inner sep=0pt, xshift=-3.5pt, yshift=3.5pt, anchor=north west, font=\scriptsize]-45:$##1$}}{content()},
        insert before/.wrap pgfmath arg={%
          [{##1}, no edge, math content, before drawing tree={x'+=7.5pt}]
        }{T()},
        insert after/.wrap pgfmath arg={%
          [{##1}, no edge, math content, before drawing tree={x'-=7.5pt}]
        }{F()},
      },
      if={n_children("!u")==1}{%
        before packing={calign with current edge},
      }{}
    },
  }
}

que produz o mesmo resultado acima sem redefinir labelo estilo de Forest.

informação relacionada