IntegerPoints2  procedure generalizes  IntegerPoints1  procedure and finds all the integer points inside a bounded curved region of arbitrary dimension.  We also use a brute force method, but to find the ranges for each variable  Optimization[Minimize]  and   Optimization[Maximize]  is used instead of  simplex[minimize]  or  simplex[minimize] .

Required parameters of the procedure: SN is a set or a list of  inequalities and/or equations with any number of variables, the Var is the list of variables. Bound   is an optional parameter - list of ranges for each variable in the event, if  Optimization[Minimize/Maximize]  fails. By default  Bound  is NULL.

If all constraints are linear, then in this case it is recommended to use  IntegerPoints1  procedure, as it is better to monitor specific cases (no solutions or an infinite number of solutions for an unbounded region).

Code of the procedure:

IntegerPoints2 := proc (SN::{list, set}, Var::(list(symbol)), Bound::(list(range)) := NULL)

local SN1, sn, n, i, p, q, xl, xr, Xl, Xr, X, T, k, t, S;

uses Optimization, combinat;

n := nops(Var);

if Bound = NULL then

SN1 := SN;

for sn in SN1 do

if type(sn, `<`) then

SN1 := subs(sn = (`<=`(op(sn))), SN1) fi od;

for i to n do

p := Minimize(Var[i], SN1); q := Maximize(Var[i], SN1);

xl[i] := eval(Var[i], p[2]); xr[i] := eval(Var[i], q[2]) od else

assign(seq(xl[i] = lhs(Bound[i]), i = 1 .. n));

assign(seq(xr[i] = rhs(Bound[i]), i = 1 .. n)) fi;

Xl := map(floor, convert(xl, list)); Xr := map(ceil, convert(xr, list));

X := [seq([$ Xl[i] .. Xr[i]], i = 1 .. n)];

T := cartprod(X); S := table();

for k while not T[finished] do

t := T[nextvalue]();

if convert(eval(SN, zip(`=`, Var, t)), `and`) then

S[k] := t fi od;

convert(S, set);

end proc:

 

In the first example, we find all the integer points in the four-dimensional ball of radius 10:

Ball := IntegerPoints2({x1^2+x2^2+x3^2+x4^2 < 10^2}, [x1, x2, x3, x4]):  # All the integer points

nops(Ball);  # The total number of the integer points

seq(Ball[1000*n], n = 1 .. 10);  # Some points

                                                                    48945

                  [-8, 2, 0, -1], [-7, 0, 1, -3], [-6, -4, -6, 2], [-6, 1, 1, 1], [-5, -6, -2, 4], [-5, -1, 2, 0],

                                [-5, 4, -6, -2], [-4, -5, 1, 5], [-4, -1, 6, 1], [-4, 3, 5, 6]

 

 

In the second example, with the visualization we find all the integer points in the inside intersection of  a cone and a cylinder:

A := <1, 0, 0; 0, (1/2)*sqrt(3), -1/2; 0, 1/2, (1/2)*sqrt(3)>:  # Matrix of rotation around x-axis at Pi/6 radians

f := unapply(A^(-1) . <x, y, z-4>, x, y, z):  

S0 := {4*x^2+4*y^2 < z^2}:  # The inner of the cone

S1 := {x^2+z^2 < 4}:  # The inner of the cylinder

S2 := evalf(eval(S1, {x = f(x, y, z)[1], y = f(x, y, z)[2], z = f(x, y, z)[3]})):

S := IntegerPoints2(`union`(S0, S2), [x, y, z]);  # The integer points inside of the intersection of the cone and the rotated cylinder

Points := plots[pointplot3d](S, color = red, symbol = solidsphere, symbolsize = 8):

Sp := plot3d([r*cos(phi), r*sin(phi), 2*r], phi = 0 .. 2*Pi, r = 0 .. 5, style = surface, color = "LightBlue", transparency = 0.7):

F := plottools[transform]((x, y, z)->convert(A . <x, y, z>+<0, 0, 4>, list)):

S11 := plot3d([2*cos(t), y, 2*sin(t)], t = 0 .. 2*Pi, y = -4 .. 7, style = surface, color = "LightBlue", transparency = 0.7):

plots[display]([F(S11), Sp, Points], scaling = constrained, orientation = [25, 75], axes = normal);

      

 

 

In the third example, we are looking for the integer points in a non-convex area between two parabolas. Here we have to specify ourselves the ranges to enumeration (Optimization[Minimize] command fails for this example):

P := IntegerPoints2([y > (-x^2)*(1/2)+2, y < -x^2+8], [x, y], [-4 .. 4, -4 .. 8]);

A := plots[pointplot](P, color = red, symbol = solidcircle, symbolsize = 10):

B := plot([(-x^2)*(1/2)+2, -x^2+8], x = -4 .. 4, -5 .. 9, color = blue):

plots[display](A, B, scaling = constrained);

     

 

 IntegerPoints2.mw

 


Please Wait...