EDITAR

EDITAR

Hoy necesito nuevamente su ayuda para manejar el paquete forest(es un paquete realmente poderoso, pero también bastante complejo). Básicamente, ya he pasado varias horas intentando dibujar un juego de ultimátum en forma de árbol que debería verse así:

ingrese la descripción de la imagen aquí

Hasta ahora, he logrado crear este código que de alguna manera funciona (pero no funciona bien):

\documentclass{report}
\usepackage[T1]{fontenc}
\usepackage{amssymb}
\usepackage{mathtools}
\usepackage{forest}
\usepackage[labelfont=bf,skip=0pt,labelsep=period]{caption}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.6}
\usetikzlibrary{matrix,calc,positioning}
\pgfplotsset{soldot/.style={color=black,only marks,mark=*}}
\pgfplotsset{/pgfplots/xlabel near ticks/.style={/pgfplots/every axis x label/.style={at={(ticklabel cs:0.5)},anchor=near ticklabel}},/pgfplots/ylabel near ticks/.style={/pgfplots/every axis y label/.style={at={(ticklabel cs:0.5)},rotate=90,anchor=near ticklabel}}}
\begin{document}
\begin{figure}
\begin{forest}
for tree={l sep=4em, s sep=8em, anchor=center}
[$P_1$, circle, draw, 
    [,name=0, edge label={node[midway,left,outer sep=1.5mm,]{$x=0$}}]
    [$P_2$, l*=2, before computing xy={s=(s("!p")+s("!n"))/2}, circle, draw, edge label={node[midway,right,]{$x$}}
        [{$c-x,x$}, edge label={node[midway,left,outer sep=1.5mm,]{$Y$}}]
        [{$0,0$}, edge label={node[midway,right,outer sep=1.5mm,]{$N$}}]]
    [,name=1, edge label={node[midway,right,outer sep=1.5mm,]{$x=c$}}]]
\draw (0) to[bend right=45] (1);
\end{forest}
\end{figure}
\end{document}

El resultado que obtengo es este:

ingrese la descripción de la imagen aquí

Lo ideal es que las cosas que me gustaría modificar sean varias. Primero, me gustaría que (a) la línea curva toque las ramas del árbol, evitando ese feo espacio en blanco. En segundo lugar, (b) me gustaría evitar la superposición entre la línea curva y el nodo P2. En tercer lugar, (c) me gustaría asegurarme de que los ángulos de las dos ramas en los dos nodos sean los mismos. En otras palabras, el ángulo del segundo nodo es más amplio que el del primer nodo y me gustaría que fueran iguales. Cuarto, (d) me gustaría que las ramas del segundo nodo fueran más cortas que las del primero, si es posible. Todas las preguntas son igualmente relevantes. Cualquier ayuda con cualquiera de los cuatro problemas será muy apreciada.

PD: Idealmente, me gustaría ceñirme a mi código actual tanto como sea posible (en otras palabras, me gustaría aplicar los cambios mínimos necesarios al código para obtener los cambios que necesito porque este es un código que puedo entender). más o menos fácilmente).

Respuesta1

Aquí hay una solución que creo que cumple con todos los deseos establecidos. Supuse, a partir de la imagen de destino, que no quería que el arco llegara al punto más alto del nodo P_2. Si eso no es necesario, no necesita molestarse con algunos de los cálculos involucrados en mi código.

\documentclass[tikz, border=10pt, multi]{standalone}

Cargamos bibliotecas TikZ throughy calcpara dibujar el arco correctamente.

\usetikzlibrary{through,calc}
\usepackage{forest}

Ahora configuramos algunos estilos. Algunos de estos simplifican su código existente. Si prefieres no utilizarlos, puedes omitirlos.

