10

I am quite new at using LaTeX, however now I need to draw an 8x8 Karnaugh map. I have already found many helpful codes on this topic, however when I try to modify those codes the result is simply messy. I would appreciate the help, I am lost :)

  • 1
    Welcome to TeX.SX! Please help us help you and add a minimal working example (MWE) that illustrates your problem. Reproducing the problem and finding out what the issue is will be much easier when we see compilable code, starting with \documentclass{...} and ending with \end{document}. – Stefan Pinnow Apr 6 '18 at 9:18
20

kvmap

Ben Frank was kind enough to package this answer and put it on CTAN (package kvmap).

With the kvmap package you can input your Karnaugh map like a tabular. This works even for very large sizes (I just tested 64x64 fields), so it is definitely able to typeset an 8x8 map.

If you want to draw implicants you can use the \bundle macro and pass the coordinates of the corners to it. For further explanation see the old answer (which explains the code a bit better).

Full code example:

\documentclass{article}
\usepackage{kvmap}

\begin{document}
    \begin{kvmap}
        \begin{kvmatrix}{a,b,c,d,e,f}
        0 & 1 & 1 & 0 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\
        0 & 0 & 1 & 1 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
        0 & 1 & 1 & 0 & 0 & 0 & 0 & 0
        \end{kvmatrix}
        \bundle{3}{3}{2}{3}
        \bundle[color=blue]{3}{2}{3}{1}
        \bundle[invert=true,reducespace=2pt,overlapmargins=6pt]{1}{0}{2}{7}
    \end{kvmap}
\end{document}

Old answer

The following code will produce Karnaugh maps in any size you want it to have (tested for some 2n) as TikZ pictures. You input your map like you would input a table in LaTeX using the kvmatrix environment. The only argument of this environment is a comma-separated list of your variable names. Therefore a simple 2x2 matrix would look like

\begin{kvmatrix}{a,b}
    0 & 1\\
    0 & 1
\end{kvmatrix}

There is a second environment provided, kvmap, which is basically a tikzpicture (but for the sake of semantic consistency). You should use this if you are planning to work with the fields. Each field is named by its x- and y-index in the following way: xy (where 00 is the top-left corner and nm is the bottom-right corner with n+1 and m+1 as the dimensions of your matrix, e.g. 11 for a 2x2 matrix).

The code is also able to draw borders around cells which can be bundled. Therefore you would use the command \package[options]{x1}{y1}{x2}{y2} with the coordinates of the corners of the rectangle. If the package should be open to the margin use the invert option (if the coordinates are at the outer-most rows/columns; the overlapmargins option specifies how far the bundle is drawn into the margin). You can color a package with the color option and to avoid overlapping with other packages specify a reduction of space with reducespace.

\begin{kvmap}
    \begin{kvmatrix}{a,b}
        0 & 1\\
        0 & 1
    \end{kvmatrix}
    \package[color=red]{1}{0}{1}{1}
\end{kvmap}

Here the working code:

\documentclass{article}
\usepackage{xparse}
\usepackage{tikz}
\usepackage{environ}

\ExplSyntaxOn
\cs_generate_variant:Nn \seq_set_split:Nnn   { Nno, Nnx }
\cs_generate_variant:Nn \int_mod:nn          { VV       }
\cs_generate_variant:Nn \int_div_truncate:nn { VV       }

% see https://tex.stackexchange.com/questions/418853/latex3-pad-something-unexpandable
\cs_new:Npn \__kvmap_graycode_xor_bits:nn #1#2
  {
    \int_compare:nTF { #1 = #2 }
      { 0 } { 1 }
  }
\cs_new:Npn \__kvmap_graycode_xor:w #1#2\q_stop#3#4\q_stop
  {
    \__kvmap_graycode_xor_bits:nn { #1 } { #3 }
    \tl_if_empty:nF { #2 }
      {
        \__kvmap_graycode_xor:w #2\q_stop#4\q_stop
      }
  }
\cs_new:Npn \__kvmap_graycode_xor:nn #1#2
  {
    \__kvmap_graycode_xor:w #1\q_stop#2\q_stop
  }
\cs_generate_variant:Nn \__kvmap_graycode_xor:nn { xx }

\cs_new:Npn \kvmap_graycode_at:nn #1#2
{
    \__kvmap_graycode_xor:xx
      { \tl_tail:f { \int_to_bin:n { #1 - 1 + #2 } } }
      { \tl_tail:f { \int_to_bin:n { \fp_eval:n { floor((#1-1)/2) + #2 } } } }
}
\cs_generate_variant:Nn \kvmap_graycode_at:nn { nV }

\bool_new:N \l__kvmap_matrix_isintikz_bool
\int_new:N \l__kvmap_matrix_height_int
\int_new:N \l__kvmap_matrix_width_int
\cs_new:Nn \__kvmap_zeichnegraycode:
  {
    \int_step_inline:nnnn { 1 } { 1 } { \l__kvmap_matrix_width_int }
      {
\node ~ at ~ (\fp_eval:n { 0.5 + (##1-1) }, .3)
{ \kvmap_graycode_at:nV { ##1 } \l__kvmap_matrix_width_int };
      }
    \int_step_inline:nnnn { 1 } { 1 } { \l__kvmap_matrix_height_int }
      {
\node[anchor = east] ~ at ~ (0, \fp_eval:n { -0.5 - (##1-1) })
{ \kvmap_graycode_at:nV { ##1 } \l__kvmap_matrix_height_int };
      }
  }

\tikzset{kvnode/.style = { inner ~ sep = 8pt }}
\cs_new:Npn \__kvmap_zeichnematrix:n #1
{
\int_zero:N \l_tmpa_int
\seq_set_from_clist:Nn \l_tmpa_seq { #1 }
\seq_map_inline:Nn \l_tmpa_seq
{
\node[kvnode] ~
(\int_mod:VV \l_tmpa_int \l__kvmap_matrix_width_int
                    \int_div_truncate:VV \l_tmpa_int \l__kvmap_matrix_width_int ) ~
at ~
(.5+\int_mod:VV \l_tmpa_int \l__kvmap_matrix_width_int,
                -.5-\int_div_truncate:nn \l_tmpa_int \l__kvmap_matrix_width_int ) ~
{$##1$};
\int_incr:N \l_tmpa_int
}
}

\keys_define:nn { kvmap/package }
{
reducespace    .dim_set:N      = \l__kvmap_package_reducespace_dim,
reducespace    .initial:n      = { 0pt },
color          .tl_set:N       = \l__kvmap_package_color_tl,
color          .initial:n      = { black },
invert         .bool_set:N     = \l__kvmap_package_invert_bool,
invert         .initial:n      = false,
overlapmargins .dim_set:N      = \l__kvmap_package_overlapmargins_dim,
overlapmargins .initial:n      = { 0pt },
}
\tikzset{kvpacket/.style = { rounded ~ corners = 5pt }}
\int_new:N \l__kvmap_package_minx_int
\int_new:N \l__kvmap_package_miny_int
\int_new:N \l__kvmap_package_maxx_int
\int_new:N \l__kvmap_package_maxy_int
\NewDocumentCommand { \package } { O{} m m m m }
{
\group_begin:
\keys_set:nn { kvmap/package } { #1 }
\int_set:Nn \l__kvmap_package_minx_int { \int_min:nn { #2 } { #4 } }
\int_set:Nn \l__kvmap_package_miny_int { \int_min:nn { #3 } { #5 } }
\int_set:Nn \l__kvmap_package_maxx_int { \int_max:nn { #2 } { #4 } }
\int_set:Nn \l__kvmap_package_maxy_int { \int_max:nn { #3 } { #5 } }
\bool_if:nTF { \l__kvmap_package_invert_bool && (
(\int_compare_p:n  { \l__kvmap_matrix_height_int - 1 = \l__kvmap_package_maxy_int } &&
\int_compare_p:n { 0 = \l__kvmap_package_miny_int }) ||
(\int_compare_p:n { \l__kvmap_matrix_width_int - 1 = \l__kvmap_package_maxx_int} &&
\int_compare_p:n { 0 = \l__kvmap_package_minx_int } )) }
{
\int_compare:nT { \l__kvmap_matrix_height_int - 1 = \l__kvmap_package_maxy_int }
{
\draw[draw=\l__kvmap_package_color_tl,kvpacket] ~
([xshift=\l__kvmap_package_reducespace_dim,yshift=\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_miny_int . north ~ west) --
([xshift=\l__kvmap_package_reducespace_dim,yshift=\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_miny_int . south ~ west) --
([xshift=-\l__kvmap_package_reducespace_dim,yshift=\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_miny_int . south ~ east) --
([xshift=-\l__kvmap_package_reducespace_dim,yshift=\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_miny_int . north ~ east);
\draw[draw=\l__kvmap_package_color_tl,kvpacket] ~
([xshift=\l__kvmap_package_reducespace_dim,yshift=-\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ west) --
([xshift=\l__kvmap_package_reducespace_dim,yshift=-\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_maxy_int . north ~ west) --
([xshift=-\l__kvmap_package_reducespace_dim,yshift=-\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_maxy_int . north ~ east) --
([xshift=-\l__kvmap_package_reducespace_dim,yshift=-\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ east);
}
\int_compare:nT { \l__kvmap_matrix_width_int - 1 = \l__kvmap_package_maxx_int }
{
\draw[draw=\l__kvmap_package_color_tl,kvpacket] ~
([yshift=-\l__kvmap_package_reducespace_dim,
xshift=-\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_miny_int . north ~ west) --
([yshift=-\l__kvmap_package_reducespace_dim,
xshift=-\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_miny_int . north ~ east) --
([yshift=\l__kvmap_package_reducespace_dim,
xshift=-\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ east) --
([yshift=\l__kvmap_package_reducespace_dim,
xshift=-\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ west);
\draw[draw=\l__kvmap_package_color_tl,kvpacket] ~
([yshift=-\l__kvmap_package_reducespace_dim,
xshift=\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_miny_int . north ~ east) --
([yshift=-\l__kvmap_package_reducespace_dim,
xshift=\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_miny_int . north ~ west) --
([yshift=\l__kvmap_package_reducespace_dim,xshift=
\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ west) --
([yshift=\l__kvmap_package_reducespace_dim,xshift=
\l__kvmap_package_overlapmargins_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ east);
}
}
{
\draw[draw=\l__kvmap_package_color_tl, kvpacket] ~
([xshift=\l__kvmap_package_reducespace_dim,
yshift=-\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_minx_int
\int_use:N \l__kvmap_package_miny_int . north ~ west) ~
rectangle ~
([xshift=-\l__kvmap_package_reducespace_dim,
yshift=\l__kvmap_package_reducespace_dim]
\int_use:N \l__kvmap_package_maxx_int
\int_use:N \l__kvmap_package_maxy_int . south ~ east);
}
\group_end:
}
\cs_new:Npn \kvmap_diagram:nn #1#2
{
\draw ~ (0,0) ~ grid ~
(\int_use:N \l__kvmap_matrix_width_int, -\int_use:N \l__kvmap_matrix_height_int);
\__kvmap_zeichnematrix:n  { #1 }
\__kvmap_zeichnegraycode:
\draw ~ (0,0) ~ -- ~ (-.7,.7);
\int_set:Nn \l_tmpa_int
{ \fp_eval:n { floor(ln(\l__kvmap_matrix_width_int)/ln(2)) }  }
\tl_clear:N \l_tmpa_tl
\int_step_inline:nnnn { 1 } { 1 } { \l_tmpa_int }
{
 \tl_put_right:Nn \l_tmpa_tl { \clist_item:nn { #2 } { ##1 } }
}
\node[anchor = west] ~ at ~ (-.5, .7) ~ { $\tl_use:N \l_tmpa_tl$ };
\tl_clear:N \l_tmpa_tl
\int_step_inline:nnnn { \l_tmpa_int + 1 } { 1 }
{ \l_tmpa_int + \fp_eval:n { floor(ln(\l__kvmap_matrix_height_int)/ln(2)) } }
{
 \tl_put_right:Nn \l_tmpa_tl { \clist_item:nn { #2 } { ##1 } }
}
\node[anchor = east] ~ at ~ (-.4, .2) ~ { $\tl_use:N \l_tmpa_tl$ };
}
\cs_generate_variant:Nn \kvmap_diagram:nn { xn }

\NewDocumentEnvironment { kvmap } { O{} }
{
\group_begin:
\keys_set:nn { kvmap } { #1 }
\int_gzero:N \l__kvmap_matrix_height_int
\int_gzero:N \l__kvmap_matrix_width_int
\begin{tikzpicture}
}
{
\end{tikzpicture}
\group_end:
}

\seq_new:N \l__kvmap_tmp_seq
\NewEnviron { kvmatrix } [ 1 ]
{
\seq_set_split:Nno \l_tmpa_seq { \\ } { \BODY }
\seq_remove_all:Nn \l_tmpa_seq { }
\seq_set_split:Nnx \l_tmpb_seq { & } { \seq_item:Nn \l_tmpa_seq { 1 } }
\seq_remove_all:Nn \l_tmpb_seq { }
\int_gset:Nn \l__kvmap_matrix_width_int  { \seq_count:N \l_tmpb_seq }
\int_gset:Nn \l__kvmap_matrix_height_int { \seq_count:N \l_tmpa_seq }
\seq_clear:N \l__kvmap_tmp_seq
\seq_map_inline:Nn \l_tmpa_seq
{
\seq_clear:N \l_tmpb_seq
\seq_set_split:Nnn \l_tmpb_seq { & } { ##1 }
\seq_concat:NNN \l__kvmap_tmp_seq \l__kvmap_tmp_seq \l_tmpb_seq
}
\tikzifinpicture
{ \bool_set_true:N  \l__kvmap_matrix_isintikz_bool }
{ \bool_set_false:N \l__kvmap_matrix_isintikz_bool }
\bool_if:NF \l__kvmap_matrix_isintikz_bool
{ \begin{tikzpicture} }
\kvmap_diagram:xn
{ \seq_use:Nnnn \l__kvmap_tmp_seq { , } { , } { , } }
{ #1                       }
\bool_if:NF \l__kvmap_matrix_isintikz_bool
{ \end{tikzpicture} }
}
\ExplSyntaxOff

\begin{document}
    \begin{kvmap}
        \begin{kvmatrix}{a,b,c,d,e,f}
        0 & 1 & 1 & 0 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\
        0 & 0 & 1 & 1 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
        0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
        0 & 1 & 1 & 0 & 0 & 0 & 0 & 0
        \end{kvmatrix}
        \package{3}{3}{2}{3}
        \package[color=blue]{3}{2}{3}{1}
        \package[invert=true,reducespace=2pt,overlapmargins=6pt]{1}{0}{2}{7}
    \end{kvmap}
\end{document}

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.