Optimisation in swi prolog - prolog

Say I want to find argmax(x,y,z) -1/2(20x^2+32xy +16y^2)+2x+2y.
subject to:
x>=0, y>=0,z>=0 and -x-y+z =0.
I know the partial derivatives being set to 0 is :
-20x-16y+2=0 and -16x-16y+2 =0
so we could have x= 0 and y =1/8 and z=1/8.
How would I do this in Swi-prolog? I see that there is library simplex for linear solving, but this is a quadratic problem but the partial derivatives are not. (I am a bit confused!)
This is what I have:
:- use_module(library(simplex)).
my_constraints(S):-
gen_state(S0),
constraint([-20*x, -16*y] = 0, S0, S1),
constraint([-16*x,-16*y] = 0, S1,S2),
constraint([x] >= 0,S2,S3),
constraint([y] >= 0,S3,S4),
constraint([z] >= 0,S4,S5),
constraint([-x-y+z] = 0,S5,S).
?- my_constraints(S), variable_value(S,x,Val1),variable_value(S,y,Val2).
false.

There are several issues here. First, just to get this out of the way: library(simplex) can only handle linear constraints. So yes, it cannot—at least not directly—be used to solve your actual problem.
But library(simplex) is often useful regardless, and so I want to quickly point out the following:
variable_value/3 only works on the solved tableau. This means that you must have invoked maximize/3 first.
For example:
?- my_constraints(S), maximize([x,y], S, Max), variable_value(Max, x, X).
S = ...,
Max = ...,
X = 0.
Note that you must change the final goal of my_constraint/1 to constraint([-1*x, -1*y,z] = 0, S5, S) to conform to the syntax required by this library.
That being said, let us now get to the core of the issue: There are well-known ways to iteratively solve quadratic optimization problems, using a series of linear programs and reasoning about gradients to get closer to a solution. Thus, library(simplex) can indirectly still be used to solve your problem.
In particular, check out the method of steepest ascent available from miscellaneous programs. It includes a small symbolic derivative calculator written in Prolog. Yes, it's "symbolic" ;-)
Plugging in your task, I get:
?- maximize(- 0.5*(20*x(1)^2 + 32*x(1)*x(2) + 16*x(2)^2) + 2*x(1) + 2*x(2),
[[-1,0,0],
[0,-1,0],
[0,0,-1],
[-1,-1,1],
[1,1,-1]],
[0,0,0,0,0],
[0,0,0], Max).
Max = [4.298588509886033e-17, 0.125, 0.12500000000000006] ;
false.
Which is, up to the unbearable nastiness of floating point arithmetic, something that I hope you can work with.

Related

Combine boolean and integer logic in linear arithmetic using the Z3 Solver?

I would like to solve problems combining boolean and integer logic in linear arithmetic with a SAT/SMT solver. At first glance, Z3 seems promising.
First of all, is it at all possible to solve the following problem? This answer makes it seem like it works.
int x,y,z
boolean a,b,c
( (3x + y - 2z >= 10) OR (A AND (NOT B OR C)) OR ((A == C) AND (x + y >= 5)) )
If so, how does Z3 solve this kind of problem in theory and is there any documentation about it?
I could think of two ways to solve this problem. One would be to convert the Boolean operations into a linear integer expression. Another solution I read about is to use the Nelson-Oppen Combination Method described in [Kro 08].
I found a corresponding documentation in chapter 3.2.2. Solving Arithmetical Fragments, Table 1 a listing of the implemented algorithms for a certain logic.
Yes, SMT solvers are quite good at solving problems of this sort. Your problem can be expressed using z3's Python interface like this:
from z3 import *
x, y, z = Ints('x y z')
A, B, C = Bools('A B C')
solve (Or(3*x + y - 2*z >= 10
, And(A, Or(Not(B), C))
, And(A == C, x + y >= 5)))
This prints:
[A = True, z = 3, y = 0, B = True, C = True, x = 5]
giving you a (not necessarily "the") model that satisfies your constraints.
SMT solvers can deal with integers, machine words (i.e., bit-vectors), reals, along with many other data types, and there are efficient procedures for combinations of linear-integer-arithmetic, booleans, uninterpreted-functions, bit-vectors amongst many others.
See http://smtlib.cs.uiowa.edu for many resources on SMT solving, including references to other work. Any given solver (i.e., z3, yices, cvc etc.) will be a collection of various algorithms, heuristics and tactics. It's hard to compare them directly as each shine in their own way for certain sublogics, but for the base set of linear-integer arithmetic, booleans, and bit-vectors, they should all perform fairly well. Looks like you already found some good references, so you can do further reading as necessary; though for most end users it's neither necessary nor that important to know how an SMT solver internally works.