\forestset{%

auto edge labelautomatiza el código para formatear el archivo edge label. Crea el nodo, pone el contenido en modo matemático y decide si colocar la etiqueta a la izquierda o a la derecha del borde. Esto significa que

edge label=x^2, auto edge label

hará lo correcto.

  auto edge label/.style={%
    before typesetting nodes={%

No hagas nada si es el nodo raíz.

      if level=0{}{

Si el nodo está en la segunda mitad de los hijos de su padre, o si es el hijo del medio...

        if={n()>(n_children("!u")/2)}{

Si el nodo es el hijo del medio...

          if={n()==((n_children("!u")+1)/2)}{
            edge label/.wrap value={
              node[midway, right] {$##1$}
            },
          }{

Si el nodo está en la segunda mitad de los hijos de su padre...

            edge label/.wrap value={
              node[midway, outer sep=1.5mm, right] {$##1$}
            },
          },
        }{

Si el nodo está en la primera mitad de los hijos de su padre...

          edge label/.wrap value={
            node[midway, outer sep=1.5mm, left] {$##1$}
          },
        }
      },
    },
  },

Este es el estilo para nodos vacíos más bonitos. Es de la página 65 del manual actual. Es parte de la linguisticsbiblioteca. Por lo tanto, si usa esa biblioteca, puede omitir esta definición y simplemente aplicar el estilo listo para usar.

Tenga en cuenta que creo que la explicación en esta parte del manual se refiere erróneamente a opciones que no existen, pero no estoy seguro de esto.

  nice empty nodes/.style={% page 65 of the manual - this is from the linguistics library
    for tree={
      calign=fixed edge angles
    },
    delay={
      where content={}{
        shape=coordinate,
        for parent={
          for children={anchor=north}
        }
      }{}
    }
  },

Este es el estilo para dibujar los arcos. Pasa esto como una opción al padre de los nodos a través de los cuales se debe dibujar el arco.

No se dibujan bordes como parte del árbol, excepto para el segundo hijo. Si hubiera más de 3 niños, esto tendría que volverse un poco más sofisticado. Este código asume 3 hijos.

En cambio, el arco se dibuja después calculando los puntos apropiados según la posición del nodo medio y el ángulo predeterminado de los nodos cuando se usa calign=fixed edge angles. En este momento se dibujan los bordes del primer y tercer hijo.

[Esto realmente debería ser un poco más sofisticado en términos de verificar varias posibilidades, pero debería funcionar en casos relevantes como el MWE.]

  arc below/.style={
    tikz+={%
      \clip (.center) coordinate (o) -- (!1.north) coordinate (a) |- (!2.north) coordinate (b) -| (!3.north) coordinate (c) -- cycle;
      \node [draw, circle through={(b)}] at (o) {};
      \draw [\forestoption{edge}] () -- ($(o)!1!-35:(b)$) ($(o)!1!35:(b)$) -- ();
    },
    for children={
      if n=2{}{no edge},
    }
  }
}

Estilo TikZ simple para mayor comodidad.

\tikzset{%
  my circle/.style={draw, circle}
}

Luego podemos aplicar todo esto al árbol de la siguiente manera.

\begin{document}
\begin{forest}
  for tree={

Del MWE.

    l sep=4em,
    s sep=8em,

Aplique dos de los nuevos estilos a todo el árbol.

    auto edge label,
    nice empty nodes,

Ponga todos los nodos en modo matemático para ahorrar signos de dólar.

    math content,
  }

Especifique el arc belowestilo de la raíz.

  [P_1, my circle, arc below
    [, edge label={x=0}]
    [P_2, my circle, edge label=x
      [{c-x,x}, edge label=Y]
      [{0,0}, edge label=N]
    ]
    [, edge label={x=c}]
  ]
\end{forest}
\end{document}

árbol con estilos

Código completo:

\documentclass[tikz, border=10pt, multi]{standalone}
\usetikzlibrary{through,calc}
\usepackage{forest}
\forestset{%
  auto edge label/.style={%
    before typesetting nodes={%
      if level=0{}{
        if={n()>(n_children("!u")/2)}{
          if={n()==((n_children("!u")+1)/2)}{
            edge label/.wrap value={
              node[midway, right] {$##1$}
            },
          }{
            edge label/.wrap value={
              node[midway, outer sep=1.5mm, right] {$##1$}
            },
          },
        }{
          edge label/.wrap value={
            node[midway, outer sep=1.5mm, left] {$##1$}
          },
        }
      },
    },
  },
  nice empty nodes/.style={% page 65 of the manual - this is from the linguistics library
    for tree={
      calign=fixed edge angles
    },
    delay={
      where content={}{
        shape=coordinate,
        for parent={
          for children={anchor=north}
        }
      }{}
    }
  },
  arc below/.style={
    tikz+={%
      \clip (.center) coordinate (o) -- (!1.north) coordinate (a) |- (!2.north) coordinate (b) -| (!3.north) coordinate (c) -- cycle;
      \node [draw, circle through={(b)}] at (o) {};
      \draw [\forestoption{edge}] () -- ($(o)!1!-35:(b)$) ($(o)!1!35:(b)$) -- ();
    },
    for children={
      if n=2{}{no edge},
    }
  }
}
\tikzset{%
  my circle/.style={draw, circle}
}
\begin{document}
\begin{forest}
  for tree={
    l sep=4em,
    s sep=8em,
    auto edge label,
    nice empty nodes,
    math content,
  }
  [P_1, my circle, arc below
    [, edge label={x=0}]
    [P_2, my circle, edge label=x
      [{c-x,x}, edge label=Y]
      [{0,0}, edge label=N]
    ]
    [, edge label={x=c}]
  ]
\end{forest}
\end{document}

EDITAR

Si desea aumentar aún más la separación entre los dos primeros niveles del árbol, la forma más sencilla es simplemente aumentar el valor de l seppara el nodo raíz. He aquí un ejemplo deliberadamente exagerado:

\begin{forest}
  for tree={
    l sep=4em,
    s sep=8em,
    auto edge label,
    nice empty nodes,
    math content,
  }
  [P_1, my circle, arc below, l sep*=6
    [, edge label={x=0}]
    [P_2, my circle, edge label=x
      [{c-x,x}, edge label=Y]
      [{0,0}, edge label=N]
    ]
    [, edge label={x=c}]
  ]
\end{forest}

mayor separación de niveles

Aquí la distancia mínima entre la raíz y sus hijos se establece en seis veces la distancia mínima habitual entre niveles con l sep*=6. Si prefiere agregar una cantidad absoluta, podría decir l sep+=<dimension>. O si simplemente desea anular el valor predeterminado, l sep=<dimension>especifique la distancia mínima con precisión.

Es importante que lo quel sep asegure sea lamínimodistancia. Entonces, si l sepse establece una distancia muy pequeña para un nivel y un poco más grande para otro, es posible que termines con la misma distancia en cada caso porque otros factores harán quebosquenecesita que los nodos estén espaciados a distancias mayores que cualquiera de los mínimos especificados.

Observo que su árbol de destino real no es, de hecho, como el que mostró en la pregunta. De hecho, la parte más complicada de mi código anterior no es necesaria en absoluto para el árbol final.

Aquí hay una versión automatizada de ese árbol como referencia. Esta versión prescinde de las bibliotecas TikZ ya que sólo son necesarias para arc below. arc throughes un nuevo estilo que conecta con los anclajes oeste y este en lugar de pasar por el ancla norte. my arcdetermina el estilo del arco. Esto se puede configurar dentro del árbol usando my arcs={<key list>}para determinar el estilo. Por defecto, está vacío y el arco se dibuja con el estilo de la edgeopción actual. Especificar el estilo con my arcspermite complementar o anular el edgeestilo. Por ejemplo, el arco puede ser densely dashedparejo si los bordes están dibujados sólidamente.

\forestset{%
  arc through/.style={
    tikz+={%
      \path [\forestoption{edge}, my arc] (!1) [out=-35, in=180] to (!2.west) (!2.east) [out=0, in=-145] to (!3);
    }
  },
  my arcs/.code={%
    \tikzset{%
      my arc/.style={#1},
    }
  },
}
\tikzset{%
  my arc/.style={},
}

arco discontinuo a través

\documentclass[tikz, border=10pt, multi]{standalone}
\usepackage{forest}
\forestset{%
  auto edge label/.style={%
    before typesetting nodes={%
      if level=0{}{
        if={n()>(n_children("!u")/2)}{
          if={n()==((n_children("!u")+1)/2)}{
            edge label/.wrap value={
              node[midway, right] {$##1$}
            },
          }{
            edge label/.wrap value={
              node[midway, outer sep=1.5mm, right] {$##1$}
            },
          },
        }{
          edge label/.wrap value={
            node[midway, outer sep=1.5mm, left] {$##1$}
          },
        }
      },
    },
  },
  nice empty nodes/.style={% page 65 of the manual - this is from the linguistics library
    for tree={
      calign=fixed edge angles
    },
    delay={
      where content={}{
        shape=coordinate,
        for parent={
          for children={anchor=north}
        }
      }{}
    }
  },
  arc through/.style={
    tikz+={%
      \path [\forestoption{edge}, my arc] (!1) [out=-35, in=180] to (!2.west) (!2.east) [out=0, in=-145] to (!3);
    }
  },
  my arcs/.code={%
    \tikzset{%
      my arc/.style={#1},
    }
  },
}
\tikzset{%
  my circle/.style={draw, circle},
  my arc/.style={},
}
\begin{document}
\begin{forest}
  for tree={
    l sep=4em,
    s sep=8em,
    auto edge label,
    nice empty nodes,
    math content,
    my arcs={densely dashed},
  }
  [P_1, my circle, arc through
    [, edge label={x=0}]
    [P_2, my circle, edge label=x
      [{c-x,x}, edge label=Y]
      [{0,0}, edge label=N]
    ]
    [, edge label={x=c}]
  ]
\end{forest}
\end{document}

EDITAR A UN LADO

Esta versión es sólo paraClemente. Aunque tiene más de 546 caracteres, sigue siendo solo 644. Y Kile hace que el código exclusivo de TikZ tenga 563 caracteres, por lo que probablemente mis estadísticas cuenten los caracteres de manera diferente.

Personalmente, no creo que esto sea una ventaja, pero ahí lo tienes.

No es muy transparente, por lo que no recomiendo usarlo.

Sin embargo, la forma en que se dibuja el arco es mucho más clara que mi código anterior. Lo que probablemente haría es basarme arc belowen este método en lugar de usar la throughbiblioteca.

El principal ahorro de caracteres se consigue eliminando la automatización. Las etiquetas de los bordes ya no se colocan automáticamente según la posición del niño en relación con sus hermanos. Entonces, si agrega un nodo, debe verificar si alguno de leftlos s debe convertirse en rights o viceversa. Además, no se utiliza ningún estilo para los círculos, lo que reduce la flexibilidad y la facilidad de mantenimiento del código. Finalmente, los signos de dólar se utilizan para el contenido de los nodos y no math contentporque math content,contienen más caracteres que el número requerido para asignar un par de signos de dólar a cada nodo que los necesita.

Irónicamente, el dibujo del arco ahora utilizabosquepresenta más funciones y TikZ presenta menos. ( y()se usa con un contenedor pgfmath para obtener la información necesaria para el arco, en lugar de depender de la throughbiblioteca).

\documentclass{standalone}
\usepackage{forest}
\usetikzlibrary{calc}
\begin{document}
\begin{forest}
  ey/.style={shape=coordinate,no edge},
  elr/.style 2 args={edge label={node[midway,outer sep=1.5mm,#1]{$#2$}}},
  el/.style={elr={left}{#1}},
  er/.style={elr={right}{#1}},
  for tree={l sep=4em,s sep=8em,calign=fixed edge angles}
  [$P_1$,draw,circle
    [,el={x=0},ey]
    [$P_2$,draw,circle,er=x,anchor=north,before drawing tree={TeX/.wrap pgfmath arg={\gdef\rs{#1}}{y("!u")-y()}},tikz={\draw(!u)--($(!u)!1!-35:(.north)$)arc(235:305:\rs pt)--(!u);}
      [${c-x,x}$,el=Y]
      [${0,0}$,er=N]]
    [,er={x=c},ey]]
\end{forest}
\end{document}

versión corta y amarga

Respuesta2

Sé que quieres seguir adelante, forestpero mientras esperas una respuesta, puedes intentar comprender la forma en que un pobre dibuja tu plan. No es tan difícil:

Dibujemos P1en alguna parte

\node[circle,draw] (P1) {$P_1$};

Dibujemos P2a una cierta distancia conocida debajo.P1

\node[circle, draw, on grid, below = 2cm of P1, anchor=north] (P2) {$P_2$};

con on gridy anchor=northforzamos una 2cmdistancia entre el centro de P1 y el norte de P2. Lo necesitaremos para un arco perfecto.

Ahora podemos trazar la línea entre P1yP2

\draw (P1)-- node[right]{$x$} (P2);

A continuación, decida qué ángulos desea para los niños izquierdo y derecho. La longitud del brazo comenzará 2cmdesde P1el centro. Al final del niño de la derecha, dibujamos el arco porque conocemos el ángulo inicial, el ángulo final y el radio.

\draw (P1) -- node[right] {$x=c$} ++ (-60:2cm) arc (-60:-120:2cm);
\draw (P1) -- node[left] {$x=0$} ++ (240:2cm);

Y terminamos con P2los niños usando comandos similares:

\draw (P2) -- node[right] {$N$} ++ (-60:2cm) node[below] {$0,0$};
\draw (P2) -- node[left] {$Y$} ++ (240:2cm) node[below] {$c-x,x$};

Eso es todo. El resultado:

ingrese la descripción de la imagen aquí

y código completo:

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{positioning}

\begin{document}
\begin{tikzpicture}
\draw (-2,-2) grid (2,2);
\node[circle,draw] (P1) {$P_1$};
\node[circle, draw, on grid, below = 2cm of P1, anchor=north] (P2) {$P_2$};
\draw (P1)-- node[right]{$x$} (P2);

\draw (P1) -- node[right] {$x=c$} ++ (-60:2cm) arc (-60:-120:2cm);
\draw (P1) -- node[left] {$x=0$} ++ (240:2cm);

\draw (P2) -- node[right] {$N$} ++ (-60:2cm) node[below] {$0,0$};
\draw (P2) -- node[left] {$Y$} ++ (240:2cm) node[below] {$c-x,x$};
\end{tikzpicture}
\end{document}

Respuesta3

  1. El "espacio en blanco" no es más que nodos vacíos. Aunque no haya agregado texto, los nodos se crean y, a su vez, crean el espacio en blanco. Para resolver esto, simplemente agregue coordinatea las opciones para esos nodos, comoname=1, coordinate,...
  2. Resuelto por el siguiente punto.
  3. Para los ángulos, agregue calign=fixed edge anglesa sus for tree={}opciones.
  4. No encuentro una manera de hacer esto, ni siquiera en el manual. Creo que me estoy perdiendo algo obvio.

En cualquier caso, aquí está el resultado actual:

ingrese la descripción de la imagen aquí

Respuesta4

Editar: istgameversión 2.0

Con elistgameEn la versión 2.0, puede tener más controles sobre el tipo de arco continuo de ramas:

\documentclass{standalone}

\usepackage{istgame}

\begin{document}    
\begin{istgame}[->,font=\footnotesize]
\cntmdistance{15mm}{30mm}
\cntmAistb[->]{x=0}[al]{x=1}[ar]
\cntmApreset[ultra thin]<1.5>
\istrootcntmA(0)[null node]{1}
  \istbA{x}[r]
  \endist
\xtdistance{10mm}{20mm}
\istroot(1)(0-1)[null node]<45>{2}
  \istb{Y}[l]{c-x,x}
  \istb{N}[r]{0,0}
  \endist
\end{istgame}

\end{document}

ingrese la descripción de la imagen aquí

Respuesta original

Esta es otra solución para obtener la forma del ultimatumjuego que deseas, utilizando elistgamepaquete. (Puedes encontrar otra forma de dibujar el juego del ultimátum en el documento del paquete). Dado que el istgameentorno es casi el mismo que el tikzpicture, puedes usar tikz macrosdentro del istgameentorno.

\documentclass{standalone}

\usepackage{istgame}

\begin{document}    
\begin{istgame}[->,font=\footnotesize]
\istroot(0)[null node]{1}+15mm..15mm+
  \istb{x=0}[l]
  \istb<level distance=1.42*15mm>{x}[r]
  \istb{x=c}[r]
  \endist
\xtdistance{10mm}{20mm}
\istroot(1)(0-2)[null node]<45>{2}
  \istb{Y}[l]{c-x,x}
  \istb{N}[r]{0,0}
  \endist
\draw[-,ultra thin,tension=1] plot [smooth] coordinates {(0-1)(0-2)(0-3)};
\end{istgame}

\end{document}

información relacionada