Prolog is and =. Why don't they work the same way as the logical constraints? - prolog

I'm still very new to prolog, and am trying to wrap my head around why math constraints don't seem to work the same way logical ones do.
It seems like there's enough information to solve this:
f(A, B) :- A = (B xor 2).
But when I try f(C, 3), I get back C = 3 xor 2. which isn't very helpful. Even less useful is the fact that it simply can't find a solution if the inputs are reversed. Using is instead of = makes the example input return the correct answer, but the reverse refuses to even attempt anything.
From my earlier experimentation, it seems that I could write a function that did this logically using the binary without trouble, and it would in fact go both ways. What makes the math different?
For reference, my first attempt at solving my problem looks like this:
f(Input, Output) :-
A is Input xor (Input >> 11),
B is A xor ((A >> 7) /\ 2636928640),
C is B xor ((B << 15) /\ 4022730752),
Output is C xor (C >> 18).
This works fine going from input to output, but not the other way around. If I switch the is to =, it produces a long logical sequence with values substituted but can't find a numerical solution.
I'm using swi-prolog which has xor built in, but it could just as easily be defined. I was hoping to be able to use prolog to work this function in both directions, and really don't want to have to implement the logical behaviors by hand. Any suggestions about how I might reformulate the problem are welcome.

Pure Prolog is not supposed to handle math. The basic algorithm that drives Prolog - Unify and backtrack on failure - Doesn't mention arithmetic operators. Most Prolog implementations add arithmetics as an ugly hack into their bytecode.
The reason for this is that arithmetic functions do not act the same way as functors. They cannot be unified in the same way. Not every function is guaranteed to work for each combination of ground and unground arguments. For example, the algorithm for raising X to the power of Y is not symmetric to finding the Yth root of X. If all arithmetic functions were symmetric, encryption and cryptography wouldn't work!
That said, here are the missing facts about Prolog operators:
First, '=' is not "equals" in Prolog, but "unify". The goal X = Y op Z where op is an operator, unifies X with the functor 'op'(Y,Z). It has nothing to do with arithmetic equality or assignment.
Second, is, the ugly math hack, is not guaranteed to be reversible. The goal X is Expr, where Expr is an arithmetic expression, first evaluates the expression and then tries to assign it to X. It won't always work for each combination of numbers and variables - Check your Prolog library documentation.
To summarize:
Writing reversible mathematical functions requires the mathematical knowledge and algorithm to make the function reversible. Prolog won't do the magic for you in this case.
If you're looking for smart equation solving, you might want to check Prolog constraint-solving libraries for finite and contiguous domains. Not the same thing as reversible math, but somewhat smarter than Prolog's naive arithmetic operators.

If you want to compare the result of evaluating expression, you should use the operator (=:=)/2, or when checking for apartness the operator (=/=)/2.
The operator works also for bitwise operations, since bitwise operations work on integeres, and integers are numbers. The operator is part of the ISO core standard. For the following clause:
f(A, B) :- A =:= (B xor 2).
I get the following runs, in SWI-Prolog, Jekejeke Prolog etc..:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.31)
Copyright (c) 1990-2016 University of Amsterdam, VU Amsterdam
?- f(100, 102).
true.
?- f(102, 100).
true.
?- f(100, 101).
false.
If you want a more declarative way of handling bits, you can use a SAT solver integrated into Prolog. A good SAT solver should also support limited or unlimited bit vectors, but I cant currenty tell whats available here and what the restrictions would be.
See for example this question here:
Prolog SAT Solver

Related

Real numbers not working in Prolog

