我对使用 LaTeX 还很陌生,但现在我需要绘制一个 8x8 卡诺图。我已经找到了很多关于这个主题的有用代码,但是当我尝试修改这些代码时,结果却很混乱。如果能得到帮助,我将不胜感激,我迷路了 :)
答案1
Ben Frank 很好心地把这个答案打包并放在了 CTAN 上(打包)
kvmap
)。
使用该kvmap
软件包,您可以像表格一样输入您的卡诺图。即使对于非常大的尺寸(我刚刚测试了 64x64 字段),这也可以正常工作,因此它绝对能够排版 8x8 地图。
如果您想绘制蕴涵项,可以使用\bundle
宏并将角的坐标传递给它。有关进一步解释,请参阅旧答案(它更好地解释了代码)。
完整代码示例:
\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}
旧答案
以下代码将生成任意大小的卡诺图(针对某个 2 n进行测试),作为 TikZ 图片。使用环境输入卡诺图就像在 LaTeX 中输入表格一样kvmatrix
。此环境的唯一参数是逗号分隔的变量名称列表。因此,一个简单的 2x2 矩阵看起来像
\begin{kvmatrix}{a,b}
0 & 1\\
0 & 1
\end{kvmatrix}
还提供了第二个环境,kvmap
它基本上是一个 tikzpicture(但为了语义一致性)。如果您打算使用字段,则应使用它。每个字段都按以下方式通过其 x 和 y 索引命名:(xy
其中00
是左上角,nm
是右下角,n+1 和 m+1 是矩阵的尺寸,例如
11
2x2 矩阵)。
代码还能够在可以捆绑的单元格周围绘制边框。因此,您可以使用\package[options]{x1}{y1}{x2}{y2}
带有矩形角坐标的命令。如果包应该打开到边距,请使用选项invert
(如果坐标位于最外面的行/列;选项overlapmargins
指定将包绘制到边距的距离)。您可以使用选项为包着色,color
并使用指定减少空间以避免与其他包重叠reducespace
。
\begin{kvmap}
\begin{kvmatrix}{a,b}
0 & 1\\
0 & 1
\end{kvmatrix}
\package[color=red]{1}{0}{1}{1}
\end{kvmap}
这是工作代码:
\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}