1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22 package org.hipparchus.optim.linear;
23
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.Serializable;
28
29 import org.hipparchus.linear.ArrayRealVector;
30 import org.hipparchus.linear.RealVector;
31
32 /**
33 * A linear constraint for a linear optimization problem.
34 * <p>* A linear constraint has one of the forms:</p>
35 * <ul>
36 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
37 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> <= v</li>
38 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
39 * <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
40 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
41 * <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> <=
42 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
43 * <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> >=
44 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
45 * </ul>
46 * <p>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>
47 * are the coordinates of the current point and v is the value of the constraint.
48 * </p>
49 *
50 */
51 public class LinearConstraint implements Serializable {
52 /** Serializable version identifier. */
53 private static final long serialVersionUID = -764632794033034092L;
54 /** Coefficients of the constraint (left hand side). */
55 private final transient RealVector coefficients;
56 /** Relationship between left and right hand sides (=, <=, >=). */
57 private final Relationship relationship;
58 /** Value of the constraint (right hand side). */
59 private final double value;
60
61 /**
62 * Build a constraint involving a single linear equation.
63 * <p>A linear constraint with a single linear equation has one of the forms:</p>
64 * <ul>
65 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
66 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> <= v</li>
67 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
68 * </ul>
69 * @param coefficients The coefficients of the constraint (left hand side)
70 * @param relationship The type of (in)equality used in the constraint
71 * @param value The value of the constraint (right hand side)
72 */
73 public LinearConstraint(final double[] coefficients,
74 final Relationship relationship,
75 final double value) {
76 this(new ArrayRealVector(coefficients), relationship, value);
77 }
78
79 /**
80 * Build a constraint involving a single linear equation.
81 * <p>A linear constraint with a single linear equation has one of the forms:</p>
82 * <ul>
83 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> = v</li>
84 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> <= v</li>
85 * <li>c<sub>1</sub>x<sub>1</sub> + ... c<sub>n</sub>x<sub>n</sub> >= v</li>
86 * </ul>
87 * @param coefficients The coefficients of the constraint (left hand side)
88 * @param relationship The type of (in)equality used in the constraint
89 * @param value The value of the constraint (right hand side)
90 */
91 public LinearConstraint(final RealVector coefficients,
92 final Relationship relationship,
93 final double value) {
94 this.coefficients = coefficients;
95 this.relationship = relationship;
96 this.value = value;
97 }
98
99 /**
100 * Build a constraint involving two linear equations.
101 * <p>A linear constraint with two linear equation has one of the forms:</p>
102 * <ul>
103 * <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
104 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
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> >=
108 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
109 * </ul>
110 * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
111 * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
112 * @param relationship The type of (in)equality used in the constraint
113 * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
114 * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
115 */
116 public LinearConstraint(final double[] lhsCoefficients, final double lhsConstant,
117 final Relationship relationship,
118 final double[] rhsCoefficients, final double rhsConstant) {
119 double[] sub = new double[lhsCoefficients.length];
120 for (int i = 0; i < sub.length; ++i) {
121 sub[i] = lhsCoefficients[i] - rhsCoefficients[i];
122 }
123 this.coefficients = new ArrayRealVector(sub, false);
124 this.relationship = relationship;
125 this.value = rhsConstant - lhsConstant;
126 }
127
128 /**
129 * Build a constraint involving two linear equations.
130 * <p>A linear constraint with two linear equation has one of the forms:</p>
131 * <ul>
132 * <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> =
133 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
134 * <li>l<sub>1</sub>x<sub>1</sub> + ... l<sub>n</sub>x<sub>n</sub> + l<sub>cst</sub> <=
135 * r<sub>1</sub>x<sub>1</sub> + ... r<sub>n</sub>x<sub>n</sub> + r<sub>cst</sub></li>
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 * </ul>
139 * @param lhsCoefficients The coefficients of the linear expression on the left hand side of the constraint
140 * @param lhsConstant The constant term of the linear expression on the left hand side of the constraint
141 * @param relationship The type of (in)equality used in the constraint
142 * @param rhsCoefficients The coefficients of the linear expression on the right hand side of the constraint
143 * @param rhsConstant The constant term of the linear expression on the right hand side of the constraint
144 */
145 public LinearConstraint(final RealVector lhsCoefficients, final double lhsConstant,
146 final Relationship relationship,
147 final RealVector rhsCoefficients, final double rhsConstant) {
148 this.coefficients = lhsCoefficients.subtract(rhsCoefficients);
149 this.relationship = relationship;
150 this.value = rhsConstant - lhsConstant;
151 }
152
153 /**
154 * Gets the coefficients of the constraint (left hand side).
155 *
156 * @return the coefficients of the constraint (left hand side).
157 */
158 public RealVector getCoefficients() {
159 return coefficients;
160 }
161
162 /**
163 * Gets the relationship between left and right hand sides.
164 *
165 * @return the relationship between left and right hand sides.
166 */
167 public Relationship getRelationship() {
168 return relationship;
169 }
170
171 /**
172 * Gets the value of the constraint (right hand side).
173 *
174 * @return the value of the constraint (right hand side).
175 */
176 public double getValue() {
177 return value;
178 }
179
180 /** {@inheritDoc} */
181 @Override
182 public boolean equals(Object other) {
183 if (this == other) {
184 return true;
185 }
186 if (other instanceof LinearConstraint) {
187 LinearConstraint rhs = (LinearConstraint) other;
188 return relationship == rhs.relationship &&
189 value == rhs.value &&
190 coefficients.equals(rhs.coefficients);
191 }
192 return false;
193 }
194
195 /** {@inheritDoc} */
196 @Override
197 public int hashCode() {
198 return relationship.hashCode() ^
199 Double.valueOf(value).hashCode() ^
200 coefficients.hashCode();
201 }
202
203 /**
204 * Serialize the instance.
205 * @param oos stream where object should be written
206 * @throws IOException if object cannot be written to stream
207 */
208 private void writeObject(ObjectOutputStream oos)
209 throws IOException {
210 oos.defaultWriteObject();
211 final int n = coefficients.getDimension();
212 oos.writeInt(n);
213 for (int i = 0; i < n; ++i) {
214 oos.writeDouble(coefficients.getEntry(i));
215 }
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
228 // read the vector data
229 final int n = ois.readInt();
230 final double[] data = new double[n];
231 for (int i = 0; i < n; ++i) {
232 data[i] = ois.readDouble();
233 }
234
235 try {
236 // create the instance
237 ArrayRealVector vector = new ArrayRealVector(data, false);
238 final java.lang.reflect.Field f = getClass().getDeclaredField("coefficients");
239 f.setAccessible(true); // NOPMD
240 f.set(this, vector);
241 } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
242 IOException ioe = new IOException();
243 ioe.initCause(e);
244 throw ioe;
245 }
246
247 }
248 }