Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

member predicate 1

Status
Not open for further replies.

misoijnr

Programmer
Nov 17, 2010
32
BE
hi, help me put this predicate into perspective, was trying to make one to find path on the facts attached.

findpath(Dest,L) :-
find_route(node(NodeID), Dest, L.
findpath(S, Dest, Sol) :-
way(S, Dest, , Path),
invert(Path, Sol).

path( P, P, L, L).
path( Node, Goal, Path, Sol) :-
route( Node, WayID), not( way(WayID) ),
not( member( WayID, Path)),
path( WayID, Goal, [WayID | Path], Sol).

member(X,[X|Xs]).
member(X,[_|Ys]) :- member(X,Ys).

node(NodeID) :- member(NodeID, [lat,long]).
node_tag(NodeID) :- member(NodeID,[name,highway,add:street,crossing,crossing_ref]).
way(WayID) :- member(WayID, Nodelist).
way_tag(WayID):-member(WayID,[name,highway,foot,maxspeed,lanes,oneway,bridge])
 
It will work, just make get_path take 3 parameters (add Path also as the 3rd).

Also make sure you take into account that edge(A, B, X) also means edge(B, A, X). So when you implement the algorithm and your current node is Z, find a neighbor either by calling edge(Z, Neighbor, D) or by calling edge(Neighbor, Z, D). Z could be in either place in your edge information.
 
i used this, but i get error below-
get_path(X, Y, Path) :-
path([X], Y, Path, 0, Length),
reverse(Path, DirectPath),
printPath(DirectPath),
fail.


1 ?- start_algorithm.
Enter start node ID: 231994501.
Enter end node ID: 249394762.
ERROR: path/5: Undefined procedure: edge/3
2 ?-

whats the problem? thanks
 
Well, if you look at the code, it's 'do_something' that you need to call, not 'start_algorithm'

'do_something' calls 'init' and then 'start_algorithm'

If you just call 'start_algorithm' directly, you won't be calling 'init', so your code won't find any 'edge' facts. 'init' does just that, consults files 'leuven.pl' and 'graph.pl' so that node, way and edge information is available for future use
 
good, i have seen that.
i am trying to use this code, but seems something is wrong, it cant print the path after i enter start and end nodes:

path([B | Rest], B, [B | Rest], Length, Length).
path([A | Rest], B, Path, CurrentLength, Length) :-
edge(A, C, X),
\+member(C, [A | Rest]),
NewLength is CurrentLength + X,
path([C, A | Rest], B, Path, NewLength, Length).

get_path(A, B, Path) :-
path([A], B, Path, 0, Length),
reverse(Path, DirectPath),
printPath(DirectPath),

fail.

thank you so much for your support, i am now begining to see the power of prolog.


 
What nodes did you try? Because as I told you, your current algorithm does not take into account that edge(A, B, X) also means edge(B, A, X), so maybe some possibilities are not considered.

Make sure that you don't choose nodes that are not connected in your graph, or are connected but only if you consider edges to be bidirectional.

Also change printPath to this:

Code:
printPath([]) :- nl.
printPath([X]) :-
    !, writeln(X).
printPath([X|T]) :-
    write(X),
    write(', '),
    printPath(T).

It will help you see better by putting a newline after each solution.

Now you may get a lot of duplicate solutions because as I've told earlier, edges are not unique. It's not too complicated to make the generation process generate unique edges (you have to test at each edge generation that it doesn't exist already).
 
it is working but generates a lot of nodes continuously, i think there should be use cut, to give only the path from start node to end node through directly connected and in one way only. this is where it get complicated for me.
how do we avoid duplicates?
thanx
 
You don't need the cut. Those are only due to duplicated edges.

Go back to where you have defined the 'process' predicate and modify it like below:

Code:
process([]).
process([_]).
process([A, B | Rest]) :-
    distance(A, B, Dab),      % compute distance A - B
    \+edge(A, B, _),          % verify that edge doesn't exist already
    assert(edge(A, B, Dab)),  % create edge
    assert(edge(B, A, Dab)),  % create the opposite edge
    process([B | Rest]).      % continue processing with the other pairs
process([A, B | Rest]) :-
    distance(A, B, Dab),      % compute distance A - B
    edge(A, B, _),            % if such an edge already exists
    process([B | Rest]).      % continue processing with the other pairs

This code should avoid generating duplicates (didn't test it though since it's late). You should clear the 'graph.pl' and rerun the generation predicate. I think it was called 'start' back then
 
hi, i have rerun the code above,
but error
% leuven.pl compiled 4.31 sec, 2,000,216 bytes
ERROR: process/1: Undefined procedure: edge/3
Exception: (6) start ?
is it missing something while checking if duplicates exist? on the \+edge above?
 
Ok, try adding this code in the upper part of the file where you have 'start', 'create_db' and 'process':

Code:
:- dynamic(edge/3).

This way you tell Prolog that it should expect to have some 'edge' clauses asserted dynamically, even though there are none defined explicitly, so it should stop complaining about not having 'edge' defined.
 
that has worked,
but still, when i enter start node and end node, it gives continous result nodes.
how do i limit only to nodes in the same e.g way(80362707, [937819764, 937819761, 937819774, 937819762, 937819764]).

from leuven.pl is a way with list of nodes within it.
so that it does not enter into a loop of so many nodes from the edges. i.e how do we generate edges of nodes in the same list of way[] from leuven.pl? so that when i enter 937819764 as start node and 937819764 as the end node, it gives me the nodes i have to go through to reach the last node with the total lenght, i.e nodes to arrive at 937819764, are 937819761 then 937819774 then 937819762

also way[wayId,[]], how can we link ways? so that we can generate paths that one can get from way1 to way2 before arriving at final node?
i know its alot of work, but am keenly following your advise. thanks
 
Ok, I didn't try on the large 'leuven.pl' file, so maybe it goes on forever because there are many results.

Do the following modification to the code, so that Prolog will stop after each solution and print it to you:

Code:
init :-
    consult('leuven.pl'),    % get the nodes and ways
    consult('graph.pl').     % get the edges that we generated earlier

find_path(Path) :-
    init,         % call init to consult the 2 files we need
    start_algorithm(Path).

start_algorithm(Path) :-
    write('Enter start node ID: '),
    read(X),      % X is a value entered by the user
    write('Enter end node ID: '),
    read(Y),      % Y is a value entered by the user
    get_path(X, Y, Path),

get_path(X, Y, Path) :-
    path([X], Y, ReversedPath, 0, Length),
    reverse(ReversedPath, Path),
    printPath(Path).

Run find_path(Path) and see what results you get for Path. After each result, press ';' to go to the next one. See if something interesting happens.
 
do i need to define start_algorithm/1 as dynamic? check this error
% leuven.pl compiled 5.02 sec, 2,000,452 bytes
% graph.pl compiled 0.23 sec, 1,506,752 bytes
ERROR: find_path/1: Undefined procedure: start_algorithm/1

and how do i improve the code to retunr the total distance between the start and end node.
thanks
 
Make sure you replaced your original code with the one I provided.

'start_algorithm' should take 1 parameter, like in the last code snippet. The original version had 0 parameters, and that's what's causing the error
 
i have replaced. where do i set the parameter values?
and how do i replace the node Ids with name of node_tag? i.e user enters the start name and laste name and the prolog program returns the nodes(name_tags) between the start and end nodes and also list the way names .i.e go from way1 then way2 and finally reach node last.

thanks
 
and how do i replace the node Ids with name of node_tag?"


Come on, this is easy.

Code:
node(16387325, 50.8686270, 4.6984337).
node_tag(16387325, 'name', 'Kardinaal Mercierlaan').

If the program expects user input (read(X)) and the user enters 'Kardinaal Mercierlaan', then X would take that value. So you should query:

Code:
node_tag(ID, 'name', X)

... so the variable ID will be bound to 16387325 ...

Then you can go on with the normal algorithm using ID. The node_tag was only used to retrieve the ID from the value 'Kardinaal Mercierlaan'

You should easily find the error about not finding some predicate, if you look closer.

ERROR: find_path/1: Undefined procedure: start_algorithm/1

This error means that in the 'find_path' predicate that takes 1 parameter (find_path/1) you make a call to 'start_algorithm' also with 1 parameter. But where you defined 'start_algorithm' it doesn't take 1 parameter, hence the error. It should be easy to spot and fix
 
Anyway, I suggest you rely on node IDs for the moment and not names. Let the user enter IDs. From what I see, most of the nodes in your 'leuven.pl' don't have a node_tag with name information.
 
i have tried but cant spot where i need to correct the error-
ERROR: find_path/1: Undefined procedure: start_algorithm/1

the code is this
find_path(Path) :-
init, % call init to consult the 2 files we need
start_algorithm(Path).

start_algorithm(Path) :-
% node_tag(ID, 'name', X),
write('Enter start node ID: '),
read(X), % X is a value entered by the user
write('Enter end node ID: '),
read(Y), % Y is a value entered by the user
get_path(X, Y, Path),

get_path(X, Y, Path) :-
path([X], Y, ReversedPath, 0, Length),
reverse(ReversedPath, Path),
printPath(Path).
 
'start_algorithm' ends with a comma. It should end with a dot. So probably Prolog won't even compile your code, you shouldn't try to run it when the compilation reports error, but rather try to fix those errors.
 
i have noted the error, thanks,

if you have time, re-edit the code for me to do the following, then i can continue from there:
-Use leuven.pl to preprocess another file with- Node Id and Its names, way_tag with nodes, names and way with node id, way id, name of the way and edge with way name and distance calculated from euclidean.

and finally re-edit the code for me on the user input.
What i wanted this code to do is:
-A user enters its type like pedestrian, driver, or cyclist.
- then enters the name of where he is and where he wants to go.
-an itinerary is generated from the facts from leuven.pl

i.e, go from point A(name) to Point B, through point C etc and giving the shortest distance or route to take and the total distance from the euclidean algorithm we have used above.
If u can write for me a skeleton of this program that runs, then i continue learning.
i have really appreciated your support. I know i have consumed so much of your time on a simple problem to you, am really trying to learn prolog, it sounds an interesting language to learn.

cheerz kahleen
 
Well, I really think that you should try yourself taking little steps to fulfill your goal. Asking some random guy on a forum solve each and every step is neither appropriate for learning, nor rewarding. Rewarding is when you discover by yourself that using this or that condition helps in restricting the results to pedestrian paths or cyclist paths, for example.

I suggest you build a smaller version of 'leuven.pl' that contains a sufficient collection of nodes and ways of interest for you, and at the same time it's small enough to comprehend, because a 800Kb version is far from comprehensible. Try every idea that you have on the smaller version, struggle to get the result that you want, if you don't succeed use the debugger to see what's wrong and how to correct it. I promise it would be fun, the problem is interesting and full of rewards if you take the time to try and solve it.

Good luck
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top