representing large binary vector as problog fact/rule

In ProbLog, how do I represent the following as p-fact/rule :
A binary vector of size N, where P bits are 1 ? i.e. a bit is ON with probability P/N, where N > 1000
i come up with this, but it seem iffy :
0.02::one(X) :- between(1,1000,X).
Want to use it later to make calculations on what happens if i apply two-or-more operations of bin-vec such as : AND,OR,XOR,count,overlap, hamming distance, but do it like Modeling rather than Simulation
F.e. if I ORed random 10 vec's, what is the probable overlap-count of this unionized vector and a new rand vec
... or what is the probability that they will overlap by X bits
.... questions like that
PS> I suspect cplint is the same.
Another try, but dont have idea how to query for 'single' result
1/10::one(X,Y) :- vec(X), between(1,10,Y). %vec: N=10, P=?
vec(X) :- between(1,2,X). %num of vecs
%P=2 ??
two(A,B,C,D) :- one(1,A), one(2,B), A =\= B, one(1,C), one(2,D), C =\= D.
based on #damianodamiono , so far :
P/N::vec(VID,P,N,_Bit).
prob_on([],[],_,_).
prob_on([H1|T1],[H2|T2],P,N):-
vec(1,P,N,H1), vec(2,P,N,H2),
prob_on(T1,T2,P,N).
query(prob_on([1],[1],2,10)).
query(prob_on([1,2,3,5],[1,6,9,2],2,10)).
I'm super happy to see that someone uses Probabilistic Logic Programming! Anyway, usually you do not need to create a list with 1000 elements and then attach 1000 probabilities. For example, if you want to state that each element of the list has a probabilty to be true of P/N (suppose 0.8), you can use (cplint and ProbLog have almost the same syntax, so you can run the programs on both of them):
0.8::on(_).
in the recursion.
For example:
8/10::on(_).
prob_on([]). prob_on([H|T]):-
on(H),
prob_on(T).
and then ask (in cplint)
?- prob(prob_on([1,2,3]),Prob).
Prob = Prob = 0.512
in ProbLog, you need to add query(prob_on([1,2,3])) in the program. Note the usage of the anonymous variable in the probabilistic fact on/1 (is needed, the motivation may be complicated so I omit it). If you want a probability that depends on the lenght of the list and other variables, you can use flexible probabilities:
P/N::on(P,N).
and then call it in your predicate with
...
on(P,N),
...
where both P and N are ground when on/2 is called. In general, you can add also a body in the probabilistic fact (turning it into a clause), and perform whatever operation you want.
With two lists:
8/10::on_1(_).
7/10::on_2(_).
prob_on([],[]).
prob_on([H1|T1],[H2|T2]):-
on_1(H1),
on_2(H2),
prob_on(T1,T2).
?- prob(prob_on([1,2,3,5],[1,6,9,2]),Prob).
Prob = 0.09834496
Hope this helps, let me know if something is still not clear.

sudoku solver in prolog without clpfd

I have an AI project in which I should make a sudoku solver in Prolog but without using the clpfd package. How should I write the code and is there any way to print whenever a variable gets a value?
Without clpfd, you have to write a classic generate-and-test search. The nice thing about clpfd is that the constraints limit the search space. You can emulate this without using clpfd though. Let's simplify the task a bit so I can illustrate. How can you find X and Y values that solve both of these equations: X + Y = 10, 2*X + Y - 1 = 15?
First, encode your two equations:
eq1(X,Y) :- 10 is X + Y.
eq2(X,Y) :- 15 is 2*X + Y - 1.
Now create your search space in a solver predicate:
solution(X, Y) :-
between(1, 10, X), between(1, 10, Y),
eq1(X,Y),
eq2(X,Y).
Now you can run it and see:
?- solution(X,Y).
X = 6,
Y = 4 ;
false.
This is less efficient than it would be with clpfd because clpfd would notice things about the equations that would help it constrain the search space:
?- [library(clpfd)].
true.
?- X + Y #= 10, 2*X + Y - 1 #= 15.
2*X+Y#=16,
X+Y#=10.
?- X + Y #= 10, 2*X + Y - 1 #= 15, X in 1..10.
X = 6,
Y = 4.
See, it has already figured out that there is only one solution and I didn't have to constrain Y at all. That's very impressive! But you can still use Prolog without clpfd, it's just worse. :) In this example, we probably tried all 10x10=100 possible combinations to find this one solution. Less efficient. But not impossible.
So, what are the constraints you have to figure out for sudoku? Probably something like this:
unique(Row) :- sort(Row, Sorted), length(Row, Length), length(Sorted, Length).
all_digits(Row) :- forall(between(1,9,X), memberchk(X, Row)).
And so forth.
Edit: Combinatorial complexity estimation
Suppose we do a totally unprincipled search: that is, we even try obviously wrong cases like a grid of all 9s. We have 9x9=81 cells and 9 possible values (1-9). This yields 9^81 = a very large number, unlikely to be checked in your lifetime. And most of those grids are going to be fruitless permutations.
Suppose you constrain your search so that each row is a permutation of 1-9. There are 9! permutations of 1-9; with nine of those, you can multiply that outcome by nine, so there should be 9!^9. This is still awful! clpfd is probably able to further winnow this down by combining the 3x3 grid constraints; I'm not sure how I would go about doing that manually, other than in a semi-procedural way, choosing a 3x3 grid permutation and then passing each 3x1 row of that on to the next 3x3 grid selection.
It's worth noting that most of the optimization in classic Prolog programs comes down to either making the generate step generate better-qualified candidates or making the test step less expensive. A more obvious implementation can still be useful for checking a more complex implementation.
Thanks to #mat for checking my math and recommending this excellent article on the combinatorial problem of Sudoku.

