How to add partial horizontal lines in horizontally aligned math environments
The answer of egreg has the tiny drawback, that the values for \tleq
has to be found manually. This answer fills the gap.
Package amsmath
processes its equations twice. In the first run, the widths are measured.
The switch \ifmeasure@
is true during this measuring phase.
In the second run the equations are actually typeset. Depending on the measured widths of the first run amsmath
is now able to move the equation number if necessary, for example.
Also environment alignat*
stores the widths of the cells and calculates the maximal widths of the columns.
After the measuring phase the widths of the columns are available in macro \maxcolumn@width
. The values are prefixed with \or
for easy use with \ifcase
, e.g.:
\or 23.1945pt \or 25.221pt \or 10.00002pt \or 12.77773pt \or 54.77959pt \or 62.81717pt \or 74.90263pt \or 0.0pt \or 0.0pt
Count register \column@
holds the current column number.
The following example defines the macro \tline
that uses these data to draw a line with the width of the current column. In right aligned columns it is placed after the cell contents, in left aligned columns \tline
should start the cell.
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\newcommand*{\tline}{%
\ifmeasuring@
% first measuring run
\else
% second run
% \typeout{\meaning\maxcolumn@widths}% debug info
\ifodd\column@
\expandafter\rlap
\else
\expandafter\llap
\fi
{%
\vrule height-1ex depth \dimexpr1ex+.4pt\relax width
\ifcase\numexpr\column@+1\expandafter\relax
\maxcolumn@widths
\fi
}%
\fi
}
\makeatother
\begin{document}
\begin{alignat*}{4}
a^1 x^\star &\leq b_1 &\quad& \Rightarrow & \delta_1 a^1 x^\star &\leq
\delta_1 b_1 \\
a^2 x^\star &\leq b_2 && \Rightarrow & \delta_2 a^2 x^\star &\leq
\delta_2 b_2 \\[-4.5pt]
&\;\;\vdots && \;\;\vdots & &\;\;\vdots \\
a^m x^\star &\leq b_m && \Rightarrow & \delta_m a^m x^\star
\tline&\tline \leq\delta_m b_m \quad (+) \\
&&&& \sum_{1 \leq i \leq m} \delta_i a^i x^\star &\leq \delta_i b_i &
\quad\Rightarrow \delta^t A x^\star \leq \delta^t b
\end{alignat*}
\end{document}
Remark:
- The space above
\vdots
is a little large for my taste, macro\vdots
already adds6pt
at the top of the dots. Therefore I have reduced it a bit.
\cline
in alignat*
and better vertical centered dots
An easier solution is
\cline
, it also works in environmentalignat*
, only the space before needs some adjusting.\rvdots
of egreg's answer (see Qrrbrbirlbel's comment) cheats a little, it reduces the height by1pt
. The example below defines\mvdots
that uses\vcenter
instead of\vbox
that reduces the asymmetry by participating the descender.
Example file:
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\DeclareRobustCommand{\mvdots}{%
\vcenter{%
\baselineskip4\p@\lineskiplimit\z@
\hbox{.}\hbox{.}\hbox{.}%
}%
}
\makeatother
\begin{document}
\begin{alignat*}{4}
a^1 x^\star &\leq b_1 &\quad& \Rightarrow & \delta_1 a^1 x^\star &\leq
\delta_1 b_1 \\
a^2 x^\star &\leq b_2 && \Rightarrow & \delta_2 a^2 x^\star &\leq
\delta_2 b_2 \\
&\;\;\mvdots && \;\;\mvdots & &\;\;\mvdots \\
a^m x^\star &\leq b_m && \Rightarrow & \delta_m a^m x^\star
& \leq\delta_m b_m \quad (+) \\[-2ex]
\cline{5-6}
&&&&\sum_{1 \leq i \leq m} \delta_i a^i x^\star &\leq \delta_i b_i &
\quad\Rightarrow \delta^t A x^\star \leq \delta^t b
\end{alignat*}
\end{document}
If you don't mind doing some eye measurements, here's an alignat
based solution:
\documentclass{article}
\usepackage{amsmath}
\newcommand{\tleq}[2]{\mathrel{
\llap{\vrule height-1ex depth \dimexpr1ex+0.4pt\relax width #1}
\rlap{\vrule height-1ex depth \dimexpr1ex+0.4pt\relax width #2}
{\leq}}
}
\begin{document}
\begin{alignat*}{4}
a^1 x^\star &\leq b_1 &\quad& \Rightarrow & \delta_1 a^1 x^\star &\leq \delta_1 b_1 \\
a^2 x^\star &\leq b_2 && \Rightarrow & \delta_2 a^2 x^\star &\leq \delta_2 b_2 \\
&\;\;\vdots && \;\;\vdots & &\;\;\vdots \\
a^m x^\star &\leq b_m && \Rightarrow & \delta_m a^m x^\star
&\tleq{5.7em}{6.2em} \delta_m b_m \quad (+) \\
&&&& \sum_{1 \leq i \leq m} \delta_i a^i x^\star &\leq \delta_i b_i &
\quad\Rightarrow \delta^t A x^\star \leq \delta^t b
\end{alignat*}
\end{document}
I take as a point from which to draw the rule the relation symbol (left edge). This is called \tleq
and takes as arguments the left and the right lengths of the rule to draw.
The following uses an ordinary array
to obtain the desired output:
\documentclass{article}
\usepackage{array}% http://ctan.org/pkg/array
\begin{document}
\[
\renewcommand{\arraystretch}{1.2}
\begin{array}{r@{}>{{}}l@{}>{\quad}c<{\quad}@{}r@{}>{{}}l@{}>{\quad}c<{\quad}@{}l}
a^1 x^\star &\leq b_1 & \Rightarrow & \delta_1 a^1 x^\star &\leq \delta_1 b_1 \\
a^2 x^\star &\leq b_2 & \Rightarrow & \delta_2 a^2 x^\star &\leq \delta_2 b_2 \\
\vdots & & & \vdots \\
a^m x^\star &\leq b_m & \Rightarrow & \delta_m a^m x^\star &\leq \delta_m b_m \quad (+) \\
\cline{4-5}
&&& \displaystyle \sum_{1 \leq i \leq m} \delta_i a^i x^\star &\leq \delta_i b_i &
\Rightarrow & \delta^t A x^\star \leq \delta^t b
\end{array}
\]
\end{document}
The interface provided above is very similar to that of amsmath
's align
using a <LHS> &<rel> <RHS>
interface.
For more adjustments vertically, I would suggest using struts \rule{0pt}{<height>}
and play around with the value of <height>
. For example, inserting \rule{0pt}{1.2\normalbaselineskip}
inside the \sum
-line provides a decent padding:
You can find more information in Column and row padding in tables.