• Aucun résultat trouvé

All-pairs shortest path problem

Distributed Constraint Solving

7.1 All-pairs shortest path problem

While there is not space here to give GDC programs for a full multi-agent system, with heterogeneous agents interacting, some idea of the possibilities can be given by a family of graph programs in GDC which work on a distributed principle, with no overall control or global data structure. These programs have in common the representation of each vertex in a graph by a GDC actor and each arc by a shared channel. The principle of using recursion to turn ephemeral actors to long-lived actors and partial binding to turn use-once channels to long-lived channels is used.

The first problem considered is the all-pairs shortest-path problem on a directed graph. Initially, each vertex is represented by an actor that has as data: a unique identifier, a list of channel/cost pairs representing outward directed arcs and a list of channel/cost pairs representing incoming arcs. An undirected graph would have to be represented by having two channels for each arc, one for each direction. An example graph is shown in Figure 7.1.1 where the letters are vertex names and the numbers arc costs. The network of actors represents this figure:

:- vertex(a, [a(BA,7),a(GA,9)],[a(AC,5),a(AD,3),a(AF,8)]), vertex(b, [a(DB,4),a(FB,6)], [a(BA,7)]),

vertex(c, [a(AC,5),a(DC,2)], [a(CE,4)]),

vertex(d, [a(AD,3),a(ED,1)],[a(DB,4),a(DC,2),a(DG,2),a(DF,6)]), vertex(e, [a(CE,4),a(GE,5)], [a(ED,1),a(EF,10)]),

vertex(f, [a(AF,8),a(EF,10),a(DF,6)],[a(FB,6),a(FG,7)]), vertex(g, [a(FG,7),a(DG,2)], [a(GA,9),a(GE,5)]).

Note that for convenience of reference, the channels have been given names that correspond to the arcs they represent.

Fig. 7.1.1 An example graph for the shortest path problem

The distributed solution to the shortest path problem requires channels representing arcs to be used as streams. Messages are sent in the reverse direction to their direction in the graph, since messages received from another node contain the path and cost to that node. The algorithm is initialized by each actor representing the vertex named x sending a message down its outgoing streams of the form p(x,[x],N) where N is the associated cost of the arc. Each actor also merges its incoming streams and sets up a table. When an actor representing vertex y receives a message of the form p(x,P,N) it checks its table to see if it has a record of a path to x of lower cost than N. If it has, it does nothing more until it receives its next message. If it does not, it updates its table and sends on each of its outgoing streams a message of the form p(x,[y|P],N´) where N´ is obtained from N by adding the cost paired with the arc represented by the stream. So actors receive messages containing a destination, a route leading to that destination and the cost of that route. If no other route is known to that destination or an existing known route is of higher cost, the new route is stored as the lowest cost route. Messages are sent out to each further node, z, proposing a new route to x through y as the shortest route from z to x.

The code to initialize vertex/3 is:

vertex(Id,InArcs,OutArcs)

where mergeall uses standard stream merger to merge all the incoming streams into one stream. The actor emptytable sets up a new table of paths and lowest costs and addtotable adds an entry to this table. The code for sendouts is given below.

The code for an actor representing a vertex is:

vertex(Id,[p(To,Path,Cost)|Ins],Outs,Table)

:- lowerCostPathExists(To,Cost,Table,Flag), vertex1(Flag,Id,To,[Id|Path],Cost,Ins,Outs,Table).

vertex1(true,Id,To,Path,Cost,Ins,Outs,Table) :- vertex(Id,Ins,Outs,Table).

vertex1(false,Id,To,Path,Cost,Ins,Outs,Table) :- addToTable(p(To,Path,Cost),Table,Table1),

sendouts(To,Path,Cost,Outs,Outs1), vertex(Id,Ins,Outs1,Table1).

sendouts(From,Path,Cost,[],Outs) :- Outs=[].

sendouts(From,Path,Cost,[a(Out,Cost1)|Outs],Outs1) :- Cost2:=Cost+Cost1,

Out=[p(From,Path,Cost2)|Out1],

sendouts(From,Path,Cost,Outs,Outs2), Outs1=[a(Out1,Cost1)|Outs2].

where lowerCostPathExists(From,Cost,Table,Flag) binds Flag to true if a path to From of cost lower than Cost exists in table Table and to false otherwise.

At any time a vertex will hold an approximation to the lowest cost paths to other vertices. This approximation will improve as more messages are sent. When the whole system reaches a quiescent state when no more messages are being sent, the all-pairs shortest path problem is solved. In practice, there would also be a way of querying vertices to find the solutions held in them.

Consider the graph in Figure 7.1.1 and assume that the tables of paths are just lists, following initialization, the actor network becomes:

:- merge([p(c,[c],5)|AC],[p(d,[],3)|AD],M0), merge(M0,[p(f,[f],8)|AF],A),

vertex(a,A,[a(BA,7),a(GA,9)],[p(a,[],0)]),

vertex(b,[p(a,[a],7)|BA],[a(DB,4),a(FB,6)],[p(b,[],0)]), vertex(c,[p(e,[e],4)|CE],[a(AC,5),a(DC,2)],[p(c,[],0)]), merge([p(b,[b],4)|DB],[p(d,[],2)|DC],M1),