I have following code:
:-use_module(library(clpfd)).
afn(A,B,C):-
C #= B*A.
It works all right with integers but not with decimal numbers:
43 ?- afn(20, 10, C).
C = 200.
44 ?- afn(20, -10, C).
C = -200.
45 ?- afn(20, -10.5, C).
ERROR: Domain error: `clpfd_expression' expected, found `-10.5'
46 ?-
How can I work with decimals also here? Thanks.
Edit: I find following works with decimals:
afn(A,B,C):-
C is B * A.
67 ?- afn(20.895, 40.5, C).
C = 846.2475.
Is 'is' a correct approach ?!
CLP(FD) implements reasoning over integers.
To extend declarative arithmetic to decimal numbers, you have basically two options:
use a dedicated constraint solver over rationals. See CLP(Q).
scale all numbers so that only integers arise and continue using CLP(FD).
I have seen both approaches successfully applied. Option (2) is sometimes preferable because CLP(FD) is more widely available, and also because you can successfully solve non-linear constraints with it over finite domains.
EDIT: In your case, a suitable query could look like:
?- afn(200, -105, C).
C = -21000.
At the end, you have to scale the results again. This way, you can simulate decimals via integers.
Note that resorting to floats is not a good solution at all, since you cannot really trust the results. Therefore, either use rational numbers or integers, as long as more advanced formats are not yet widely available in Prolog systems.
You have to distinguish
Functional (or "moded") arithmetic. This is the one you are familiar with from other programming languages: You know which of your arguments are input and which is output, and you simply compute the output from the inputs. That's what you get from is/2 (which is part of standard Prolog), and if that's all you want to do, stick with it.
?- A=3, B=1.5, C is B * A.
C = 4.5
?- A=3, C=4.5, C is B * A.
instantiation fault <<< input B not kown
Relational arithmetic. Here, you state an equation or inequation that must hold between the variables involved. There is no notion of input/output arguments. The system's job is instead to make sure that all the stated relations hold at the time a solution for the variables is presented.
There are many different ways to implement relational arithmetic, and many methods only work for subsets of the problem (e.g. only integers, or only linear expressions), therefore these features are typically provided in the form of libraries.
One available implementation of general relational arithmetic over the real numbers is ECLiPSe's library(ic) (see 2, 3), which represents real numbers as floating point intervals:
?- A=3, C=4.5, C $= B * A.
B = 1.5__1.5 <<< precise result
?- C $= B * A, C=1, A=10.
B = 0.099999999999999992__0.1 <<< imprecise but accurate result
There are 2 delayed goals.
?- ln(X) $>= sin(X).
X = X{0.36787944117144228 .. 1.0Inf} <<< partially solved
There are 3 delayed goals.
Having said that, using interval arithmetic and interpreting results correctly is not always straightforward, that's why the kind of workarounds suggested by #mat can be useful (when applicable).

Minor inconsistency due to different operator precedence of ** and ^

Why is argument precendence of **/2 (xfx) and (^)/2 (xfy) not the same in Prolog?
This causes minor inconsistencies, such as the following:
?- X = 1, Y is 1 ^ -X.
X = Y, Y = 1.
and:
?- Y is 1 ** -1.
Y = 1.
but:
?- X = 1, Y is 1 ** -X.
ERROR: Syntax error: Operator priority clash
ERROR: X = 1, Y is 1 *
ERROR: ** here **
ERROR: * -X .
Minor point: It's (^)/2 and not ^/2 to indicate that ^ is used as an operator and to make it valid Prolog syntax and a predicate indicator (7.1.6.6).
(**)/2 and (^)/2 are both evaluable functors (9), so they can be used for Arithmetic evaluation (8.7) with (is)/2 and Arithmetic comparison (8.7) with (=:=)/2, (<)/2 and the like. Their definitions differ slightly.
(**)/2 always gives back a float in the same way as (/)/2 always gives a float. (SWI does not follow the standard here, it has its own conventions).
?- X is 2**2.
X = 4.0.
?- X is 2/2.
X = 1.0.
(^)/2 is here to permit integer exponentiation which has become much more important with many systems now supporting arbitrarily large integers. Think of 2^2^X. That is, if both arguments are integers, the result is an integer as well, in the same way that (*)/2 handles this case.
?- X is 2^2, Y is 2*2.
X = 4, Y = 4.
?- X is 2.0^2, Y is 2.0*2.
X = 4.0, Y = 4.0.
In those cases where (^)/2 would give a real value with two integer arguments (like 2^ -1), a type error is produced, and then there are more errors for otherwise complex or undefined results.
(^)/2 was used for exponentiation for quite some time.
An early use of the exponentiation operator is in D.H.D. Warren's Thesis of 1977 in the example for symbolic differentiation. (It is at least not mentioned in Philippe Roussel's 1975 manual). Throughout the thesis and the 1978 User's guide, the ~ character is used consistently where one would expect a ^ like in integers are restricted to the range -2~17 to 2~17-1 , ie. -131072 to 131071. The declaration was the following and is unchanged since 1982.
:- op(300, xfy, ~). % 1977
:- op(200, xfy, ^). % 1982 - today
From 1982 on, it was used in quantification of setof/3 and bagof/3 but also as lambdas in natural language parsers. For all these uses it already had the right associativity and priority. As an evaluable functor it was present in several systems.
The first system to use (^)/2 as an evaluable functor meaning power is probably C-Prolog.
Compared to this heritage, the (**)/2 appeared in Prolog relatively late, most probably inspired by Fortran. It was proposed for inclusion (N80 1991-07, Paris papers) shortly before the first Committee Draft (CD 1992). Systems provided it also as exp/2.
(**)/2 has the same priority as (^)/2 but does not have any associativity, which at first might strike as odd, since there are quite some cases, where it is common to have exponentiation twice. Most prominently, the Gaussian function in its simplest form
e-x2
Instead of using the constant e and exponentiation, a special evaluable functor exp/1 is provided. Above is thus written as exp(- X**2). In fact, also Wikipedia uses this notation. Given this functor, there are no needs for associativity in this common case.
Should there actually be one, I would be very interested to see it.
Compared to other systems it seems quite common to offer two kinds of exponentiation. Think of Haskell which has ^ and **.
To conclude: There does not seem to be a frequent case where nested float exponentiation is needed. So minimal support seems to be preferable.
#false answered your first question.
The example you give is due to the following difference:
?- integer(-1).
true.
?- X = 1, integer(-X).
false.
and the following precedences:
?- current_op(X, xfx, **).
X = 200.
?- current_op(X, fy, -).
X = 200.
The reason (not justification) for the inconsistency is that in the original standard from 1995 only **/2 was an arithmetic exponentiation operator, while ^/2 was only used for quantifying variables in bagof/3 and setof/3. For the latter use, it made sense to have right-associativity, so you could write X^Y^foo(X,Y,Z). Why **/2 was not given xfy associativity I don't know (it would have been consistent with Fortran, for instance).
The ^/2 as an exponentiation operator was added in a 2012 "corrigendum", without revising the syntax, leading to the current inconsistency.
But note that you can simply fix this yourself by adding a directive
:- op(200, xfy, **).
This is unlikely to cause any problems. Moreover, in many modern Prologs operator declarations are effective only locally in a module.

