/// <summary> /// The method that controls the creation of the history graph. /// </summary> public StoryGraph CreateStoryGraph(StoryNode rootNode) { // We clone the root into a separate variable. StoryNode originRoot = (StoryNode)rootNode.Clone(); // We continue to work until at least one target state is reached. while (!reachedGoalState) { // We create a new graph by starting to expand the root. BFSTraversing(newStoryGraph.GetRoot()); // We go through the created graph, looking for target states in it. BFSGoalAchieveControl(newStoryGraph.GetRoot()); // If it was not possible to find even one target state in the constructed graph. if (!reachedGoalState || newStoryGraph.GetNodes().Count > maxNodes) { graphСonstructor.CreateGraph(newStoryGraph, @"D:\Graphviz\bin\newStoryGraph.dt"); // Then we clear the graph, and all the links added to the root. newStoryGraph = new StoryGraph(); originRoot.GetEdges().Clear(); originRoot.GetLinks().Clear(); // After that, we reassign to the previously cleared column an indication of the root. newStoryGraph.SetRoot((StoryNode)originRoot.Clone()); reachedGoalState = false; } } // We return a graph that is guaranteed to have at least one target state. return(newStoryGraph); }
public bool TarjanAlgStep(StoryNode checkedNode, ref string[] colors, bool duplicated, StoryNode duplicatedNode) { bool result = true; colors[checkedNode.GetNumberInSequence()] = "grey"; foreach (StoryNode nextNode in checkedNode.GetLinks()) { if (!result) { return(result); } if (colors[nextNode.GetNumberInSequence()] == "grey") { if (duplicated) { if (duplicatedNode.Equals(nextNode)) { bool test = true; } } if (checkedNode.isChildren(nextNode) && !duplicated) { continue; } else if (duplicated && checkedNode.isChildren(nextNode) && !duplicatedNode.Equals(nextNode)) { continue; } result = false; return(result); } else if (colors[nextNode.GetNumberInSequence()] == "black") { continue; } else { result = TarjanAlgStep(nextNode, ref colors, duplicated, duplicatedNode); if (!result) { return(result); } } } colors[checkedNode.GetNumberInSequence()] = "black"; return(result); }
public void DeleteTestNode(ref StoryNode testNode) { foreach (var edge in testNode.GetEdges().ToList()) { edge.GetUpperNode().RemoveEdge(edge); edge.GetLowerNode().RemoveEdge(edge); edge.ClearEdge(); } foreach (var link in testNode.GetLinks().ToList()) { testNode.DeleteLink(link); } }
/// <summary> /// A method that traverses the graph according to the concept of breadth-first search /// and determines the presence of at least one target state in it. /// </summary> public bool BFSGoalAchieveControl(StoryNode rootNode) { // We create a queue and a list of visited nodes. Queue <StoryNode> queue = new Queue <StoryNode>(); HashSet <StoryNode> visitedNodes = new HashSet <StoryNode>(); // Add the root node to the queue and the list of visited nodes. queue.Enqueue(rootNode); visitedNodes.Add(rootNode); // We are in a loop until the queue is empty. while (queue.Count > 0) { // We take the current node under consideration from the queue. StoryNode currentNode = queue.Dequeue(); // We check if the target state has been reached in the node under consideration. reachedGoalState = storyworldConvergence.ControlToAchieveGoalState(ref currentNode); // If so, terminate the method and return true. if (reachedGoalState) { return(true); } // Otherwise, we go through the nodes associated with the node in question. foreach (StoryNode nextNode in currentNode.GetLinks()) { // If they have already been visited earlier, then we continue, moving on to the next. if (visitedNodes.Contains(nextNode)) { continue; } // Otherwise, we add to the queue and the list of visited nodes. queue.Enqueue(nextNode); visitedNodes.Add(nextNode); } } // If no target state was found, then terminate the method and return false. return(false); }
/// <summary> /// /// </summary> /// <param name="firstNode">Current node</param> /// <param name="secondNode">New node</param> public void ConnectionTwoNodes(PlanAction action, StoryNode firstNode, StoryNode secondNode, bool duplicate) { Edge newEdge = new Edge(); newEdge.SetAction(action); newEdge.SetUpperNode(ref firstNode); newEdge.SetLowerNode(ref secondNode); firstNode.AddEdge(newEdge); secondNode.AddEdge(newEdge); firstNode.AddLinkToNode(ref secondNode); secondNode.AddLinkToNode(ref firstNode); if (firstNode.GetEdges().Count != firstNode.GetLinks().Count) { bool test = true; } }
/// <summary> /// A method in which we sequentially create a story graph, node by node, starting at the root, using the concept of Breadth First Search. /// </summary> public void BFSTraversing(StoryNode rootNode, bool root = true) { // We create a queue and a list of visited nodes. Queue <StoryNode> queue = new Queue <StoryNode>(); HashSet <StoryNode> visitedNodes = new HashSet <StoryNode>(); // Добавляем узел в очередь и список посещённых узлов. queue.Enqueue(rootNode); visitedNodes.Add(rootNode); // We initialize numeric variables storing the number of the current agent and the number of the last node in the sequence. int actualAgentNumber = 0; int globalNodeNumber = -1; // We will perform the action in a loop until the queue becomes empty. while (queue.Count > 0 && newStoryGraph.GetNodes().Count <= maxNodes) { // We take the node in question from the queue. StoryNode currentNode = queue.Dequeue(); // If we come across a node with a target state, then we do not expand it. if (storyworldConvergence.ControlToAchieveGoalState(ref currentNode)) { //currentNode.goalState = true; continue; } else { // If the node in question is a root. if (currentNode.Equals(rootNode) && root) { // We call the method for creating a new node. Step(newStoryGraph.GetRoot(), actualAgentNumber, root, ref globalNodeNumber, ref queue); // Add the considered node back to the queue (in the case of the root, we only changed it and will consider it again), // and also to the list of visited nodes. We remove the flag indicating that we are considering the root node. queue.Enqueue(currentNode); visitedNodes.Add(currentNode); root = false; } // If the node in question IS NOT a root. else { // We determine the index of the agent, which will have to act when creating a new node. actualAgentNumber = GetActualAgentNumber(currentNode.GetWorldState().GetIndexOfAgent(currentNode.GetActiveAgent()), ref currentNode); // We call the method to create a new node. Step(newStoryGraph.GetNode(currentNode), actualAgentNumber, root, ref globalNodeNumber, ref queue); } } // We go through the nodes associated with the considered one. foreach (StoryNode nextNode in currentNode.GetLinks()) { // If one of them has already been visited earlier, then we continue, moving on to the next. if (visitedNodes.Contains(nextNode)) { continue; } // Otherwise, we add them to the queue and the list of visited nodes. queue.Enqueue(nextNode); visitedNodes.Add(nextNode); } // We clear the link pointing to the node in question. currentNode = null; } }