// (c) 2023-2024 Fair Isaac Corporation
import static com.dashoptimization.objects.Utils.sum;
import com.dashoptimization.XPRSconstants;
import com.dashoptimization.XPRSenumerations.ObjSense;
import com.dashoptimization.objects.LinExpression;
import com.dashoptimization.objects.LinTermList;
import com.dashoptimization.objects.Variable;
import com.dashoptimization.objects.XpressProblem;
/**
* QCQP problem (linear objective, convex quadratic constraints) Based on AMPL
* model catenary.mod (Source:
* http://www.orfe.princeton.edu/~rvdb/ampl/nlmodels/) This model finds the
* shape of a hanging chain by minimizing its potential energy.
*/
public class Catenary {
static final int N = 100; // Number of chainlinks
static final int L = 1; // Difference in x-coordinates of endlinks
static final double H = 2.0 * L / N; // Length of each link
public static void main(String[] args) {
try (XpressProblem prob = new XpressProblem()) {
int i;
Variable[] x, y;
LinExpression obj;
///// VARIABLES
x = prob.addVariables(N + 1).withName("x(%s)").withLB(XPRSconstants.MINUSINFINITY).toArray();
y = prob.addVariables(N + 1).withName("y(%s)").withLB(XPRSconstants.MINUSINFINITY).toArray();
// Bounds: positions of endpoints
// Left anchor
x[0].fix(0);
y[0].fix(0);
// Right anchor
x[N].fix(L);
y[N].fix(0);
///// OBJECTIVE
/* Minimise the potential energy: sum(j in 1..N) (y(j-1)+y(j))/2 */
obj = new LinTermList();
for (i = 1; i <= N; i++) {
obj.addTerm(y[i - 1], 0.5).addTerm(y[i], 0.5);
}
prob.setObjective(obj, ObjSense.MINIMIZE);
///// CONSTRAINTS
/*
* Positions of chainlinks: forall(j in 1..N) (x(j)-x(j-1))^2+(y(j)-y(j-1))^2 <=
* H^2
*/
for (i = 1; i <= N; i++) {
prob.addConstraint(sum(LinExpression.create().addTerm(x[i]).addTerm(x[i - 1], -1).square(),
LinExpression.create().addTerm(y[i]).addTerm(y[i - 1], -1).square()).leq(H * H)
.setName("Link_" + i));
}
///// SOLVING + OUTPUT
prob.lpOptimize(""); // Solve the problem
System.out.println("Solution: " + prob.attributes().getObjVal());
for (i = 0; i <= N; i++) {
System.out.println(i + ": " + x[i].getSolution() + ", " + y[i].getSolution());
}
}
}
}
|