Does Prolog use Eager Evaluation?

Because Prolog uses chronological backtracking(from the Prolog Wikipedia page) even after an answer is found(in this example where there can only be one solution), would this justify Prolog as using eager evaluation?
mother_child(trude, sally).
father_child(tom, sally).
father_child(tom, erica).
father_child(mike, tom).
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).
With the following output:
?- sibling(sally, erica).
true ;
false.
To summarize the discussion with #WillNess below, yes, Prolog is strict. However, Prolog's execution model and semantics are substantially different from the languages that are usually labelled strict or non-strict. For more about this, see below.
I'm not sure the question really applies to Prolog, because it doesn't really have the kind of implicit evaluation ordering that other languages have. Where this really comes into play in a language like Haskell, you might have an expression like:
f (g x) (h y)
In a strict language like ML, there is a defined evaluation order: g x will be evaluated, then h y, and f (g x) (h y) last. In a language like Haskell, g x and h y will only be evaluated as required ("non-strict" is more accurate than "lazy"). But in Prolog,
f(g(X), h(Y))
does not have the same meaning, because it isn't using a function notation. The query would be broken down into three parts, g(X, A), h(Y, B), and f(A,B,C), and those constituents can be placed in any order. The evaluation strategy is strict in the sense that what comes earlier in a sequence will be evaluated before what comes next, but it is non-strict in the sense that there is no requirement that variables be instantiated to ground terms before evaluation can proceed. Unification is perfectly content to complete without having given you values for every variable. I am bringing this up because you have to break down a complex, nested expression in another language into several expressions in Prolog.
Backtracking has nothing to do with it, as far as I can tell. I don't think backtracking to the nearest choice point and resuming from there precludes a non-strict evaluation method, it just happens that Prolog's is strict.
That Prolog pauses after giving each of the several correct answers to a problem has nothing to do with laziness; it is a part of its user interaction protocol. Each answer is calculated eagerly.
Sometimes there will be only one answer but Prolog doesn't know that in advance, so it waits for us to press ; to continue search, in hopes of finding another solution. Sometimes it is able to deduce it in advance and will just stop right away, but only sometimes.
update:
Prolog does no evaluation on its own. All terms are unevaluated, as if "quoted" in Lisp.
Prolog will unfold your predicate definitions as written and is perfectly happy to keep your data structures full of unevaluated uninstantiated holes, if so entailed by your predicate definitions.
Haskell does not need any values, a user does, when requesting an output.
Similarly, Prolog produces solutions one-by-one, as per the user requests.
Prolog can even be seen to be lazier than Haskell where all arithmetic is strict, i.e. immediate, whereas in Prolog you have to explicitly request the arithmetic evaluation, with is/2.
So perhaps the question is ill-posed. Prolog's operations model is just too different. There are no "results" nor "functions", for one; but viewed from another angle, everything is a result, and predicates are "multi"-functions.
As it stands, the question is not correct in what it states. Chronological backtracking does not mean that Prolog will necessarily backtrack "in an example where there can be only one solution".
Consider this:
foo(a, 1).
foo(b, 2).
foo(c, 3).
?- foo(b, X).
X = 2.
?- foo(X, 2).
X = b.
So this is an example that does have only one solution and Prolog recognizes that, and does not attempt to backtrack. There are cases in which you can implement a solution to a problem in a way that Prolog will not recognize that there is only one logical solution, but this is due to the implementation and is not inherent to Prolog's execution model.
You should read up on Prolog's execution model. From the Wikipedia article which you seem to cite, "Operationally, Prolog's execution strategy can be thought of as a generalization of function calls in other languages, one difference being that multiple clause heads can match a given call. In that case, [emphasis mine] the system creates a choice-point, unifies the goal with the clause head of the first alternative, and continues with the goals of that first alternative." Read Sterling and Shapiro's "The Art of Prolog" for a far more complete discussion of the subject.
from Wikipedia I got
In eager evaluation, an expression is evaluated as soon as it is bound to a variable.
Then I think there are 2 levels - at user level (our predicates) Prolog is not eager.
But it is at 'system' level, because variables are implemented as efficiently as possible.
Indeed, attributed variables are implemented to be lazy, and are rather 'orthogonal' to 'logic' Prolog variables.

