Q(a, b) :- Edge(a, b).
Q(a, b) :- Q(a, x),
Edge(x, b).
The function of this code is to search all pair of nodes which are reachable. How is that recursive?
This is recursive because the predicate calls itself:
q(A, B) :- q(A, X),edge(X, B).
What the actual execution order is depends on the implementation. It may be "bottom up":
From any edge(A,B) derive q(A,B)
Apply q(A, B) :- q(A, X),edge(X, B). until a fixpoint has been reached (i.e. not further q(A,B) can be deduced).
owever, you should be able to rearrange the code without being at risk of generating non-termination search, unlike in Prolog.
This should work too:
q(A, B) :- q(A, X),edge(X, B).
q(A, B) :- edge(A, B).
Related
Reader beware: Clueless about functional programming and even more clueless about Scheme.
I have a recursive function in Scheme. In the non-base-case portion, the function calls itself twice, comparing the two calls in an if statement. I need to return the result that is greater. So... what I'm currently doing is:
(if (> (recursive-call a b-1) (recursive-call a-1 b))
(recursive-call a b-1)
(recursive-call a-1 b))
Which obviously requires that I make 3 recursive calls instead of 2.
Is there a way to reference the value of the recursive calls from the if statement? I am not allowed to define additional functions or use let. I'm thinking it has to do with out-mode parameters but don't know how to use, assign, or access the value of an out-mode parameter. When I asked the professor, I was pointed to parameter passing methods in functional languages as well as the general process of a function return. It wasn't helpful in the least. I can't post the full code as it's an assignment for a class. Any chance this is enough for someone to point me in the right direction?
Note: The only constructs we're allowed are null?, car, cdr, else, lcm, +, >, if, parameters to the recursive function (which must be a list and numbers only), integer literals, and parenthesis. No use of max, define, or let, unfortunately.
Note: b-1 and a-1 are names for variables. If you wanted a subtraction you'd use (- a 1). I'll use (- a 1) in my answer, but if it really was a variable you can just replace it.
The obvious way to do this particular logic without restrictions is:
;; return the largest of the two
(max (recursive-call a (- b 1))
(recursive-call (- a 1) b))
The standard Scheme way would be to bind values you use more than once in variables using let so that you don't do the computation more than you need to:
;; cache computed values in local bindings
(let ((a (recursive-call a (- b 1)))
(b (recursive-call (- a 1) b)))
(if (> a b) a b))
Since you are restricted to not use either of those you can rewrite the let version to its primitive form. A let can be rewritten like this:
(let ((ba va) (bb vb))
...)
; ===
((lambda (ba bb)
...)
va
vb)
I guess you should be able to figure it out from here.
I have the following working program: (It can be tested on this site: http://swish.swi-prolog.org, I've removed the direct link to a saved program, because I noticed that anybody can edit it.)
It searches for a path between two points in an undirected graph. The important part is that the result is returned in the scope of the "main" predicate. (In the Track variable)
edge(a, b).
edge(b, c).
edge(d, b).
edge(d, e).
edge(v, w).
connected(Y, X) :-
(
edge(X, Y);
edge(Y, X)
).
path(X, X, _, []) :-
connected(X, _).
path(X, Y, _, [X, Y]) :-
connected(Y, X).
path(X, Z, Visited, [X|Track]) :-
connected(X, Y),
not(member(X, Visited)),
path(Y, Z, [X|Visited], Track).
main(X, Y) :-
path(X, Y, [], Track),
print(Track),
!.
Results:
?- main(a, e).
[a, b, d, e]
true
?- main(c, c).
[]
true
?- main(b, w).
false
My questions:
The list of visited nodes is passed down to the predicates in 2 different ways. In the bound Visited variable and in the unbound Track variable. What are the names of these 2 different forms of parameter passing?
Normally I only wanted to use the unbound parameter passing (Track variable), to have the results in the scope of the main predicate. But I had to add the Visited variable too, because the member checking didn't work on the Track variable (I don't know why). Is it possible to make it work with only passing the Track in an unbound way? (without the Visited variable)
Many thanks!
The short answer: no, you cannot avoid the extra argument without making everything much messier. This is because this particular algorithm for finding a path needs to keep a state; basically, your extra argument is your state.
There might be other ways to keep a state, like using a global, mutable variable, or dynamically changing the Prolog data base, but both are more difficult to get right and will involve more code.
This extra argument is often called an accumulator, because it accumulates something as you go down the proof tree. The simplest example would be traversing a list:
foo([]).
foo([X|Xs]) :-
foo(Xs).
This is fine, unless you need to know what elements you have already seen before getting here:
bar(List) :-
bar_(List, []).
bar_([], _).
bar_([X|Xs], Acc) :-
/* Acc is a list of all elements so far */
bar_(Xs, [X|Acc]).
This is about the same as what you are doing in your code. And if you look at this in particular:
path(X, Z, Visited, /* here */[X|Track]) :-
connected(X, Y),
not(member(X, Visited)),
path(Y, Z, [X|Visited], /* and here */Track).
The last argument of path/4 has one element more at a depth of one less in the proof tree! And, of course, the third argument is one longer (it grows as you go down the proof tree).
For example, you can reverse a list by adding another argument to the silly bar predicate above:
list_reverse(L, R) :-
list_reverse_(L, [], R).
list_reverse_([], R, R).
list_reverse_([X|Xs], R0, R) :-
list_reverse_(Xs, [X|R0], R).
I am not aware of any special name for the last argument, the one that is free at the beginning and holds the solution at the end. In some cases it could be an output argument, because it is meant to capture the output, after transforming the input somehow. There are many cases where it is better to avoid thinking about arguments as strictly input or output arguments. For example, length/2:
?- length([a,b], N).
N = 2.
?- length(L, 3).
L = [_2092, _2098, _2104].
?- length(L, N).
L = [],
N = 0 ;
L = [_2122],
N = 1 ;
L = [_2122, _2128],
N = 2 . % and so on
Note: there are quite a few minor issues with your code that are not critical, and giving that much advice is not a good idea on Stackoverflow. If you want you could submit this as a question on Code Review.
Edit: you should definitely study this question.
I also provided a somewhat simpler solution here. Note the use of term_expansion/2 for making directed edges from undirected edges at compile time. More important: you don't need the main, just call the predicate you want from the top level. When you drop the cut, you will get all possible solutions when one or both of your From and To arguments are free variables.
Concept
I am implementing an interpreter that allows a user to define arbitrary combinators and apply them to arbitrary terms. For example, a user may define the Church encoding for pairs by inputting the following combinator definitions:
pair a b c → c a b
true a b → a
first a → a true
The user may then input first (pair a b), which is reduced step-by-step according to the previously defined rules:
first (pair a b)
→ pair a b true
→ true a b
→ a
Other combinators may also be defined, such as those used in the SKI combinator calculus:
S x y z → x z (y z)
K x y → x
I x → x
The identity combinator could also be defined in terms of the first two combinators by I → S S K K or I → S K (K K) or I = S K x. The universal iota combinator could then be defined by:
ι x → x S K
These examples hopefully illustrate what I am trying to do.
Implementation
I am attempting to implement this using graph reduction and a graph rewriting system. Let tree be a data type defined recursively by
tree = leaf | (tree tree)
This is a binary tree, where nodes may be either leafs (terminal nodes) or branches (internal nodes) consisting of a pair of subtrees. The branches represent the application of a term to another term, while leaves represent combinators and arguments. Let rule be a data type defined by
rule = (tree tree)
This corresponds to a reduction rule that transforms the left tree into the right tree (a → b). The list of rules may then be defined by
rules = rule | (rule rules)
Effectively, when evaluating an expression such as pair a b c → c a b, the interpreter constructs a tree of the form (((pair a) b) c) corresponding to the left hand side, a tree of the form ((c a) b) corresponding to the right hand side, constructs a pair of both trees corresponding to a rule (where a,b,c are somehow specified to be arbitrary parameters and not necessarily combinators or terminal symbols), and appends this pair to the list rules. When reducing an expression of the form first (pair a b), the interpreter constructs the corresponding tree (first ((pair a) b)) and applies the reduction rules as follows:
(first ((pair a) b))
→ (((pair a) b) true)
→ ((true a) b)
→ a
To do this, the interpreter must perform pattern matching on the tree and its subtrees, "moving around" the combinators and arbitrary parameters to construct a new tree corresponding to the right hand side of the rule. An example implementation of the tree structure in C is given by
struct tree_t {
bool is_leaf;
union {
char* symbol;
struct {
tree_t* left;
tree_t* right;
};
};
};
A pattern matching function could be implemented as
bool matches(tree_t* pattern, tree_t* replacement) {
if (pattern -> is_leaf && replacement -> is_leaf)
//do stuff, return a boolean
else if (pattern -> is_leaf && replacement -> is_branch)
//do stuff, return a boolean
else if (pattern -> is_branch && replacement -> is_leaf)
//do stuff, return a boolean
else if (pattern -> is_branch && replacement -> is_branch)
return matches(pattern -> left, replacement -> left) && matches(pattern -> right, replacement -> right);
//The above tests for equality recursively by testing for equality in each subtree.
}
However, I am unsure of how to implement important details of this process, including:
Matching an input tree with the LHS tree of a reduction rule.
Transforming the input tree into the RHS tree of the reduction rule, preserving parameters (which may be leaves or branches) and "moving them around" around to their appropriate places.
I believe pattern-matching on a node would involve examining the left child and right child of the node and so on, until terminal nodes are reached. Does anyone know of a program or tutorial online that has implemented a similar concept in C and that I could learn from? Am I even on the right track in approaching the problem through this method, or is there a simpler way?
You need to take it in two separate steps. A pattern matcher matches a pattern against a tree, and builds a dictionary mapping variables in the pattern to values in the tree.
Then you pass that dictionary to a separate function that fills in the replacement, by replacing variables with their values from the dictionary.
The pattern matching approach described in SICP will work just fine in C, though you may find it easier to use a mutable data structure for the dictionary. See https://mitpress.mit.edu/sicp/full-text/sicp/book/node99.html
I often see type declarations similar to this when looking at Haskell:
a -> (b -> c)
I understand that it describes a function that takes in something of type a and returns a new function that takes in something of type b and returns something of type c. I also understand that types are associative (edit: I was wrong about this - see the comments below), so the above could be rewritten like this to get the same result:
(a -> b) -> c
This would describe a function that takes in something of type a and something of type b and returns something of type c.
I've also heard that you can make a complement (edit: really, the word I was looking for here is dual - see the comments below) to the function by switching the arrows:
a <- b <- c
which I think is equivalent to
c -> b -> a
but I'm not sure.
My question is, what is the name of this kind of math? I'd like to learn more about it so I can use it to help me write better programs. I'm interested in learning things like what a complimentary function is, and what other transformations can be performed on type declarations.
Thanks!
Type declarations are not associative, a -> (b -> c) is not equivalent to (a -> b) -> c. Also, you can't "switch" the arrows, a <- b <- c is not valid syntax.
The usual reference to associativity is in this case that -> it right associative, which means that a -> b -> c is interpreted as a -> (b -> c).
Speaking broadly this falls into the realm of Lambda Calculus.
Since this notation has to do with types of functions type inference might be of interest to you as well.
(The wrong assumptions you made about associativity should already be cleared up sufficiently by the other answers so i will not reiterate that)
a -> (b -> c)
and
(a -> b) -> c
are not equivalent in Haskell. That is type theory which can be founded in category theory.
The former is a function taking an argument of type a and returning a function of type b -> c. While the latter is a function taking a function of type a -> b as argument and returning a value of type c.
What do you mean by the complement of a function? The type of the inverse function of a function of type a -> (b -> c) has the type (b -> c) -> a.
Functions of type a->b->c, which are actually chains of functions like you said, are examples of Currying
Ok, so i have this
edu_less(hs,college).
edu_less(college,masters).
edu_less(masters,phd).
I need to write a function to tell if something is less than the other. The predicate is
edu_le.
So if i put edu_le(hs,phd). it should return yes.
I came up with this.
edu_le(A,B) :- A = B.
edu_le(A,B) :- edu_less(A,B).
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
I really don't want it to go through everything and return multiple answers.
Is it possible to only return yes or no if it finds that it is in fact less than or equal to the 2nd argument?
So basically if i use the example edu_le(hs,phd) again, then because hs is less than college, and college is than masters, and masters is less than phd, then hs must be less than phd and it would say yes.
Sorry, really new to prolog, still trying to get the hang of this.
In the predicate definition
edu_le(A,B) :- A = B.
edu_le(A,B) :- edu_less(A,B).
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
the second clause is superfluous and causes repeated generation of answers. Use
edu_le(A,B) :- A = B.
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
This gives you one true answer, then no more answers (false) on backtracking. You can use a cut in the first clause, but then generating won't work anymore.
?- edu_le(hs,X).
X = hs ;
X = college ;
X = masters ;
X = phd ;
false.
becomes incomplete:
?- edu_le(hs,X).
X = hs.
As mat suggested, use once/1 instead. In a good Prolog implementation, this predicate works as if your program had cuts in strategic places, speeding up your program without disturbing its logical semantics.
The most practical way to write predicates like that is to use the cut (!). The cut causes further clauses not to be considered when backtracking. You would write your predicate as following:
edu_le(A,B) :- A = B, !.
edu_le(A,B) :- edu_less(A,B), !.
edu_le(A,B) :- edu_less(A,C), edu_le(C,B).
The last clause does not need a cut because there are no further clauses to consider anyway. The cut is placed after any tests to determine whether the clause should succeed.
Logic programming purists disapprove of the cut, because it makes the meaning of a predicate depend on the ordering of the clauses, which is unlike logic in mathematics.
!/0 also makes this program incomplete, consider for example the most general query with both versions:
?- edu_le(X, Y).
It is often better to use once/1 if you only want a single proof of a particular goal:
?- once(edu_le(hs, phd)).
I would suggest you NOT to follow the path proposed by Juho Östman and keep purity - otherwise, why should you use Prolog in first instance? If you are too lenient with sticking to the logical paradigm you obtain some unpleasing results. In this case, Juho's predicate is definitely different from yours, and I'll show you why.
First, just drop the useless edu_le(A,B) :- edu_less(A,B). rule, as larsmans suggests. You will obtain a less redundant version of your original predicate:
edu_le1(A, A).
edu_le1(A, B) :- edu_less(A, C), edu_le1(C, B).
It just behaves as edu_le, meaning: given an arbitrary query, it produces exactly the same answer, except for duplicates (edu_le1 has less). You may just be happy with it, but it still has some redundant answers that you may not like; e.g, under SWI:
?- edu_le1(hs, hs)
true ;
false.
Now you may say you do not like it because it still has the redundant false, but if you use Juho's predicate instead (without the useless rule):
edu_le2(A, A) :- !.
edu_le2(A, B) :- edu_less(A, C), edu_le2(C, B).
it's true that you eliminate the useless final false:
?- edu_le2(hs, hs)
true.
?-
but you lose more than that: You lose, as mat remarks, the possibility of generating all the solutions when one variable is not instantiated:
?- edu_le1(hs, B) %same, with more copies, for edu_le
B = hs ;
B = college ;
B = masters ;
B = phd ;
false.
?- edu_le2(hs, B)
B = hs. %bad!
?-
In other words, the latter predicate is NOT equivalent to the former: edu_le and edu_le1 have type edu_le(?A, ?B), while instead edu_le2 has type edu_le2(+A, +B) (see [1] for the meaning). Be sure: edu_le2 is less useful because it does less things, and thus can be reused in less contexts. This because the cut in edu_le2 is a red cut, i.e., a cut that changes the meaning of the predicate where it is introduced. You may nevertheless be content with it, given that you understand the difference between the two. It all depends on what you want to do with it.
If you want to get the best of the two worlds, you need to introduce in edu_le1 a proper green cut that lowers the redundancy when A and B are completely instantiated to terms. At the purpose, you must check that A and B are instantiated to the same term before cutting. You cannot do it with =, because = does not check, but unifies. The right operator is ==:
edu_le3(A, B) :- (A == B -> ! ; true), A = B.
edu_le3(A, B) :- edu_less(A, C), edu_le3(C, B).
Note that the additional cut in the first rule is active only when A and B happen to be the same term. Now that the cut is a proper green cut, the predicate works also in the most general cases as your original one:
?- edu_le3(A, A).
true.
?- edu_le3(A, B). %note that A and B are not the same term
A = B ;
A = hs,
B = college ;
A = hs,
B = masters ;
A = hs,
B = phd ;
A = college,
B = masters ;
A = college,
B = phd ;
A = masters,
B = phd ;
false.
?-
with Prolog backtracking through all the solutions.
I don't think there is some way to eliminate the last false without introducing too strong dependency on edu_lt. This because we must keep open the possibility that there is another edu_lt to explore, in the case you decide later to enrich it with more ground facts. So, in my opinion, this is the best you can have.
[1] SWI Prolog reference manual, section 4.1.