BEARBEITEN

BEARBEITEN

Heute brauche ich wieder Ihre Hilfe, um mit dem Paket fertig zu werden forest(es ist ein wirklich leistungsstarkes Paket, aber auch ziemlich komplex). Im Grunde habe ich bereits mehrere Stunden damit verbracht, ein Ultimatumspiel in Baumform zu zeichnen, das so aussehen sollte:

Bildbeschreibung hier eingeben

Bisher ist es mir gelungen, diesen Code zu erstellen, der irgendwie funktioniert (aber nicht gut):

\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}

Die Ausgabe, die ich erhalte, ist diese:

Bildbeschreibung hier eingeben

Idealerweise möchte ich mehrere Dinge ändern. Erstens möchte ich, dass (a) die gekrümmte Linie die Zweige des Baums berührt, um diesen hässlichen weißen Raum zu vermeiden. Zweitens möchte ich (b) die Überlappung zwischen der gekrümmten Linie und dem Knoten P2 vermeiden. Drittens möchte ich (c) sicherstellen, dass die Winkel der beiden Zweige in den beiden Knoten gleich sind. Mit anderen Worten, der Winkel des zweiten Knotens ist größer als der des ersten Knotens, und ich möchte, dass sie gleich sind. Viertens möchte ich, dass (d) die Zweige des zweiten Knotens möglichst kürzer sind als die des ersten. Alle Fragen sind gleichermaßen relevant. Jede Hilfe zu einem der vier Probleme wird sehr geschätzt.

PS: Idealerweise möchte ich so weit wie möglich bei meinem aktuellen Code bleiben (mit anderen Worten, ich möchte die unbedingt notwendigen Mindeständerungen am Code vornehmen, um die erforderlichen Änderungen zu erhalten, da es sich um einen Code handelt, den ich mehr oder weniger leicht verstehen kann).

Antwort1

Hier ist eine Lösung, die meiner Meinung nach alle genannten Anforderungen erfüllt. Ich bin aufgrund des Zielbildes davon ausgegangen, dass Sie nicht möchten, dass der Bogen den obersten Punkt des Knotens verfehlt P_2. Wenn dies nicht erforderlich ist, müssen Sie sich mit einigen der in meinem Code enthaltenen Berechnungen nicht befassen.

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

Wir laden throughTikZ calc-Bibliotheken, um den Bogen korrekt zu zeichnen.

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

Nun richten wir einige Stile ein. Einige davon vereinfachen Ihren vorhandenen Code. Wenn Sie sie nicht verwenden möchten, können Sie sie weglassen.

\forestset{%

auto edge labelautomatisiert den Code zur Formatierung der edge label. Es erstellt den Knoten, versetzt den Inhalt in den Mathematikmodus und entscheidet, ob das Label links oder rechts vom Rand platziert wird. Das bedeutet, dass

edge label=x^2, auto edge label

wird das Richtige tun.

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

Tun Sie nichts, wenn es der Stammknoten ist.

      if level=0{}{

Wenn sich der Knoten in der zweiten Hälfte der untergeordneten Knoten seines Elternteils befindet oder wenn er das mittlere untergeordnete Knoten ist ...

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

Wenn der Knoten das mittlere untergeordnete Element ist ...

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

Wenn sich der Knoten in der zweiten Hälfte der untergeordneten Knoten seines übergeordneten Knotens befindet ...

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

Wenn sich der Knoten in der ersten Hälfte der untergeordneten Knoten seines übergeordneten Knotens befindet ...

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

Dies ist der Stil für schönere leere Knoten. Er stammt von Seite 65 des aktuellen Handbuchs. Er ist Teil der linguisticsBibliothek. Wenn Sie diese Bibliothek verwenden, können Sie diese Definition also weglassen und den Stil direkt anwenden.

Beachten Sie, dass sich die Erklärung in diesem Teil des Handbuchs meiner Meinung nach fälschlicherweise auf nicht vorhandene Optionen bezieht, aber da bin ich mir nicht sicher.

  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}
        }
      }{}
    }
  },

Dies ist der Stil zum Zeichnen der Bögen. Sie übergeben dies als Option an das übergeordnete Element der Knoten, durch die der Bogen gezeichnet werden soll.

