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.legacy.optim.linear;
018
019import org.apache.commons.math4.legacy.linear.ArrayRealVector;
020import org.apache.commons.math4.legacy.linear.RealVector;
021
022/**
023 * A linear constraint for a linear optimization problem.
024 * <p>
025 * A linear constraint has one of the forms:
026 * <ul>
027 *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
028 *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
029 *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &gt;= v</li>
030 *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
031 *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
032 *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
033 *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
034 *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &gt;=
035 *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
036 * </ul>
037 * 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>
038 * are the coordinates of the current point and v is the value of the constraint.
039 *
040 * @since 2.0
041 */
042public class LinearConstraint {
043    /** Coefficients of the constraint (left hand side). */
044    private final RealVector coefficients;
045    /** Relationship between left and right hand sides {@code (=, <=, >=)}. */
046    private final Relationship relationship;
047    /** Value of the constraint (right hand side). */
048    private final double value;
049
050    /**
051     * Build a constraint involving a single linear equation.
052     * <p>
053     * A linear constraint with a single linear equation has one of the forms:
054     * <ul>
055     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
056     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
057     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &gt;= v</li>
058     * </ul>
059     *
060     * @param coefficients The coefficients of the constraint (left hand side)
061     * @param relationship The type of (in)equality used in the constraint
062     * @param value The value of the constraint (right hand side)
063     */
064    public LinearConstraint(final double[] coefficients,
065                            final Relationship relationship,
066                            final double value) {
067        this(new ArrayRealVector(coefficients), relationship, value);
068    }
069
070    /**
071     * Build a constraint involving a single linear equation.
072     * <p>
073     * A linear constraint with a single linear equation has one of the forms:
074     * <ul>
075     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
076     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &lt;= v</li>
077     *   <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> &gt;= v</li>
078     * </ul>
079     *
080     * @param coefficients The coefficients of the constraint (left hand side)
081     * @param relationship The type of (in)equality used in the constraint
082     * @param value The value of the constraint (right hand side)
083     */
084    public LinearConstraint(final RealVector coefficients,
085                            final Relationship relationship,
086                            final double value) {
087        this.coefficients = coefficients;
088        this.relationship = relationship;
089        this.value        = value;
090    }
091
092    /**
093     * Build a constraint involving two linear equations.
094     * <p>
095     * A linear constraint with two linear equation has one of the forms:
096     * <ul>
097     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
098     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
099     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
100     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
101     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &gt;=
102     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
103     * </ul>
104     *
105     * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
106     * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
107     * @param relationship The type of (in)equality used in the constraint
108     * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
109     * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
110     */
111    public LinearConstraint(final double[] lhsCoefficients, final double lhsConstant,
112                            final Relationship relationship,
113                            final double[] rhsCoefficients, final double rhsConstant) {
114        double[] sub = new double[lhsCoefficients.length];
115        for (int i = 0; i < sub.length; ++i) {
116            sub[i] = lhsCoefficients[i] - rhsCoefficients[i];
117        }
118        this.coefficients = new ArrayRealVector(sub, false);
119        this.relationship = relationship;
120        this.value        = rhsConstant - lhsConstant;
121    }
122
123    /**
124     * Build a constraint involving two linear equations.
125     * <p>
126     * A linear constraint with two linear equation has one of the forms:
127     * <ul>
128     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
129     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
130     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &lt;=
131     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
132     *   <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> &gt;=
133     *       r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
134     * </ul>
135     *
136     * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
137     * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
138     * @param relationship The type of (in)equality used in the constraint
139     * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
140     * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
141     */
142    public LinearConstraint(final RealVector lhsCoefficients, final double lhsConstant,
143                            final Relationship relationship,
144                            final RealVector rhsCoefficients, final double rhsConstant) {
145        this.coefficients = lhsCoefficients.subtract(rhsCoefficients);
146        this.relationship = relationship;
147        this.value        = rhsConstant - lhsConstant;
148    }
149
150    /**
151     * Gets the coefficients of the constraint (left hand side).
152     *
153     * @return the coefficients of the constraint (left hand side).
154     */
155    public RealVector getCoefficients() {
156        return coefficients;
157    }
158
159    /**
160     * Gets the relationship between left and right hand sides.
161     *
162     * @return the relationship between left and right hand sides.
163     */
164    public Relationship getRelationship() {
165        return relationship;
166    }
167
168    /**
169     * Gets the value of the constraint (right hand side).
170     *
171     * @return the value of the constraint (right hand side).
172     */
173    public double getValue() {
174        return value;
175    }
176
177    /** {@inheritDoc} */
178    @Override
179    public boolean equals(Object other) {
180        if (this == other) {
181            return true;
182        }
183        if (other instanceof LinearConstraint) {
184            LinearConstraint rhs = (LinearConstraint) other;
185            return relationship == rhs.relationship &&
186                value == rhs.value &&
187                coefficients.equals(rhs.coefficients);
188        }
189        return false;
190    }
191
192    /** {@inheritDoc} */
193    @Override
194    public int hashCode() {
195        return relationship.hashCode() ^
196            Double.valueOf(value).hashCode() ^
197            coefficients.hashCode();
198    }
199}