我想定义一个用于优化问题的宏。下面给出了我的尝试。我想知道为什么\optimizationproblema
可以工作,但\optimizationproblemb
不能(当我尝试使用后者时,我收到“错位对齐标签”错误)。显然我的约束不被视为属于数组\optimizationproblemb
?如果有更好的方法来解决定义宏的问题,那也很好。我想保持用法大致相同(即,
\optimizationproblem{minimize}{x}{f(x)}{g(x) <= 0}
应该表示最小化 f(x) 在 x 上的服从 g(x) <= 0;我还需要某种方法来抑制无约束问题的“服从”部分[我\IfValueTF
在实际代码中使用了一个测试]),但我并不真正关心实现。
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\NewDocumentCommand{\optimizationproblema}{mmmm}
{
\begin{array}{c@{\ }c@{\ }l}
\displaystyle\operatorname*{#1}_{#2} & :
& #3 \\
\mathrm{subject \ to} & : &
\begin{array}[t]{@{}r@{\ }c@{\ }l@{\qquad}l}
#4
\end{array}
\end{array}
}
\NewDocumentCommand{\optimizationproblemb}{momo}
{
\begin{array}{c@{\ }c@{\ }l}
\displaystyle\operatorname*{#1}_{#2} & :
& #3 \\
\mathrm{subject \ to} & : &
\begin{array}[t]{@{}r@{\ }c@{\ }l@{\qquad}l}
#4
\end{array}
\end{array}
}
\NewDocumentCommand{\constraint}{mmm}
{
#1 & #2 & #3 \\
}
\begin{document}
\[
\optimizationproblema
{
minimize
}
{
x \in \mathbf{R}^{n}
}
{
c^{T} x
}
{
\constraint{A x}{=}{b}
\constraint{x}{\geq}{0}
}
\]
%\[
% \optimizationproblemb
% {
% minimize
% }
% [
% x \in \mathbf{R}^{n}
% ]
% {
% c^{T} x
% }
% [
% \constraint{A x}{=}{b}
% \constraint{x}{\geq}{0}
% ]
%\]
\end{document}
非常感谢@egreg 的帮助。我还有两个功能想要实现,我想知道我是否可以从社区获得更多帮助。特别是,我想支持框约束和枚举约束。在 egreg 使用 LaTeX3 给出解决方案之前,我的约束命令是一个带有签名 mmmggo 的宏。前三个参数表示标准约束;第四和第五个参数表示框约束中的附加信息;第六个参数表示枚举约束的枚举。我尝试让这些功能正常工作,如下所示(失败的部分已被注释掉)。关于我做出某些选择的动机,有几点说明:我想让约束在使用中可读,这就是为什么我更喜欢使用下面给出的约束命令格式化约束的原因;如果没有枚举任何约束,我想阻止打印用于设置枚举的 \qquad,以保持问题的水平居中。我认为框约束问题基本已解决(我总是可以在第三个参数中包含框约束的附加信息,如下所示)。但是,我非常希望能够 (1) 将枚举作为可选参数,(2) 在不使用枚举约束时抑制用于设置枚举的 \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
可选参数的实现xparse
不希望在最后一个参数之前有空格,以避免在调用后跟要打印的括号时出现问题。
所以如果你打电话
\[
\optimizationproblemb
{minimize}
[x \in \mathbf{R}^{n}]
{c^{T} x}% <-------------- Don't forget this!!!
[\constraint{A x}{=}{b}
\constraint{x}{\geq}{0}]
\]
你不会遇到任何问题。但是我不明白为什么约束应该是可选的。
在这种情况下,我建议使用键值语法:
\documentclass{article}
\usepackage{amsmath}
\usepackage{array}
\usepackage{xparse}
\ExplSyntaxOn
% Allocate some variables
\tl_new:N \l_stirling_operator_tl
\tl_new:N \l_stirling_domain_tl
\tl_new:N \l_stirling_function_tl
\tl_new:N \l_stirling_constraints_tl
\tl_new:N \l_stirling_sidecondition_tl
% Define the keys
\keys_define:nn { stirlingopt }
{
operator .tl_set:N = \l_stirling_operator_tl,
domain .tl_set:N = \l_stirling_domain_tl,
function .tl_set:N = \l_stirling_function_tl,
constraint .code:n = \stirling_add_constraint:nnn #1,
}
\NewDocumentCommand{\optimizationproblem}{m}
{
% Clear the variables
\tl_clear:N \l_stirling_operator_tl
\tl_clear:N \l_stirling_domain_tl
\tl_clear:N \l_stirling_function_tl
\tl_clear:N \l_stirling_constraints_tl
% Set the keys from the argument
\keys_set:nn { stirlingopt } { #1 }
% Print
\begin{array}{c@{{}\mathrel{:}{}}l}
\displaystyle
\operatorname*{\l_stirling_operator_tl}\sb{\l_stirling_domain_tl} &
\l_stirling_function_tl
\tl_if_empty:NF \l_stirling_constraints_tl
{ % this will be executed only if constraints are specified
\\[2ex]
\textnormal{subject~to} &
\begin{array}[t]{@{}r@{}>{{}}c<{{}}@{}l@{}}
\l_stirling_constraints_tl
\end{array}
}
\end{array}
}
% A helper macro for the constraints
\cs_new_protected:Npn \stirling_add_constraint:nnn #1 #2 #3
{
\tl_put_right:Nn \l_stirling_constraints_tl { #1 & #2 & #3 \\ }
}
\ExplSyntaxOff
\begin{document}
\[
\optimizationproblem{
operator=minimize,
domain=x\in\mathbf{R}^{n},
function=c^{T}x,
constraint={Ax}{=}{b},
constraint={x}{\geq}{0},
}
\]
\end{document}
请注意,键的顺序无关紧要;当然约束将按照它们表达的顺序添加。
一个人可以没有任何限制,例如
\[
\optimizationproblem{
operator=minimize,
domain=x\in\mathbf{R}^{n},
function=c^{T}x,
}
\]
结果是
我对数组的排版方式做了一些更改,以获得更好的间距。