Skip to content

Instantly share code, notes, and snippets.

@erikerlandson
Last active February 26, 2024 18:42
Show Gist options
  • Save erikerlandson/91a050ab41f61621d0c24bcb25e59e1f to your computer and use it in GitHub Desktop.
Save erikerlandson/91a050ab41f61621d0c24bcb25e59e1f to your computer and use it in GitHub Desktop.
An example quadratic programming (QP) optimization using JOptimizer in Scala
object testJO {
// libraryDependencies += "com.joptimizer" % "joptimizer" % "4.0.0"
import com.joptimizer.functions.PDQuadraticMultivariateRealFunction
import com.joptimizer.functions.PSDQuadraticMultivariateRealFunction
import com.joptimizer.functions.ConvexMultivariateRealFunction
import com.joptimizer.functions.LinearMultivariateRealFunction
import com.joptimizer.optimizers.OptimizationRequest
import com.joptimizer.optimizers.JOptimizer
// solution space is dimension n; in this example n = 2
// matrix P is n X n
val P = Array(
Array(1.0, 0.4),
Array(0.4, 1.0)
)
// vector q is length n
val q = Array(0.0, 0.0)
// r is a scalar
val r = 0.0
// My P is positive definite but I'm testing if it will take positive semi-def
val objective = new PSDQuadraticMultivariateRealFunction(P, q, r)
// A is k X n, where k is number of equalities. Here k = 1
// vector b has dimension k
// conceptually, setting up a matrix equation Ax = b
// This constraint corresponds to x[0] + x[1] = 1
val A = Array(Array(1.0, 1.0))
val b = Array(1.0)
// Convex inequalities. These are typical linear inequalities.
// Each linear inequality corresponds to form: c.x <= t , where c is
// a vector of length n and t is a scalar threshold
// The following corresponds to x[0] >= 0.6, x[1] >= 0
val ineq: Array[ConvexMultivariateRealFunction] = Array(
new LinearMultivariateRealFunction(Array(-1.0, 0.0), 0.6),
new LinearMultivariateRealFunction(Array(0.0, -1.0), 0.0)
)
val oreq = new OptimizationRequest()
oreq.setF0(objective)
// set this to a strictly feasible point
// here, we have an equality constraint x[0] + x[1] = 1, pick a point satisfying that
// Also we have x[0] >= 0.6, so make sure x[0] in this initial point is >= 0.6
oreq.setInitialPoint(Array(0.9, 0.1))
oreq.setFi(ineq)
oreq.setA(A)
oreq.setB(b)
// these seem pretty aggressive, consider loosening a bit in real life?
oreq.setToleranceFeas(1e-12)
oreq.setTolerance(1e-12)
// given the problem definition above, this should return x = [0.6, 0.4]
def run = {
val opt = new JOptimizer()
opt.setOptimizationRequest(oreq)
opt.optimize()
opt.getOptimizationResponse().getSolution()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment