From 17935a59605352781824d9b107c7537375869820 Mon Sep 17 00:00:00 2001 From: PtrMan Date: Sat, 27 Sep 2014 14:18:58 +0200 Subject: [PATCH] code --- CausalReasoningSystem.java | 38 +++++ ConvertInputGraphToCausalGraph.java | 77 +++++++++ DecoratedCausalGraph.java | 120 ++++++++++++++ InputGraph.java | 22 +++ TrackbackGenerator.java | 249 ++++++++++++++++++++++++++++ 5 files changed, 506 insertions(+) create mode 100644 CausalReasoningSystem.java create mode 100644 ConvertInputGraphToCausalGraph.java create mode 100644 DecoratedCausalGraph.java create mode 100644 InputGraph.java create mode 100644 TrackbackGenerator.java diff --git a/CausalReasoningSystem.java b/CausalReasoningSystem.java new file mode 100644 index 0000000..7460068 --- /dev/null +++ b/CausalReasoningSystem.java @@ -0,0 +1,38 @@ +package causalreasoningsystem; + +import java.util.ArrayList; +import java.util.Random; + +public class CausalReasoningSystem +{ + public static void main(String[] args) + { + InputGraph inputGraph = new InputGraph(); + inputGraph.numberOfNodes = 8; + inputGraph.connections.add(new InputGraph.Connection(0, 2)); + inputGraph.connections.add(new InputGraph.Connection(1, 2)); + inputGraph.connections.add(new InputGraph.Connection(1, 3)); + inputGraph.connections.add(new InputGraph.Connection(4, 3)); + inputGraph.connections.add(new InputGraph.Connection(5, 3)); + inputGraph.connections.add(new InputGraph.Connection(7, 3)); + inputGraph.connections.add(new InputGraph.Connection(4, 6)); + + + /* works + InputGraph inputGraph = new InputGraph(); + inputGraph.numberOfNodes = 4; + inputGraph.connections.add(new InputGraph.Connection(0, 3)); + inputGraph.connections.add(new InputGraph.Connection(1, 3)); + inputGraph.connections.add(new InputGraph.Connection(2, 3)); + */ + + // TODO< cristal example > + + DecoratedCausalGraph causalGraph = ConvertInputGraphToCausalGraph.convert(inputGraph); + + ArrayList result = TrackbackGenerator.generate(new Random(), causalGraph); + + int x = 0; + } + +} diff --git a/ConvertInputGraphToCausalGraph.java b/ConvertInputGraphToCausalGraph.java new file mode 100644 index 0000000..28b09d8 --- /dev/null +++ b/ConvertInputGraphToCausalGraph.java @@ -0,0 +1,77 @@ +package causalreasoningsystem; + +import java.util.ArrayList; + +public class ConvertInputGraphToCausalGraph +{ + public static DecoratedCausalGraph convert(InputGraph input) + { + DecoratedCausalGraph resultGraph; + int[] numberOfInputEdges; + int[] numberOfOutputEdges; + int nodeIndex; + + // indices for the index into the arrays of the nodes + int[] incommingEdgesIndices; + int[] outgoingEdgesIndices; + + numberOfInputEdges = new int[input.numberOfNodes]; + numberOfOutputEdges = new int[input.numberOfNodes]; + + resultGraph = new DecoratedCausalGraph(); + resultGraph.nodes = createNodes(input.numberOfNodes); + + // count all input/output edges + for( InputGraph.Connection iterationConnection : input.connections ) + { + numberOfOutputEdges[iterationConnection.sourceIndex]++; + numberOfInputEdges[iterationConnection.destinationIndex]++; + } + + // allocate all input/output edges + nodeIndex = 0; + for( DecoratedCausalGraph.Node iterationNode : resultGraph.nodes ) + { + iterationNode.incommingEdgeElementIndices = new int[numberOfInputEdges[nodeIndex]]; + iterationNode.outgoingEdgeElementIndices = new int[numberOfOutputEdges[nodeIndex]]; + + nodeIndex++; + } + + // fill incomming/outgoing edge arrays + incommingEdgesIndices = new int[input.numberOfNodes]; + outgoingEdgesIndices = new int[input.numberOfNodes]; + + for( InputGraph.Connection iterationConnection : input.connections ) + { + int incommingArrayIndex; + int outgoingArrayIndex; + + incommingArrayIndex = incommingEdgesIndices[iterationConnection.destinationIndex]; + outgoingArrayIndex = outgoingEdgesIndices[iterationConnection.sourceIndex]; + + resultGraph.nodes.get(iterationConnection.destinationIndex).incommingEdgeElementIndices[incommingArrayIndex] = iterationConnection.sourceIndex; + resultGraph.nodes.get(iterationConnection.sourceIndex).outgoingEdgeElementIndices[outgoingArrayIndex] = iterationConnection.destinationIndex; + + incommingEdgesIndices[iterationConnection.destinationIndex]++; + outgoingEdgesIndices[iterationConnection.sourceIndex]++; + } + + return resultGraph; + } + + private static ArrayList createNodes(int count) + { + ArrayList result; + int i; + + result = new ArrayList(); + + for( i = 0; i < count; i++ ) + { + result.add(new DecoratedCausalGraph.Node()); + } + + return result; + } +} diff --git a/DecoratedCausalGraph.java b/DecoratedCausalGraph.java new file mode 100644 index 0000000..13e99e6 --- /dev/null +++ b/DecoratedCausalGraph.java @@ -0,0 +1,120 @@ +package causalreasoningsystem; + +import java.util.ArrayList; +import java.util.Random; + +public class DecoratedCausalGraph +{ + public static class Node + { + public static class Anotation + { + /* + public class OutgoingEdge + { + public boolean isRed; + + public ArrayList outgoingEdgeBounced = new ArrayList(); + // invariant: elements in that list are not allready in the output + // elements get removed as elements are taken out + + public boolean areRemainingOutgoingEdgeBounced() + { + return outgoingEdgeBounced.size() > 0; + } + } + + public OutgoingEdge[] outgoingEdges; + */ + + public boolean isOrWasInWorkingSet; // is/was this node in the working set for ttraversal? + + // flags used to indicate that the node of the incomming edge must occur before that node + // flag is not set for elements which are allready in the output + public boolean[] incommingEdgesRedFlags; + + public int incommingEdgesRedFlagsCounter; + + public void recountIncommingRedFlags() + { + int incommingEdgeI; + + incommingEdgesRedFlagsCounter = 0; + + for( incommingEdgeI = 0; incommingEdgeI < incommingEdgesRedFlags.length; incommingEdgeI++ ) + { + if( incommingEdgesRedFlags[incommingEdgeI] ) + { + incommingEdgesRedFlagsCounter++; + } + } + } + + public int outputIndex = -1; + + public boolean isInOutput() + { + return outputIndex != -1; + } + + /* + public boolean existAnyRemainingOutgoingEdgeBounced() + { + int i; + + for( i = 0; i < outgoingEdges.length; i++ ) + { + if( outgoingEdges[i].areRemainingOutgoingEdgeBounced() ) + { + return true; + } + } + + return false; + } + + // INVARIANT< only callable if existAnyRemainingOutgoingEdgeBounced() returns true, else it goes into an infinite loop > + public OutgoingEdge getRandomOutgoingEdgeWithRemainingOutgoingEdgeBounced(Random random) + { + for(;;) + { + int currentOutgoingEdgeIndex; + + currentOutgoingEdgeIndex = random.nextInt(outgoingEdges.length); + + if( outgoingEdges[currentOutgoingEdgeIndex].areRemainingOutgoingEdgeBounced() ) + { + return outgoingEdges[currentOutgoingEdgeIndex]; + } + } + }*/ + } + + public Anotation anotation = new Anotation(); + + public int[] outgoingEdgeElementIndices; + public int[] incommingEdgeElementIndices; + + public boolean isRoot() + { + return incommingEdgeElementIndices.length == 0; + } + } + + public ArrayList nodes = new ArrayList(); + + //public int[] rootIndices; + + public void resetAnnotation() + { + int i; + + for( i = 0; i < nodes.size(); i++ ) + { + nodes.get(i).anotation = new Node.Anotation(); + + int incommingEdgesArrayLength = nodes.get(i).incommingEdgeElementIndices.length; + nodes.get(i).anotation.incommingEdgesRedFlags = new boolean[incommingEdgesArrayLength]; + } + } +} diff --git a/InputGraph.java b/InputGraph.java new file mode 100644 index 0000000..0043aa2 --- /dev/null +++ b/InputGraph.java @@ -0,0 +1,22 @@ +package causalreasoningsystem; + +import java.util.ArrayList; + +public class InputGraph +{ + public static class Connection + { + public int sourceIndex; + public int destinationIndex; + + public Connection(int sourceIndex, int destinationIndex) + { + this.sourceIndex = sourceIndex; + this.destinationIndex = destinationIndex; + } + } + + public ArrayList connections = new ArrayList(); + + public int numberOfNodes; +} diff --git a/TrackbackGenerator.java b/TrackbackGenerator.java new file mode 100644 index 0000000..cd2d889 --- /dev/null +++ b/TrackbackGenerator.java @@ -0,0 +1,249 @@ +package causalreasoningsystem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +// TODO< remove elements from workingset if it is written out ??? > +public class TrackbackGenerator +{ + static public ArrayList generate(Random random, DecoratedCausalGraph causalGraph) + { + ArrayList result; + + // list with all indices of nodes which can be added to the output + // node could also be linked indirectly + List workingNodeIndices; + + result = new ArrayList<>(); + + causalGraph.resetAnnotation(); + + // add all root indices + workingNodeIndices = getRootIndices(causalGraph); + + for(;;) + { + if( workingNodeIndices.size() == 0 ) + { + break; + } + + // get and remove random node from workingset + int currentElementIndexIndex = random.nextInt(workingNodeIndices.size()); + int currentElementIndex = workingNodeIndices.get(currentElementIndexIndex); + workingNodeIndices.remove(currentElementIndexIndex); + + assert !causalGraph.nodes.get(currentElementIndex).anotation.isInOutput(); + + // walk all outgoing edges and remove red flag if its there, + // if there is a redflag count the redflag counter down, + // if the counter hits zero, add it to the workingNodes + int outgoingEdgeI; + + for( outgoingEdgeI = 0; outgoingEdgeI < causalGraph.nodes.get(currentElementIndex).outgoingEdgeElementIndices.length; outgoingEdgeI++ ) + { + boolean redFlagOfEdge; + int outgoingNodeIndex; + + outgoingNodeIndex = causalGraph.nodes.get(currentElementIndex).outgoingEdgeElementIndices[outgoingEdgeI]; + + int incommingEdgeElementIndicesIndex = getIndexOfElementInArray(causalGraph.nodes.get(outgoingNodeIndex).incommingEdgeElementIndices, currentElementIndex); + + redFlagOfEdge = causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlags[incommingEdgeElementIndicesIndex]; + if( redFlagOfEdge ) + { + assert causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlagsCounter > 0; + + causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlagsCounter--; + causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlags[incommingEdgeElementIndicesIndex] = false; + if( + causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlagsCounter == 0 && + !causalGraph.nodes.get(outgoingNodeIndex).anotation.isOrWasInWorkingSet + ) + { + causalGraph.nodes.get(outgoingNodeIndex).anotation.isOrWasInWorkingSet = true; + + // add it to the workingNodes + workingNodeIndices.add(new Integer(outgoingNodeIndex)); + } + } + } + + + + + int outputIndex = result.size(); + causalGraph.nodes.get(currentElementIndex).anotation.outputIndex = outputIndex; + result.add(new Integer(currentElementIndex)); + + + + // repeat for all outgoing edges of the current element: + // mark all incomming edges of the outgoing nodes as red if they don't point at an element which is allready in the output + + for( outgoingEdgeI = 0; outgoingEdgeI < causalGraph.nodes.get(currentElementIndex).outgoingEdgeElementIndices.length; outgoingEdgeI++ ) + { + int outgoingNodeIndex; + int incommingEdgeI; + + outgoingNodeIndex = causalGraph.nodes.get(currentElementIndex).outgoingEdgeElementIndices[outgoingEdgeI]; + + for( incommingEdgeI = 0; incommingEdgeI < causalGraph.nodes.get(outgoingNodeIndex).incommingEdgeElementIndices.length; incommingEdgeI++ ) + { + int reflectedNodeIndex; + + reflectedNodeIndex = causalGraph.nodes.get(outgoingNodeIndex).incommingEdgeElementIndices[incommingEdgeI]; + + if( causalGraph.nodes.get(reflectedNodeIndex).anotation.isInOutput() ) + { + continue; + } + + causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlags[incommingEdgeI] = true; + } + + causalGraph.nodes.get(outgoingNodeIndex).anotation.recountIncommingRedFlags(); + } + + // now we add outgoing nodes if they don't have any red flaged incomming edges + // (means that all nodes which point at that node are allready in the output) + + for( outgoingEdgeI = 0; outgoingEdgeI < causalGraph.nodes.get(currentElementIndex).outgoingEdgeElementIndices.length; outgoingEdgeI++ ) + { + int outgoingNodeIndex; + int incommingEdgeI; + + outgoingNodeIndex = causalGraph.nodes.get(currentElementIndex).outgoingEdgeElementIndices[outgoingEdgeI]; + + if( + causalGraph.nodes.get(outgoingNodeIndex).anotation.incommingEdgesRedFlagsCounter == 0 && + !causalGraph.nodes.get(outgoingNodeIndex).anotation.isOrWasInWorkingSet + ) + { + causalGraph.nodes.get(outgoingNodeIndex).anotation.isOrWasInWorkingSet = true; + + workingNodeIndices.add(new Integer(outgoingNodeIndex)); + } + } + + } + + // we must have the same amount of nodes in the graph and nodes in the result + assert result.size() == causalGraph.nodes.size(); + + return result; + + /* + bounceFrom(rootIndicesIndex, causalGraph); + + int currentNodeIndex = rootIndicesIndex; + + boolean existsAnyRemainingOutgoingEdgeBounced = causalGraph.nodes.get(currentNodeIndex).anotation.existAnyRemainingOutgoingEdgeBounced(); + if( !existsAnyRemainingOutgoingEdgeBounced ) + { + // TODO< add following node of red egde and continue algorithm > + } + else + { + DecoratedCausalGraph.Node.Anotation.OutgoingEdge currentOutgoingEdge; + + currentOutgoingEdge = causalGraph.nodes.get(currentNodeIndex).anotation.getRandomOutgoingEdgeWithRemainingOutgoingEdgeBounced(random); + + // choose and remove random bounced edge and add it to the result + // TODO< > + + // TODO< add the node to the traversingNodes > + } + */ + + // TODO + + //return result; + } + + // TODO< what do we about the red connection? > + + /** + * + * goes to all outgoing nodes and links in bounced connections + * + * + */ + /* + static private void bounceFrom(int nodeIndex, DecoratedCausalGraph causalGraph) { + DecoratedCausalGraph.Node selectedNode; + + selectedNode = causalGraph.nodes.get(nodeIndex); + + ** + * + * iterate trough each outgoing connection of this node and anotate the outgoing path with the nodes which should follow before the red nodes get inserted + * + * + for( int outgoingEdgeIndex = 0; outgoingEdgeIndex < selectedNode.outgoingEdgeElementIndices.length; outgoingEdgeIndex++ ) + { + DecoratedCausalGraph.Node outgoingNode; + int iterationOutgoingIndex; + + iterationOutgoingIndex = selectedNode.outgoingEdgeElementIndices[outgoingEdgeIndex]; + + outgoingNode = causalGraph.nodes.get(iterationOutgoingIndex); + + outgoingNode.anotation.outgoingEdges[outgoingEdgeIndex].isRed = true; + + for( int iterationBouncedIndex : outgoingNode.incommingEdgeElementIndices ) + { + if( iterationBouncedIndex == iterationOutgoingIndex ) + { + // we don't want to include the actual incomming path in our bounced indices for that node + continue; + } + + if( causalGraph.nodes.get(iterationBouncedIndex).anotation.inOutput ) + { + // we are not interested in bounced noes which are allready in the output + continue; + } + + selectedNode.anotation.outgoingEdges[outgoingEdgeIndex].outgoingEdgeBounced.add(new Integer(iterationBouncedIndex)); + } + } + }*/ + + static private ArrayList getRootIndices(DecoratedCausalGraph causalGraph) + { + ArrayList result; + int i; + + result = new ArrayList(); + + i = 0; + for( DecoratedCausalGraph.Node iterationNode : causalGraph.nodes ) + { + if( iterationNode.isRoot() ) + { + result.add(new Integer(i)); + } + + i++; + } + + return result; + } + + static private int getIndexOfElementInArray(int[] array, int element) + { + int i; + + for( i = 0; i < array.length; i++ ) + { + if( array[i] == element ) + { + return i; + } + } + + throw new RuntimeException(); + } +}