Außer zum zweiten Kind werden keine Kanten als Teil des Baums selbst gezeichnet. Wenn es mehr als 3 Kinder geben könnte, müsste dies etwas ausgefeilter werden. Dieser Code geht von 3 Kindern aus.

Stattdessen wird der Bogen anschließend gezeichnet, indem die entsprechenden Punkte basierend auf der Position des mittleren Knotens und dem Standardwinkel zu den Knoten bei Verwendung berechnet werden calign=fixed edge angles. Die Kanten zum ersten und dritten Kind werden zu diesem Zeitpunkt gezeichnet.

[Dies sollte im Hinblick auf die Überprüfung verschiedener Möglichkeiten eigentlich etwas ausgefeilter sein, aber in relevanten Fällen wie dem MWE sollte es funktionieren.]

  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},
    }
  }
}

Einfacher TikZ-Stil für mehr Komfort.

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

Dann können wir das Ganze einfach wie folgt auf den Baum anwenden.

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

Vom MWE.

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

Wenden Sie zwei der neuen Stile auf den gesamten Baum an.

    auto edge label,
    nice empty nodes,

Setzen Sie alle Knoten in den Mathematikmodus, um Dollarzeichen zu sparen.

    math content,
  }

Geben Sie den arc belowStil für die Wurzel an.

  [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}

Baum mit Stilen

Vollständiger Code:

\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}

BEARBEITEN

Wenn Sie den Abstand zwischen den ersten beiden Ebenen des Baums weiter vergrößern möchten, können Sie am einfachsten den Wert für l sepden Stammknoten erhöhen. Hier ist ein absichtlich übertriebenes Beispiel:

\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}

erhöhte Niveautrennung

Hier wird der Mindestabstand zwischen der Wurzel und ihren untergeordneten Elementen auf das Sechsfache des üblichen Mindestabstands zwischen Ebenen mit festgelegt l sep*=6. Wenn Sie lieber einen absoluten Betrag hinzufügen möchten, können Sie sagen l sep+=<dimension>. Oder wenn Sie einfach die Standardeinstellung überschreiben möchten, l sep=<dimension>gibt den Mindestabstand genau an.

Es ist wichtig, dass l sepsichergestellt wird, dassMinimumAbstand. Wenn also l sepfür eine Ebene sehr klein und für eine andere etwas größer eingestellt ist, kann es sein, dass Sie in beiden Fällen den gleichen Abstand erhalten, da andere Faktoren dazu führen, dassWalderfordert, dass die Knoten in größeren Abständen angeordnet sind als die jeweils angegebenen Mindestabstände.

Ich stelle fest, dass Ihr tatsächlicher Zielbaum nicht dem in der Frage gezeigten entspricht. Tatsächlich ist der schwierigste Teil meines obigen Codes für Ihren endgültigen Baum überhaupt nicht erforderlich.

Hier ist eine automatisierte Version dieses Baums als Referenz. Diese Version verzichtet auf die TikZ-Bibliotheken, da sie nur für benötigt werden arc below. arc throughist ein neuer Stil, der mit den West- und Ostankern verbunden wird, anstatt durch den Nordanker zu verlaufen. my arcbestimmt den Stil des Bogens. Dies kann im Baum festgelegt werden, indem my arcs={<key list>}der Stil bestimmt wird. Standardmäßig ist es leer und der Bogen wird mit dem Stil der aktuellen edgeOption gezeichnet. Durch Festlegen des Stils mit my arcskann der edgeStil ergänzt oder überschrieben werden. Beispielsweise kann der Bogen densely dashedgerade sein, wenn die Kanten durchgezogen gezeichnet sind.

\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={},
}

gestrichelter Bogen durch

\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}

BEARBEITEN BEIseite

Diese Version ist nur fürClément. Obwohl es mehr als 546 Zeichen sind, sind es immer noch nur 644. Und Kile macht den Nur-TikZ-Code 563 Zeichen lang, also zählt meine Statistik die Zeichen wahrscheinlich anders.

Persönlich halte ich das nicht für einen Vorteil, aber so ist es nun einmal.

