How to create transitive function in LISP for R relation? - lisp

To construct the transitive and reflexive closure R *.
The binary relation R = {(1,1), (1,2), (2,1), (2,2), (3,1), (3,4), (4,1), (4,2), (4,4)}

What we can do is turn the data into some graph structure, like an adjacency hash table. Then we can traverse it and back-fill the missing transitive and reflexive relationships.
TXR Lisp program:
;; association data
(defvar rel-pairs '((1 1) (1 2) (2 1) (2 2) (3 1) (3 4) (4 1) (4 2) (4 4)))
;; turn data into hash table associating each domain value
;; with its range values.
(defvar rel [group-reduce (hash) car (op cons (cadr #2) #1) rel-pairs])
(defun ensure-trans-reflex (hash)
;; ensure reflexivity: if [hash key] maps to some values,
;; each of those values should appears as keys mapping
;; back to the key.
(dohash (key values hash)
(each ((val values))
(pushnew key [hash val])))
;; ensure transivity: individually starting at each
;; key in the hash, we recursively traverse the graph,
;; and associate that key with values thus reachable.
(dohash (key values hash hash)
(let ((visited (hash)))
(labels ((transitivize (key value)
(each ((next-val [hash value]))
(when (test-set [visited next-val])
(pushnew next-val [hash key])
(transitivize key next-val)))))
(each ((val values))
(transitivize key val))))))
(prinl rel)
(ensure-trans-reflex rel)
(prinl rel)
Output:
$ txr rel.tl
#H(() (1 (2 1)) (2 (2 1)) (3 (4 1)) (4 (4 2 1)))
#H(() (1 (4 3 2 1)) (2 (3 4 2 1)) (3 (2 3 4 1)) (4 (3 4 2 1)))
Basically, the example data ends up associating every key with every key including itself.

Here is an implementation in Common Lisp which exhibits a problem with a naïve approach to this sort of question.
First of all some definitions.
The kernel of the relation is a map with entries which look like (x . y). R(a, b) if there is an entry in the kernel like (a . b). I am not sure if 'kernel' is the correct mathematical term (I'm pretty sure it's not), but it's what I'm going to use.
The relation R is reflexive if R(a, a) for any a which occurs either in the domain or the range of the relation.
The transitive closure of R, R* is the relation such that R*(a, b if R(a, b) or (R(a, c) and R*(c, b)).
So I'm going to implement the kernel of the map just as a list, and I will explicitly use car, cdr, and cons to extract the parts of entries in the kernel. This is grotty old-fashioned Lisp, but in this case it's pretty much fine, since the natural objects in this part of the language (conses) map very nicely onto the objects in the problem. Note also that I have not tried to use any fancy data structures at all: everything is just walking down lists. This would make the thing slow if the kernel was very large. But it's not very large.
Here is the kernel you are given:
(defparameter *kernel*
'((1 . 1)
(1 . 2)
(2 . 1)
(2 . 2)
(3 . 1)
(3 . 4)
(4 . 1)
(4 . 2)
(4 . 4)))
This kernel is not reflexive: (3 . 3) is missing for instance. Here is a function which, given a kernel, returns a reflexive version of it. This function has very poor complexity, but the kernel is small and the function gets called once.
(defun reflexifize-kernel (kernel)
;; given the kernel of a map, return a reflexive version of it
;; This has pretty grotty complexity but it gets called only once
(loop for element in (loop with d/r = '()
for e in kernel
do (pushnew (car e) d/r)
do (pushnew (cdr e) d/r)
finally (return d/r))
for ik = (cons element element)
unless (member ik kernel :test #'equal)
collect ik into identities
finally (return (append kernel identities))))
And we can check this:
> (reflexifize-kernel *kernel*)
((1 . 1)
(1 . 2)
(2 . 1)
(2 . 2)
(3 . 1)
(3 . 4)
(4 . 1)
(4 . 2)
(4 . 4)
(3 . 3))
You can see it's added the appropriate entry at the end (and it would have added more entries if it needed to).
Now I'll write a function which, given the left-hand-side of a mapping and a kernel returns two things:
the first match for this left-hand-side in the kernel, or nil if there is none;
the remainder of the kernel after this match, or () if there is one (note that nil and () are the same in Common Lisp, but they might not be in other Lisps).
The nice thing here is that we can just use the remainder of the kernel to look for more matches, and this function works really nicely with the implementation of the kernel above: this is a case where Lisp's data structures really work well for us.
(defun next-match (lhs kernel)
;; return the next match (as (lhs . rhs)) for lhs in kernel, and the
;; remainder of the kernel, or nil and () if there is no match
(let ((found (member lhs kernel :key #'car)))
(if found
(values (first found) (rest found))
(values nil '()))))
So, now we can write a function, Rp which is true if R(a, b) is true:
(defun Rp (lhs rhs kernel)
;; is R(lhs, rhs) true
(multiple-value-bind (entry remaining-kernel) (next-match lhs kernel)
(cond ((null entry)
nil)
((eql (cdr entry) rhs)
t)
(t (Rp lhs rhs remaining-kernel)))))
This is called Rp because it's a predicate (ending in p in the usual Lisp convention), and it tells us if two elements satisfy R. And of course since CL is case-insensitive by default, this is the same function as rp.
And this function works fine:
> (rp 1 1 (reflexifize-kernel *kernel*))
t
> (rp 1 3 (reflexifize-kernel *kernel*))
nil
And now we can write R*p: it's clearer, I think and certainly more efficient to write a 'unified' version of R*p which does not rely on Rp, but is very similar code with it: it's really just got a final step which searches for the transitive closure.
(defun R*p (lhs rhs kernel)
;; is lhs related to rhs in kernel? (See note below!)
(multiple-value-bind (entry remaining-kernel) (next-match lhs kernel)
(if (null entry)
nil
(let ((match-rhs (cdr entry)))
(if (eql rhs match-rhs)
t
(or (R*p lhs rhs remaining-kernel)
(R*p match-rhs rhs kernel)))))))
OK, so this looks obviously correct, right?
first we look for a match for lhs;
if there's a match, and its rhs is rhs then we're done;
if there isn't then
first search for more matches in the kernel and check them
if that fails look for matches for the rhs we found whose rhs is rhs.
And this is just transparently the definition of the transitive closure, right? So if we feed it a reflexive kernel (which we can create now), it will work.
Well, no, it won't work. It won't work because there are loops in the kernel you've been given. Let's say we want to call (R*p 1 3 (reflexivize-kernel *kernel*)). It's obvious from the kernel that this should be false.
But in fact the function fails to terminate. It fails to terminate because it finds there's an entry for R(1, 2) and so it starts looking for R*(2, 3): it then finds R(2, 1), starts looking for R*(1, 3) ... oops.
(Note that the implementation above does depth-first search. Breadth-first search doesn't help: it will help find a mapping when there is one but when there isn't it will just loop in the same way.)
The way to deal with this is to use what's called an occurs check: when searching we keep track of the things we have already looked at up the search tree. If we find we're looking at a lhs which we have already looked at we fail immediately, as this is a loop. Here is an implementation of a version of R*p which does that, using a local function so we don't need to provide the so-far list in the interface, whichh would be annoying.
(defun R*p (lhs rhs kernel)
;; is lhs related to rhs in kernel, with an occurs check.
(labels ((R*p-loop (lhs rhs kernel so-far)
(if (member lhs so-far)
;; we've looped, give up
nil
(multiple-value-bind (entry remaining-kernel)
(next-match lhs kernel)
(if (null entry)
nil
(let ((match-rhs (cdr entry)))
(if (eql rhs match-rhs)
t
(or (R*p-loop lhs rhs remaining-kernel so-far)
(R*p-loop match-rhs rhs kernel
(cons lhs so-far))))))))))
(R*p-loop lhs rhs kernel '())))
And this version works:
> (R*p 1 3 (reflexifize-kernel *kernel*))
nil
> (R*p 1 1 (reflexifize-kernel *kernel*))
t
> (R*p 1 2 (reflexifize-kernel *kernel*))
t
> (R*p 2 1 (reflexifize-kernel *kernel*))
t
> (R*p 2 3 (reflexifize-kernel *kernel*))
nil

Related

Racket: Why wont this compile?

I'm attempting to program a simple function that adds integers to a list descending from a range of "high" and "low", incremented by "step"
For example,
if the input is (3 12 3), the expected output is '(12 9 6 3)
Below is the following code:
(define (downSeries step high low [(define ret '())])
(if (< high low)
ret
(cons ret (- high step))
(downSeries (step (- high step) low))))
I'm pretty new to racket, but I'm really not sure why this isn't compiling. Any tips? Thank you.
Since only racket is tagged and no special languages are describes it is expeted the first line in the definition window is #lang racket. Answer will be different for student languages.
1 The last argument is nested in two parentheses and is illegal syntax. Default arguments only have one set:
(define (test mandatory (optional '()))
(list mandatory optional))
(test 1) ; ==> (1 ())
(test 1 2) ; ==> (1 2)
2 You have 4 operands in your if form. It takes maximum 3!
(if prediate-expression
then-expression
else-expression)
Looking at the code you should have the cons expression in the position of ret argument. Having it before the recursion makes it dead code. ret will always be (). Eg this loks similar to a typical fold implementation:
(define (fold-1 combine init lst)
(if (null? lst)
init ; fully grown init returned
(fold-1 combine
(combine (car lst) init) ; init grows
(cdr lst))))

Number Partitioning in R5RS

I was asked in an internship interview to do a R5RS program that creates a function, let's say two-subsets. This function has to return #t if the list L contains two subsets with equal sums of elements and with equal numbers of elements, otherwise it returns #f. It takes in entry the list L (only positive numbers) and some parameters (that I judge useful. There is no conditions on the number of parameters) all equal to 0 at the beginning.
The requirements as I still remember were as follow:
- Do not define other functions and call them inside the "two-subsets" function.
- It can only use the following constructs: null?, cond, car, cdr, else, + ,=, not, and, #t, #f, two-subsets (itself for recursive call), the names of the parameters, such as list, sum, ...etc, numeric constants and parentheses.
There were some given examples on the results that we are supposed to have, let's say:
(two-subsets '(7 7) 0 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(7 7 1) 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(5 3 2 4) 0 0) returns #t. The two subsets are {2, 5} and {3, 4}.
(two-subsets '(1 2 3 6 9) 0 0) returns #f.
I started by writing the signature that it looks to me it should be something like this:
(define two-subsets (lambda (L m n ... other parameters)
(cond
The problem is really complicated and it's complexity is obviously more than O(n), I read on it on https://en.wikipedia.org/wiki/Partition_problem .
I tried to start by defining the algorithm first before coding it. I thought about taking as parameters: sum of the list L so in my conditions I'll iterate only on the combinations which sum is <= sum(L)/2. By doing that I can reduce a little bit the complexity of the problem, but still I couldn't figure out how to do it.
It looks like an interesting problem and I really want to know more about it.
Here is a version which does not depend on the numbers being all positive. I am reasonably sure that, by knowing they are, you can do much better than this.
Note this assumes that:
the partition does not need to be exhaustive;
but the sets must not be empty.
I'd be very interested to see a version which relies on the elements of the list being +ve!
(define (two-subsets? l sl sld ssd)
;; l is the list we want to partition
;; sl is how many elements we have eaten from it so far
;; sld is the length difference in the partitions
;; ssd is the sum difference in the partitions
(cond [(and (not (= sl 0))
(= sld 0)
(= ssd 0))
;; we have eaten some elements, the differences are zero
;; we are done.
#t]
[(null? l)
;; out of l, failed
#f]
;; this is where I am sure we could be clever about the set containing
;; only positive numbers, but I am too lazy to think
[(two-subsets? (cdr l)
(+ sl 1)
(+ sld 1)
(+ ssd (car l)))
;; the left-hand set worked
#t]
[(two-subsets? (cdr l)
(+ sl 1)
(- sld 1)
(- ssd (car l)))
;; the right-hand set worked
#t]
[else
;; finally drop the first element of l and try the others
(two-subsets? (cdr l) sl sld ssd)]))

Writing the Foo Function In LISP With the following Specification

I am struggling to find the right approach to solve the following function
(FOO #'– '(1 2 3 4 5))
=> ((–1 2 3 4 5) (1 –2 3 4 5) (1 2 –3 4 5) (1 2 3 –4 5) (1 2 3 4 –5))
The first Parameter to the foo function is supposed to be a function "-" that has to be applied to each element returning a list of list as shown above. I am not sure as to what approach I can take to create this function. I thought of recursion but not sure how I will preserve the list in each call and what kind of base criteria would I have. Any help would be appreciated. I cannot use loops as this is functional programming.
It's a pity you cannot use loop because this could be elegantly solved like so:
(defun foo (fctn lst)
(loop
for n from 0 below (length lst) ; outer
collect (loop
for elt in lst ; inner
for i from 0
collect (if (= i n) (funcall fctn elt) elt))))
So we've got an outer loop that increments n from 0 to (length lst) excluded, and an inner loop that will copy verbatim the list except for element n where fctn is applied:
CL-USER> (foo #'- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
Replacing loop by recursion means creating local functions by using labels that replace the inner and the outer loop, for example:
(defun foo (fctn lst)
(let ((len (length lst)))
(labels
((inner (lst n &optional (i 0))
(unless (= i len)
(cons (if (= i n) (funcall fctn (car lst)) (car lst))
(inner (cdr lst) n (1+ i)))))
(outer (&optional (i 0))
(unless (= i len)
(cons (inner lst i) (outer (1+ i))))))
(outer))))
Part of the implementation strategy that you choose here will depend on whether you want to support structure sharing or not. Some of the answers have provided solutions where you get completely new lists, which may be what you want. If you want to actually share some of the common structure, you can do that too, with a solution like this. (Note: I'm using first/rest/list* in preference to car/car/cons, since we're working with lists, not arbitrary trees.)
(defun foo (operation list)
(labels ((foo% (left right result)
(if (endp right)
(nreverse result)
(let* ((x (first right))
(ox (funcall operation x)))
(foo% (list* x left)
(rest right)
(list* (revappend left
(list* ox (rest right)))
result))))))
(foo% '() list '())))
The idea is to walk down list once, keeping track of the left side (in reverse) and the right side as we've gone through them, so we get as left and right:
() (1 2 3 4)
(1) (2 3 4)
(2 1) (3 4)
(3 2 1) (4)
(4 3 2 1) ()
At each step but the last, we take the the first element from the right side, apply the operation, and create a new list use revappend with the left, the result of the operation, and the rest of right. The results from all those operations are accumulated in result (in reverse order). At the end, we simply return result, reversed. We can check that this has the right result, along with observing the structure sharing:
CL-USER> (foo '- '(1 2 3 4 5))
((-1 2 3 4 5) (1 -2 3 4 5) (1 2 -3 4 5) (1 2 3 -4 5) (1 2 3 4 -5))
By setting *print-circle* to true, we can see the structure sharing:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((l '(1 2 3 4 5)))
(list l (foo '- l)))
((1 . #1=(2 . #2=(3 . #3=(4 . #4=(5))))) ; input L
((-1 . #1#)
(1 -2 . #2#)
(1 2 -3 . #3#)
(1 2 3 -4 . #4#)
(1 2 3 4 -5)))
Each list in the output shares as much structure with the original input list as possible.
I find it easier, conceptually, to write some of these kind of functions recursively, using labels, but Common Lisp doesn't guarantee tail call optimization, so it's worth writing this iteratively, too. Here's one way that could be done:
(defun phoo (operation list)
(do ((left '())
(right list)
(result '()))
((endp right)
(nreverse result))
(let* ((x (pop right))
(ox (funcall operation x)))
(push (revappend left (list* ox right)) result)
(push x left))))
The base case of a recursion can be determined by asking yourself "When do I want to stop?".
As an example, when I want to compute the sum of an integer and all positive integers below it, I can do this recusively with a base case determined by answering "When do I want to stop?" with "When the value I might add in is zero.":
(defun sumdown (val)
(if (zerop val)
0
(+ (sumdown (1- val)) val)))
With regard to 'preserve the list in each call', rather than trying to preserve anything I would just build up a result as you go along. Using the 'sumdown' example, this can be done in various ways that are all fundamentally the same approach.
The approach is to have an auxiliary function with a result argument that lets you build up a result as you recurse, and a function that is intended for the user to call, which calls the auxiliary function:
(defun sumdown1-aux (val result)
(if (zerop val)
result
(sumdown1-aux (1- val) (+ val result))))
(defun sumdown1 (val)
(sumdown1-aux val 0))
You can combine the auxiliary function and the function intended to be called by the user by using optional arguments:
(defun sumdown2 (val &optional (result 0))
(if (zerop val)
result
(sumdown2 (1- val) (+ val result))))
You can hide the fact that an auxiliary function is being used by locally binding it within the function the user would call:
(defun sumdown3 (val)
(labels ((sumdown3-aux (val result)
(if (zerop val)
result
(sumdown3-aux (1- val) (+ val result)))))
(sumdown3-aux val 0)))
A recursive solution to your problem can be implemented by answering the question "When do I want to stop when I want to operate on every element of a list?" to determine the base case, and building up a result list-of-lists (instead of adding as in the example) as you recurse. Breaking the problem into smaller pieces will help - "Make a copy of the original list with the nth element replaced by the result of calling the function on that element" can be considered a subproblem, so you might want to write a function that does that first, then use that function to write a function that solves the whole problem. It will be easier if you are allowed to use functions like mapcar and substitute or substitute-if, but if you are not, then you can write equivalents yourself out of what you are allowed to use.

What's the difference between (list nil) and '(nil) in Lisp? [duplicate]

This question already has answers here:
Why does this function return a different value every time?
(4 answers)
Unexpected persistence of data [duplicate]
(1 answer)
Closed 7 years ago.
First of all, let me say I'm a beginner in Lisp. To be honest I have been a beginner for some time now, but there are still many things I don't know well.
While I was writing this question, I came up with a strange bug in my code.
Here is a function that will return the list (0 1 ... n) with the list e appended. It uses rplacd along the way to keep track of the last element, to avoid a final call to last.
For example, (foo 4 '(x)) returns (0 1 2 3 4 x).
The "head" is stored in a, which is not simply nil, because there is only one nil, and never a copy of it (if I understand correctly), hence I can't simply append to nil.
(defun foo (n e)
(let* ((a (list nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
(defun bar (n e)
(let* ((a '(nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
The only difference between these functions is the (list nil) replaced by '(nil) in bar. While foo works as expected, bar always returns nil.
My initial guess is this happens because the original cdr of a is indeed nil, and the quoted list may be considered constant. However, if I do (setf x '(nil)) (rplacd x 1) I get (nil . 1) as expected, so I must be at least partially wrong.
When evaluated, '(nil) and (list nil) produce similar lists, but the former can be considered constant when present in source code. You should not perform any destructive operations on a constant quoted list in Common Lisp. See http://l1sp.org/cl/3.2.2.3 and http://l1sp.org/cl/quote. In particular, the latter says "The consequences are undefined if literal objects (including quoted objects) are destructively modified."
Quoted data is considered a constant. If you have two functions:
(defun test (&optional (arg '(0)))
(setf (car arg) (1+ (car arg)))
(car arg))
(defun test2 ()
'(0))
These are two functions both using the constant list (0) right?
The implementation may choose to not mutate constants:
(test) ; ==> Error, into the debugger we go
The implementation can cons the same list twice (the reader might do that for it)
(test2) ; ==> (0)
(test) ; ==> 1
(test) ; ==> 2
(test) ; ==> 3
(test2) ; ==> (0)
The implementation can see it's the same and hench save space:
(test2) ; ==> (0)
(test) ; ==> 1
(test) ; ==> 2
(test) ; ==> 3
(test2) ; ==> (3)
In fact. The last two behavior might happen in the same implementation dependent on the function being compiled or not.
In CLISP both functions work the same. I also see when disassembling with SBCL that the constant actually is mutated so I wonder if perhaps it has constant folded (cdr '(0)) at compile time and doesn't use the mutated list at all. It really doesn't matter since both are considered good "undefined" behavior.
The part from CLHS about this is very short
The consequences are undefined if literal objects (including quoted
objects) are destructively modified.

Recursive range in Lisp adds a period?

(define ..
(lambda (start stop)
(cond ((> (add1 start) stop) (quote ()))
((eq? (add1 start) stop) (sub1 stop))
(else (cons start (.. (add1 start) stop))))))
I have defined a simple range function.
The intent is for
(.. 1 5) --> (1 2 3 4)
Instead, a bizarre period is being added to my tuple and I have no idea why:
(.. 1 5) --> (1 2 3 . 4)
I don't understand why this is happening. Any help is appreciated
A list in Scheme is either the empty list () (also known as nil in some Lisps), or a cons cell whose car (also known as first) is an element of the list and whose cdr (also known as rest) is either the rest of the list (i.e., another list), or an atom that terminates the list. The conventional terminator is the empty list (); lists terminated by () are said to be "proper lists". Lists terminated by any other atom are called "improper lists". The list (1 2 3 4 5) contains the elements 1, 2, 3, 4, and 5, and is terminated by (). You could construct it by
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))
Now, when the system prints a cons cell, the general case is to print it by
(car . cdr)
For instance, the result of (cons 1 2) is printed as
(1 . 2)
Since lists are built of cons cells, you can use this notation for lists too:
'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))
That's rather clunky, though, so most lisps (all that I know of) have a special case for printing cons cells: if the cdr is a list (either another cons cell, or ()), then don't print the ., and don't print the surrounding parenthesis of the cdr (which it would otherwise have, since it's a list). So, if you're seeing a result like
(1 2 3 . 4)
it means you've got an improper list that is terminated by the atom 4. It has the structure
(1 . (2 . (3 . 4)))
Now the question is: where in your code did the list construction go awry? .. is always supposed to return a proper list, so let's look at the cases: The first case always returns a proper list (the empty list):
((> (add1 start) stop) (quote ()))
The second case looks like it can return something that's not a list (assuming that (sub1 stop) == (- stop 1)):
((eq? (add1 start) stop) (sub1 stop))
Now, if .. were functioning correctly, then the third case would always be returning a proper list (since (cons x y) is a proper list if y is):
(else (cons start (.. (add1 start) stop)))
Make your second case return a list and you should be all set.
Your expression (sub1 stop) needs to read (list (sub1 stop))
In order for cons to build up a proper list, the second element needs to be a list itself. Thus, your function .. should return a list of some type for every cond clause.
Remove this part of the cond
((eq? (add1 start) stop) (sub1 stop))
It's causing a premature finish.