Projecting Inequalities

As soon as linear inequations are involved, projection gets more demanding complexity wise. The current clp(Q,R) version uses a Fourier-Motzkin algorithm for the projection of linear inequalities. The choice of a suitable algorithm is somewhat dependent on the number of variables to be eliminated, the total number of variables, and other factors. It is quite easy to produce problems of moderate size where the elimination step takes some time. For example, when the dimension of the projection is 1, you might be better off computing the supremum and the infimum of the remaining variable instead of eliminating n-1 variables via implicit projection.

In order to make answers as concise as possible, redundant constraints are removed by the system as well. In the following set of inequalities, half of them are redundant.

       
% library('clpqr/examples/eliminat')
example(2, [X0,X1,X2,X3,X4]) :- { +87*X0 +52*X1 +27*X2 -54*X3 +56*X4 =< -93, +33*X0 -10*X1 +61*X2 -28*X3 -29*X4 =< 63, -68*X0 +8*X1 +35*X2 +68*X3 +35*X4 =< -85, +90*X0 +60*X1 -76*X2 -53*X3 +24*X4 =< -68, -95*X0 -10*X1 +64*X2 +76*X3 -24*X4 =< 33, +43*X0 -22*X1 +67*X2 -68*X3 -92*X4 =< -97, +39*X0 +7*X1 +62*X2 +54*X3 -26*X4 =< -27, +48*X0 -13*X1 +7*X2 -61*X3 -59*X4 =< -2, +49*X0 -23*X1 -31*X2 -76*X3 +27*X4 =< 3, -50*X0 +58*X1 -1*X2 +57*X3 +20*X4 =< 6, -13*X0 -63*X1 +81*X2 -3*X3 +70*X4 =< 64, +20*X0 +67*X1 -23*X2 -41*X3 -66*X4 =< 52, -81*X0 -44*X1 +19*X2 -22*X3 -73*X4 =< -17, -43*X0 -9*X1 +14*X2 +27*X3 +40*X4 =< 39, +16*X0 +83*X1 +89*X2 +25*X3 +55*X4 =< 36, +2*X0 +40*X1 +65*X2 +59*X3 -32*X4 =< 13, -65*X0 -11*X1 +10*X2 -13*X3 +91*X4 =< 49, +93*X0 -73*X1 +91*X2 -1*X3 +23*X4 =< -87 }.
Consequently, the answer consists of the system of nine non-redundant inequalities only:
     clp(q) ?- use_module(library('clpqr/examples/elimination')).
     clp(q) ?- example(2, [X0,X1,X2,X3,X4]).
     
     {X0-2/17*X1-35/68*X2-X3-35/68*X4>=5/4},
     {X0-73/93*X1+91/93*X2-1/93*X3+23/93*X4=<-29/31},
     {X0-29/25*X1+1/50*X2-57/50*X3-2/5*X4>=-3/25},
     {X0+7/39*X1+62/39*X2+18/13*X3-2/3*X4=<-9/13},
     {X0+2/19*X1-64/95*X2-4/5*X3+24/95*X4>=-33/95},
     {X0+2/3*X1-38/45*X2-53/90*X3+4/15*X4=<-34/45},
     {X0-23/49*X1-31/49*X2-76/49*X3+27/49*X4=<3/49},
     {X0+44/81*X1-19/81*X2+22/81*X3+73/81*X4>=17/81},
     {X0+9/43*X1-14/43*X2-27/43*X3-40/43*X4>=-39/43}
     

The projection (the shadow) of this polyhedral set into the X0,X1 space can be computed via the implicit elimination of non-query variables:

     clp(q) ?- example(2, [X0,X1|_]).
     
     {X0+2619277/17854273*X1>=-851123/17854273},
     {X0+6429953/16575801*X1=<-12749681/16575801},
     {X0+19130/1213083*X1>=795400/404361},
     {X0-1251619/3956679*X1>=21101146/3956679},
     {X0+601502/4257189*X1>=220850/473021}
     

Projection is quite a powerful concept that leads to surprisingly terse executable specifications of nontrivial problems like the computation of the convex hull from a set of points in an n-dimensional space: Given the program

     
% library('clpqr/examples/elimination')
conv_hull(Points, Xs) :- lin_comb(Points, Lambdas, Zero, Xs), zero(Zero), polytope(Lambdas). polytope(Xs) :- positive_sum(Xs, 1). positive_sum([], Z) :- {Z=0}. positive_sum([X|Xs], SumX) :- { X >= 0, SumX = X+Sum }, positive_sum(Xs, Sum). zero([]). zero([Z|Zs]) :- {Z=0}, zero(Zs). lin_comb([], [], S1, S1). lin_comb([Ps|Rest], [K|Ks], S1, S3) :- lin_comb_r(Ps, K, S1, S2), lin_comb(Rest, Ks, S2, S3). lin_comb_r([], _, [], []). lin_comb_r([P|Ps], K, [S|Ss], [Kps|Ss1]) :- { Kps = K*P+S }, lin_comb_r(Ps, K, Ss, Ss1).
we can post the following query:
     clp(q) ?- conv_hull([ [1,1], [2,0], [3,0], [1,2], [2,2] ], [X,Y]).
     
     {Y=<2},
     {X+1/2*Y=<3},
     {X>=1},
     {Y>=0},
     {X+Y>=2}
     
This answer is easily verified graphically:
            |
          2 -    *    *
            |
            |
          1 -    *
            |
            |
          0 -----|----*----*----
                 1    2    3
     
The convex hull program directly corresponds to the mathematical definition of the convex hull. What does the trick in operational terms is the implicit elimination of the Lambdas from the program formulation. Please note that this program does not limit the number of points or the dimension of the space they are from. Please note further that quantifier elimination is a computationally expensive operation and therefore this program is only useful as a benchmark for the projector and not so for the intended purpose.