merge([p(g,[g],2)|DG],M1,M2), merge([p(f,[f],6)|DF],M2,D),

vertex(d,D,[a(AD,3),a(ED,1)],[p(d,[],0)]), merge([p(d,[d],1)|ED],[p(f,[],10)|EF],E), vertex(e,E,[a(CE,4),a(GE,5)],[p(e,[],0)]), merge([p(b,[b],6)|FB],[p(g,[],7)|FG],F),

vertex(f,F,[a(AF,8),a(EF,10),a(DF,6)],[p(f,[],0)]), merge([p(a,[a],9)|GA],[p(e,[],5)|GE],G),

vertex(g,G,[a(FG,7),a(DG,2)],[p(g,[],0)]).

The next step will depend on which actors are chosen for reduction (no commitment was made to these existing on separate processors so they will not necessarily reduce

in parallel) and how the indeterminism of merge is resolved. Note that the actors for vertices b and c have no inward merger of streams as b and c each have only one outgoing arc (and hence only one incoming stream of messages). Suppose that these are chosen for reducing. Then b, having received a message from a will record that it now knows a path to a and will send messages to d and f proposing that they use this path to access a. Vertex c, having received a message from e, will similarly record that it knows a path to e and will send a message to a and d, resulting in:

:- merge([p(c,[c],5),p(e,[c,e],9)|AC],[p(d,[],3)|AD],M0), merge(M0,[p(f,[f],8)|AF],A),

vertex(a,A,[a(BA,7),a(GA,9)],[p(a,[],0)]),

vertex(b,BA,[a(DB,4),a(FB,6)],[p(a,[a],7),p(b,[],0)]), vertex(c,CE,[a(AC,5),a(DC,2)],[p(c,[],0),p(e,[e],4)]),

merge([p(b,[b],4),p(a,[b,a],11)|DB],[p(d,[],2),p(e,[c,e],6)|DC]M1), merge([p(g,[g],2)|DG],M1,M2),

merge([p(f,[f],6)|DF],M2,D),

vertex(d,D,[a(AD,3),a(ED,1)],[p(d,[],0)]), merge([p(d,[d],1)|ED],[p(f,[],10)|EF],E), vertex(e,E,[a(CE,4),a(GE,5)],[p(e,[],0)]),

merge([p(b,[b],6),p(a,[b,a],13)|FB],[p(g,[],7)|FG],F), vertex(f,F,[a(AF,8),a(EF,10),a(DF,6)],[p(f,[],0)]), merge([p(a,[a],9)|GA],[p(e,[],5)|GE],G),

vertex(g,G,[a(FG,7),a(DG,2)],[p(g,[],0)]).

Suppose that all mergers are resolved by passing on the head of the first stream, the actor network will then become:

:- merge([p(e,[c,e],9)|AC],[p(d,[],3)|AD],M0), merge([p(c,[c],5)|M0],[p(f,[f],8)|AF],A), vertex(a,A,[a(BA,7),a(GA,9)],[p(a,[],0)]),

vertex(b,BA,[a(DB,4),a(FB,6)],[p(a,[a],7),p(b,[],0)]), vertex(c,CE,[a(AC,5),a(DC,2)],[p(c,[],0),p(e,[e],4)]), merge([p(a,[b,a],11)|DB],[p(d,[],2),p(e,[c,e],6)|DC],M1), merge(DG,[p(b,[b],4)|M1],M2),

merge(DF,[p(g,[g],2)|M2],D),

vertex(d,[p(f,[f],6)|D],[a(AD,3),a(ED,1)],[p(d,[],0)]), merge(ED,[p(f,[],10)|EF],E),

vertex(e,[p(d,[d],1)|E],[a(CE,4),a(GE,5)],[p(e,[],0)]), merge([p(a,[b,a],13)|FB],[p(g,[],7)|FG],F),

vertex(f,[p(b,[b],6)|F],[a(AF,8),a(EF,10),a(DF,6)],[p(f,[],0)]), merge(GA,[p(e,[],5)|GE],G),

vertex(g,[p(a,[a],9)|G],[a(FG,7),a(DG,2)],[p(g,[],0)]).

resulting in the actors for vertices d, e, f and g having messages to deal with. From these messages they will record that they now know paths to f, d, b and a respectively and send further messages and the system will continue in this way.

Although the code is simple, it shows some elements of the DAI paradigm. There is no overall coordinator or global record of information as there is in more standard forms of solving shortest path problems (for example Dijkstra’s method [1959]).

Actors negotiate on finding an overall solution by sending messages proposing routes to each other. The language used for communication is very simple, just the agreement that messages have the three arguments, destination, path and cost in that order. Actors have knowledge of the rest of the graph in the form of the table of routes, which grows as computation proceeds. It would be possible to extend this framework leading to a more complete DAI system, allowing a variety of different messages to be exchanged, with individual actors being heterogeneous, each holding different sorts of information and having different sorts of problem-solving abilities.