Squared Distance Problem
In this example, we demonstrate how to formulate and solve a general optimization problem within the OPTIMake framework, i.e., a problem with the number of stages set to 1.
When the number of stages is set to 1, the OPTIMake modeling interface reduces to:
- The above optimization problem is a general optimization problem formulation, where the objective function, equality constraints, and inequality constraints are defined through the modeling interface functions
objective,start_equality, andinequality, respectively. - When the number of stages is 1, the multi-stage modeling interface functions cannot be called:
end_objective,end_equality,equality.
OPTIMake is not designed for solving large-scale general optimization problems. OPTIMake can efficiently model and solve general optimization problems (single-stage problems) when the following conditions are met:
- Variable/constraint dimensions are less than 100
- Fixed dimensions and sparsity structure
Problem Description
The minimum distance between a circle and a rectangle (when the circle and rectangle intersect, the minimum distance is 0) can be formulated as an optimization problem.
Let the center of the rectangle be , with length and width respectively, the circle centered at the origin with radius .
Suppose and are points inside the rectangle and the circle, respectively. Then the minimum distance problem can be described as minimizing the distance between and , i.e.,
The constraint that lies inside the circle can be described by the following quadratic constraint:
The constraint that lies inside the rectangle can be described in several ways. Here we use the vertices of the rectangle. Let the four vertices of the rectangle be . Then a point inside the rectangle can be described as a weighted average of the 4 vertices, i.e.,
Modeling
The above optimization problem is modeled in OPTIMake as follows:
prob = multi_stage_problem('squared_distance', 1)
# rectangle parameters
# center: (x, y), rotation: phi
# length: l, width: w
l, w = prob.parameters(['l', 'w'], stage_dependent=False)
x, y, phi = prob.parameters(['x', 'y', 'phi'], stage_dependent=False)
# circle parameters
# center: (0, 0), radius: r
r = prob.parameters(['r'], stage_dependent=False)
# point inside the circle
xo = prob.variable('xo')
yo = prob.variable('yo')
theta1 = prob.variable('theta1', hard_lowerbound=0.0)
theta2 = prob.variable('theta2', hard_lowerbound=0.0)
theta3 = prob.variable('theta3', hard_lowerbound=0.0)
theta4 = prob.variable('theta4', hard_lowerbound=0.0)
# rectangle vertices
V = Matrix([[+l / 2.0, +w / 2.0],
[+l / 2.0, -w / 2.0],
[-l / 2.0, -w / 2.0],
[-l / 2.0, +w / 2.0]])
# rotation matrix
R = Matrix([[cos(phi), -sin(phi)],
[sin(phi), cos(phi)]])
# rotated rectangle vertices
V = V * R
theta = Matrix([theta1, theta2, theta3, theta4])
# point inside the rectangle
pos_rec = V.transpose() * theta + Matrix([[x], [y]])
xr, yr = pos_rec[0], pos_rec[1]
obj = general_objective((xr - xo)**2 + (yr - yo)**2)
prob.objective(obj)
seq = general_equality([theta1 + theta2 + theta3 + theta4 - 1.0])
prob.start_equality(seq)
ineq = general_inequality(
expr = [xo**2 + yo**2 - r**2],
sign = ['<='],
bound = [0.0])
prob.inequality(ineq)
option = codegen_option()
option.default_tolerance_level = 'high'
codegen = code_generator()
codegen.codegen(prob, option)
Solving
#include "squared_distance_prob.h"
#include "squared_distance_solver.h"
#include <stdio.h>
int main(void)
{
Squared_distance_Problem prob;
Squared_distance_Option option;
Squared_distance_WorkSpace ws;
Squared_distance_Output output;
squared_distance_init(&prob, &option, &ws);
/* params */
prob.param[SQUARED_DISTANCE_PARAM_X] = 2.0; /* x */
prob.param[SQUARED_DISTANCE_PARAM_Y] = 2.0; /* y */
prob.param[SQUARED_DISTANCE_PARAM_PHI] = 0.2; /* phi */
prob.param[SQUARED_DISTANCE_PARAM_L] = 4.0; /* l */
prob.param[SQUARED_DISTANCE_PARAM_W] = 2.0; /* w */
prob.param[SQUARED_DISTANCE_PARAM_R] = 1.0; /* r */
/* option */
option.print_level = 1;
int solve_status = squared_distance_solve(&prob, &option, &ws, &output);
printf("solve_status = %d\n", solve_status);
printf("squared distance = %f\n", output.obj);
printf("(xo, yo) = (%f, %f)\n", \
output.primal.var[0][SQUARED_DISTANCE_VAR_XO], output.primal.var[0][SQUARED_DISTANCE_VAR_YO]);
return 0;
}
Results
When , , , , , , the computed (can be obtained via output.obj):

When , , , , , , the computed :

When , , , , , , i.e., when the circle and rectangle intersect, the computed :
