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 Answer
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}
\documentclass{...}
and ending with\end{document}
.