    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017
    018    package org.apache.commons.math.optimization.linear;
    019
    020    import java.io.IOException;
    021    import java.io.ObjectInputStream;
    022    import java.io.ObjectOutputStream;
    023    import java.io.Serializable;
    024
    025    import org.apache.commons.math.linear.MatrixUtils;
    026    import org.apache.commons.math.linear.RealVector;
    027    import org.apache.commons.math.linear.ArrayRealVector;
    028
    029
    030    /**
    031     * A linear constraint for a linear optimization problem.
    032     * <p>
    033     * A linear constraint has one of the forms:
    034     * <ul>
    035     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
    036     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
    037     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
    038     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
    039     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    040     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
    041     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    042     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> >=
    043     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    044     * </ul>
    045     * The c<sub>i</sub>, l<sub>i</sub> or r<sub>i</sub> are the coefficients of the constraints, the x<sub>i</sub>
    046     * are the coordinates of the current point and v is the value of the constraint.
    047     * </p>
    048     * @version $Revision: 922713 $ $Date: 2010-03-14 02:26:13 +0100 (dim. 14 mars 2010) $
    049     * @since 2.0
    050     */
    051    public class LinearConstraint implements Serializable {
    052
    053        /** Serializable version identifier. */
    054        private static final long serialVersionUID = -764632794033034092L;
    055
    056        /** Coefficients of the constraint (left hand side). */
    057        private final transient RealVector coefficients;
    058
    059        /** Relationship between left and right hand sides (=, &lt;=, >=). */
    060        private final Relationship relationship;
    061
    062        /** Value of the constraint (right hand side). */
    063        private final double value;
    064
    065        /**
    066         * Build a constraint involving a single linear equation.
    067         * <p>
    068         * A linear constraint with a single linear equation has one of the forms:
    069         * <ul>
    070         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
    071         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
    072         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
    073         * </ul>
    074         * </p>
    075         * @param coefficients The coefficients of the constraint (left hand side)
    076         * @param relationship The type of (in)equality used in the constraint
    077         * @param value The value of the constraint (right hand side)
    078         */
    079        public LinearConstraint(final double[] coefficients, final Relationship relationship,
    080                                final double value) {
    081            this(new ArrayRealVector(coefficients), relationship, value);
    082        }
    083
    084        /**
    085         * Build a constraint involving a single linear equation.
    086         * <p>
    087         * A linear constraint with a single linear equation has one of the forms:
    088         * <ul>
    089         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
    090         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
    091         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
    092         * </ul>
    093         * </p>
    094         * @param coefficients The coefficients of the constraint (left hand side)
    095         * @param relationship The type of (in)equality used in the constraint
    096         * @param value The value of the constraint (right hand side)
    097         */
    098        public LinearConstraint(final RealVector coefficients, final Relationship relationship,
    099                                final double value) {
    100            this.coefficients = coefficients;
    101            this.relationship = relationship;
    102            this.value        = value;
    103        }
    104
    105        /**
    106         * Build a constraint involving two linear equations.
    107         * <p>
    108         * A linear constraint with two linear equation has one of the forms:
    109         * <ul>
    110         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
    111         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    112         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
    113         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    114         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> >=
    115         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    116         * </ul>
    117         * </p>
    118         * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
    119         * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
    120         * @param relationship The type of (in)equality used in the constraint
    121         * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
    122         * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
    123         */
    124        public LinearConstraint(final double[] lhsCoefficients, final double lhsConstant,
    125                                final Relationship relationship,
    126                                final double[] rhsCoefficients, final double rhsConstant) {
    127            double[] sub = new double[lhsCoefficients.length];
    128            for (int i = 0; i < sub.length; ++i) {
    129                sub[i] = lhsCoefficients[i] - rhsCoefficients[i];
    130            }
    131            this.coefficients = new ArrayRealVector(sub, false);
    132            this.relationship = relationship;
    133            this.value        = rhsConstant - lhsConstant;
    134        }
    135
    136        /**
    137         * Build a constraint involving two linear equations.
    138         * <p>
    139         * A linear constraint with two linear equation has one of the forms:
    140         * <ul>
    141         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
    142         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    143         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
    144         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    145         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> >=
    146         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    147         * </ul>
    148         * </p>
    149         * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
    150         * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
    151         * @param relationship The type of (in)equality used in the constraint
    152         * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
    153         * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
    154         */
    155        public LinearConstraint(final RealVector lhsCoefficients, final double lhsConstant,
    156                                final Relationship relationship,
    157                                final RealVector rhsCoefficients, final double rhsConstant) {
    158            this.coefficients = lhsCoefficients.subtract(rhsCoefficients);
    159            this.relationship = relationship;
    160            this.value        = rhsConstant - lhsConstant;
    161        }
    162
    163        /**
    164         * Get the coefficients of the constraint (left hand side).
    165         * @return coefficients of the constraint (left hand side)
    166         */
    167        public RealVector getCoefficients() {
    168            return coefficients;
    169        }
    170
    171        /**
    172         * Get the relationship between left and right hand sides.
    173         * @return relationship between left and right hand sides
    174         */
    175        public Relationship getRelationship() {
    176            return relationship;
    177        }
    178
    179        /**
    180         * Get the value of the constraint (right hand side).
    181         * @return value of the constraint (right hand side)
    182         */
    183        public double getValue() {
    184            return value;
    185        }
    186
    187        /** {@inheritDoc} */
    188        @Override
    189        public boolean equals(Object other) {
    190
    191          if (this == other) {
    192            return true;
    193          }
    194
    195          if (other instanceof LinearConstraint) {
    196              LinearConstraint rhs = (LinearConstraint) other;
    197              return (relationship == rhs.relationship) &&
    198                     (value        == rhs.value) &&
    199                     coefficients.equals(rhs.coefficients);
    200          }
    201          return false;
    202        }
    203
    204        /** {@inheritDoc} */
    205        @Override
    206        public int hashCode() {
    207            return relationship.hashCode() ^
    208                   Double.valueOf(value).hashCode() ^
    209                   coefficients.hashCode();
    210        }
    211
    212        /** Serialize the instance.
    213         * @param oos stream where object should be written
    214         * @throws IOException if object cannot be written to stream
    215         */
    216        private void writeObject(ObjectOutputStream oos)
    217            throws IOException {
    218            oos.defaultWriteObject();
    219            MatrixUtils.serializeRealVector(coefficients, oos);
    220        }
    221
    222        /** Deserialize the instance.
    223         * @param ois stream from which the object should be read
    224         * @throws ClassNotFoundException if a class in the stream cannot be found
    225         * @throws IOException if object cannot be read from the stream
    226         */
    227        private void readObject(ObjectInputStream ois)
    228          throws ClassNotFoundException, IOException {
    229            ois.defaultReadObject();
    230            MatrixUtils.deserializeRealVector(this, "coefficients", ois);
    231        }
    232
    233    }