Handle huge numeric values prolog - prolog

I'm working with prolog and i need to handle huge numerical values (i know, prolog is not originaly designed to handle numbers). I'm using ECLiPSe 6.1 and the documentation of some built in predicates as fd_global:ordered_sum\2 says:
Any input variables which do not already have finite bounds will be given default bounds of -10000000 to 10000000
How can i handle value greater than 10000000? (In general, not necessarily with ECLiPSe).

If you use library(ic), then generally variables get infinite bounds by default, when used in the basic constraints:
?- lib(ic).
Yes (0.13s cpu)
?- sum([X,Y,Z]) #= 0.
X = X{-1.0Inf .. 1.0Inf}
Y = Y{-1.0Inf .. 1.0Inf}
Z = Z{-1.0Inf .. 1.0Inf}
There is 1 delayed goal.
Yes (0.00s cpu)
However, the algorithms in some of the global constraint implementations cannot handle infinite bounds, and therefore impose the default bounds you mention:
?- ic_global:ordered_sum([X,Y,Z], 0).
X = X{-10000000 .. 0}
Y = Y{-5000000 .. 5000000}
Z = Z{0 .. 10000000}
There are 5 delayed goals.
Yes (0.06s cpu)
To avoid this, you can initialize the variables with larger finite bounds before invoking the global constraint:
?- [X,Y,Z] :: -1000000000000000..1000000000000000, ic_global:ordered_sum([X,Y,Z], 0).
X = X{-1000000000000000 .. 0}
Y = Y{-500000000000000 .. 500000000000000}
Z = Z{0 .. 1000000000000000}
There are 5 delayed goals.
Yes (0.00s cpu)

Related

Get a value from residual goals

