Efficient way of generating graphs from source nodes - algorithm

Let's say I have a graph G, and around each node I have a few source nodes xs. I have to create a new graph G' using xs=[[a, b, c], [d, e], [f]] nodes such that they won't conflict with grey donuts as shown in the figure below.
Expected output G' is [[a, d, f], [a, e, f], [b, e, f]]; all others are conflicting a gray donut.
I currently solved it by taking all permutation and combination of nodes xs. This works for smaller numbers of nodes, but as my number of nodes xs increases with bigger graph G, it soon becomes 100s of thousands of combination to try.
I am looking for an efficient algorithm which will help me speed things up and get me all the non-conflicting graphs with a minimum number of iterations.

You have a fairly obvious minimum set of edges for each stage of your path. They are both necessary and sufficient for your solution. For notational convenience, I'll label the original graph X--Y--Z. Your corresponding G' nodes are
X a b c
Y d f
Z f
You do this in two steps:
For each edge in G, you must test for validity each possible edge in G`. This consists of
X--Y [a, b, c] X [d, e]
a total of 6 edges; 3 qualify: set XY = [a--d, a--e, b--d]
Y--Z [d, e] X [f]
a total of 2 edges; 2 qualify: set YZ = [d--f, e--f]
Now, you need only generate all combinations of XY x YZ where the Y nodes match. If you sort the lists by the "inner" node, you can do this very quickly as
[a--d, b--d] x [d--f]
[a--e] x [e--f]
Most current languages have modules to perform combinations for you, so the code will be short enough.
Does that get you going?

Related

How can I code a specific game in Prolog?

I have a problem with coding the program described below
Consider the following game. A board with three black stones, three white stones and an empty space is given. The goal of the game is to swap places of black pawns with white pawns. Moving rules define the following sentences: Move the white and black pieces alternately. Each pawn can move vertically or horizontally taking up an empty space. Each piece can jump vertically or horizontally over another piece (of any color). Write a program in Prolog to find all possible ways to find a winning sequence. For example, if we ask the question:
? - play (w, s (w, w, w, e, b, b, b), s (b, b, b, e, w, w, w), S, R ).
The prologue should answer, for example:
S = [s (w, w, w, e, b, b, b), s (w, e, w, w, b, b, b), ..., s (b, b, b, e, w, w, w)] R = [[w, 2,4], [b, 6,2], [w, 4,6], ..., [w, 4,6]]
Here [ w, 2,4] means moving the white pawn from position 2 to position 4. Of course Prolog should return both letters S and R in full (without "...").
What is the maximum number of different pawn settings possible on the board? Check the query:
? - play (_, s (w, w, w, e, b, b, b), s (b, b, e, w, w, b, w), _, _).
What does Prolog's answer mean? Hint: solve the problem for play/4 without R first
There's also a game board that looks like this:
I have no clue at all even where to start? How can I do that? Could you guys, help me with this one?
This is a standard state space search, a standard paradigm of GOFAI since the mid 50s at least.
The barebones algorithm:
search(State,Path,Path) :- is_final(State),!. % Done, bounce "Path" term
search(State,PathSoFar,PathOut) :-
generate_applicable_operators(State,Operators),
(is_empty(Operators) -> fail ; true),
select_operator(Operators,Op,PathSoFar),
apply_operator(State,Op,NextState), % depth-first / best first
search(NextState,[[NextState,Op]|PathSoFar],PathOut).
% Called like this, where Path will contain the reverse Path through
% State Space by which one may reach a final state:
search(InitialState,[[InitialState,nop]],Path).
First you need to represent a given state in this case the state of the board (at some time t).
We can either list the board positions and their content (w for white, b for black, e for empty token) or list the tokens and their positions. Let's list the board positions.
In Prolog, a term that can be easily pattern-matched is appropriate. The question already provides something: (w, w, w, e, b, b, b). This seems to be inspired by LISP and is not well adapted to Prolog. Let's use a list instead: [w, w, w, e, b, b, b]
The mapping of board positions to list positions shall be:
+---+---+
| 0 | 1 |
+---+---+---+
| 2 | 3 | 4 |
+---+---+---+
| 5 | 6 |
+---+---+
And we are done with setting up a state description!
Then you need to represent/define the operators (operations?) that can be applied to a state: they transform a valid state into another valid state.
An operator corresponds to "moving a token" and of course not all operators apply to a given state (you cannot move a token from field 1 if there is no token there; you cannot move a token to field 1 if there already is a token there).
So you want to write a predicate that links a board state to the operators applicable to that state: generate_applicable_operators/2
Then you need to select the operator that you want to apply. This can be done randomly, exhaustively, according to some heuristic (for example A*), but definitely needs to examine the path taken through the state space till now to avoid cycles: select_operator/3.
Then you apply the operator to generate the next state: apply_operator/3.
And finally recursively call search/3 to find the next move. This continues until the "final state", in this case [b, b, b, e, w, w, w] has been reached!
You can also use Iterative Deepening if you want to perform "breadth-first search" instead, but for that the algorithm structure must be modified.
And that's it.

How can I add an element to a list using the delete1() predicate in prolog?

I need to add an element to a list using the delete1 predicate that I have written:
delete1(H,[H|T],T).
delete1(H,[D|X],[D|Y]):-delete1(H,X,Y).
How can I do that? Well, I know how to delete element but can't figure out how to add an element there. I need to show all the possible lists that will be the result of adding 56 to [x,y,z,a] list. Do you have any ideas?
If they are well-programmed, Prolog predicates can run "backwards":
f(X,Y) should be read as X is related to Y via f.
Given an x, on can compute the Y (possibly several Y via backtracking): f(x,Y) is interpreted as The set of Y such that: f(x) = Y.
Given a y, on can compute the X (possibly several X via backtracking): f(X,y) is interpreted as The set of X such that: f(X) = y.
Given an (x,y), on can compute the truth value: f(x,y) interpreted as true if (but not iff) f(x) == y.
(How many Prolog predicates are "well-programmed"? If there is a study about how many Prolog predicates written outside of the classroom can work bidirectionally I would like to know about it; my guess is most decay quickly into unidirectional functions, it's generally not worth the hassle of adding the edge cases and the test code to make predicates work bidirectionally)
The above works best if
f is bijective, i.e.: "no information is thrown away when computing in either direction"
the computation in both directions is tractable (having encryption work backwards is hard)
So, in this case:
delete(Element,ListWith,ListWithout) relates the three arguments (Element,ListWith,ListWithout) as follows:
ListWithout is ListWith without Element.
Note that "going forward" from (Element,ListWith) to ListWithout destroys information, namely the exact position of the deleted element, or even if there was one in the first place. BAD! NOT BIJECTIVE!
To make delete1/3 run backwards we just have to:
?- delete1(56,L,[a,b,c]).
L = [56, a, b, c] ;
L = [a, 56, b, c] ;
L = [a, b, 56, c] ;
L = [a, b, c, 56] ;
There are four solutions to the reverse deletion problem.
And the program misses one:
L = [a, b, c]
or even a few more:
L = [56, a, b, 56, c]
etc.
As you can see, it is important to retain information!

Algorithm for allowing concurrent walk of a graph

In a directed acyclic graph describing a set of tasks to process, i need to find all tasks that can be processed concurrently. The graph has no loops and is quite small (~1000 nodes, ~2000 edges), performance is not a primary concern.
Examples with desired result:
[] is a group. All tasks in a group must be processed before continuing
[x & y] means x and y can be processed concurrently (x and y in parallel)
x -> y means x and y must be processed sequentially (x before y)
1
a -> [b & c] -> c
2
[a & e] -> b -> c -> [d & f]
3
[ [a -> b] & [e -> f] ] -> [ [c -> d] & g ]
I do not want to actually execute the graph, but rather build a data structure that is as parallel as possible, while maintaining the order. The nomenclature and names of algorithms is not that familiar to me, so i'm having a hard time trying to find similar problems/solutions online.
Mathematically, I would frame this problem as finding a minimally defined series-parallel partial order extending the given partial order.
I would start by transitively reducing the graph and repeatedly applying two heuristics.
If x has one dependent y, and y has one dependency x, merge them into a new node z = [x → y].
If x and y have the same dependencies and dependents, merge them into a new node z = [x & y].
Now, if the input is already series-parallel, the result will be one node. In general, however, this will leave a graph that embeds an N-shaped structure like b → c, b → g, f → g from the last example in the question. This structure must be addressed by adding one or more of b → f, c → f, c → g, f → b, f → c, g → c. But in a different instance, this act would in turn create new N-shaped structures. There's no obvious notion of a closure, which is why this problem feels hard to me.
Some of these choices seem worse than others. For example, c → f forces the sequence b → c → f → g, whereas f → c is the only choice that doesn't increase the length of the critical path.
I guess what I'd try is,
If heuristics 1 and 2 have no targets, form a graph with edges x--y if and only if x and y have either a common dependent or a common dependency, compute the connected components of this graph, and &-merge the smallest component that isn't a singleton, followed by another transitive reduction.
Here's a solution i came up with (pseudocode):
sequence = []
for each (node, depth) in depthFirstSearch(graph)
sequence[depth].push(node)
return sequence
The sequence defines the order to process the graph. If an item in it contains more than one node, they can be processed concurrently.
While this allows for some concurrency, it does not advance as fast as it could. For example, f in the 3rd example in the question would require a to be completed first (as it will be at depth 1, when a and e are depth 0). Ideally work on f could start when e is done.

Spacial clustering algorithm

Given a collection of points on a 2D plane, I want to find collections of X points that are within Y of each other. For example:
8|
7| a b
6|
5| c
4|
3| e
2| d
1|
-------------------------
1 2 3 4 5 6 7 8 9 0 1
a, b, c and d are points on the 2D plane. Given arguments of 3 for the number of points (X) and 3 for the distance (Y), the algorithm would return [[a, b, c]]. Some examples:
algorithm(X = 3, Y = 3) returns [[a, b, c]]
algorithm(X = 2, Y = 3) returns [[a, b, c], [d, e]] -- [a, b, c] contains at least two points
algorithm(X = 4, Y = 3) returns [] -- no group of 4 points close enough
algorithm(X = 5, Y = 15) returns [[a, b, c, d, e]]
Constraints:
x and y axis (the numbers above) are both 10,000 units long
there are 800 points (a, b, c, d etc) on the graph
I don't think it matters, but I'm using JavaScript
Things I've tried:
I actually care about outputting new points that are close to more than one input point, so I tried iterating on a grid and 'looking around' it using Pythagoras to find each point a given distance away. This is too slow given the total area. See the source here.
You can also see the data size in real data test.
DBSCAN, which seems to have a different purpose - I know how big I want my cluster size to be.
I'm currently trying to compare points to each other and build up close pairs, then close triplets, etc, until the end, but this seems to be going down a bit of an inefficiency hole also. I'm going to continue and try some kind of hashing or dictionary to avoid these loops.
With only 800 points, you can probably just build the graph by comparing each pair, then run Bron--Kerbosch to find maximal cliques. Here's a legit-seeming Javascript implementation of that algorithm: https://github.com/SeregPie/almete.BronKerbosch

Prolog graph representation missing fact

I have a graph with edges in Prolog. I'm representing the graph as a set of prolog facts. Where e.g. s(a,b,2). = b is the successor of a. Here are my facts in prolog for this graph.
Facts:
s(a,b,2).
s(a,c,1).
s(b,e,4).
s(b,g,2).
s(c,d,1).
s(c,x,3).
s(x,g,1).
goal(g).
Am I missing a fact here? s(e,g,1).
Where g is the successor of e? Or does it even get searched on this node as "b" only has 2 branches "e" & "g". Can someone please explain this to me? Thanks
We can enumerate the graph for example in a breadth-first [Wiki] fashion, and thus determine that the edges are:
s(a, b, 2).
s(a, c, 1).
s(b, e, 4).
s(b, g, 2),
s(c, d, 1).
s(c, x, 3).
s(e, g, 1).
s(x, g, 1).
goal(g).
If we look at the original source code. The s(e, g, 1). part was missing.

Resources