\section{SOS Constraints}
  
  An special ordered set (SOS) is a set of variables with a defined
  order. There are two common kinds of SOS, namely, special ordered
  sets of the first kind (SOS1) and special ordered sets of the second
  kind (SOS2). SOS1 require that no more than one variable in the set
  be nonzero. SOS2 require that no more than two variables in the set
  be nonzero, and that two nonzero variables must be adjacent in the
  ordering. In general, one can consider SOS$k$, where no more than
  $k$ variables in the set may be nonzero, and all nonzero variables
  must be within $k-1$ of each other in the ordering. SOS1 are often
  used to represent multiple-choice style constraints using binary or
  integer variables. SOS2 are often used to model non-convex
  piecewise-linear constraints.

  An \code{SOSConstraint} is a Pyomo \code{Constraint} object that
  enforces SOS-style constraints on a group of variables. However,
  these constraints are not algebraic; rather, \code{SOSConstraint}
  objects simply indicate to an SOS-aware solver that a certain group
  of variables should be treated as an SOS1, SOS2, or SOS$k$. Thus,
  \code{SOSConstraint} objects should only be used when using a solver
  that understands SOS constraints, such as CPLEX.\footnote{Future
  versions of Pyomo may include transformations to model SOS
  constraints algebraically, allowing all solvers to handle
  \code{SOSConstraint} objects.}

  \subsection{SOSConstraint Declarations}

    Unlike other Pyomo components, \code{SOSConstraint} requires at
    least two keyword arguments: \code{var}, indicating the \code{Var}
    objects to be used in the SOS, and either \code{level} or
    \code{sos}, indicating what class of SOS the constraint represents.
    \lstinputlisting{examples/sos-constraint/ex1.py}

    A subset of the \code{Var} elements provided can be selected to be
    used. This is done via the \code{set} keyword argument, which
    expects a \code{Set} object whose indices are the indices of the
    \code{Var} elements to use.
    \lstinputlisting{examples/sos-constraint/ex2.py}

    Like other Pyomo components, \code{SOSConstraint} objects can be
    indexed. The indices of the index set are passed to the argument
    of \code{var}, which defaults to the index set of the \code{Var}
    object provided. The following code will create three SOS1
    constraints, namely
    \begin{equation*}
      \begin{aligned}
	\{x_0, x_1, x_2\} & \text{~is SOS1} \\
	\{x_3, x_4, x_5\} & \text{~is SOS1} \\
	\{x_6, x_7, x_8\} & \text{~is SOS1}:
      \end{aligned}
    \end{equation*}
    \lstinputlisting{examples/sos-constraint/ex3.py}

    The SOS constraints created can overlap; the following code will
    create three SOS1 constraints with overlapping variables, namely
    \begin{equation*}
      \begin{aligned}
	\{x_0, x_1, x_2\} & \text{~is SOS1} \\
	\{x_2, x_3, x_4\} & \text{~is SOS1} \\
	\{x_4, x_5, x_6\} & \text{~is SOS1}:
      \end{aligned}
    \end{equation*}
    \lstinputlisting{examples/sos-constraint/ex4.py}

    Higher-order SOS constraints, such as SOS2 or SOS$k$ constraints,
    only differ by the argument provided to \code{level} or
    \code{sos}:
    \lstinputlisting{examples/sos-constraint/ex5.py}

    
% LocalWords:  Pyomo SOSConstraint RangeSet sos LocalWords indices py CPLEX MIP
