Finding bounds for 21-variable inequalities
I have the following inequalities on 21 variables:
http://pastebin.com/raw.php?i=FTU970Em
When I run "Reduce[ineq,Integers]" on this, Mathematica hangs for a long time.
That makes sense: there are MANY sets of values for x[1]..x[21] that satisfy the inequalities.
All I really want is bounds for each variable (eg, "2 <= x[i] <= 7" for each i).
How can I get this efficiently w/ Mathematica? Is there a better program for this?
Note: this is part of the larger project:
Partially re-create Risk-like game based on incomplete log files
The entire hideous list of inequalities: http://pastebin.com/CyX9f70J
Running "Reduce[ineq,Intege开发者_如何学Gors]" on the above yields "false", so I've probably incorrectly translated: http://conquerclub.barrycarter.info/ONEOFF/7460216.html
I second the CLP(FD) suggestion given in the other thread. Using SWI-Prolog 5.10:
:- use_module(library(clpfd)).
vars([X0,X1,X2,X3,X4,X5,X6,X7,X8,X9,X10,X11,X12,X13,X14,X15,X16,X17,X18,
X19,X20,X21]) :-
X0 #= 3, X1 #>= 1, X1 #=< X0, X2 #>= 1, X2 #=< X1,
X3 #>= 1, X3 #=< X2, X4 #>= 1, X4 #=< X3, X5 #=< X4 + 3,
X5 #>= 1, X6 #>= 1, X6 #=< X5, X7 #>= 1, X7 #=< X6,
X8 #>= 1, X8 #=< X7, X9 #>= 1, X9 #=< X8, X10 #>= 1,
X10 #=< X9, X11 #>= 1, X11 #=< X10, X12 #>= 1, X12 #=< X11,
X13 #>= 1, X13 #=< X12, X14 #=< X13 + 4, X14 #>= 1, X15 #>= 1,
X15 #=< X14, X16 #>= 1, X16 #=< X15, X17 #=< X16 + 6, X17 #>= 1,
X18 #>= 1, X18 #=< X17, X19 #>= 1, X19 #=< X18, X20 #>= 1,
X20 #=< X19, X21 #>= 1, X21 #=< X20, X21 #= 1.
Example queries:
?- vars(Vs), maplist(fd_dom, Vs, Ds).
Ds = [3..3, 1..3, 1..3, 1..3, 1..3, 1..6, 1..6, 1..6, ... .. ...|...]
?- vars(Vs), label(Vs).
Vs = [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ;
Vs = [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1] ;
Vs = [3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1] ;
etc.
It's late enough that there are probably a number of slick reductions, but this works...
ineq={...}; pivotAt[set_, j_] := Select[set, And[ Not[FreeQ[#, x[u_] /; u <= j]], FreeQ[#, x[u_] /; u > j] ] &] triangularize[set_] := Module[{left, i, new}, left = set; Reap[ For[i = 0, i <= 21, i++, new = pivotAt[left, i]; Sow[new]; left = Complement[left, new]; ]][[2, 1]] ] Module[{ tri, workingIntervals, partials, increment, i }, tri = triangularize[ineq]; workingIntervals[set_] := set /. { t_ <= c_ :> {t, Interval[{-\[Infinity], Max[c]}]}, t_ == c_ :> {t, Interval[{Min[c], Max[c]}]}, t_ >= c_ :> {t, Interval[{Max[c], \[Infinity]}]}}; partials = {}; increment[slice_] := Rule[#[[1, 1]], IntervalIntersection @@ #[[All, 2]]] &[ workingIntervals[slice /. partials ] ]; For[i = 1, i <= Length[tri], i++, partials = Join[partials, {increment[tri[[i]]]}]; ]; partials ]
It's permissive in that correlations between variables ("this high means that low") are not accounted.
-- EDIT --
The result of the above is, of course
{x[0] -> Interval[{3, 3}], x[1] -> Interval[{1, 3}], x[2] -> Interval[{1, 3}], x[3] -> Interval[{1, 3}], x[4] -> Interval[{1, 3}], x[5] -> Interval[{1, 6}], x[6] -> Interval[{1, 6}], x[7] -> Interval[{1, 6}], x[8] -> Interval[{1, 6}], x[9] -> Interval[{1, 6}], x[10] -> Interval[{1, 6}], x[11] -> Interval[{1, 6}], x[12] -> Interval[{1, 6}], x[13] -> Interval[{1, 6}], x[14] -> Interval[{1, 10}], x[15] -> Interval[{1, 10}], x[16] -> Interval[{1, 10}], x[17] -> Interval[{1, 16}], x[18] -> Interval[{1, 16}], x[19] -> Interval[{1, 16}], x[20] -> Interval[{1, 16}], x[21] -> Interval[{1, 1}]}
Are there many sets of values which satisfy the inequalities ?
I ran the following commands through Mathematica:
In[14]:= ineqs = {x0 == 3, x1 >= 1, x1 <= x0, x2 >= 1, x2 <= x1,
x3 >= 1, x3 <= x2, x4 >= 1, x4 <= x3, x5 <= x4 + 3, x5 >= 1,
x6 >= 1, x6 <= x5, x7 >= 1, x7 <= x6, x8 >= 1, x8 <= x7, x9 >= 1,
x9 <= x8, x10 >= 1, x10 <= x9, x11 >= 1, x11 <= x10, x12 >= 1,
x12 <= x11, x13 >= 1, x13 <= x12, x14 <= x13 + 4, x14 >= 1,
x15 >= 1, x15 <= x14, x16 >= 1, x16 <= x15, x17 <= x16 + 6,
x17 >= 1, x18 >= 1, x18 <= x17, x19 >= 1, x19 <= x18, x20 >= 1,
x20 <= x19, x21 >= 1, x21 <= x20, x21 == 1};
In[15]:= vars =
Union[{x0, x1, x1, x2, x2, x3, x3, x4, x4, x5, x5, x6, x6, x7, x7,
x8, x8, x9, x9, x10, x10, x11, x11, x12, x12, x13, x13, x14, x14,
x15, x15, x16, x16, x17, x17, x18, x18, x19, x19, x20, x20, x21,
x21, x21}];
In[16]:= FindInstance[ineqs, vars]
and got the result:
Out[16]= {{x0 -> 3, x1 -> 1, x10 -> 1, x11 -> 1, x12 -> 1, x13 -> 1,
x14 -> 1, x15 -> 1, x16 -> 1, x17 -> 1, x18 -> 1, x19 -> 1, x2 -> 1,
x20 -> 1, x21 -> 1, x3 -> 1, x4 -> 1, x5 -> 1, x6 -> 1, x7 -> 1,
x8 -> 1, x9 -> 1}}
I haven't been able to persuade Mathematica to provide another set of assignments and a little work with pencil and paper doesn't point me towards other sets of assignments. But it's late here, I may have missed something obvious.
OK, it turns out that solving this particular set of equations is easy, once you rewrite some of them slightly:
x5 <= x4 + 3 becomes x5 - 3 <= x4
x6 <= x5 becomes x6 - 3 <= x5 - 3
and so on until:
x13 <= x12 becomes x13 - 3 <= x12 - 3
x14 <= x13 + 4 becomes x14 - 7 <= x13 -3
By doing this, {x0, x1, x2, x3, x4, x5-3, x6-3, ..., x13-3, x14-7, ..., x21} becomes a strictly decreasing sequence of integers starting at 3 and ending at 1.
In fact, any sequence w/ that property works, since xi>=1 is trivally satisfied.
However, while this works to solve this particular set of inequalities, it doesn't work in general, so I don't consider it a complete solution.
精彩评论