If I have X #> 3. Prolog will give the residual goal X in 4..sup.. How can I assign X one of the possible values from 4 to sup? Any random value will suffice.
In SWI-Prolog,you can get random value assign with using secret option random_value(Seed).
see this:How does `random_variable `random_value` work in SWI-Prolog's labeling/2?
:- use_module(library(clpfd)).
random_labeling_test(A):-
A in 1..5,
labeling([random_value(332)],[A]).
?- random_labeling_test(A).
A = 5 ;
A = 1 ;
A = 2 ;
A = 4 ;
A = 3.
332 is meaningless.Set random seed into here.current milliseconds is often used .
I'm not sure this option is safe.
But in your case,this cannot work because upper bounds is infinite.It is reasonable.
In ECLiPSe, labeling variable selection and assigning value selection is completly controllable with using indomain and delete.
see this:http://eclipseclp.org/doc/tutorial/tutorial088.html
One naive way to solve this is to use a predicate like this:
enumeration(Z) :-
length(_, N),
enumeration_(N, Z).
enumeration_(N, N).
enumeration_(N0, N) :- N #= -N0.
You can now solve your task as follows:
?- X #> 3, enumeration(X).
X = 4 ;
X = 5 ;
X = 6 ;
X = 7 ;
X = 8 .
Pros:
a quite simple solution
portable to different Prolog systems.
Con:
potentially quite slow.
Example:
?- X #> 2^100, enumeration(X).
[waiting...]
To make this more efficient, you need to take into account the actual domains of variables.
There are at least two ways to do this:
(a) Use your solver's reflection predicates
Reflection predicates let you reason about the actual domains of variables by making them available as Prolog terms.
For example, where available, you can use fd_inf/2 to obtain the infimum of a constrained variable's domain:
?- X #> 3, fd_inf(X, Inf).
Inf = 4,
X in 4..sup.
You can use this as a starting point for the enumeration. I leave this as a challenge.
See your Prolog system's manual for more information about its reflection predicates.
(b) Inspect the residual goals
Alternatively, you can inspect the residual goals as Prolog terms. This is also a reflection mechanism, though one that only needs a single predicate for all kinds of different constraint solvers.
For example, where available, you can use copy_term/3 to obtain the residual goals as a list of Prolog goals:
?- X #> 3, copy_term(X, X, Gs).
Gs = [clpfd:(X in 4..sup)],
X in 4..sup.
From these goals, it is again straight-forward to deduce the infimum of X's domain.
Note that the top-level can use this same mechanism to actually produce the residual goals.

How can I assert facts about all List members in Prolog?

I'd like to assert facts about all members of a List in prolog, and have any resulting unification retained. As an example, I'd like to assert that each list member is equal to five, but none of the below constructs does this:
?- L=[X,Y,Z], forall(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
?- L=[X,Y,Z], foreach(member(E,L), E=5).
L = [_h27057686,_h27057704,_h27057722]
X = _h27057686
Y = _h27057704
Z = _h27057722
yes
I would like a way to pose the query such that X=5,Y=5, and Z=5.
There is a lot of terminology that you might be getting wrong, or I am misunderstanding you.
"Equal to" is not the same as "could unify", or "unify", but it depends how you mean it.
With SWI-Prolog, from the top level:
?- X == 5.
false. % the free variable X is not the integer 5
?- unifiable(X, 5, U).
U = [X=5]. % you could unify X with 5, then X will be 5
?- X = 5.
X = 5. % X unifies with 5 (and is now bound to the integer 5)
The comment by CapelliC already has the answer that you are most likely after: given a list of variables (either free or not), make so that each variable in the list is bound to the integer 5. This is best done by unification (the third query above). The maplist simply applies the unification to each element of the list.
PS. In case you are wondering how to read the maplist(=(5), L):
These three are equivalent:
maplist(=(5), [X,Y,Z])
maplist(=, [5,5,5], [X,Y,Z])
X=5, Y=5, Z=5
And of course X=5 is the same as =(X,5).

Prolog Use of Cuts

I am re-writing the following function in Prolog:
V1:
f(X,Y):- X < 2, Y is X+1.
f(X,3):- 2 =< X, X < 5.
f(X,Y):- 5 =< X, Y is 8-X.
As V2:
f(X,Y) :-
X < 2,
Y is X + 1.
f(X,Y) :-
X >= 2,
X < 5,
Y is 3.
f(X,Y) :-
X >= 5,
Y is 8-X.
I then wanted to experiment with cuts. For green cuts (V3):
f(X,Y) :-
X < 2, !,
Y is X + 1.
f(X,Y) :-
X >= 2,
X < 5, !,
Y is 3.
f(X,Y) :-
X >= 5,
Y is 8-X.
For red cuts (V4):
f(X,Y) :-
X < 2, !,
Y is X + 1.
f(X,Y) :-
X < 5, !,
Y is 3.
f(X,Y) :-
Y is 8-X.
However, I don't understand their advantage, as deleting the cuts would allow the same behaviour of the code... Any help?
All your versions V1..V4 are observationally equivalent, so you got some reasoning right. Still, there are differences.
Avoiding superfluous choice points
In many implementations, V1 and V2 might be particularly less efficient, for, internally, they "leave open a choice point". This is so because such Prologs do not look any further to the other rules. So each goal f(1,X) consumes a bit of memory that can be freed only on backtracking (or using !). Here is a simple way to try this out yourself:
loop(Goal) :-
Goal,
loop(Goal).
Here is what I get in SWI:
?- time(loop(f1(1,2))).
% 5,991,554 inferences, 81.282 CPU in 81.443 seconds (100% CPU, 73713 Lips)
ERROR: Out of local stack
?- time(loop(f2(1,2))).
% 5,991,553 inferences, 85.032 CPU in 85.212 seconds (100% CPU, 70462 Lips)
ERROR: Out of local stack
Whereas V3 and V4 seem to run indefinitely - at least much longer than 85s. Experiments such as this one are funny for very tiny programs but are not very practical for bigger ones. Fortunately, there is a simple way to tell in many Prologs whether or not a query is executed determinately. To see if your system does this, enter:
?- X = 1.
X = 1.
For your variations:
?- f1(1,2).
true
; % <== Prolog asked for another answer
false. % <== only to conclude that there is none.
?- f2(1,2).
true
; false. % same again
?- f3(1,2).
true. % <== Prolog knows there will be no further answer
?- f4(1,2).
true.
Avoiding recalculations - making cuts red
While V3 avoids superfluous choice points, V4 now even avoids superfluous calculations. So it should be the most efficient. But it comes at the price of fixing the order of the clauses.
However, V3 was only possible, because two necessary conditions for green cuts coincided:
Non-overlapping conditions. That should be obvious to you.
Safe testing of instantiations. This is far from obvious. Please note that the goal X < 2 has an implicit test for a correct instantiation attached! It produces an instantiation error should X be an uninstantiated variable. It is because of this very test that the cut in V3 happens to be a green cut. Without that testing, it would be a red cut.
Note also that V1 and V2 would not be equivalent, if the second rule would be alone! For the goal f(X,5). would fail in V1 but it would produce an error in V2.
As you noted the first version shows green cuts and the second red cuts.
It is not necessary that you will feel the difference between these two versions.
a) one reason can be efficiency, but for toy codes with fast machines you hardly notice it.
b) shuffling the rules should not change code's behavior in case of green cuts, and that's true for the first code. But in the second code, if you put the second clause before the first one than the behavior changes: f(0,3) is true, but initially it was false. Therefore you would feel difference if you shuffle the rules.
Advantage of shuffling is that you don't care about order but content - that's one of the points declarative programing.

Generating integers < limit

I am trying to generate all integers (natural numbers) smaller than a limit, let's say 10.
I have a predicate nat(X) which produces all numbers from 0 to infinity.
Now my problem is, if I do:
nat10(X) :- nat(X), X =< 10.
This will never terminate, as it tries to find other solutions with nat(X) until infinity.
I need a construct that let's me fail the whole predicate if one subgoal fails. How would I go about doing that?
Depending upon the problem being solved, you might want to consider constraint logic programming over finite domains (CLPFD).
But in this context, you need just prevent Prolog from backtracking if X > 10. The current predicate nat10/1 has no such constraint, so we'll add it:
nat10(X) :- nat(X), ( X > 10 -> !, fail ; true ).
So if X > 10, we do a cut (!) to prevent backtracking to nat(X) (thus avoiding generating natural numbers above 10 infinitely) and then simply fail. Otherwise, we succeed (true).
| ?- nat10(X).
X = 1 ? ;
X = 2 ? ;
...
X = 9 ? ;
X = 10 ? ;
(3 ms) no
| ?-
If you can use clpfd, then this answer is for you!
:- use_module(library(clpfd)).
Simply try:
nat10(X) :-
X in 0..10,
indomain(X).

Prolog: Random Labeling

I have a program written in Sicstus Prolog using constraints.
My goal is to use labeling/2 and some other method to obtain a random instantiation of my variables.
Example:
X #> 2, Y #= 2*X, Z #<10
If I use
List = [X,Y,Z],
labeling([], List)
The first result obtained will be X = Y = Z = 0. How do you think is the best way to return a random set of values for X, Y and Z?
I do not know much about the labeling options in recent SICStus versions, but with library(clpfd) of SWI-Prolog, there are the options random_variable(Seed) and random_value(Seed), you can use them for example with labeling([random_variable(10),random_value(10)], List). Maybe you can get the authors of SICStus to integrate similar options?
In sicstus, this is done with a custom selection of variables / values.
In your case, just do:
labeling([value(mySelValores)], List)
mySelValores(Var, _Rest, BB, BB1) :-
fd_set(Var, Set),
select_best_value(Set, Value),
(
first_bound(BB, BB1), Var #= Value
;
later_bound(BB, BB1), Var #\= Value
).
select_best_value(Set, BestValue):-
fdset_to_list(Set, Lista),
length(Lista, Len),
random(0, Len, RandomIndex),
nth0(RandomIndex, Lista, BestValue).
See value(Enum) in https://sicstus.sics.se/sicstus/docs/4.0.4/html/sicstus/Enumeration-Predicates.html.
Hope it helps ;)
you can use
all_different([X,Y,Z]) in order to get different values
however, working with random seed in Sicstus could be tricky and you may need to define a function to change the seed or start the random function again.
check below
www.sics.se/sicstus/docs/3.7.1/html/sicstus_23.html
I have opted in Jekejeke Prolog, for a new predicate random_labeling/1 in connection
with CLP(FD) that takes implicitly the random number generator from the knowledge base
that can be accessed and modified via the sys_random Prolog flag.
Jekejeke Prolog 3, Runtime Library 1.3.4
(c) 1985-2019, XLOG Technologies GmbH, Switzerland
?- use_module(library(finite/clpfd)).
% 20 consults and 0 unloads in 944 ms.
Yes
?- use_module(library(basic/random)).
% 0 consults and 0 unloads in 0 ms.
Yes
?- random_new(111,R), set_prolog_flag(sys_random,R),
X in 0..5, Y #= X*X, random_label([X,Y]),
write(X-Y), nl, fail; true.
4-16
3-9
5-25
1-1
2-4
0-0
Yes
?- random_new(111,R), set_prolog_flag(sys_random,R),
X in 0..5, Y #= X*X, random_label([X,Y]),
write(X-Y), nl, fail; true.
4-16
3-9
5-25
1-1
2-4
0-0
I am planning a further predicate random_labeling/2. But it would not take a seed, but instead a Java java.util.Random instance. This is more versatile than a seed. But I guess changing the API to labeling/2 and some options would be the best way to go.
Edit 29.12.2018: I will now take notes, since I guess its a good idea
to adopt indomain/2, currently I have implemented random_indomain/1,
and from this implemented random_label/1. See also here:
indomain/2 from ECLiPSe Prolog
random: Try the enumeration in a random order. On backtracking,
the previously tested value is removed. This method uses random/1 to
create random numbers, use seed/1 before to make results reproducible.
http://eclipseclp.org/doc/bips/lib/gfd_search/indomain-2.html

Resources