0

I want to detect a cycle in an nondirected graph and return true or false. My node is a pair of (X, Y) coordinates on a table.

I have a game which plays on a tic-tac-toe grid. The predicate quantum(pos(X, Y), pos(Z, T), Color) resembles a piece on my grid. It can be put on two cells on my 3x3 table. I can have two quantum positions from different pieces into the same cell, and sometimes they can form a cycle and I want to detect it.

Since my nodes are cells (tuple of X, Y coordinates), my quantum piece acts like an edge between two nodes. I thought of getting all my quantum pieces from the state and form a list (DirectedEdges) of pairs of cells, made by the first findall. My graph is nondirected, so I made ReverseEdges and combined them both to get my list of nondirected edges.

My cycle function doesn't work on my nondirected graph and I don't get it why. I don't think I needed to add that much context to ask my question.

The parameters of cycle are: Node is the starting point (the first parameter), Next iterates through the Graph (the second parameter), Visited is the list of visited nodes (third parameter) and Edges is the list which contains all the edges of my Graph (forth parameter).

EDIT: State is a list of pieces on my board, it can have more pieces or less pieces.

State = [quantum(pos(1, 1), pos(3, 1), white), quantum(pos(1, 2), pos(3, 2), black), quantum(pos(1, 1), pos(3, 2), white)]

State = [quantum(pos(1, 1), pos(3, 1), white), quantum(pos(1, 2), pos(3, 2), black), quantum(pos(1, 1), pos(3, 2), white), quantum(pos(1, 2), pos(3, 1), black)].

For the first State I want has_cycle(State) to return false, because it doesn't have a cycle, and true for the second State. The color does not interfere with the cycle.

    cycle(Node, Node, _, _) :- !, true.
    cycle(_, Node, Visited, _) :- member(Node, Visited), !, fail.
    cycle(Node, Next, Visited, Edges) :- member((Next, NextNext), Edges), cycle(Node, NextNext, [Next|Visited], Edges). 

has_cycle(State) :-
    findall((pos(X, Y), pos(Z, T)), member(quantum(pos(X, Y), pos(Z, T), _), State), DirectedEdges),
    findall((pos(X, Y), pos(Z, T)), member((pos(Z, T), pos(X, Y)), DirectedEdges), ReverseEdges),
    append(DirectedEdges, ReverseEdges, Edges),
    member((Node, Next), Edges),
    cycle(Node, Next, [Next], Edges).
Guy Coder
  • 24,501
  • 8
  • 71
  • 136
B. Franklin
  • 11
  • 1
  • 4
  • Possible duplicate of [Cycle detection in a graph](https://stackoverflow.com/questions/6721139/cycle-detection-in-a-graph) – fferri May 18 '18 at 21:19
  • Please post an example query. What is `State` supposed to be? Input? Output? Partial? – Isabelle Newbie May 18 '18 at 22:19
  • yes, nondirected – B. Franklin May 19 '18 at 04:29
  • When you say your `cycle` predicate (not function) doesn't work, what exactly do you mean? – lurker May 19 '18 at 13:05
  • For example for the second State I described, the graph of pieces has a cycle made by the cells (1, 1) - (3, 1) - (1, 2) - (3, 2) - (1, 1). And in that case my predicate returns false, and it should return true, because i have a cycle. – B. Franklin May 19 '18 at 14:31
  • Thanks for the test cases. It makes no sense to mark the `Next` node as visited before you even start visiting a node. You should mark the current node as visited. Also, try debugging using a simpler representation; even if in your real application you do want `pos(1, 2)` terms, from the point of view of the graph algorithm, names like `a`, `b`, `c` are just as good, but inputs and outputs become easier to read. – Isabelle Newbie May 19 '18 at 16:17

0 Answers0