这个问题是在 xparse 命令中使用数组环境。有人建议我为扩展单独提出一个问题。非常感谢 egreg 的帮助。我还有两个功能想要实现,我想知道我是否可以从社区获得更多帮助。
具体来说,我希望支持框约束和枚举约束。在 egreg 使用 LaTeX3 给出解决方案之前,我的约束命令是一个带有签名的宏mmmggo
。前三个参数表示标准约束;第四和第五个参数表示框约束中的附加信息;第六个参数表示枚举约束的枚举。我尝试让这些功能正常工作,如下所示(失败的部分已被注释掉)。
关于我做出某些选择的动机,有几点需要说明:我希望使约束在使用中可读,这就是为什么我更喜欢使用下面给出的约束命令来格式化约束;如果没有枚举任何约束,我希望防止打印用于设置枚举的\qquad
参数,以保持问题的水平居中。我认为框约束问题基本已解决(我总是可以在第三个参数中包含框约束的附加信息,如下所示)。但是,我真的很想能够
- 将枚举作为可选参数,并且
- 当没有使用枚举约束时,抑制
\qquad
用于设置枚举(以保留优化问题的水平居中)。
\documentclass{article}
\usepackage{amsmath}
\usepackage{array}
\usepackage{xparse}
\ExplSyntaxOn
% allocate the variables for an optimization problem
\tl_new:N \l_optprob_operator_tl
\tl_new:N \l_optprob_variable_tl
\tl_new:N \l_optprob_objective_tl
\tl_new:N \l_optprob_constraints_tl
% define the keys
\keys_define:nn{optprob}
{
operator .tl_set:N = \l_optprob_operator_tl,
variable .tl_set:N = \l_optprob_variable_tl,
objective .tl_set:N = \l_optprob_objective_tl,
constraint .code:n = \optprob_add_constraint:nnnnnn #1,
% constraint .code:n = \constraint{#1}
}
\NewDocumentCommand{\optimizationproblem}{m}
{
% clear the variables
\tl_clear:N \l_optprob_operator_tl
\tl_clear:N \l_optprob_variable_tl
\tl_clear:N \l_optprob_objective_tl
\tl_clear:N \l_optprob_constraints_tl
% get the keys
\keys_set:nn{optprob}{#1}
% print the optimization problem
\tl_if_empty:NTF \l_optprob_objective_tl
{
% feasibility problem
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}l}
\l_optprob_constraints_tl
\end{array}
}
{
% optimization problem
\begin{array}{c@{{}\mathrel{:}{}}l}
\displaystyle\operatorname*{\l_optprob_operator_tl}\sb{\l_optprob_variable_tl} &
\l_optprob_objective_tl \\[2ex]
\tl_if_empty:NF \l_optprob_constraints_tl
{
% constrained optimization problem
\textnormal{subject~to} &
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}l}
\l_optprob_constraints_tl
\end{array}
}
\end{array}
}
}
\NewDocumentCommand{\constraint}{mmmggo}
{
\IfValueTF{#4}
{
\IfValueTF{#6}
{
#1 & #2 & #3 #4 #5 & \qquad #6 \\
}
{
#1 & #2 & #3 #4 #5 \\
}
}
{
\IfValue{#6}
{
#1 & #2 & #3 & \qquad #6 \\
}
{
#1 & #2 & #3 \\
}
}
}
% helper function to process the constraints
\cs_new_protected:Npn \optprob_add_constraint:nnnnnn #1 #2 #3 #4
{
\tl_put_right:Nn \l_optprob_constraints_tl {#1 & #2 & #3 & \qquad #4 \\}
}
\ExplSyntaxOff
\begin{document}
\[
\optimizationproblem
{
operator = minimize,
variable = x \in \mathbf{R}^{n},
objective = c^{T} x,
constraint = {A_{i} x}{=}{b_{i}}{i = 1 , \ldots , m},
% constraint = {A_{i} x}{=}{b_{i}}[i = 1 , \ldots , m],
constraint = {F_{j} x}{\leq}{g_{j}}{j = 1 , \ldots , m},
% constraint = {F_{j} x}{\geq}{g_{j}}[j = 1 , \ldots , m],
constraint = {0}{\leq}{x \leq 1}{},
% constraint = {0}{\leq}{x}{\leq}{1},
}
\]
\end{document}
答案1
我的建议是添加两个新键;可以添加一些检查以确保它们遵循关联的constraint
键。
\documentclass{article}
\usepackage{amsmath}
\usepackage{array}
\usepackage{xparse}
\ExplSyntaxOn
% allocate the variables for an optimization problem
\tl_new:N \l_optprob_operator_tl
\tl_new:N \l_optprob_variable_tl
\tl_new:N \l_optprob_objective_tl
\tl_new:N \l_optprob_constraints_tl
% define the keys
\keys_define:nn{optprob}
{
operator .tl_set:N = \l_optprob_operator_tl,
variable .tl_set:N = \l_optprob_variable_tl,
objective .tl_set:N = \l_optprob_objective_tl,
constraint .code:n = \optprob_add_constraint:nnn #1,
cinfo .code:n = \optprob_add_info:n { #1 },
cnumber .code:n = \optprob_add_number:n { #1 },
}
\NewDocumentCommand{\optimizationproblem}{m}
{
% clear the variables
\tl_clear:N \l_optprob_operator_tl
\tl_clear:N \l_optprob_variable_tl
\tl_clear:N \l_optprob_objective_tl
\tl_clear:N \l_optprob_constraints_tl
% get the keys
\keys_set:nn{optprob}{#1}
% print the optimization problem
\tl_if_empty:NTF \l_optprob_objective_tl
{
% feasibility problem
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}l}
\l_optprob_constraints_tl
\end{array}
}
{
% optimization problem
\begin{array}{c@{{}\mathrel{:}{}}l}
\displaystyle\operatorname*{\l_optprob_operator_tl}\sb{\l_optprob_variable_tl} &
\l_optprob_objective_tl \\[2ex]
\tl_if_empty:NF \l_optprob_constraints_tl
{
% constrained optimization problem
\textnormal{subject~to} &
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}l}
\l_optprob_constraints_tl
\end{array}
}
\end{array}
}
}
% helper function to process the constraints
\cs_new_protected:Npn \optprob_add_constraint:nnn #1 #2 #3
{
\tl_if_empty:NF \l_optprob_constraints_tl
{ \tl_put_right:Nn \l_optprob_constraints_tl { \\ } }
\tl_put_right:Nn \l_optprob_constraints_tl { #1 & #2 & #3 }
}
\cs_new_protected:Npn \optprob_add_info:n #1
{
\tl_put_right:Nn \l_optprob_constraints_tl { \quad (#1) }
}
\cs_new_protected:Npn \optprob_add_number:n #1
{
\tl_put_right:Nn \l_optprob_constraints_tl { & \qquad #1 }
}
\ExplSyntaxOff
\begin{document}
\[
\optimizationproblem
{
operator = minimize,
variable = x \in \mathbf{R}^{n},
objective = c^{T} x,
constraint = {A_{i} x}{=}{b_{i}},
cinfo = {i = 1 , \ldots , m},
constraint = {F_{j} x}{\leq}{g_{j}},
cinfo = {j = 1 , \ldots , m},
}
\]
\[
\optimizationproblem
{
operator = minimize,
variable = x \in \mathbf{R}^{n},
objective = c^{T} x,
constraint = {A_{i} x}{=}{b_{i}},
cinfo = {i = 1 , \ldots , m},
cnumber = 1,
constraint = {F_{j} x}{\leq}{g_{j}},
cinfo = {j = 1 , \ldots , m},
cnumber = 2,
}
\]
\end{document}
cinfo
如果值包含逗号,请不要忘记值周围的括号。
答案2
@egreg 非常感谢您的帮助!我最终对您提供的答案做了一个小改动,我想将其作为我原始问题的最终答案发布。我还希望您能检查我的工作。在您的解决方案中,字段cinfo
没有完全对齐,所以我想在数组中创建一个单独的列来保存这些字段。但是,处理字段的函数cnumber
需要知道cinfo
字段是否已针对当前约束进行处理,以便将cnumber
字段放在正确的列中。我使用变量来实现这一点\l_optprob_cinfo_flag_tl
。如果我的解决方案的风格或逻辑有任何问题,请告诉我,再次感谢您帮助我按照我想要的方式设置这个宏。
\documentclass{article}
\usepackage{amsmath}
\usepackage{array}
\usepackage{xparse}
\ExplSyntaxOn
% allocate the variables for an optimization problem
\tl_new:N \l_optprob_operator_tl
\tl_new:N \l_optprob_variable_tl
\tl_new:N \l_optprob_objective_tl
\tl_new:N \l_optprob_constraints_tl
\tl_new:N \l_optprob_cinfo_flag_tl
% define the keys
\keys_define:nn{optprob}
{
operator .tl_set:N = \l_optprob_operator_tl,
variable .tl_set:N = \l_optprob_variable_tl,
objective .tl_set:N = \l_optprob_objective_tl,
constraint .code:n = \optprob_add_constraint:nnn #1,
cinfo .code:n = \optprob_add_info:n { #1 },
cnumber .code:n = \optprob_add_number:n { #1 },
}
\NewDocumentCommand{\optimizationproblem}{m}
{
% clear the variables
\tl_clear:N \l_optprob_operator_tl
\tl_clear:N \l_optprob_variable_tl
\tl_clear:N \l_optprob_objective_tl
\tl_clear:N \l_optprob_constraints_tl
\tl_clear:N \l_optprob_cinfo_flag_tl
% get the keys
\keys_set:nn{optprob}{#1}
% print the optimization problem
\tl_if_empty:NTF \l_optprob_objective_tl
{
% feasibility problem
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}l@{}l}
\l_optprob_constraints_tl
\end{array}
}
{
% optimization problem
\begin{array}{c@{{}\mathrel{:}{}}l}
\displaystyle\operatorname*{\l_optprob_operator_tl}\sb{\l_optprob_variable_tl} &
\l_optprob_objective_tl \\[2ex]
\tl_if_empty:NF \l_optprob_constraints_tl
{
% constrained optimization problem
\textnormal{subject~to} &
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}l@{}l}
\l_optprob_constraints_tl
\end{array}
}
\end{array}
}
}
% helper function to process the constraints
\cs_new_protected:Npn \optprob_add_constraint:nnn #1 #2 #3
{
\tl_if_empty:NF \l_optprob_constraints_tl
{ \tl_put_right:Nn \l_optprob_constraints_tl { \\ } }
\tl_put_right:Nn \l_optprob_constraints_tl { #1 & #2 & #3 }
\tl_clear:N \l_optprob_cinfo_flag_tl
}
\cs_new_protected:Npn \optprob_add_info:n #1
{
\tl_put_right:Nn \l_optprob_constraints_tl { & \quad (#1) }
\tl_put_right:Nn \l_optprob_cinfo_flag_tl {set flag}
}
\cs_new_protected:Npn \optprob_add_number:n #1
{
\tl_if_empty:NT \l_optprob_cinfo_flag_tl
{
\tl_put_right:Nn \l_optprob_constraints_tl { & }
}
\tl_put_right:Nn \l_optprob_constraints_tl { & \qquad #1 }
}
\ExplSyntaxOff
\begin{document}
\[
\optimizationproblem
{
operator = minimize,
variable = x \in \mathbf{R}^{n},
objective = c^{T} x,
constraint = {A_{i} x}{=}{b_{i}},
cinfo = {i = 1 , \ldots , m},
constraint = {F_{j} x}{\leq}{g_{j}},
cinfo = {j = 1 , \ldots , m},
}
\]
\[
\optimizationproblem
{
operator = minimize,
variable = x \in \mathbf{R}^{n},
objective = c^{T} x,
constraint = {A_{i} x}{=}{b_{i}},
cinfo = {i = 1 , \ldots , m},
cnumber = 1,
constraint = {F_{j} x}{\leq}{g_{j}},
cinfo = {j = 1 , \ldots , m},
cnumber = 2,
}
\]
\[
\optimizationproblem
{
operator = minimize,
variable = x \in \mathbf{R}^{n},
objective = c^{T} x,
constraint = {A_{i} x}{=}{b_{i}},
cinfo = {i = 1 , \ldots , m},
cnumber = 1,
constraint = {F x}{\leq}{g},
cnumber = 2,
}
\]
\end{document}