I’d like to develop an efficient strategy that can quickly test if a pre-specified path exists in a large fully-connected directed labeled graph. For example, starting at some node, say node0, does there exist a path to another node, say node9, that follows a sequence of labeled links, say node0 -> link3 -> link1 -> link4+ -> link1 -> node9, where link+ means one or more repetitions of that link’s label. The graph is dynamic, such that nodes and links will be continuously added and deleted. Unique node and link labels would be strings constructed from underlying semantic information.
My first (simplest) idea is to intern all labeled graph nodes and links in a separate package as symbols. Then install a hash table as the symbol-value of each node. The hash table would carry the associations for that node from all of the links emanating from that node to their respective target nodes. Testing whether the next link in the chain exists, then is a simple table lookup. The total number of lookups depends on the length of the chain of links. All programmatic references to node and label symbols would be via the package name.
However, I’m not sure about the advisability of using symbols and symbol values as data structures. Does putting them in their own package mitigate potential conflicts in this case?
If you want to use symbols, you do not need hash-tables; you can store data in the symbol-value slot of the symbol, and any additional data in its symbol-plist. Lookup is either already done at read time, or with find-symbol or intern at runtime. You could use unintern to dissociate the symbol from its home package, but other nodes could still reference it, so you would need to remove any other reference to that symbol when removing a node (that's why sometimes you store both the ingoing and outgoing edges of a node).
It can be done, and as far as I know, this used to be a common way to work with symbols historically. One possible drawback is that when you create a package you have to name it (so no on-the-fly, anonymous package). You have to potentially choose a string that is not currently used as a package name, and you restrict the name of your nodes to a specific package.
Another way to implement this is to have a node class which holds a name, where the name can be any symbol the user choose (in any package). A graph class maintains all nodes, and edges, etc, and you can manipulate those objects in isolation, without messing up with the environment's list of packages, etc. This could be a little bit cleaner.
It was recently made available, so I'd like also to point out that this book exists: Programming Algorithms by Vsevolod Domkin, which uses Common Lisp to implement algorithms.
Rather than obsess about implementation, I would design a protocol which the system needs to follow. Here is one such (note I have made some assumptions here, some of which are probably implicit, and none of which may agree with how you want things to work):
;;;; Protocol
;;;
;;; By assumption there is one link with each label, each link points
;;; at one other node.
;;;
;;; NODEs have identity and can be destructively modified but it is
;;; not specified whether node equality is object identity.
;;;
(defgeneric node-link-labelled (node label)
(:documentation "Return the node linked to NODE via LABEL, or NIL".))
(defgeneric (setf node-link-labelled) (target node label)
(:documentation "set the link with label LABEL of NODE to TARGET, replacing it if
it exists. Return TARGET."))
(defgeneric nodes-equal (n1 n2)
(:documentation "Are N1 and N2 the same node?"))
(defgeneric node-remove-link (node label)
(:documentation "Remove the link with label LABEL from NODE. Return NODE.
The link need not exist"))
(defgeneric mapc-node-links (fn node)
(:documentation "call FN with arguments NODE, LABEL TARGET for each link of NODE.
FN is allowed to delete the link corresponding to LABEL but should not otherwise
modify NODE"))
Then you can write implementations for this protocol. Here is a simple one in which nodes are conses of (<something> . <links>). This will be slow for large numbers of links, but probably very fast for small numbers. It has the nice feature that you can give nodes names, which is not supported in the above protocol.
;;;; Consy nodes are simple
;;;
(defun make-consy-node (&optional (label 'node))
(list label))
(defmethod node-link-labelled ((node cons) label)
(cdr (assoc label (cdr node))))
(defmethod nodes-equal ((n1 cons) (n2 cons))
(eql n1 n2))
(defmethod (setf node-link-labelled) (target (node cons) label)
(let ((found (assoc label (cdr node))))
(if found
(setf (cdr found) target)
(push (cons label target) (cdr node))))
target)
(defmethod node-remove-link ((node cons) label)
(setf (cdr node) (delete-if (lambda (link)
(eql (car link) label))
(cdr node)))
node)
(defmethod mapc-node-links (fn (node cons))
;; This is at least safe
(loop for (label . target) in (copy-list (cdr node))
do (funcall fn node label target))
node)
Or you can implement nodes as hash tables, which will be fast for graphs with many per-node links:
;;;; Hashy nodes
;;;
(defun make-hashy-node ()
(make-hash-table))
(defmethod nodes-equal ((n1 hash-table) (n2 hash-table))
(eql n1 n2))
(defmethod node-link-labelled ((node hash-table) label)
(values (gethash label node nil)))
(defmethod (setf node-link-labelled) (target (node hash-table) label)
(setf (gethash label node) target)
target)
(defmethod node-remove-link ((node hash-table) label)
(remhash label node)
node)
(defmethod mapc-node-links (fn (node hash-table))
(maphash (lambda (label target)
(funcall fn node label target))
node)
node)
Or you can do any number of other things. And since they all follow the protocol you can mix them:
(let ((n1 (make-hashy-node)))
(setf (node-link-labelled n1 'foo) (make-hashy-node)
(node-link-labelled n1 'bar) (make-consy-node 'n2))
n1)
You can define node construction as part of the protocol if you want:
(defgeneric make-node-of-sort (sort &key)
(:documentation "make a node whose sort is SORT. Methods on this GF should
use EQL specializers on SORT"))
...
(defmethod make-node-of-sort ((sort (eql 'consy)) &key (name 'node))
(list name))
...
Related
I've written two versions of a lisp function. The main difference between the two is that one is done with recursion, while the other is done with iteration.
Here's the recursive version (no side effects!):
(defun simple-check (counter list)
"This function takes two arguments:
the number 0 and a list of atoms.
It returns the number of times the
atom 'a' appears in that list."
(if (null list)
counter
(if (equal (car list) 'a)
(simple-check (+ counter 1) (cdr list))
(simple-check counter (cdr list)))))
Here's the iterative version (with side effects):
(defun a-check (counter list)
"This function takes two arguments:
the number 0 and a list of atoms.
It returns the number of times the
atom 'a' appears in that list."
(dolist (item list)
(if (equal item 'a)
(setf counter (+ counter 1))
(setf counter (+ counter 0))))
counter)
As far as I know, they both work. But I'd really like to avoid side-effects in the iterative version. Two questions I'd like answered:
Is it possible to avoid side effects and keep iteration?
Assuming the answer to #1 is a yes, what are the best ways to do so?
For completeness, note that Common Lisp has a built-in COUNT:
(count 'a list)
In some ways, the difference between side-effect or no side-effect is a bit blurred. Take the following loop version (ignoring that loop also has better ways):
(loop :for x :in list
:for counter := (if (eq x 'a) (1+ counter) counter)
:finally (return counter))
Is counter set at each step, or is it rebound? I. e., is an existing variable modified (like in setf), or is a new variable binding created (as in a recursion)?
This do version is very much like the recursive version:
(do ((list args (rest list))
(counter 0 (+ counter (if (eq (first list) 'a) 1 0))))
((endp list) counter))
Same question as above.
Now the “obvious” loop version:
(loop :for x :in list
:count (eq x 'a))
There isn't even an explicit variable for the counter. Are there side-effects?
Internally, of course there are effects: environments are created, bindings established, and, especially if there is tail call optimization, even in the recursive version destroyed/replaced at each step.
I see as side effects only effects that affect things outside of some defined scope. Of course, things appear more elegant if you can also on the level of your internal definition avoid the explicit setting of things, and instead use some more declarative expression.
You can also iterate with map, mapcar and friends.
https://lispcookbook.github.io/cl-cookbook/iteration.html
I also suggest a look at remove-if[-not] and other reduce and apply:
(length (remove-if-not (lambda (x) (equal :a x)) '(:a :b :a))) ;; 2
Passing counter to the recursive procedure was a means to enable a tail recursive definition. This is unnecessary for the iterative definition.
As others have pointed out, there are several language constructs which solve the stated problem elegantly.
I assume you are interested in this in a more general sense such as when you cannot find
a language feature that solves a problem directly.
In general, one can maintain a functional interface by keeping the mutation private as below:
(defun simple-check (list)
"return the number of times the symbol `a` appears in `list`"
(let ((times 0))
(dolist (elem list times)
(when (equal elem 'a)
(incf times)))))
DrRacket is a functional programming language built in lisp.
I created an effectful function called run-ins which take in an instruction and make some changes to specified variables (I'm trying to re-create a working computer)
Now, I want to create another function, called run-loinst id est: run a list of instrcutions, and this is the code:
(define (run-loinst loinst)
(map run-ins loinst))
As it turns out, when I run run-loinst on a list of instructions with repeating terms, the repeated instructions are only run once, and it seems that the effect of an earlier list element will not take place before the running of a later term.
So, how can I write a code that would allow me to run multiple instructions and have their effects build on the effects of previous terms in sequential order?
(BTW, the below is the code of run-ins and supporting function)
(define (run-ins ins)
(cond [(string=? (ins-type ins) "+")
(set-Rs! (second (ins-lori ins))
(+ (* (first (ins-low ins)) (first (ins-lori ins))) (second (ins-lori ins))))]
[(string=? (ins-type ins) "set")
(set-Rs! (second (ins-lori ins))
(* (first (ins-low ins)) (first (ins-lori ins))))]
[else void]))
(define (set-Rs! index val)
(local [(define (fn-1 n acc)
(if (= n (length Rs))
acc
(cond [(= index n) (fn-1 (add1 n) (append acc (list val)))]
[else (fn-1 (add1 n) (append acc (list (list-ref Rs n))))])))]
(set! Rs (fn-1 0 empty))))
If I'm understanding your code correctly, you're storing the state of the computer inside of the Instruction objects. Because of this, when you make a change to each Instruction object individually it has no effect on the later ones in the list. I would suggest instead to separate your state out from your instructions and use something like fold.
If you have some function which takes an Instruction and machine state (in that order), runs the Instruction on that state, and returns the new state (lets call this function run), you can run a list of Instructions on a given machine state like so:
(fold run current-state instructions-list)
And this will return the new state after running all the instructions.
I'm trying to reverse a list in scheme and I came up with to the following solution:
(define l (list 1 2 3 4))
(define (reverse lista)
(car (cons (reverse (cdr (cons 0 lista))) 0)))
(display (reverse l))
Although it works I don't really understand why it works.
In my head, it would evaluate to a series of nested cons until cons of () (which the cdr of a list with one element).
I guess I am not understanding the substitution model, could someone explain me why it works?
Obs:
It is supposed to work only in not nested lists.
Taken form SICP, exercise 2.18.
I know there are many similar questions, but as far as I saw, none presented
this solution.
Thank you
[As this happens quite often, I write the answer anyway]
Scheme implementations do have their builtin versions of reverse, map, append etc. as they are specified in RxRS (e.g. https://www.cs.indiana.edu/scheme-repository/R4RS/r4rs_8.html).
In the course of learning scheme (and actually any lisp dialect) it's really valuable to implement them anyway. The danger is, one's definition can collide with the built-in one (although e.g. scheme's define or lisp's label should shadow them). Therefore it's always worth to call this hand-made implementation with some other name, like "my-reverse", "my-append" etc. This way you will save yourself much confusion, like in the following:
(let ([append
(lambda (xs ys)
(if (null? xs)
ys
(cons (car xs) (append (cdr xs) ys))))])
(append '(hello) '(there!)))
-- this one seems to work, creating a false impression that "let" works the same as "letrec". But just change the name to "my-append" and it breaks, because at the moment of evaluating the lambda form, the symbol "my-append" is not yet bound to anything (unlike "append" which was defined as a builtin procedure).
Of course such let form will work in a language with dynamic scoping, but scheme is lexical (with the exception of "define"s), and the reason is referential transparency (but that's so far offtopic that I can only refer interested reader to one of the lambda papers http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf).
This reads pretty much the same as the solutions in other languages:
if the list is empty, return an empty list. Otherwise ...
chop off the first element (CAR)
reverse the remainder of the list (CDR)
append (CONS) the first element to that reversal
return the result
Now ... given my understanding from LISP days, the code would look more like this:
(append (reverse (cdr lista)) (list (car lista)))
... which matches my description above.
There are several ways to do it. Here is another:
(define my-reverse
(lambda (lst)
(define helper
(lambda (lst result)
(if (null? lst)
result
(helper (cdr lst) (cons (car lst) result)))))
(helper lst '())))
NOTE: I would like to do this without rackets built in exceptions if possible.
I have many functions which call other functions and may recursively make a call back to the original function. Under certain conditions along the way I want to stop any further recursive steps, and no longer call any other functions and simply return some value/string (the stack can be ignored if the condition is met).. here is a contrived example that hopefully will show what I'm trying to accomplish:
(define (add expr0 expr1)
(cond
[(list? expr0) (add (cadr expr0) (cadr (cdr expr0)))]
[(list? expr1) (add (cadr expr1) (cadr (cdr expr1)))]
[else (if (or (equal? expr0 '0) (equal? expr1 '0))
'(Adding Zero)
(+ expr0 expr1))]
))
If this were my function and I called it with (add (add 2 0) 3), Then the goal would be to simply return the entire string '(Adding Zero) ANYTIME that a zero is one of the expressions, instead of making the recursive call to (add '(Adding Zero) 3)
Is there a way to essentially "break" out of recursion? My problem is that if i'm already deep inside then it will eventually try to evaluate '(Adding Zero) which it doesn't know how to do and I feel like I should be able to do this without making an explicit check to each expr..
Any guidance would be great.
In your specific case, there's no need to "escape" from normal processing. Simply having '(Adding Zero) in tail position will cause your add function to return (Adding Zero).
To create a situation where you might need to escape, you need something a
little more complicated:
(define (recursive-find/collect collect? tree (result null))
(cond ((null? tree) (reverse result))
((collect? tree) (reverse (cons tree result)))
((not (pair? tree)) (reverse result))
(else
(let ((hd (car tree))
(tl (cdr tree)))
(cond ((collect? hd)
(recursive-find/collect collect? tl (cons hd result)))
((pair? hd)
(recursive-find/collect collect? tl
(append (reverse (recursive-find/collect collect? hd)) result)))
(else (recursive-find/collect collect? tl result)))))))
Suppose you wanted to abort processing and just return 'Hahaha! if any node in the tree had the value 'Joker. Just evaluating 'Hahaha! in tail position
wouldn't be enough because recursive-find/collect isn't always used in
tail position.
Scheme provides continuations for this purpose. The easiest way to do it in my particular example would be to use the continuation from the predicate function, like this:
(call/cc
(lambda (continuation)
(recursive-find/collect
(lambda (node)
(cond ((eq? node 'Joker)
(continuation 'Hahaha!)) ;; Processing ends here
;; Otherwise find all the symbols
;; in the tree
(else (symbol? node))))
'(Just 1 arbitrary (tree (stucture) ((((that "has" a Joker in it)))))))))
A continuation represents "the rest of the computation" that is going to happen after the call/cc block finishes. In this case, it just gives you a way to escape from the call/cc block from anywhere in the stack.
But continuations also have other strange properties, such as allowing you to jump back to whatever block of code this call/cc appears in even after execution has left this part of the program. For example:
(define-values a b (call/cc
(lambda (cc)
(values 1 cc))))
(cc 'one 'see-see)
In this case, calling cc jumps back to the define-values form and redefines a and b to one and see-see, respectively.
Racket also has "escape continuations" (call/ec or let/ec) which can escape from their form, but can't jump back into it. In exchange for this limitation you get better performance.
I am learning Scheme and as a toy example I am doing a solution verifier (not a solver) for Towers of Hanoi.
I want to use a purely functional style (just to get into the mindset) and I represent the tower as a simple list of three lists. The starting state can look something like this:
'((0 1 2 3 4) () ())
How would I implement a function that takes a state, a source index and a target index and returns the new state? In an imperative style this would be something trivial like:
state[target].push(state[source].pop())
But every functional solution I can think of is terribly convoluted. For example:
(define (makeMove state source target)
(letrec ((recMake (lambda(tower pos disc)
(if (null? tower) '()
(cons (if (eqv? pos source)
(cdr (car tower))
(if (eqv? pos target)
(cons disc (car tower))
(car tower)))
(recMake (cdr tower)
(+ pos 1)
disc))))))
(recMake state 0 (car (list-ref state source)))))
This seems to work, but there must be a better way. I suppose a map would be somewhat better than recursion, but still too much. Would it be easier if I represented state differently?
Also, feel free to criticize my code. I don't really know what I am doing.
EDIT:
If possible, I prefer that you not assume that the number of towers are always 3.
Here's a super-straightforward way. I'm not sure what the significance of the disc "numbers" are in your implementation, but I made it behave the same as your answer does, pushing and popping them.
(define (make-move state source target)
(define (alter-tower tower index disc)
(cond ((= index source) (cdr tower)) ; remove a disc
((= index target) (cons disc tower)) ; add a disc
(else tower))) ; this tower wasn't changed
(let ((disc (car (list-ref state source))))
(let ((s0 (alter-tower (list-ref state 0) 0 disc))
(s1 (alter-tower (list-ref state 1) 1 disc))
(s2 (alter-tower (list-ref state 2) 2 disc)))
(list s0 s1 s2))))
If you assume the existence of a map-with-index function, which comes standard in many languages and libraries but is not built into Scheme, then you could roll up the bottom set of operations on each tower into a call to that, and it would be much cleaner.
In general, try to come up with pure functions down to the lowest level possible which do what you want. In this solution, I invented a pure function "alter-tower" which can return the result of your command on a single tower, and that's what makes the rest of the solution very straightforward.
Since you asked for feedback, I note that = is identical for eqv? when applied to numbers, that internal defines work in Scheme and act as you'd expect (e.g. you can call them recursively) and that the usual naming convention in Lisp is to separate multi-word identifiers with hyphens, instead of using camel-case.
Good luck!
EDIT: Here's a version, for example, that uses Racket's list comprehensions:
(define (make-move state source target)
(define (alter-tower tower index disc)
(cond ((= index source) (cdr tower)) ; remove a disc
((= index target) (cons disc tower)) ; add a disc
(else tower))) ; this tower wasn't changed
(let ((disc (car (list-ref state source))))
(for/list ([(tower idx) (in-indexed state)])
(alter-tower tower idx disc))))
Many functional languages have a map that can take a predicate which consumes the index, so those two lines might instead look like:
(map (lambda (tower idx) (alter-tower tower idx disc)) state)
So depending on your Scheme dialect and libraries it might be different. (I don't think there's an SRFI for this, but I might be mistaken.) Or you could always write the above version of map yourself.