Defining the material conditional in Prolog

I have been trying to acclimate to Prolog and Horn clauses, but the transition from formal logic still feels awkward and forced. I understand there are advantages to having everything in a standard form, but:
What is the best way to define the material conditional operator --> in Prolog, where A --> B succeeds when either A = true and B = true OR B = false? That is, an if->then statement that doesn't fail when if is false without an else.
Also, what exactly are the non-obvious advantages of Horn clauses?
What is the best way to define the material conditional operator --> in Prolog
When A and B are just variables to be bound to the atoms true and false, this is easy:
cond(false, _).
cond(_, true).
But in general, there is no best way because Prolog doesn't offer proper negation, only negation as failure, which is non-monotonic. The closest you can come with actual propositions A and B is often
(\+ A ; B)
which tries to prove A, then goes on to B if A cannot be proven (which does not mean that it is false due to the closed-world assumption).
Negation, however, should be used with care in Prolog.
Also, what exactly are the non-obvious advantages of Horn clauses?
That they have a straightforward procedural reading. Prolog is a programming language, not a theorem prover. It's possible to write programs that have a clear logical meaning, but they're still programs.
To see the difference, consider the classical problem of sorting. If L is a list of numbers without duplicates, then
sort(L, S) :-
permutation(L, S),
sorted(S).
sorted([]).
sorted([_]).
sorted([X,Y|L]) :-
X < Y,
sorted([Y|L]).
is a logical specification of what it means for S to contain the elements of L in sorted order. However, it also has a procedural meaning, which is: try all the permutations of L until you have one that it sorted. This procedure, in the worst case, runs through all n! permutations, even though sorting can be done in O(n lg n) time, making it a very poor sorting program.
See also this question.

What does the s() predicate do in Prolog?

I have been trying to learn Prolog, and am totally stumped on what the predicate s() does.
I see it used often and there is so little resources on the internet about Prolog that I cannot find an answer.
Ex.
/* sum(Is,S) is true if S is the sum of the list of integers Is. */
sum([],0).
sum([0|Is],S):-sum(Is,S).
sum([s(I)|Is], s(Z) ):-sum([I|Is],Z).
s/1 does not do anything in itself, and it's not really a predicate. They are just terms, a representation of the successor of their argument. So, s(0) is used to represent the successor of 0 (i.e. 1), s(s(0)) is used to represent the successor of s(0) (i.e. 2), and so on and so forth. They are so widespread in Prolog because Prolog is quite fine a language to perform symbolic computation, whereas even simple arithmetic operations feel clunky, meaning that they are not seamlessly integrated with the programming paradigm.
s/1 stands for successor. It's used to represent numbers in a logically accessible ways.
It is Prolog-implementation specific. It refers to a successor-predicate, see this for some more info

Resources