% mpformulation - Version 2.0 % % Formerly the constraints package (versions 1.0 to 1.12) % % Copyright (c) 2025-2026 FYP % Report bugs and comments to mpformulation.sty@gmail.com % % This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) any later version. % The latest version of this license is in http://www.latex-project.org/lppl.txt and version 1.3 or later is part of all distributions of LaTeX version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % The Current Maintainer of this work is FYP. % This work consists of the files mpformulation.sty, mpformulation-doc.tex, % mpformulation-doc.pdf, the mpformulation_example*.tex files and README.md. \NeedsTeXFormat{LaTeX2e}[2021/06/01] \ProvidesPackage{mpformulation}[2026/09/28 v2.0 Formulations of mathematical programs] \RequirePackage{keyval} \RequirePackage{amsmath} \makeatletter \newlength{\constraintSep} \setlength{\constraintSep}{0.5\baselineskip} \newlength{\constraintEqspace} \if@twocolumn \setlength{\constraintEqspace}{1em} \else \setlength{\constraintEqspace}{2em} \fi \newlength{\constraintLeftmargin} \setlength{\constraintLeftmargin}{6em} \newlength{\constraintTopsep} \setlength{\constraintTopsep}{0pt} \newlength{\constraintBottomsep} \setlength{\constraintBottomsep}{0pt} % Punctuation: after the expression, at the end of each constraint (after % the quantifier), and at the end of the last constraint \newcommand{\constraintExprSuffix}{} \newcommand{\constraintQuantSuffix}{} \newcommand{\constraintLastSuffix}{.} \newif\ifLastConstraint\LastConstraintfalse % Minimum horizontal gap between expression and quantifier used to decide % whether the quantifier fits on one line \newlength{\constraintQuantGap} \setlength{\constraintQuantGap}{1em} \let\constraintRHSgap\constraintQuantGap % Largest automatic column of left-aligned quantifiers (quant_align=left), % evaluated when used \newcommand{\constraintQuantColMax}{0.6\linewidth} % Smallest indent allowed when a line is too wide for the full indent \newlength{\constraintMinIndent} \setlength{\constraintMinIndent}{0pt} % Extra indent of expression continuation lines (after a \\ in the expression) \newlength{\constraintExprContIndent} \setlength{\constraintExprContIndent}{2em} \let\constraintLHScontIndent\constraintExprContIndent % Quantifier break mode: % auto : \\ in the quantifier is an optional break; a quantifier without \\ that does % not fit is broken automatically at its top-level commas % manual : \\ is an optional break; no automatic break % always : every \\ is honored; no automatic break \def\@constraint@breakmode{auto} % Expression break mode: % auto : \\ in the expression is an optional break, used only when the expression does % not fit on one line % always : every \\ in the expression is honored \def\@constraint@lhsbreakmode{auto} % Layout of a constraint, tried in order until one fits: % (a) one line; the indent may shrink down to min_indent % (b) expression on one line, quantifier broken (at its \\ or at its commas) % (c) expression alone on a line, quantifier right-aligned on the line(s) below % (d) expression broken at its \\, quantifier on the last expression line or below % The equation number is always on the last line. \ExplSyntaxOn \seq_new:N \l__mpformulation_pieces_seq \seq_new:N \l__mpformulation_items_seq \seq_new:N \l__mpformulation_lines_seq \seq_new:N \l__mpformulation_lhs_seq \seq_new:N \l__mpformulation_rhs_seq \tl_new:N \l__mpformulation_item_tl \tl_new:N \l__mpformulation_line_tl \tl_new:N \l__mpformulation_cand_tl \tl_new:N \l__mpformulation_lhs_tl \tl_new:N \l__mpformulation_rhs_tl \tl_new:N \l__mpformulation_last_tl \tl_new:N \l__mpformulation_rows_tl \tl_new:N \l__mpformulation_suffix_tl \int_new:N \l__mpformulation_depth_int \int_new:N \l__mpformulation_index_int \bool_new:N \l__mpformulation_open_bool \bool_new:N \l__mpformulation_done_bool \bool_new:N \l__mpformulation_force_rhs_bool \bool_new:N \l__mpformulation_force_lhs_bool \box_new:N \l__mpformulation_tmp_box \box_new:N \l__mpformulation_num_box \box_new:N \l__mpformulation_left_box \box_new:N \l__mpformulation_right_box \dim_new:N \l__mpformulation_width_dim \dim_new:N \l__mpformulation_lhs_dim \dim_new:N \l__mpformulation_rhs_dim \dim_new:N \l__mpformulation_lines_dim \dim_new:N \l__mpformulation_num_dim \dim_new:N \l__mpformulation_avail_dim \dim_new:N \l__mpformulation_indent_dim \dim_new:N \l__mpformulation_need_dim \dim_new:N \l__mpformulation_head_dim \dim_new:N \l__mpformulation_relw_dim \dim_new:N \l__mpformulation_col_dim \dim_new:N \g__mpformulation_relw_dim \box_new:N \l__mpformulation_head_box \seq_new:N \l__mpformulation_obj_seq \seq_new:N \l__mpformulation_tmp_seq \tl_new:N \l__mpformulation_lhsraw_tl \tl_new:N \l__mpformulation_lhssuffix_tl \tl_new:N \l__mpformulation_relleft_tl \tl_new:N \l__mpformulation_relright_tl \tl_new:N \l__mpformulation_numbering_tl \tl_new:N \l__mpformulation_modellabel_tl \tl_new:N \l__mpformulation_namelabel_tl \int_new:N \g__mpformulation_env_int \int_new:N \l__mpformulation_env_int \bool_new:N \l__mpformulation_aligned_bool \bool_new:N \l__mpformulation_relfound_bool \bool_new:N \l__mpformulation_relalign_bool \bool_new:N \g__mpformulation_stinline_bool \bool_new:N \g__mpformulation_stinline_pending_bool \bool_new:N \g__mpformulation_modelnum_pending_bool \bool_new:N \g__mpformulation_keeplast_bool \cs_generate_variant:Nn \seq_set_split:Nnn { NnV } % Measuring pass of an environment: the body is typeset once in a discarded % box, without numbers, labels or global flags, to find the common column of % left-aligned quantifiers and the relation-alignment width \bool_new:N \l__mpformulation_measure_bool \cs_new_protected:Npn \__mpformulation_body_end: { \prg_do_nothing: } \tl_new:N \l__mpformulation_quantalign_tl \tl_new:N \l__mpformulation_quantcol_tl \dim_new:N \l__mpformulation_qcol_dim \dim_new:N \g__mpformulation_qcol_dim \dim_new:N \l__mpformulation_lastind_dim \dim_new:N \l__mpformulation_qcolcur_dim \dim_new:N \l__mpformulation_qpos_dim \bool_new:N \l__mpformulation_samerow_bool \tl_new:N \l__mpformulation_quantoverflow_tl \dim_new:N \l__mpformulation_lastend_dim \box_new:N \l__mpformulation_lastexpr_box \cs_new_protected:Npn \constraints@setqcol #1#2 { \cs_gset:cpn { constraints@qcol@ #1 } {#2} } % Equation number of a line or of the objective: per labelled line % (numbering=line or sub), or once for the whole model (numbering=model) \cs_new_protected:Npn \__mpformulation_number:n #1 { \bool_if:NTF \l__mpformulation_measure_bool { \hbox_set:Nn \l__mpformulation_num_box { } } { \__mpformulation_number_real:n {#1} } \dim_set:Nn \l__mpformulation_num_dim { \box_wd:N \l__mpformulation_num_box } } \cs_new_protected:Npn \__mpformulation_number_real:n #1 { \str_if_eq:VnTF \l__mpformulation_numbering_tl { model } { \bool_if:NTF \g__mpformulation_modelnum_pending_bool { \hbox_set:Nn \l__mpformulation_num_box { \hspace { \constraintEqspace } ( \theequation ) } \bool_gset_false:N \g__mpformulation_modelnum_pending_bool } { \hbox_set:Nn \l__mpformulation_num_box { } } } { \tl_if_blank:nTF {#1} { \hbox_set:Nn \l__mpformulation_num_box { } } { \refstepcounter { equation } \hbox_set:Nn \l__mpformulation_num_box { \hspace { \constraintEqspace } ( \theequation ) } } } \dim_set:Nn \l__mpformulation_num_dim { \box_wd:N \l__mpformulation_num_box } } % Relation alignment: split an expression at its first top-level relation symbol, % or at & if given. Sets \l__mpformulation_relleft_tl, \l__mpformulation_relright_tl % and \l__mpformulation_relfound_bool. \cs_new_protected:Npn \__mpformulation_rel_add:Nn #1#2 { \tl_if_single_token:nTF {#2} { \tl_put_right:Nn #1 {#2} } { \tl_put_right:Nn #1 { {#2} } } } \cs_new_protected:Npn \__mpformulation_rel_split:n #1 { \tl_clear:N \l__mpformulation_relleft_tl \tl_clear:N \l__mpformulation_relright_tl \bool_set_false:N \l__mpformulation_relfound_bool \tl_if_in:nnTF {#1} { & } { \seq_set_split:Nnn \l__mpformulation_tmp_seq { & } {#1} \seq_pop_left:NN \l__mpformulation_tmp_seq \l__mpformulation_relleft_tl \tl_set:Nx \l__mpformulation_relright_tl { \seq_use:Nn \l__mpformulation_tmp_seq { } } \bool_set_true:N \l__mpformulation_relfound_bool } { \tl_map_inline:nn {#1} { \bool_if:NTF \l__mpformulation_relfound_bool { \__mpformulation_rel_add:Nn \l__mpformulation_relright_tl {##1} } { \str_case:nnTF {##1} { { = } { } { < } { } { > } { } { \le } { } { \leq } { } { \leqslant } { } { \ge } { } { \geq } { } { \geqslant } { } { \ne } { } { \neq } { } { \in } { } { \notin } { } { \subset } { } { \subseteq } { } { \equiv } { } { \approx } { } { \sim } { } } { \bool_set_true:N \l__mpformulation_relfound_bool \tl_put_right:Nn \l__mpformulation_relright_tl {##1} } { \__mpformulation_rel_add:Nn \l__mpformulation_relleft_tl {##1} } } } } } \cs_generate_variant:Nn \__mpformulation_rel_split:n { V } \cs_new_protected:Npn \constraints@setrelw #1#2 { \cs_gset:cpn { constraints@relw@ #1 } {#2} } % With st_inline, the expression column is moved right if needed so that % "subject to" fits before the first constraint \cs_new_protected:Npn \__mpformulation_st_column: { \bool_if:NT \g__mpformulation_stinline_bool { \hbox_set:Nn \l__mpformulation_tmp_box { \textrm { \constraintSubjecttoText } } \dim_set:Nn \l__mpformulation_col_dim { \constraintSubjecttoIndent + \box_wd:N \l__mpformulation_tmp_box + \constraintSenseSep } \dim_compare:nNnT \l__mpformulation_col_dim > \constraintLeftmargin { \skip_set:Nn \constraintLeftmargin { \l__mpformulation_col_dim } } } } \prg_generate_conditional_variant:Nnn \tl_if_head_eq_meaning:nN { V } { p } % Width of text-style / display-style math \cs_new_protected:Npn \__mpformulation_wd:n #1 { \hbox_set:Nn \l__mpformulation_tmp_box { $ #1 $ } \dim_set:Nn \l__mpformulation_width_dim { \box_wd:N \l__mpformulation_tmp_box } } \cs_new_protected:Npn \__mpformulation_wd_display:n #1 { \hbox_set:Nn \l__mpformulation_tmp_box { $ \displaystyle #1 $ } \dim_set:Nn \l__mpformulation_width_dim { \box_wd:N \l__mpformulation_tmp_box } } \cs_generate_variant:Nn \__mpformulation_wd:n { V } \cs_generate_variant:Nn \__mpformulation_wd_display:n { V } % Indent for a line whose content (without indent) is #1 wide: % the full indent if possible, otherwise as much as fits, but >= min_indent \cs_new_protected:Npn \__mpformulation_set_indent:n #1 { \dim_set:Nn \l__mpformulation_indent_dim { \dim_max:nn { \constraintMinIndent } { \dim_min:nn { \constraintLeftmargin } { \linewidth - (#1) } } } } % Net number of opening delimiters in a piece (brace groups are skipped) \cs_new_protected:Npn \__mpformulation_depth_add:n #1 { \tl_map_inline:nn {#1} { \str_case:nn {##1} { { ( } { \int_incr:N \l__mpformulation_depth_int } { [ } { \int_incr:N \l__mpformulation_depth_int } { \{ } { \int_incr:N \l__mpformulation_depth_int } { \langle } { \int_incr:N \l__mpformulation_depth_int } { ) } { \int_decr:N \l__mpformulation_depth_int } { ] } { \int_decr:N \l__mpformulation_depth_int } { \} } { \int_decr:N \l__mpformulation_depth_int } { \rangle } { \int_decr:N \l__mpformulation_depth_int } } } } % Remove leading spaces and spacing commands from a line start \cs_new_protected:Npn \__mpformulation_strip_head:N #1 { \tl_trim_spaces:N #1 \bool_lazy_any:nT { { \tl_if_head_eq_meaning_p:VN #1 \, } { \tl_if_head_eq_meaning_p:VN #1 \; } { \tl_if_head_eq_meaning_p:VN #1 \: } { \tl_if_head_eq_meaning_p:VN #1 \ } { \tl_if_head_eq_meaning_p:VN #1 \quad } { \tl_if_head_eq_meaning_p:VN #1 \qquad } } { \tl_set:Nx #1 { \tl_tail:N #1 } \__mpformulation_strip_head:N #1 } } % Automatic quantifier lines: split #1 at top-level commas and fill lines of % width <= #3 greedily; #2 ends the last line. % Result in \l__mpformulation_lines_seq. \cs_new_protected:Npn \__mpformulation_auto_lines:nnn #1#2#3 { % Split at commas, then merge pieces while delimiters are open \seq_set_split_keep_spaces:Nnn \l__mpformulation_pieces_seq { , } {#1} \seq_clear:N \l__mpformulation_items_seq \int_zero:N \l__mpformulation_depth_int \bool_set_false:N \l__mpformulation_open_bool \seq_map_inline:Nn \l__mpformulation_pieces_seq { \bool_if:NTF \l__mpformulation_open_bool { \tl_put_right:Nn \l__mpformulation_item_tl { , ##1 } } { \tl_set:Nn \l__mpformulation_item_tl {##1} } \__mpformulation_depth_add:n {##1} \int_compare:nNnTF \l__mpformulation_depth_int > 0 { \bool_set_true:N \l__mpformulation_open_bool } { \bool_set_false:N \l__mpformulation_open_bool \seq_put_right:NV \l__mpformulation_items_seq \l__mpformulation_item_tl } } \bool_if:NT \l__mpformulation_open_bool { \seq_put_right:NV \l__mpformulation_items_seq \l__mpformulation_item_tl } % Fill lines greedily \seq_clear:N \l__mpformulation_lines_seq \seq_pop_left:NN \l__mpformulation_items_seq \l__mpformulation_line_tl \seq_map_inline:Nn \l__mpformulation_items_seq { \tl_set_eq:NN \l__mpformulation_cand_tl \l__mpformulation_line_tl \tl_put_right:Nn \l__mpformulation_cand_tl { , ##1 } \__mpformulation_wd:n { \l__mpformulation_cand_tl #2 } \dim_compare:nNnTF \l__mpformulation_width_dim > {#3} { \tl_put_right:Nn \l__mpformulation_line_tl { , } \seq_put_right:NV \l__mpformulation_lines_seq \l__mpformulation_line_tl \tl_set:Nn \l__mpformulation_line_tl {##1} \__mpformulation_strip_head:N \l__mpformulation_line_tl } { \tl_set_eq:NN \l__mpformulation_line_tl \l__mpformulation_cand_tl } } \tl_put_right:Nn \l__mpformulation_line_tl {#2} \seq_put_right:NV \l__mpformulation_lines_seq \l__mpformulation_line_tl } % Quantifier lines for a target width #2 ( #1): the user's \\ if any, % otherwise automatic (mode auto) or one line. Sets \l__mpformulation_lines_seq % and \l__mpformulation_lines_dim (widest line). \cs_new_protected:Npn \__mpformulation_rhs_lines:nn #1#2 { \int_compare:nNnTF { \seq_count:N \l__mpformulation_rhs_seq } > 1 { \seq_set_eq:NN \l__mpformulation_lines_seq \l__mpformulation_rhs_seq } { \str_if_eq:eeTF { \@constraint@breakmode } { auto } { \__mpformulation_auto_lines:nVn {#1} \l__mpformulation_suffix_tl {#2} } { \seq_clear:N \l__mpformulation_lines_seq \seq_put_right:NV \l__mpformulation_lines_seq \l__mpformulation_rhs_tl } } \dim_zero:N \l__mpformulation_lines_dim \seq_map_inline:Nn \l__mpformulation_lines_seq { \__mpformulation_wd:n {##1} \dim_set:Nn \l__mpformulation_lines_dim { \dim_max:nn \l__mpformulation_lines_dim \l__mpformulation_width_dim } } } \cs_generate_variant:Nn \__mpformulation_auto_lines:nnn { nV } % Right box from \l__mpformulation_lines_seq, number on the last line \cs_new_protected:Npn \__mpformulation_right_from_lines: { \int_compare:nNnTF { \seq_count:N \l__mpformulation_lines_seq } = 1 { \hbox_set:Nn \l__mpformulation_right_box { $ \seq_item:Nn \l__mpformulation_lines_seq { 1 } $ \box_use:N \l__mpformulation_num_box } } { \tl_clear:N \l__mpformulation_rows_tl \int_zero:N \l__mpformulation_index_int \seq_map_inline:Nn \l__mpformulation_lines_seq { \int_incr:N \l__mpformulation_index_int \int_compare:nNnTF \l__mpformulation_index_int = { \seq_count:N \l__mpformulation_lines_seq } { \tl_put_right:Nn \l__mpformulation_rows_tl { ##1 & \mbox { \box_use:N \l__mpformulation_num_box } } } { \tl_put_right:Nn \l__mpformulation_rows_tl { ##1 & \\ } } } \hbox_set:Nn \l__mpformulation_right_box { $ \begin{array}[t]{@{}r@{}l@{}} \l__mpformulation_rows_tl \end{array} $ } } } % Output one line: indent #1, content of the left and right boxes \cs_new_protected:Npn \__mpformulation_row:n #1 { \par \noindent \bool_lazy_and:nnT { \g__mpformulation_stinline_pending_bool } { ! \l__mpformulation_measure_bool } { \rlap { \hspace* { \constraintSubjecttoIndent } \textrm { \constraintSubjecttoText } } \bool_gset_false:N \g__mpformulation_stinline_pending_bool } \hspace* { \dim_eval:n {#1} } \box_use:N \l__mpformulation_left_box \hspace* { \fill } \box_use:N \l__mpformulation_right_box \par } \cs_new_protected:Npn \__mpformulation_row_break: { \nobreak \skip_zero:N \parskip } % Quantifier right-aligned on the line(s) below the expression \cs_new_protected:Npn \__mpformulation_rhs_below:n #1 { \dim_set:Nn \l__mpformulation_avail_dim { \linewidth - \l__mpformulation_num_dim - \constraintLeftmargin } \bool_if:nTF { \l__mpformulation_force_rhs_bool || \dim_compare_p:nNn \l__mpformulation_rhs_dim > \l__mpformulation_avail_dim } { \__mpformulation_rhs_lines:nn {#1} { \l__mpformulation_avail_dim } } { \seq_clear:N \l__mpformulation_lines_seq \seq_put_right:NV \l__mpformulation_lines_seq \l__mpformulation_rhs_tl } \__mpformulation_row_break: \hbox_set:Nn \l__mpformulation_left_box { } \__mpformulation_right_from_lines: \__mpformulation_row:n { 0pt } } % Left-aligned quantifiers (quant_align=left): the quantifiers of an % environment start at a common column (after the widest expression, from % the previous run, at most quant_col_max, or quant_col if given) and wrap % at their \\ or commas, left-aligned. An expression that reaches the column % has its quantifier on the next line, at the column. \cs_new_protected:Npn \__mpformulation_line_left:n #1 { % Expression: one line, or broken at its \\ if too wide \bool_if:nTF { \int_compare_p:nNn { \seq_count:N \l__mpformulation_lhs_seq } > 1 && ( \l__mpformulation_force_lhs_bool || \dim_compare_p:nNn { \constraintMinIndent + \l__mpformulation_lhs_dim } > \linewidth ) } { \dim_zero:N \l__mpformulation_need_dim \int_zero:N \l__mpformulation_index_int \seq_map_inline:Nn \l__mpformulation_lhs_seq { \int_incr:N \l__mpformulation_index_int \__mpformulation_wd_display:n {##1} \int_compare:nNnF \l__mpformulation_index_int = 1 { \dim_add:Nn \l__mpformulation_width_dim { \constraintExprContIndent } } \dim_set:Nn \l__mpformulation_need_dim { \dim_max:nn \l__mpformulation_need_dim \l__mpformulation_width_dim } } \__mpformulation_set_indent:n { \l__mpformulation_need_dim } \seq_pop_right:NN \l__mpformulation_lhs_seq \l__mpformulation_last_tl \hbox_set:Nn \l__mpformulation_right_box { } \int_zero:N \l__mpformulation_index_int \seq_map_inline:Nn \l__mpformulation_lhs_seq { \int_incr:N \l__mpformulation_index_int \int_compare:nNnF \l__mpformulation_index_int = 1 { \__mpformulation_row_break: } \hbox_set:Nn \l__mpformulation_left_box { $ \displaystyle ##1 $ } \__mpformulation_row:n { \l__mpformulation_indent_dim + \int_compare:nNnTF \l__mpformulation_index_int = 1 { 0pt } { \constraintExprContIndent } } } \__mpformulation_row_break: \hbox_set:Nn \l__mpformulation_lastexpr_box { $ \displaystyle \l__mpformulation_last_tl $ } \dim_set:Nn \l__mpformulation_lastind_dim { \l__mpformulation_indent_dim + \constraintExprContIndent } } { \__mpformulation_set_indent:n { \l__mpformulation_lhs_dim } \box_set_eq:NN \l__mpformulation_lastexpr_box \l__mpformulation_left_box \dim_set_eq:NN \l__mpformulation_lastind_dim \l__mpformulation_indent_dim } \dim_set:Nn \l__mpformulation_lastend_dim { \l__mpformulation_lastind_dim + \box_wd:N \l__mpformulation_lastexpr_box } % Column of this constraint; record the environment column \dim_gset:Nn \g__mpformulation_qcol_dim { \dim_max:nn \g__mpformulation_qcol_dim { \dim_min:nn { \l__mpformulation_lastend_dim + \constraintQuantGap } { \constraintQuantColMax } } } \tl_if_blank:VTF \l__mpformulation_quantcol_tl { \dim_compare:nNnTF \l__mpformulation_qcol_dim > \c_zero_dim { \dim_set_eq:NN \l__mpformulation_qcolcur_dim \l__mpformulation_qcol_dim } { \dim_set:Nn \l__mpformulation_qcolcur_dim { \l__mpformulation_lastend_dim + \constraintQuantGap } } } { \dim_set:Nn \l__mpformulation_qcolcur_dim { \l__mpformulation_quantcol_tl } } % Quantifier position: at the column, on the expression line if the % expression ends before it, otherwise on the next line \dim_set_eq:NN \l__mpformulation_qpos_dim \l__mpformulation_qcolcur_dim \bool_set:Nn \l__mpformulation_samerow_bool { ! \dim_compare_p:nNn { \l__mpformulation_lastend_dim + \constraintQuantGap } > { \l__mpformulation_qcolcur_dim + 1sp } } \dim_set:Nn \l__mpformulation_avail_dim { \linewidth - \l__mpformulation_qpos_dim - \l__mpformulation_num_dim } % A quantifier too wide for the room after the column: with % quant_overflow=below it goes unbroken on the next line, starting under % the expression (indented by expr_cont_indent); it is wrapped only if it % does not fit there either. With quant_overflow=wrap it is wrapped at % the column. \bool_lazy_all:nT { { \str_if_eq_p:Vn \l__mpformulation_quantoverflow_tl { below } } { ! \l__mpformulation_force_rhs_bool } { \dim_compare_p:nNn \l__mpformulation_rhs_dim > \l__mpformulation_avail_dim } } { \bool_set_false:N \l__mpformulation_samerow_bool \dim_set:Nn \l__mpformulation_qpos_dim { \l__mpformulation_indent_dim + \constraintExprContIndent } \dim_set:Nn \l__mpformulation_avail_dim { \linewidth - \l__mpformulation_qpos_dim - \l__mpformulation_num_dim } } \bool_if:nTF { ! \l__mpformulation_force_rhs_bool && ! \dim_compare_p:nNn \l__mpformulation_rhs_dim > \l__mpformulation_avail_dim } { \seq_clear:N \l__mpformulation_lines_seq \seq_put_right:NV \l__mpformulation_lines_seq \l__mpformulation_rhs_tl } { \__mpformulation_rhs_lines:nn {#1} { \l__mpformulation_avail_dim } } \seq_pop_left:NN \l__mpformulation_lines_seq \l__mpformulation_line_tl \bool_if:NTF \l__mpformulation_samerow_bool { \hbox_set:Nn \l__mpformulation_left_box { \box_use:N \l__mpformulation_lastexpr_box \skip_horizontal:n { \l__mpformulation_qpos_dim - \l__mpformulation_lastend_dim } $ \l__mpformulation_line_tl $ } } { % Expression alone, quantifier on the next line \box_set_eq:NN \l__mpformulation_left_box \l__mpformulation_lastexpr_box \hbox_set:Nn \l__mpformulation_right_box { } \__mpformulation_row:n { \l__mpformulation_lastind_dim } \__mpformulation_row_break: \hbox_set:Nn \l__mpformulation_left_box { $ \l__mpformulation_line_tl $ } \dim_set_eq:NN \l__mpformulation_lastind_dim \l__mpformulation_qpos_dim } \seq_if_empty:NTF \l__mpformulation_lines_seq { \hbox_set:Nn \l__mpformulation_right_box { \box_use:N \l__mpformulation_num_box } } { \hbox_set:Nn \l__mpformulation_right_box { } } \__mpformulation_row:n { \l__mpformulation_lastind_dim } % Remaining quantifier lines, number on the last one \int_zero:N \l__mpformulation_index_int \seq_map_inline:Nn \l__mpformulation_lines_seq { \int_incr:N \l__mpformulation_index_int \__mpformulation_row_break: \hbox_set:Nn \l__mpformulation_left_box { $ ##1 $ } \int_compare:nNnTF \l__mpformulation_index_int = { \seq_count:N \l__mpformulation_lines_seq } { \hbox_set:Nn \l__mpformulation_right_box { \box_use:N \l__mpformulation_num_box } } { \hbox_set:Nn \l__mpformulation_right_box { } } \__mpformulation_row:n { \l__mpformulation_qpos_dim } } } % \@constraint@line{