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    }