protected ArrowGraphBuilderBase( Graph <T, TActivity, TEvent> graph, Func <T> edgeIdGenerator, Func <T> nodeIdGenerator, Func <T, TEvent> eventGenerator) : base(graph, edgeIdGenerator, nodeIdGenerator, eventGenerator) { // Check Start and End nodes. if (StartNodes.Count() == 1) { StartNode = StartNodes.First(); } else { throw new ArgumentException(Properties.Resources.ArrowGraphContainsMoreThanOneStartNode); } if (EndNodes.Count() == 1) { EndNode = EndNodes.First(); } else { throw new ArgumentException(Properties.Resources.ArrowGraphContainsMoreThanOneEndNode); } }
public override bool TransitiveReduction() { IDictionary <T, HashSet <T> > ancestorNodesLookup = GetAncestorNodesLookup(); if (ancestorNodesLookup is null) { return(false); } foreach (T endNodeId in EndNodes.Select(x => x.Id)) { RemoveRedundantIncomingEdges(endNodeId, ancestorNodesLookup); } return(true); }
public override bool TransitiveReduction() { // For Arrow Graphs only dummy edges need to be reduced. IDictionary <T, HashSet <T> > ancestorNodesLookup = GetAncestorNodesLookup(); if (ancestorNodesLookup is null) { return(false); } foreach (T endNodeId in EndNodes.Select(x => x.Id)) { RemoveRedundantIncomingDummyEdges(endNodeId, ancestorNodesLookup); } return(true); }
public IDictionary <T, HashSet <T> > GetAncestorNodesLookup() { if (!AllDependenciesSatisfied) { return(null); } IList <CircularDependency <T> > circularDependencies = FindStrongCircularDependencies(); if (circularDependencies.Any()) { return(null); } var nodeIdAncestorLookup = new Dictionary <T, HashSet <T> >(); foreach (T endNodeId in EndNodes.Select(x => x.Id)) { HashSet <T> totalAncestorNodes = GetAncestorNodes(endNodeId, nodeIdAncestorLookup); nodeIdAncestorLookup.Add(endNodeId, totalAncestorNodes); } return(nodeIdAncestorLookup); }
public VertexGraphBuilder( Graph <T, IEvent <T>, TActivity> graph, Func <T> edgeIdGenerator, Func <T> nodeIdGenerator) : base( graph, edgeIdGenerator, nodeIdGenerator, s_EventGenerator) { if (NormalNodes.Any()) { // Check Start and End nodes. if (!StartNodes.Any()) { throw new ArgumentException(Properties.Resources.VertexGraphCannotContainNormalNodesWithoutAnyStartNodes); } if (!EndNodes.Any()) { throw new ArgumentException(Properties.Resources.VertexGraphCannotContainNormalNodesWithoutAnyEndNodes); } } }
/// <summary> /// スタートからゴールたちまでの最善経路を計算する /// </summary> /// <param name="team"></param> /// <param name="point"></param> /// <param name="Cost"></param> /// <param name="HeuristicCost">推定コスト</param> /// <param name="directionMode">false:4方位 true:8方位</param> public void Search(Func <Node, double> Cost, Func <Node, double> HeuristicCost) { Point p = new Point(StartNode.Point); Node child, parent; //ノードの大きさ int Height = Nodes.GetLength(0); int Width = Nodes.GetLength(1); //初期設定 //Nodesのノードに自分がいる座標を保持させる for (int i = 0; i < Width; i++) { for (int j = 0; j < Height; j++) { Nodes[j, i].Point = new Point(i, j); } } //スタートノードに関する設定 StartNode.Status = NodeStatus.Open; //コストを0に StartNode.Cost = 0; //推定コスト算出 StartNode.HeuristicCost = HeuristicCost(StartNode); //総コスト StartNode.TotalCost = StartNode.Cost + StartNode.HeuristicCost; //親ノードなし StartNode.Parent = null; //初手なのでカウントは0 StartNode.Turn = 0; //初手なので必ず成功とする StartNode.SuccessProbability = 1; //未探索ノード保持(コストが昇順でソートされるようにする) List <Node> openedNode = new List <Node>(); parent = StartNode; //エンドノードに到達するまで無限ループ while (EndNodes.All((node) => node != parent)) { for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { //周りのセルの場所を取得 p = new Point(parent.Point.X + i, parent.Point.Y + j); //pが配列を溢れないか if (!(p.X < 0 || p.Y < 0 || p.X >= Width || p.Y >= Height) && !(i == 0 && j == 0)) { child = Nodes[p.Y, p.X]; //周りのセルの状態が未探索である場合(周りのセルがゴール地点である場合もある) if (child.Status == NodeStatus.None) { //子ノードをOpenに child.Status = NodeStatus.Open; //親ノードの指定 child.Parent = parent; //いま何ターン目かを設定 child.Turn = parent.Turn + 1; //そのセルの実コストと推定コスト、総コストを計算 child.Cost = Cost(child) + parent.Cost; child.HeuristicCost = HeuristicCost(child); child.TotalCost = child.Cost + child.HeuristicCost; //childよりコストが高くなる位置を取得 var index = openedNode.FindIndex((node) => child.TotalCost < node.TotalCost); //コストで昇順にソート if (index < 0) //自分よりコストが高くなるノードがない->一番うしろにノードを挿入 { openedNode.Insert(openedNode.Count, child); } else { openedNode.Insert(index, child); } } } } } //親ノードの状態をClosedに parent.Status = NodeStatus.Closed; //最もコストが低いノードを取り出して次の親ノードとする if (openedNode.Any()) { parent = openedNode.First(); } else { //ノードがない場合==移動ができない場合なので、諦める break; } //取り出したノードをリストから消去する openedNode.RemoveAt(0); } //parentを辿って、最善経路を取得 BestWayNodes = new List <Node>(); //スタートのセルまで続行 while (parent != StartNode) { //先頭にノードを追加 BestWayNodes.Insert(0, parent); //parentの親ノードに移動 parent = parent.Parent; } //方向のみを取り出す BestWayPoints = BestWayNodes.Select((node) => node.Point).ToList(); }