Understand a simple recursion in prolog - recursion

I have the following Prolog from the book mastering Prolog, and I'm trying to learn some simple recursion.
mins_to_hours(In, H, M):-
In<60,
H = 0,
M is In.
mins_to_hours(In, H, M):-
In>=60,
In1 is In-60,
H1 is H+1,
mins_to_hours(In1, H1, M).
I'm not entirely sure why it doesn't work and I've been fiddling with it for hours. Any help even to point me in the right direction is much appreciated. Thanks in advance.

A major difficulty you are facing in this example is the so-called modedness of low-level arithmetic predicates. For example, let us try the most general query with the code you posted:
?- mins_to_hours(In, H, M).
ERROR: Arguments are not sufficiently instantiated
To get rid of this shortcoming, I first replace the low-level predicates with CLP(FD) constraints, which are available in all major Prolog systems and simplify reasoning over your code.
For this, I simply replace (<)/2 by (#<)/2, (is)/2 by (#=)/2 etc. (depending on your Prolog system, you may also still have to import a library for this):
mins_to_hours(In, H, M):-
In #< 60,
H = 0,
M #= In.
mins_to_hours(In, H, M):-
In #>= 60,
In1 #= In-60,
H1 #= H+1,
mins_to_hours(In1, H1, M).
Now, let us again try the most general query, where all arguments are fresh variables:
?- mins_to_hours(In, H, M).
In = M,
H = 0,
M in inf..59 ;
H = -1,
In in 60..119,
M+60#=In,
M in 0..59 ;
H = -2,
In in 120..179,
_5238+60#=In,
_5238 in 60..119,
M+60#=_5238,
M in 0..59 .
Here, it seems very odd that H can assume negative values!
Let us try a few concrete cases:
?- mins_to_hours(30, H, M).
H = 0,
M = 30 ;
false.
This still seems quite OK!
?- mins_to_hours(60, H, M).
H = -1,
M = 0 ;
false.
This already seems much less OK!
With a bit of practice, it is easy to see the reason: In the second clause, you are inadvertently confusing the roles of H and H1! Suppose we write the second clause like this:
mins_to_hours(In, H, M):-
In #>= 60,
In1 #= In-60,
H #= H1+1,
mins_to_hours(In1, H1, M).
Then we get:
?- mins_to_hours(60, H, M).
H = 1,
M = 0 ;
false.
And for two more cases:
?- mins_to_hours(500, H, M).
H = 8,
M = 20 ;
false.
?- mins_to_hours(1000, H, M).
H = 16,
M = 40 ;
false.
Seems pretty nice!
Note that if you stick to lower-level arithmetic, you cannot that easily correct the mistake: Using predicates like (<)/2 and (is)/2 requires that you also take into account the actual execution order of Prolog, and this is much too hard for almost all beginners. I highly recommend you use CLP(FD) constraints instead, since they let you readily try the effect of different goal orders, while keeping the relation correct and general.

Related

Coq can't compute well-founded defined with Fix, but can if defined with Program Fixpoint

As an exercise to understand recursion by a well-founded relation I decided to implement the extended euclidean algorithm.
The extended euclidean algorithm works on integers, so I need some
well-founded relation on integers. I tried to use the relations in Zwf, but things didn't worked (I need to see more examples). I decided that would easier to map Z to nat with the Z.abs_nat function and then just use Nat.lt as relation. Our friend wf_inverse_image comes to help me. So here what I did:
Require Import ZArith Coq.ZArith.Znumtheory.
Require Import Wellfounded.
Definition fabs := (fun x => Z.abs_nat (Z.abs x)). (* (Z.abs x) is a involutive nice guy to help me in the future *)
Definition myR (x y : Z) := (fabs x < fabs y)%nat.
Definition lt_wf_on_Z := (wf_inverse_image Z nat lt fabs) lt_wf.
The extended euclidean algorithm goes like this:
Definition euclids_type (a : Z) := forall b : Z, Z * Z * Z.
Definition euclids_rec : (forall x : Z, (forall y : Z,(myR y x) -> euclids_type y) -> euclids_type x).
unfold myR, fabs.
refine (fun a rec b => if (Z_eq_dec a 0) then (b, 0, 1)
else let '(g, s, t) := rec (b mod a ) _ a
in (g, t - (b / a) * s, s)
).
apply Zabs_nat_lt. split. apply Z.abs_nonneg. apply Z.mod_bound_abs. assumption.
Defined.
Definition euclids := Fix lt_wf_on_Z _ euclids_rec.
Now let's see if it works:
Compute (euclids 240 46). (* Computation takes a long time and results in a huge term *)
I know that can happen if some definition is opaque, however all my definitions end with Defined.. Okey, something else is opaque, but what?
If is a library definition, then I don't think that would cool to just redefine it in my code.
It seems that my problem is related with this, this other and this too.
I decided to give Program Fixpoint a try, since I never used it. I was surprised to see that I could just copy and paste my program.
Program Fixpoint euclids' (a b: Z) {measure (Z.abs_nat (Z.abs a))} : Z * Z * Z :=
if Z.eq_dec a 0 then (b, 0, 1)
else let '(g, s, t) := euclids' (b mod a) a in
(g, t - (b / a) * s, s).
Next Obligation.
apply Zabs_nat_lt. split. apply Z.abs_nonneg. apply Z.mod_bound_abs. assumption.
Defined.
And even more surprise to see that works just fine:
Compute (euclids' 240 46). (* fast computation gives me (2, -9, 47): Z * Z * Z *)
What is opaque in euclids that is not in euclids' ?
And how to make euclids work?
Okey, something else is opaque, but what?
wf_inverse_image is opaque and so are the lemmas it relies on: Acc_lemma and Acc_inverse_image. If you make these three transparent euclids will compute.
The evidence of well-foundness is basically your parameter you do structural recursion on, so it must be transparent.
And how to make euclids work?
Fortunately, you don't have to roll your own transparent versions of the aforementioned standard definitions as there is well_founded_ltof lemma in Coq.Arith.Wf_nat which is already transparent so we can reuse it:
Lemma lt_wf_on_Z : well_founded myR.
Proof. exact (well_founded_ltof Z fabs). Defined.
That's it! After fixing lt_wf_on_Z the rest of your code just works.

implementing an algorithm to transform a real number to a continued fraction in #F

i am trying to implement a recursive function which takes a float and returns a list of ints representing the continued fraction representation of the float (https://en.wikipedia.org/wiki/Continued_fraction) In general i think i understand how the algorithm is supposed to work. its fairly simply. What i have so far is this:
let rec float2cfrac (x : float) : int list =
let q = int x
let r = x - (float q)
if r = 0.0 then
[]
else
q :: (float2cfrac (1.0 / r ))
the problem is with the base case obviously. It seems the value r never does reduce to 0.0 instead the algorithm keeps on returning values which are the likes of 0.0.....[number]. I am just not sure how to perform the comparison. How exactly should i go about it. The algorithm the function is based on says the base case is 0, so i naturally interpret this as 0.0. I dont see any other way. Also, do note that this is for an assignment where i am explicitly asked to implement the algorithm recursively. Does anyone have some guidance for me? It would be much appreciated
It seems the value r never does reduce to 0.0 instead the algorithm keeps on returning values which are the likes of 0.0.....[number].
This is a classic issue with floating point comparisons. You need to use some epsilon tolerance value for comparisons, because r will never reach exactly 0.0:
let epsilon = 0.0000000001
let rec float2cfrac (x : float) : int list =
let q = int x
let r = x - (float q)
if r < epsilon then
[]
else
q :: (float2cfrac (1.0 / r))
> float2cfrac 4.23
val it : int list = [4; 4; 2; 1]
See this MSDN documentation for more.
You could define a helper function for this:
let withinTolerance (x: float) (y: float) e =
System.Math.Abs(x - y) < e
Also note your original solution isn't tail-recursive, so it consumes stack as it recurses and could overflow the stack. You could refactor it such that a float can be unfolded without recursion:
let float2cfrac (x: float) =
let q = int x
let r = x - (float q)
if withinTolerance r 0.0 epsilon then None
else Some (q, (1.0 / r))
4.23 |> Seq.unfold float2cfrac // seq [4; 4; 2; 1]

Prolog recursive program not returning values

I'm still new to Prolog, and I've encountered an error I have no idea how to fix.
I've written a simple exponentiation program that looks like this:
exp(b, 0, R) :- R is 1. % non-recursive case: exponent is 0
exp(0, e, R) :- R is 0. % non-recursive case: base is 0
exp(Base, Exponent, Result) :- % recurse if base and exponent are non-negative
Base >= 0,
Exponent >= 0,
E1 is Exponent-1,
exp(Base, E1, R1),
Result is Base*R1.
This compiles fine, but when I run it and give it a query like, say, exp(2, 4, X). I'm met with the following output:
?- exp(2, 4, X).
false.
Is there something I've done wrong? Or is it a matter of formatting the result in some way I'm unaware of?
You are confusing variables with atoms. It works as expected if you simple change the two nonrecusive clauses to:
exp(_, 0, 1).
exp(0, _, 0).
In fact, I recommend to change the whole program to use CLP(FD) constraints throughout:
exp(_, 0, 1).
exp(0, _, 0).
exp(Base, Exponent, Result):-
Base #>= 0,
Exponent #>= 0,
E1 #= Exponent-1,
exp(Base, E1, R1),
Result #= Base*R1.
Now for example the following at least yields a solution:
?- exp(2, X, 16).
X = 4
whereas we previously had:
?- exp(2, X, 16).
>=/2: Arguments are not sufficiently instantiated
Note also the most general query:
?- exp(X, Y, Z).
Y = 0,
Z = 1 ;
X = Z, Z = 0 ;
X = Z,
Y = 1,
Z in 0..sup ;
X = Z, Z = 0,
Y in 0..sup,
_G801+1#=Y,
_G801 in -1..sup .

put a Prolog goal as input in the first argument position and returns the number of times this goal succeeds in the second argument position

As the title says I want to write a program that does this.
an example would be:
?- count(member(X,[1,2,3]), N).
N = 3
Yes
But not only for the build in member, but also for some operators like:
?- count(17 =:= 12 + 5, N).
N = 1
Yes
Can someone help me get started?
Try this:
?- findall(., Goal, Ls), length(Ls, L).
Example:
?- findall(., member(X,[1,2,3]), Ls), length(Ls, L).
L = 3,
... .
library(aggregate) has been implemented to provide solutions for your problem, and much more...
?- aggregate(count, X^member(X,[1,2,3]), N).
N = 3.
?- aggregate(count, 17 =:= 12 + 5, N).
N = 1.

Implementing Schulze voting method in SciLab

I have to implement the Schulze method in SciLab. Unfortunately, I'm completely new to this tool and neither am I good at such kind of job. Could anyone advise something as to where to look for some examples and tools to do it as fast and easy as possible? The program shouldn't be extremely flexible or qualitative, it would be fine if it just worked with some hard-coded input. As I understand, the Schulze method can be implemented using graph and I've found a toolbox for SciLab. Should I use it?
Update:
Here's what I managed to come up with. The code is a total mess and I admit it since I'm really bad at working with such kind of languages. I've tested it with the example from Wikipedia, seems to work.
The code is too long so here's a pastebin
You can find a pseudo implementation on Wikipedia:
# Input: d[i,j], the number of voters who prefer candidate i to candidate j.
# Output: p[i,j], the strength of the strongest path from candidate i to candidate j.
for i from 1 to C
for j from 1 to C
if (i ≠ j) then
if (d[i,j] > d[j,i]) then
p[i,j] := d[i,j]
else
p[i,j] := 0
for i from 1 to C
for j from 1 to C
if (i ≠ j) then
for k from 1 to C
if (i ≠ k and j ≠ k) then
p[j,k] := max ( p[j,k], min ( p[j,i], p[i,k] ) )
Translating this to SciLab would require using functions, for-loops, if-else constructs, max, min.
Below I plainly translated the pseudo code into Scilab code. I haven't tested it and you'll have to find out the arguments to call it with.
function p = schulzeMethod(d, C)
// Initialize a zero matrix p of the same size as d
p = zeros(size(d))
for i = 1:C
for j = 1:C
if i ~= j then
if d(i,j) > d(j,i) then
p(i,j) = d(i,j)
else
p(i,j) = 0
end
end
end
end
for i = 1:C
for j = 1:C
if i ~= j then
for k = 1:C
if (i ~= k) & ( j ~= k) then
p(j,k) = max(p(j,k), min(p(j,i), p(i,k)))
end
end
end
end
end
endfunction
// Create some random values
C = 10
d = rand(C, C)
// Call the function above
p = schulzeMethod(d, C)
disp(p)
Good luck, hope it helps! Please give some feedback if it worked to help others.

Resources