Understanding termination in minikanren counting bits in a list - logic-programming

I began studying some minikanren and made up this example for counting 1-bits in a list.
(define (count xs n)
(conde
[(== xs '()) (== n 0)]
[(fresh (a b)
(== xs (cons a b))
(conde
[(== a 0) (count b n)]
[(== a 1) (count b (- n 1))]))]))
Now the following works fine
> (run* (q) (fresh (a b c) (== q (list a b c)) (count q 1)))
'((0 0 1) (1 0 0) (0 1 0))
but if I change the order of the goals the program does not terminate
> (run* (q) (fresh (a b c) (count q 1) (== q (list a b c))))
. . user break
This is already something that I don't completely understand, does the order of goals matter? In which ways? I think I understood that even the subsequent goals can pose sufficient constraints so as to terminate the search, but of course I must have missed something.
Exploring more of this problem I saw that
> (run 3 (q) (fresh (a b c) (count q 1) (== q (list a b c))))
'((0 0 1) (0 1 0) (1 0 0))
> (run 4 (q) (fresh (a b c) (count q 1) (== q (list a b c))))
. . user break
so I know that it tries to look for more answers than existing. My suspect now is that when the subgoal
(== xs (cons a b))
splits the list there aren't sufficient constraints on b to make the search finite, which sounds reasonable given that nothing talks about the tail of the list besides the external (== q (list a b c)). It seems even more reasonable to expect a non termination as nothing says what c is in (== q (list a b c)), it may be another list (is it true?), but so how does the swapped version of the program terminate?
I therefore tried
(define (bit x)
(conde [(== x 0)] [(== x 1)]))
and
> (run 4 (q) (fresh (a b c) (bit a) (bit b) (bit c) (count q 1) (== q (list a b c))))
. . user break
but it still does not terminate, so maybe the problem is not that which I thought.
Overall there must be something that I'm missing in my understanding, can anyone clarify all this and point out what would be a correct way of doing this thing?

> (run* (q) (fresh (a b c) (== q (list a b c)) (count q 1)))
'((0 0 1) (1 0 0) (0 1 0))
This query terminated because the 1st conjunct (== q (list a b c)) bound the size of q ,i.e. length of (list a b c) is 3. So the 2nd conjunct (count q 1) can only succeed finitely many times. Thus it terminates.
(run* (q) (fresh (a b c) (count q 1) (== q (list a b c))))
. . user break
This query diverged because the 1st conjunct (count q 1) keeps associating q with larger and larger lists without bound. Note that the 2nd conjunct (== q (list a b c)) can produce three answers, but after that, it will never succeed. Thus whenever it fails, it backtracks into (count q 1), which succeeds again, and fails again, backtracks again, ... and repeats forever (q will be larger and larger).
You asked that
This is already something that I don't completely understand, does the order of goals matter?
The answer is yes.
As William E. Byrd said in his dissertation:
miniKanren’s conjunction operator (exist) is commutative, but only if an answer exists. If no answer exists, then reordering goals within an exist may result in divergence rather than failure.
We say that conjunction is commutative, modulo divergence versus failure.

Related

Why is for loop so slow in Racket code

I am trying to find smallest non-divisor of numbers (https://codegolf.stackexchange.com/questions/105412/find-the-smallest-number-that-doesnt-divide-n). Following version using 'named let' works properly:
(define (f1 m)
(let loop ((n 2))
(cond
[(= 0 (modulo m n))
(loop (+ 1 n))]
[else n])))
I am testing with:
(f 24)
(f 1234567)
(f 12252240)
(f 232792560)
Above version produces prompt output of: 5 2 19 and 23.
However, following version which uses built-in for loop is very slow and actually crashes with out of memory error with larger numbers:
(define (f2 m)
(for/first ((i (range 2 m))
#:when (not (= 0 (modulo m i)))
#:final (not (= 0 (modulo m i))))
i))
Is there some error in the code of second version or is for loop inefficient as compared with named let in Racket?
The range function actually allocates a list, so the time for your function is dominated by the huge list allocation. Use in-range instead:
(define (f2 m)
(for/first ([i (in-range 2 m)]
#:when (not (= 0 (modulo m i)))
#:final (not (= 0 (modulo m i))))
i))
See also the section on for performance in the Racket Guide for more notes on the relative speed of different sequence forms.
In my opinion, recursion is generally more well suited for Racket than loops. I'd approach the problem this way...
(define start-counter 1)
(define (f number counter)
(cond [(not (= (modulo number counter) 0)) counter]
[else (f number (add1 counter))]))
(define (f2 number)
(f number start-counter))

Turning a recursive procedure to a iterative procedure - SICP exercise 1.16

In the book Structure and interpretation of computer programs, there is a recursive procedure for computing exponents using successive squaring.
(define (fast-expt b n)
(cond ((= n 0)
1)
((even? n)
(square (fast-expt b (/ n 2))))
(else
(* b (fast-expt b (- n 1))))))
Now in exercise 1.16:
Exercise 1.16: Design a procedure that evolves an iterative exponentiation process that uses successive squaring and uses a logarithmic number of steps,
as does `fast-expt`. (Hint: Using the observation that
(b(^n/2))^2 = (b(^2))^n/2
, keep, along with the exponent n and the base b, an additional state variable a, and define the state transformation in such a way that the product ab^n is unchanged from state to state. At the beginning of the process a is taken to be 1, and the answer is given by the value of a at the end of the process. In general, the technique of defining an invariant quantity that remains unchanged from state to state is a powerful way to think about the design of iterative algorithms.)
I spent a week and I absolutely can't figure how to do this iterative procedure, so I gave up and looked for solutions. All solutions I found is this:
(define (fast-expt a b n)
(cond ((= n 0)
a)
((even? n)
(fast-expt a (square b) (/ n 2)))
(else
(fast-expt (* a b) b (- n 1)))))
Now, I can understand
(fast-expt a (square b) (/ n 2)))
using the hint from the book, but my brain exploded when n is odd. In the recursive procedure, I got why
(* b (fast-expt b (- n 1))))))
works. But in the iterative procedure, it becomes totally different,
(fast-expt (* a b) b (- n 1)))))
It's working perfectly but I absolutely don't understand how to arrive at this solution by myself. it seems extremely clever.
Can someone explain why the iterative solution is like this? And what's the general way to think of solving these types of problems?
2021 update: Last year, I completely forgot about this exercise and the solutions I've seen. I tried solving it and I finally solved it on my own using the invariant provided in the exercise as a basis for transforming the state variables. I used the now accepted answer to verify my solution. Thanks #Óscar López.
Here's a slightly different implementation for making things clearer, notice that I'm using a helper procedure called loop to preserve the original procedure's arity:
(define (fast-expt b n)
(define (loop b n acc)
(cond ((zero? n) acc)
((even? n) (loop (* b b) (/ n 2) acc))
(else (loop b (- n 1) (* b acc)))))
(loop b n 1))
What's acc in here? it's a parameter that is used as an accumulator for the results (in the book they name this parameter a, IMHO acc is a more descriptive name). So at the beginning we set acc to an appropriate value and afterwards in each iteration we update the accumulator, preserving the invariant.
In general, this is the "trick" for understanding an iterative, tail-recursive implementation of an algorithm: we pass along an extra parameter with the result we've calculated so far, and return it in the end when we reach the base case of the recursion. By the way, the usual implementation of an iterative procedure as the one shown above is to use a named let, this is completely equivalent and a bit simpler to write:
(define (fast-expt b n)
(let loop ((b b) (n n) (acc 1))
(cond ((zero? n) acc)
((even? n) (loop (* b b) (/ n 2) acc))
(else (loop b (- n 1) (* b acc))))))

