    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    package org.apache.commons.math3.optim.linear;
    018
    019    import java.io.IOException;
    020    import java.io.ObjectInputStream;
    021    import java.io.ObjectOutputStream;
    022    import java.io.Serializable;
    023    import org.apache.commons.math3.linear.MatrixUtils;
    024    import org.apache.commons.math3.linear.RealVector;
    025    import org.apache.commons.math3.linear.ArrayRealVector;
    026
    027    /**
    028     * A linear constraint for a linear optimization problem.
    029     * <p>
    030     * A linear constraint has one of the forms:
    031     * <ul>
    032     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
    033     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
    034     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
    035     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
    036     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    037     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
    038     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    039     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> >=
    040     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    041     * </ul>
    042     * 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>
    043     * are the coordinates of the current point and v is the value of the constraint.
    044     * </p>
    045     *
    046     * @version $Id: LinearConstraint.java 1416643 2012-12-03 19:37:14Z tn $
    047     * @since 2.0
    048     */
    049    public class LinearConstraint implements Serializable {
    050        /** Serializable version identifier. */
    051        private static final long serialVersionUID = -764632794033034092L;
    052        /** Coefficients of the constraint (left hand side). */
    053        private final transient RealVector coefficients;
    054        /** Relationship between left and right hand sides (=, &lt;=, >=). */
    055        private final Relationship relationship;
    056        /** Value of the constraint (right hand side). */
    057        private final double value;
    058
    059        /**
    060         * Build a constraint involving a single linear equation.
    061         * <p>
    062         * A linear constraint with a single linear equation has one of the forms:
    063         * <ul>
    064         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
    065         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
    066         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
    067         * </ul>
    068         * </p>
    069         * @param coefficients The coefficients of the constraint (left hand side)
    070         * @param relationship The type of (in)equality used in the constraint
    071         * @param value The value of the constraint (right hand side)
    072         */
    073        public LinearConstraint(final double[] coefficients,
    074                                final Relationship relationship,
    075                                final double value) {
    076            this(new ArrayRealVector(coefficients), relationship, value);
    077        }
    078
    079        /**
    080         * Build a constraint involving a single linear equation.
    081         * <p>
    082         * A linear constraint with a single linear equation has one of the forms:
    083         * <ul>
    084         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
    085         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
    086         *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
    087         * </ul>
    088         * </p>
    089         * @param coefficients The coefficients of the constraint (left hand side)
    090         * @param relationship The type of (in)equality used in the constraint
    091         * @param value The value of the constraint (right hand side)
    092         */
    093        public LinearConstraint(final RealVector coefficients,
    094                                final Relationship relationship,
    095                                final double value) {
    096            this.coefficients = coefficients;
    097            this.relationship = relationship;
    098            this.value        = value;
    099        }
    100
    101        /**
    102         * Build a constraint involving two linear equations.
    103         * <p>
    104         * A linear constraint with two linear equation has one of the forms:
    105         * <ul>
    106         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
    107         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    108         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
    109         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    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         * </ul>
    113         * </p>
    114         * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
    115         * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
    116         * @param relationship The type of (in)equality used in the constraint
    117         * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
    118         * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
    119         */
    120        public LinearConstraint(final double[] lhsCoefficients, final double lhsConstant,
    121                                final Relationship relationship,
    122                                final double[] rhsCoefficients, final double rhsConstant) {
    123            double[] sub = new double[lhsCoefficients.length];
    124            for (int i = 0; i < sub.length; ++i) {
    125                sub[i] = lhsCoefficients[i] - rhsCoefficients[i];
    126            }
    127            this.coefficients = new ArrayRealVector(sub, false);
    128            this.relationship = relationship;
    129            this.value        = rhsConstant - lhsConstant;
    130        }
    131
    132        /**
    133         * Build a constraint involving two linear equations.
    134         * <p>
    135         * A linear constraint with two linear equation has one of the forms:
    136         * <ul>
    137         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
    138         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    139         *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
    140         *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
    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         * </ul>
    144         * </p>
    145         * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
    146         * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
    147         * @param relationship The type of (in)equality used in the constraint
    148         * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
    149         * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
    150         */
    151        public LinearConstraint(final RealVector lhsCoefficients, final double lhsConstant,
    152                                final Relationship relationship,
    153                                final RealVector rhsCoefficients, final double rhsConstant) {
    154            this.coefficients = lhsCoefficients.subtract(rhsCoefficients);
    155            this.relationship = relationship;
    156            this.value        = rhsConstant - lhsConstant;
    157        }
    158
    159        /**
    160         * Gets the coefficients of the constraint (left hand side).
    161         *
    162         * @return the coefficients of the constraint (left hand side).
    163         */
    164        public RealVector getCoefficients() {
    165            return coefficients;
    166        }
    167
    168        /**
    169         * Gets the relationship between left and right hand sides.
    170         *
    171         * @return the relationship between left and right hand sides.
    172         */
    173        public Relationship getRelationship() {
    174            return relationship;
    175        }
    176
    177        /**
    178         * Gets the value of the constraint (right hand side).
    179         *
    180         * @return the value of the constraint (right hand side).
    181         */
    182        public double getValue() {
    183            return value;
    184        }
    185
    186        @Override
    187        public boolean equals(Object other) {
    188            if (this == other) {
    189                return true;
    190            }
    191            if (other instanceof LinearConstraint) {
    192                LinearConstraint rhs = (LinearConstraint) other;
    193                return relationship == rhs.relationship &&
    194                    value == rhs.value &&
    195                    coefficients.equals(rhs.coefficients);
    196            }
    197            return false;
    198        }
    199
    200        @Override
    201        public int hashCode() {
    202            return relationship.hashCode() ^
    203                Double.valueOf(value).hashCode() ^
    204                coefficients.hashCode();
    205        }
    206
    207        /**
    208         * Serialize the instance.
    209         * @param oos stream where object should be written
    210         * @throws IOException if object cannot be written to stream
    211         */
    212        private void writeObject(ObjectOutputStream oos)
    213            throws IOException {
    214            oos.defaultWriteObject();
    215            MatrixUtils.serializeRealVector(coefficients, oos);
    216        }
    217
    218        /**
    219         * Deserialize the instance.
    220         * @param ois stream from which the object should be read
    221         * @throws ClassNotFoundException if a class in the stream cannot be found
    222         * @throws IOException if object cannot be read from the stream
    223         */
    224        private void readObject(ObjectInputStream ois)
    225          throws ClassNotFoundException, IOException {
    226            ois.defaultReadObject();
    227            MatrixUtils.deserializeRealVector(this, "coefficients", ois);
    228        }
    229    }