OR-Tools (CP-SAT) - How to implement a non-linear function

1k Views Asked by At

I'm attempting to use Google's OR-Tools to produce a distance constraint between 2x 2D points (p0 & p1).

This becomes the non-linear expression: (p1x - p0x)² + (p1y - p0y)² = d²

I have attempted to produce this with the CP-Sat solver using the following code:

int64_t d = 50;
int64_t d_sq = d*d;

// p0 at (10, 20)
IntVar p0x = cp_model.NewConstant(0);
IntVar p0y = cp_model.NewConstant(0);

// p1 is to be determined by solver
IntVar p1x = cp_model.NewIntVar({ int64_t_min, int64_t_max });
IntVar p1y = cp_model.NewIntVar({ int64_t_min, int64_t_max });

// x1-x0 and y1-y0
IntVar xDif = cp_model.NewIntVar({ -d, d });
IntVar yDif = cp_model.NewIntVar({ -d, d });
cp_model.AddEquality(xDif, p1x - p0x);
cp_model.AddEquality(yDif, p1y - p1y);

// xdif_sq = xdif^2  &  ydif_sq = ydif^2
IntVar xDif_sq = cp_model.NewIntVar({ 0, d_sq });obvious solution is to add a tolerance range to d. But I'm having an issue 
IntVar yDif_sq = cp_model.NewIntVar({ 0, d_sq });
cp_model.AddMultiplicationEquality(xDif_sq, { xDif, xDif });
cp_model.AddMultiplicationEquality(yDif_sq, { yDif, yDif });

// dif_sq_sum = xdif^2 + ydif^2
IntVar Dif_sq_sum = cp_model.NewIntVar({ 0, 2*d_sq });
cp_model.AddEquality(Dif_sq_sum, xDif_sq + yDif_sq);

// make both sides of equation equal 
cp_model.AddEquality(iv_Dif_sq_sum, d_sq);

The problem is that because the solver only accepts integers, it can only calculate the position of p1 when the all parts are integer values.

For example, 3² + 4² = 5² works fine.

But I want to make it work for when a term is non-integer? a² + b² = (almost) c²

The obvious solution is to add a tolerance range to d. But I'm having an issue trying to achieve this as when I do, the status becomes infeasible. Here is the code I've tried.

IntVar iv_Error;
cp_model.AddMultiplicationEquality(iv_Dif_sq_sum, { iv_Error, iv_Error });
cp_model.AddLessThan(iv_Error, d + 1);
cp_model.AddGreaterThan(iv_Error, d - 1);

If anybody has any good suggestions I would be very grateful! Thanks

1

There are 1 best solutions below

0
On

Cross-posted from https://github.com/google/or-tools/discussions/3220.

The discussion is happening there.