retracting and asserting values in prolog - prolog

I have been modelling some directive graphs in prolog. It consists of nodes and edges and how they are connected. Every node has a certain value of surfers (page rank).
e.g.
e(a,c).
e(b,a).
e(b,h).
:-dynamic s/2.
s(a,1).
s(b,1).
s(c,1).
I have written an interpreter. This interpreter calculates new values for each node.
The problem is how to assign these new values to the database.
I have been doing it with retractall(s(,)) and asserting new values to every single node with e.g. assertz(s(a,sum0),
assertz(s(b,sum1), ....
This has been working, but is it possible to assert new values without asserting each particular node in the graph a value, so that the interpreter is completely independent from the graph?
I have been trying to generate a list with all nodes in a graph and indicating the nodes of a graph in this list.
sum_nodes_0(X,Y):-
list_nodes(_,L),
amount_nodes(N),
nth1(I,L,X),I=<N,sum_node(X,Y).
reset(X,S):-
list_nodes(_,L),
s(X,S),
sum_node(X,Y),
retractall(s(_,_)),
forall(member(X,L),assertz(s(X,Y))).
sum_nodes_0 displays me the new values like.
X = a,
Y = 1.0 ;
X = b,
Y = 1 ;
X = c,
Y = 2 ;
X = d,
Y = 0.5 ;
X = e,
Y = 1.5 ;
X = f,
Y = 0.5 ;
X = g,
Y = 1 ;
X = h,
Y = 0.5.
These values I want to be assigned by reset(X,S). But reset just resets one value not all. e.g.
X=h; Y=0
I have tried foreach, forall and member predicates. But it didn't work as intended.
I hope that someone has an idea.

Related

Prolog - Connectivity Graph Beginner

I am a beginner in Prolog and I have a task to do.
I need to check if the graph is connected.
For now I have that...
graph(
[arc(a,b)],
[arc(a,f)],
[arc(b,c)],
[arc(c,d)],
[arc(c,e)],
[arc(e,d)],
[arc(f,c)],
[arc(f,e)],
[arc(f,g)],
[arc(g,c)],
[arc(c,a)]).
edge(X,Y):-arc(X,Y);arc(Y,X).
path(X,Y):-edge(X,Y).
path(X,Y):-edge(X,Z),path(Z,Y).
triangle(X,Y,Z):-arc(X,Y),arc(Y,Z),arc(Z,X).
cycle(X):-arc(X,Y),path(Y,X).
connectivity([]):-forall(member(edge(X,Y)),path(X,Y)).
Check:
connectivity(graph).
upper I have arc(x,y) and I need check if every pair is connected.
Could u help me ?
Since you changed the question after I was almost done I will post what would solve the question before the change and you can figure out how to change it to meet your update.
arc(a,b).
arc(a,f).
arc(b,c).
arc(c,d).
arc(c,e).
arc(e,d).
arc(f,c).
arc(f,e).
arc(f,g).
arc(g,c).
arc(c,a).
edge(X,Y) :-
arc(X,Y), !.
edge(X,Y) :-
arc(Y,X).
path_prime(Visited,X,Y) :-
\+ member(X,Visited),
edge(X,Y), !.
path_prime(Visited,X,Y) :-
\+ member(X,Visited),
edge(X,Z),
path_prime([X|Visited],Z,Y).
path(X,X) :-
ground(X), !.
path(X,Y) :-
path_prime([],X,Y).
nodes(Nodes) :-
setof(A,B^arc(A,B),Starts),
setof(B,A^arc(A,B),Ends),
union(Starts,Ends,Nodes).
connected(X,Y) :-
nodes(Nodes),
member(X,Nodes),
member(Y,Nodes),
path(X,Y).
The first thing that has to be done is to get a list of the unique nodes which will be a set.
This can be done using
nodes(Nodes) :-
setof(A,B^arc(A,B),Starts),
setof(B,A^arc(A,B),Ends),
union(Starts,Ends,Nodes).
Notice that both the start and the end node of an arc are done separately. In particular notice that the node d is only in the destination of an arc.
Since you included edge(X,Y):-arc(X,Y);arc(Y,X). in your question, this indicated that the arcs should not be directional and so it is possible to get cycles. To avoid the cycles the list of visited nodes is added to the argument list and checked before proceeding.
As no test cases or examples of a correct solution were given, some times a node connected to itself is valid and so the clause
path(X,X) :-
ground(X), !.
was added.
This is by no means an optimal or best way to do this, just to give you something that works.
Partial run
?- connected(X,Y).
X = Y, Y = a ;
X = a,
Y = b ;
X = a,
Y = c ;
X = a,
Y = d ;
X = a,
Y = e ;
X = a,
Y = f ;
X = a,
Y = g ;
X = b,
Y = a ;
X = Y, Y = b ;
X = b,
Y = c ;
...
As I often comment, you should do problems with pen an paper first before writing code. If you don't know exactly what the code will be before you start typing the first line of code then why are you typing in code?
Questions from comments:
And setof ,union ,whats mean? Im rly beigneer and I don't understand that language and predicates.
setof/3 collects all of the values from arc/2. Since only one of the two values is needed, ^ tells setup/3 not to bind the variable in the Goal, or in beginner terms to just ignore the values from the variable.
union/3 just combines the to sets into one set; remember that a set will only have unique values.

Assigning values to multiple variables in Go

I recently came up across this:
func main() {
x, y := 0, 1
x, y = y, x+y
fmt.Println(y)
}
What I thought was that:
x, y = y, x+y
Is identical to:
x = y
y = x+y
Which would result to final values x = 1, y = 2
However the final values I get is x = 1, y = 1
Why is that?
Thanks.
This is how it's specified:
The assignment proceeds in two phases. First, the operands of index expressions and pointer indirections (including implicit pointer indirections in selectors) on the left and the expressions on the right are all evaluated in the usual order. Second, the assignments are carried out in left-to-right order.
Assignment first evaluates all expressions on the right side and then assigns the results to the variables on the left side.
Your
x, y = y, x+y
is basically equivalent to this
tmp1 := y
tmp2 := x+y
x = tmp1
y = tmp2
You can even use this fact to swap 2 variables in one line, like this:
a, b = b, a

all possible routes between the Entry and the Exit

i need help to solve the maze path. Thanks in advance
link(a,b).
link(b,c).
link(c,d).
link(f,c).
link(b,e).
link(d,e).
link(e,f).
Write a predicate that defines a route between any two adjacent points (X and Y for example) based on the fact that there is a link between them and a recursive predicate that covers the more general case of a route between any two non-adjacent points (X and Z for example) by establishing for a fact that there is a link between X and a third point in the maze (say Y) and a route between Y and Z.
Two special rooms – one connected to “a” and called “Entry” and another one connected to “f” and called “Exit”. Add a set of facts to reflect the two new rooms. Using the predicates from task 1, write a predicate that finds all possible routes between the Entry and the Exit and creates a list of the visited rooms. Write another predicate that displays the list in the interactive console at the end of every iteration, or in other words every time the Exit is reached. Write a test plan that shows your anticipated results and the actual results. Evaluate this solution and identify any potential problems and the situations that may cause their occurrence.
The problem with this solution is looping.If I want to link(a,f) prolog says no.Is anything wrong with my predicate.
| ?- link(a,b).
link(b,c).
link(c,d).
link(f,c).
link(b,e).
link(d,e).
link(e,f).
route(X,Y):- link(X,Y).
route(X,Y):- link(X,Z), route(Z,Y).
yes
yes
yes
yes
yes
yes
yes
! ----------------------------------------
! Error 20 : Predicate Not Defined
! Goal : route(_31102,_31104) :- link(_31102,_31104)
Aborted
| ?- link(a,f).
no
| ?- route(X,Y).
X = a ,
Y = b ;
X = b ,
Y = c ;
X = c ,
Y = d ;
X = f ,
Y = c ;
X = b ,
Y = e ;
X = d ,
Y = e ;
X = e ,
Y = f ;
X = a ,
Y = c ;
X = a ,
Y = e ;
X = a ,
Y = d
;
X = a ,
Y = d
| ?- link(X,Z).
X = a ,
Z = b
| ?-
| ?- link(X,Z).
X = a ,
Z = b ;
X = b ,
Z = c ;
X = c ,
Z = d ;
X = f ,
Z = c ;
X = b ,
Z = e ;
X = d ,
Z = e ;
X = e ,
Z = f
connected_to( A,B) :-
closure0(link, A,B).
See this question for a definition of closure0/3.
Or, to use your new name:
route(A0,A) :-
link(A0,A1),
closure0(link, A1,A).

Prolog Set List's Head

append([],U,U).
append([X|U1],U2,[W|U3]) :- **W = X** , append(U1,[X|U2],[I|Quyruk]) ,
**W = I**, U3 = Quyruk .
This code appends first two lists when I delete "W is X".
This code has unnecessary variables like "W is X" but they are about my question.
When I set any value to "W" between ":-" and ",append..." like "W is X" or "W = 3" or "W = 6" -- returns false.
Why can't I set any value to the W at that position in code but I CAN set "W = I" at the end of the code?
The query is append([1,2],[3],U). I want to get [2,1,3] at this code
at append([1,2,3],[4,5,6],U). I want to get [3,2,1,4,5,6].
append([1],[2,3],U). returns [1,2,3] , when I take the length of first list "1" (when first list only has one element) the code is perfect ; but when I take the length of first list >1 (when first list has more than one element) the code returns false.
In prolog, you can't assign variables, and then reassign them. Variables are unified and instantiated. Once instantiated, they cannot be re-instantiated inside of a clause. So if you have this inside of a clause:
W = X,
...
W = I,
Then first W is unified with X (=/2 is the unification operator). That means they either both now have the same value instantiated (if at least one was instantiated before), or their values will be forced to be identical instantiation later in the clause. When W = I is encountered later, then I must be unifiable with W or the clause will fail. If I has a specific value instantiated that is different from the instantiation of W (and, therefore, X), the clause will necessarily fail.
Let's see it happen (note I changed the name to my_append since Prolog rejects redefining the built-in predicate, append):
my_append([],U,U).
my_append([X|U1], U2, [W|U3]) :-
W = X,
my_append(U1, [X|U2], [I|Quyruk]),
write('I = '), write(I), write('; W = '), write(W), nl,
W = I,
U3 = Quyruk.
If we run:
?- my_append([1], [1,2], L).
I = 1; W = 1
L = [1,2,3]
yes
Life is good. Now let's try:
| ?- my_append([1,2], [3,4], L).
I = 2; W = 2 % This will be OK
I = 2; W = 1 % Uh oh... trouble
no
Prolog cannot unify 1 and 2, as I described above. They are two different values. So the predicate fails due to the W = I statement.
The solution is a little simpler than what you're attempting (although you are very close):
% Append empty to list gives the same list
my_append([], U, U).
% Append of [X|U1] and U2 is just append U1 and [X|U2]
% Or, thought of another way, you are moving elements of the first list
% over to the head of the second one at a time
my_append([X|U1], U2, U3) :-
my_append(U1, [X|U2], U3).
| ?- my_append([1,2,3],[4,5,6],L).
L = [3,2,1,4,5,6]
yes
The essence of this was in your code. Those other variables were just getting in the way (as C.B. pointed out). :)
The is operator is specifically used to compare or unify integers. W = I Is attempting to unify W with I (regardless of type). When you Unify W with X (assuming X is an integer), you have already unified W, and if X\=I (doesn't unify) you will return false.
In your example, W unifies with 1, but then you try to unify it with 2.
You have a lot of unnecessary variables, here is a very simple implementation of append:
append([],XS,XS).
append([X|XS],YS,[X|ZS]):- append(XS,YS,ZS).
To understand whats going wrong with your code, lets walk through it
append([],U,U).
append([X|U1],U2,[W|U3]) :- W is X , append(U1,[X|U2],[I|Quyruk]) , W = I, U3 = Quyruk .
?-append([1,2,3],[4,5,6],U).
I will use X1,X2,... to differentiate between different bindings.
In the first call, X unifies with 1, U1 unifies with [2,3] and U2 unifies with [4,5,6]. W and U3 are not yet bound before going into the horn clause.
W is X unifies W with 1.
append(U1,[X|U2],[I|Quyruk]) is calling append([2,3],[1,4,5,6],[I|Quyruk]). Already you should see that your recursion isn't working correctly.

The right way to use a data structure in OCaml

Ok, I have written a binary search tree in OCaml.
type 'a bstree =
|Node of 'a * 'a bstree * 'a bstree
|Leaf
let rec insert x = function
|Leaf -> Node (x, Leaf, Leaf)
|Node (y, left, right) as node ->
if x < y then
Node (y, insert x left, right)
else if x > y then
Node (y, left, insert x right)
else
node
I guess the above code does not have problems.
When using it, I write
let root = insert 4 Leaf
let root = insert 5 root
...
Is this the correct way to use/insert to the tree?
I mean, I guess I shouldn't declare the root and every time I again change the variable root's value, right?
If so, how can I always keep a root and can insert a value into the tree at any time?
This looks like good functional code for inserting into a tree. It doesn't mutate the tree during insertion, but instead it creates a new tree containing the value. The basic idea of immutable data is that you don't "keep" things. You calculate values and pass them along to new functions. For example, here's a function that creates a tree from a list:
let tree_of_list l = List.fold_right insert l Leaf
It works by passing the current tree along to each new call to insert.
It's worth learning to think this way, as many of the benefits of FP derive from the use of immutable data. However, OCaml is a mixed-paradigm language. If you want to, you can use a reference (or mutable record field) to "keep" a tree as it changes value, just as in ordinary imperative programming.
Edit:
You might think the following session shows a modification of a variable x:
# let x = 2;;
val x : int = 2
# let x = 3;;
val x : int = 3
#
However, the way to look at this is that these are two different values that happen to both be named x. Because the names are the same, the old value of x is hidden. But if you had another way to access the old value, it would still be there. Maybe the following will show how things work:
# let x = 2;;
val x : int = 2
# let f () = x + 5;;
val f : unit -> int = <fun>
# f ();;
- : int = 7
# let x = 8;;
val x : int = 8
# f ();;
- : int = 7
#
Creating a new thing named x with the value 8 doesn't affect what f does. It's still using the same old x that existed when it was defined.
Edit 2:
Removing a value from a tree immutably is analogous to adding a value. I.e., you don't actually modify an existing tree. You create a new tree without the value that you don't want. Just as inserting doesn't copy the whole tree (it re-uses large parts of the previous tree), so deleting won't copy the whole tree either. Any parts of the tree that aren't changed can be re-used in the new tree.
Edit 3
Here's some code to remove a value from a tree. It uses a helper function that adjoins two trees that are known to be disjoint (furthermore all values in a are less than all values in b):
let rec adjoin a b =
match a, b with
| Leaf, _ -> b
| _, Leaf -> a
| Node (v, al, ar), _ -> Node (v, al, adjoin ar b)
let rec delete x = function
| Leaf -> Leaf
| Node (v, l, r) ->
if x = v then adjoin l r
else if x < v then Node (v, delete x l, r)
else Node (v, l, delete x r)
(Hope I didn't just spoil your homework!)

Resources