Es ist nicht sehr transparent, daher empfehle ich die Verwendung nicht wirklich.

Allerdings ist die Art und Weise, wie der Bogen gezeichnet wird, viel schöner als in meinem früheren Code. Ich würde mich wahrscheinlich eher auf diese Methode stützen, arc belowals die throughBibliothek zu verwenden.

Die größte Zeicheneinsparung wird durch den Verzicht auf Automatisierung erreicht. Die Randbeschriftungen werden nicht mehr automatisch entsprechend der Position des untergeordneten Elements im Verhältnis zu seinen Geschwistern platziert. Wenn Sie also einen Knoten hinzufügen, müssen Sie prüfen, ob aus s lefts werden soll rightoder umgekehrt. Darüber hinaus wird für die Kreise kein Stil verwendet, was die Flexibilität und Wartbarkeit des Codes einschränkt. Schließlich werden Dollarzeichen für den Inhalt von Knoten verwendet, anstatt math contentweil math content,mehr Zeichen enthalten sind als erforderlich sind, um jedem Knoten, der sie benötigt, ein Paar Dollarzeichen zuzuweisen.

Ironischerweise verwendet die Zeichnung des Bogens jetzt tatsächlichWaldFunktionen stärker und TikZ-Funktionen weniger stark. ( y()wird mit einem pgfmath-Wrapper verwendet, um die für den Bogen benötigten Informationen zu erhalten, anstatt sich auf die throughBibliothek zu verlassen.)

\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}

kurze und saure Version

Antwort2

Ich weiß, dass Sie dabei bleiben möchten, forestaber während Sie auf eine Antwort warten, können Sie versuchen, Ihr Schema auf eine einfache Art und Weise zu zeichnen. Das ist nicht so schwierig:

Lass uns P1irgendwo zeichnen

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

Zeichnen wir P2in einer bestimmten bekannten Entfernung untenP1

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

mit on gridund anchor=northwir erzwingen eine 2cmDistanz zwischen dem Mittelpunkt von P1 und dem Norden von P2. Diese Distanz benötigen wir für einen perfekten Bogen.

Jetzt können wir die Grenze ziehen zwischen P1undP2

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

Entscheiden Sie als Nächstes, welche Winkel Sie für das linke und rechte Kind wünschen. Die Armlänge beginnt 2cmin P1der Mitte. Am Ende des rechten Kindes zeichnen wir den Bogen, da wir Anfangswinkel, Endwinkel und Radius kennen.

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

Und wir beenden die Übung mit P2Kindern, die ähnliche Befehle verwenden:

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

Das ist alles. Das Ergebnis:

Bildbeschreibung hier eingeben

und vollständiger Code:

\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}

Antwort3

  1. Der „weiße Raum“ ist nichts anderes als leere Knoten. Auch wenn Sie keinen Text hinzugefügt haben, werden die Knoten erstellt und erzeugen somit den weißen Raum. Um dieses Problem zu lösen, fügen Sie einfach coordinateden Optionen für diese Knoten Folgendes hinzu:name=1, coordinate,...
  2. Gelöst durch den nächsten Punkt.
  3. calign=fixed edge anglesErweitern Sie Ihre for tree={}Optionen für die Winkel .
  4. Ich kann keine Möglichkeit finden, dies zu tun, nicht einmal im Handbuch. Ich glaube, ich übersehe etwas Offensichtliches.

Hier jedenfalls das aktuelle Ergebnis:

Bildbeschreibung hier eingeben

Antwort4

Bearbeiten: istgameVersion 2.0

Mit demistgameVersion 2.0 haben Sie mehr Kontrolle über das bogenförmige Verzweigungskontinuum:

\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}

Bildbeschreibung hier eingeben

Ursprüngliche Antwort

ultimatumDies ist eine weitere Lösung, um die gewünschte Form des Spiels zu erhalten , indem Sie dieistgamePaket. (Eine weitere Möglichkeit zum Zeichnen des Ultimatumspiels finden Sie im Paketdokument.) Da die istgameUmgebung fast identisch mit der ist tikzpicture, können Sie Tikz macrosinnerhalb der istgameUmgebung verwenden.

\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}

verwandte Informationen