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