5

I'm trying to play with tikz and chains, but I have some troubles when I deal with several chains. How could I position the chains each others ?

For example in the following example, I position the second chain by using yshift on the first node, but it's not the best way to proceed I think...

And also I would like to know if it's possible to first chain without manually doing a dirty xshift ?

Thank you in advance.

\documentclass[a4paper, 11pt]{article}
\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{matrix,chains,positioning,decorations.pathreplacing,arrows}

\begin{document}

\begin{figure}[H]
  \centering
  \begin{tikzpicture}[
    circ/.style={
      draw,
      circle,
      fill=blue!30,
      inner sep=5pt
    },
    squa/.style={
      draw,
      inner sep=5pt,
      fill=blue!20,
    },
    start chain=1,
    start chain=2,node distance=15mm
    ] 
    % Variables
    \node[on chain=1,circ] (x1) {$x_1$};
    \node[on chain=1,circ] (x2) {$x_2$};
    \node[on chain=1,circ] (x3) {$x_3$};
    % Clauses
    \node[on chain=2,yshift=-2cm,squa] (c1) {$\lnot x_1 \lor \lnot x_2$};
    \node[on chain=2,squa] (c2) {$x_2 \lor \lnot x_3$};
    \node[on chain=2,squa] (c3) {$x_1 \lor x_2$};
    \node[on chain=2,squa] (c4) {$\lnot x_2 \lor x_3$};
    \node[on chain=2,squa] (c5) {$\lnot x_1 \lor x_3$};
    % Draw
    \draw[dashed] (x1.south) -- (c1.north);
    \draw[dashed] (x1.south) -- (c5.north);
    \draw[dashed] (x2.south) -- (c1.north);
    \draw[dashed] (x2.south) -- (c4.north);
    \draw[dashed] (x3.south) -- (c2.north);
    \draw[] (x1.south) -- (c3.north);
    \draw[] (x2.south) -- (c2.north);
    \draw[] (x2.south) -- (c3.north);
    \draw[] (x3.south) -- (c4.north);
    \draw[] (x3.south) -- (c5.north);
  \end{tikzpicture}
  \caption{Une représentation d'une CNF sous forme de graph}
  \label{fig:sat_graph}
\end{figure}

\end{document}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
  • Instead of yshift you could use (with positioning library) below=of x1. – Ignasi Dec 14 '16 at 16:48
  • It's a bit better indeed, but it's not possible to position chains, and not the first element ? It's a big strange to always change the positioning argument of the first node when I add a new node at the beginning of the chain. – tobiasBora Dec 14 '16 at 16:51
  • I don't think there's any problem with what you used if the result is what you wanted. But I don't know why do you want to use chains. – Ignasi Dec 14 '16 at 16:55
  • Did you consider a matrix for both rows or even two matrix one for each row? – Ignasi Dec 14 '16 at 16:59
  • The problem is that I cannot nest two matrix (to center it). But using both matrix and chains, I manage to do what I wanted. I posted the result in an answer. Thank you ! – tobiasBora Dec 14 '16 at 17:43
4

Chains enable simple coding of chain of nodes. With help of package `positioning it is easy to control horizontal and vertical distance between node, For example:

\documentclass[a4paper, 11pt]{article}
\usepackage{tikz}
\usetikzlibrary{chains,positioning}
\begin{document}

\begin{figure}[htb]
  \centering
  \begin{tikzpicture}[
  node distance=20mm and 15 mm,
  start chain = going right,
    circ/.style={
      draw,
      circle,
      fill=blue!30,
      inner sep=5pt,
      on chain,
    },
    squa/.style={
      draw,
      inner sep=5pt,
      fill=blue!20,
      on chain
    },
    ]
    % Variables
\node[circ] (x1) {$x_1$};
\node[circ] (x2) {$x_2$};
\node[circ] (x3) {$x_3$};
    % Clauses
\node[squa,below left=of x1] (c1) {$\lnot x_1 \lor \lnot x_2$};
\node[squa] (c2) {$x_2 \lor \lnot x_3$};
\node[squa] (c3) {$x_1 \lor x_2$};
\node[squa] (c4) {$\lnot x_2 \lor x_3$};
\node[squa] (c5) {$\lnot x_1 \lor x_3$};
    % Draw
\draw[dashed]   (x1) -- (c1)
                (x1) -- (c5)
                (x2) -- (c1)
                (x2) -- (c4)
                (x3) -- (c2);
\draw   (x1) -- (c3)
        (x2) -- (c2)
        (x2) -- (c3)
        (x3) -- (c4)
        (x3) -- (c5);
  \end{tikzpicture}
  \caption{Une représentation d'une CNF sous forme de graph}
  \label{fig:sat_graph}
\end{figure}

\end{document}

enter image description here

in the case that you like to have the same start and end point of lines at nodes, than you need in above code explicitly defined this points with node anchor as you have in your question:

\draw[dashed]   (x1.south) -- (c1.north) ...

enter image description here

Note: this answer actually summarize Ignasi comments regard chain. I also take liberty and slightly change position of the second nodes chain.

Adendum: From your and Ingnasi answers I understood, that you like to have horizontally centered bot chains. This is easy to achieve with change the order of drawing: first had to be drawn chain below, and than positioning nodes containing Variables:

\documentclass[a4paper, 11pt]{article}
\usepackage{tikz}
\usetikzlibrary{chains,positioning}

\begin{document}
    \begin{figure}[htb]
\centering
    \begin{tikzpicture}[
    node distance = 20mm and 15 mm,
      start chain = going right,
      circ/.style = {draw, circle, fill=blue!30, inner sep=5pt},
      squa/.style = {draw, inner sep=5pt, fill=blue!20,
                     on chain},
                        ]
    % Clauses
\node[squa] (c1) {$\lnot x_1 \lor \lnot x_2$};
\node[squa] (c2) {$x_2 \lor \lnot x_3$};
\node[squa] (c3) {$x_1 \lor x_2$};
\node[squa] (c4) {$\lnot x_2 \lor x_3$};
\node[squa] (c5) {$\lnot x_1 \lor x_3$};
    % Variables
\node[circ,above left= of c3] (x1)  {$x_1$};
\node[circ,above=of c3] (x2)        {$x_2$};
\node[circ,above right=of c3] (x3)  {$x_3$};

    % Draw
\draw[dashed]   (x1) -- (c1)
                (x1) -- (c5)
                (x2) -- (c1)
                (x2) -- (c4)
                (x3) -- (c2);
\draw   (x1) -- (c3)
        (x2) -- (c2)
        (x2) -- (c3)
        (x3) -- (c4)
        (x3) -- (c5);
    \end{tikzpicture}
\caption{Une représentation d'une CNF sous forme de graph}
    \label{fig:sat_graph}
    \end{figure}
\end{document}

This change of drawing order and use chains facility only in the bottom row gives (perfectly) centered both rows of nodes:

enter image description here

| improve this answer | |
4

From your OP's answer I deduce that:

  • you want to draw to rows of elements, one corresponding to variables and another to clauses
  • both rows have to be vertically centered one respect the other
  • and that you want to add elements to both rows and still keep relative positioning

To me, the best solution uses two matrix one for each row. This way they can be populated as you need it and both can be vertically centered.

As I still don't know why to use chains in this case I've suppressed them form the following code:

\documentclass[border=2mm]{standalone}

\usepackage{tikz}
\usetikzlibrary{matrix,positioning}

\begin{document}


\begin{tikzpicture}[
    circ/.style={
      draw,
      circle,
      fill=blue!30,
      inner sep=5pt
    },
    squa/.style={
      draw,
      inner sep=5pt,
      fill=blue!20,
    },
    ] 
    \matrix (var) [draw=red, matrix of nodes, nodes={circ, anchor=center}, column sep=1cm]
    { 
     |(x1)| $x_1$ & |(x2)| $x_2$ & |(x3)| $x_3$ \\
    };

    \matrix (clauses) [draw=red, below=1.5cm of var, 
        matrix of nodes, nodes={squa, anchor=center}, column sep=1cm]
    {
    |(c1)| $\lnot x_1 \lor \lnot x_2$ &
    |(c2)| $x_2 \lor \lnot x_3$ &
    |(c3)| $x_1 \lor x_2$ &
    |(c4)| $\lnot x_2 \lor x_3$ &
    |(c5)| $\lnot x_1 \lor x_3$ \\
    };
    % Draw
    \draw[dashed]
         (x1.south) -- (c1.north)
         (x1.south) -- (c5.north)
         (x2.south) -- (c1.north)
         (x2.south) -- (c4.north)
         (x3.south) -- (c2.north);
    \draw[]
         (x1.south) -- (c3.north)
         (x2.south) -- (c2.north)
         (x2.south) -- (c3.north)
         (x3.south) -- (c4.north)
         (x3.south) -- (c5.north);
  \end{tikzpicture}

\end{document}

enter image description here

Some comments to previous code and figure.

  • I've used syntax |(x1)|$x_1$ which asigns name x1 to this node instead of default solution $x_1$ which assigns var-1-1.
  • Option draw=red has been included in both matrix in order to understand how these matrix-nodes are placed one respect the other. As a side effect, inner nodes have inherited red color.
  • Previous scheme allows easily add or delete elements from variables or clauses matrix.
| improve this answer | |
  • Very interesting, I didn't know that it was that easy to give a position to the matrix ! The answer from Zarko gives the answer to the subject title, so I'll keep it as the "accepted answer", but your solution is very nice, thank you. Now I have 2 ways to do what I want, thank you ! It's only a shame that it's not possible to nest matrix... – tobiasBora Dec 14 '16 at 21:09
1

While the solution of Ignasi and Zarko seems to be the easiest way to set the relative position of two chains, it doesn't work with centering. Here is the complement solution I found to center the chains. I don't know if it's the more simple way to horizontally center the chains, but I found a solution using both chains and matrix. In a few lines, the idea is to put the chains into a node, and put the node into a matrix with the anchor set to center. To be able to do links between two cells, you need to set the remember picture option of tikzpicture. Here is what I get:

result

And here is the code:

\documentclass[a4paper, 11pt]{article}

\usepackage{float}
\usepackage{tikz}
\usetikzlibrary{matrix,chains,positioning,decorations.pathreplacing,arrows}

\begin{document}

\begin{figure}[H]
  \centering
  \begin{tikzpicture}[
    remember picture,
    circ/.style={
      draw,
      circle,
      fill=blue!30,
      inner sep=5pt
    },
    squa/.style={
      draw,
      inner sep=5pt,
      fill=blue!20,
    },
    start chain=1,
    start chain=2
    ] 
    \matrix [matrix of nodes,nodes={anchor=center},row sep = 2em]
    { 
      % Variables
      \node{\tikz{
          \node[on chain=1, circ] (x1) {$x_1$};
          \node[on chain=1, circ] (x2) {$x_2$};
          \node[on chain=1, circ] (x3) {$x_3$};
        }};
      \\
      \node{\tikz{
          % Clauses
          \node[on chain=2, squa] (c1) {$\lnot x_1 \lor \lnot x_2$};
          \node[on chain=2, squa] (c2) {$x_2 \lor \lnot x_3$};
          \node[on chain=2, squa] (c3) {$x_1 \lor x_2$};
          \node[on chain=2, squa] (c4) {$\lnot x_2 \lor x_3$};
          \node[on chain=2, squa] (c5) {$\lnot x_1 \lor x_3$};
        }};
      \\
    };
    % Draw
    \draw[dashed]
         (x1.south) -- (c1.north)
         (x1.south) -- (c5.north)
         (x2.south) -- (c1.north)
         (x2.south) -- (c4.north)
         (x3.south) -- (c2.north);
    \draw[]
         (x1.south) -- (c3.north)
         (x2.south) -- (c2.north)
         (x2.south) -- (c3.north)
         (x3.south) -- (c4.north)
         (x3.south) -- (c5.north);
  \end{tikzpicture}
\end{figure}

\end{document}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.