How do I make this imperative (arrays, loops, etc) Clojure code run half as fast as Java?

I've read that there are ways of coaxing the Clojure compiler into producing code that rivals the performance of similar code in Java, at least for code that already looks a lot like the Java code you want it to turn into. That's sound reasonable to me: idiomatic, high level Clojure code might have performance in the ballpark of what I'm used from CPython or MRI, but "ugly" Java-like code runs more or less like Java. This is a tradeoff I appreciate in Haskell, for example. Low level Haskell code with mutable arrays, loops and what not runs under GHC with appropriate compiler flags about as fast as it does in C (and then some high-tech libraries can sometimes squeeze similar performance out of prettier, higher level code).
I want help learning how to get my Java-like Clojure code to run as fast as in Java. Take this example:
(defn f [x y z n]
(+ (* 2 (+ (* x y) (+ (* y z) (* x z))))
(* 4 (+ x y z n -2) (- n 1))))
(defmacro from [[var ini cnd] & body]
`(loop [~var ~ini]
(when ~cnd
~#body
(recur (inc ~var)))))
(defn g [n]
(let [c (long-array (inc n))]
(from [x 1 (<= (f x x x 1) n)]
(from [y x (<= (f x y y 1) n)]
(from [z y (<= (f x y z 1) n)]
(from [k 1 (<= (f x y z k) n)]
(let [l (f x y z k)]
(aset c l (inc (aget c l))))))))
c))
(defn h [x]
(loop [n 1000]
(let [^longs c (g n)]
(if-let [k (some #(when (= x (aget c %)) %)
(range 1 (inc n)))]
k
(recur (* 2 n))))))
(time (print (h 1000)))
It takes about 85 seconds using Clojure 1.6 on my (admittedly) slow machine. Equivalent code in Java runs in about 0.4 seconds. I'm not greedy, I just want to get the Clojure code to run in, say, around 2 seconds.
The first thing I did was enable *warn-on-reflection* but sadly, with that lonely type hint there are no further warnings. What am I doing wrong?
This gist contains both the Java and Clojure versions of the code.
Unfortunately *warn-on-reflection* doesn't warn you about primitive boxing - which I think is the main problem here. You want to be using unboxed primitive arithmetic at all times for maximum speed.
The following hints should help you optimise this:
Do a (set! *unchecked-math* true) to get faster primitive numerical operations
Try initialising your loops with (long ~ini). You want to force the use of primitives this way
Try putting a primitive hint ^long n to the function g
Try type-hinting your long array ^longs c - this should hopefully make Clojure use the faster primitive aget.
Type hint f as a primitive function ^long [^long x ^long y ^long z ^long n] or similar. This is very important, otherwise f will return boxed numbers....
If you succeed in eliminating all the boxed numbers, then this kind of code should be nearly as fast as pure Java.

Summing vectors with common lisp 'loop' macro

I need to implement something like this:
(loop for i from 1 to N sum (f i))
except that accumulated values are represent lists of numbers like (1 2 3)
and they are added element-wise. In other words I would like to initialize summation
with (zerov N) and use (v+) to add subsequent elements:
(defun v+ (a b) (mapcar '+ a b))
(defun zerov (n) (loop for i from 1 to n collect 0))
Is it possible to do something like this with loop macro? I can implement it as a
separate function, but I would like to use loop or loop-like macro for expressiveness.
Perhaps there is a way to define simple loop-like macro just for this case?
(loop with accum = (make-list n :initial-element 0)
for i from 1 to n
do (setq accum (v+ accum (f i)))
finally (return accum))
LOOP as defined in the Common Lisp standard is not extensible.
I would write it with the normal LOOP functionality:
(let ((result (zerov n)))
(loop for i from 1 to N
do (setf result (v+ result (f i))))
result)
The I would write it as a function:
(defun sum (n f init sum)
(let ((result (funcall init n)))
(loop for i from 1 to n
do (setf result (funcall sum result (funcall f i))))
result))
If you want such a functionality as a direct language feature of a loopy macro, then an alternative would be the ITERATE macro, which is more powerful than the LOOP macro and it is also extensible.
(reduce #'v+ (loop for i from 1 to n collect (f i))
:initial-value (zerov n))
Note that Common Lisp has proper "vector" (i.e., sequence of elements of homogeneous type allowing more compact representation and efficient random access), so perhaps,
(defun v+ (a b) (map-into a #'+ a b))
(defun zerov (n) (make-array n :initial-element 0))
(defun fn (i n) (let ((v (zerov n))) (setf (aref v i) 1) v))
(defun gn (n)
(loop for v = (zerov n) then (v+ v (fn i n)) for i below n
finally (return v)))

What is the difference between these two blocks of Clojure code?

While working on the Clojure Koans, I had to calculate the factorial of a number iterativly, I did find the solution, but I have a question about the difference between 2 solutions, one that works and one that doens't, although I don't understand why:
The one that works:
(defn factorial [n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (dec n) (* n acc )))
)
The one that desn't:
(defn factorial [n]
(loop [n n
acc 1]
(if (zero? n)
1
(recur (dec n) (* n acc )))
)
Note that the only difference is the returned value of the If block if the condition is met.
The second factorial function always returns 1. The code is built to use an accumulator variable (acc), and the first code block gets it right by returning this accumulator variable.
A factorial function can be written to return 1, though, if an accumulator variable is not used. Since this method does not utilize loop / recur, it can cause a stack overflow easily: try (fact 5000).
(defn factorial [x]
(if (<= x 1)
1
(* x (factorial (- x 1)))))
(source)
it's hard to work out what you think should be happening for the question to make sense.
i think maybe you think loop is doing more than it does? your code is almost equivalent to:
(defn factorial
([n] (factorial n 1)
([n acc]
(if (zero? n)
acc
(recur (dec n) (* n acc)))))
which is a stack-safe version of
(defn factorial
([n] (factorial n 1)
([n acc]
(if (zero? n)
acc
(factorial (dec n) (* n acc)))))
so the acc (or 1) is the final value returned from the function.
all that loop does is give a different target for recur, which is useful if you have some code between the start of the function and the point where you want to repeat. it's basically a label for a goto.

Resources