Prolog program to get an (integer) number as the sum of two integer squares, why does it not work?

I'm starting learning Prolog and I want a program that given a integer P gives to integers A and B such that P = A² + B². If there aren't values of A and B that satisfy this equation, false should be returned
For example: if P = 5, it should give A = 1 and B = 2 (or A = 2 and B = 1) because 1² + 2² = 5.
I was thinking this should work:
giveSum(P, A, B) :- integer(A), integer(B), integer(P), P is A*A + B*B.
with the query:
giveSum(5, A, B).
However, it does not. What should I do? I'm very new to Prolog so I'm still making lot of mistakes.
Thanks in advance!
integer/1 is a non-monotonic predicate. It is not a relation that allows the reasoning you expect to apply in this case. To exemplify this:
?- integer(I).
false.
No integer exists, yes? Colour me surprised, to say the least!
Instead of such non-relational constructs, use your Prolog system's CLP(FD) constraints to reason about integers.
For example:
?- 5 #= A*A + B*B.
A in -2..-1\/1..2,
A^2#=_G1025,
_G1025 in 1..4,
_G1025+_G1052#=5,
_G1052 in 1..4,
B^2#=_G406,
B in -2..-1\/1..2
And for concrete solutions:
?- 5 #= A*A + B*B, label([A,B]).
A = -2,
B = -1 ;
A = -2,
B = 1 ;
A = -1,
B = -2 ;
etc.
CLP(FD) constraints are completely pure relations that can be used in the way you expect. See clpfd for more information.
Other things I noticed:
use_underscores_for_readability_as_is_the_convention_in_prolog instead ofMixingTheCasesToMakePredicatesHardToRead.
use declarative names, avoid imperatives. For example, why call it give_sum? This predicate also makes perfect sense if the sum is already given. So, what about sum_of_squares/3, for example?
For efficiency sake, Prolog implementers have choosen - many,many years ago - some compromise. Now, there are chances your Prolog implements advanced integer arithmetic, like CLP(FD) does. If this is the case, mat' answer is perfect. But some Prologs (maybe a naive ISO Prolog compliant processor), could complain about missing label/1, and (#=)/2. So, a traditional Prolog solution: the technique is called generate and test:
giveSum(P, A, B) :-
( integer(P) -> between(1,P,A), between(1,P,B) ; integer(A),integer(B) ),
P is A*A + B*B.
between/3 it's not an ISO builtin, but it's rather easier than (#=)/2 and label/1 to write :)
Anyway, please follow mat' advice and avoid 'imperative' naming. Often a description of the relation is better, because Prolog it's just that: a relational language.

Quadratic equation solving in Prolog

I have wrote a code to solve equation with like terms (eg:- x^2+5*x+6=0). Here 'x' has two values. I can take two values by entering ';'. But I need to get the all possible answers when I run the program at once. Is it possible in prolog?
Well for a quadratic equation, if the discriminant is zero, then
there is only one solution, so you can directly compute one or two
solutions, and return them in a list.
The discriminat is the expression under the square root. So the
classical prolog code for a real number solution reads as follows:
solve(A*_^2+B*_+C=0,L) :- D is B^2-4*A*C,
(D < 0 -> L = [];
D =:= 0 -> X is (-B)/(2*A), L = [X];
S is sqrt(D), X1 is (-B-S)/(2*A),
X2 is (-B+S)/(2*A), L=[X1,X2]).
Here is an example run:
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.0)
?- solve(1*x^2+5*x+6=0,L).
L = [-3.0, -2.0].

Resources