/// <summary> /// If neighbour has line of sight to currents parent and skipping current is cheaper, skips current node and sets neighbour cost / parent depending on whether current is used /// </summary> /// <param name="current"></param> /// <param name="neighbour"></param> /// <param name="settings"></param> /// <param name="openNodes"></param> private static void UpdateNode(Node current, Node neighbour, PathfindingSettings settings, BucketList <Node> openNodes) { if (LineOfSight(current.parent, neighbour)) { var costSkippingCurrent = current.parent.cost + settings.CostIncrease(current.parent.pos, neighbour.pos); if (costSkippingCurrent < neighbour.cost) { if (openNodes.Contains(neighbour)) { openNodes.Remove(neighbour); } neighbour.cost = costSkippingCurrent; neighbour.parent = current.parent; openNodes.Add(neighbour); } } else { var costUsingCurrent = current.cost + settings.CostIncrease(current.pos, neighbour.pos); if (costUsingCurrent < neighbour.cost) { if (openNodes.Contains(neighbour)) { openNodes.Remove(neighbour); } neighbour.cost = costUsingCurrent; neighbour.parent = current; openNodes.Add(neighbour); } } }
public static void Main() { var normalList = new NormalList <int>(); var bucketList = new BucketList <int>(); for (int i = 0; i < 1000000; i++) { normalList.Add(i); bucketList.Add(i); } MeasureTime(() => { for (int i = 0; i < 400000; i++) { normalList.Remove(0); } }, "normal list removing"); MeasureTime(() => { for (int i = 0; i < 400000; i++) { bucketList.Remove(0); } }, "bucket list removing"); }
private void ActionEvent(Goods goods) { if (goods.ButtonContent == ButtonAction.Buy) { var bucketGoods = new Goods { Id = goods.Id, Name = goods.Name, Cost = goods.Cost, Description = goods.Description, Image = goods.Image, ButtonContent = ButtonAction.Remove }; bucketGoods.ActionEvent += () => ActionEvent(bucketGoods); BucketList.Add(bucketGoods); } else if (goods.ButtonContent == ButtonAction.Remove) { // ReSharper disable once EventUnsubscriptionViaAnonymousDelegate goods.ActionEvent -= () => ActionEvent(goods); BucketList.Remove(goods); } }
/// <summary> /// Tries to find a path from start to goal node using settings /// </summary> /// <param name="start">Start node</param> /// <param name="goal">Goal node</param> /// <param name="settings">PathfindingSettings (which heuristics to use etc)</param> /// <param name="isoLevel">Determines which nodes are considered walkable (iso value > this)</param> /// <param name="openNodes">Nodes that were still open after algorithm finished</param> /// <param name="closedNodes">Nodes that were fully explored after algorithm finished</param> /// <param name="maxIterations">Max number of loop iterations, prevents infinite loops</param> /// <param name="nodeCount">Approximate total node count, determines start capacity of path stack</param> /// <returns></returns> public static Stack <Vector3> FindPath(Node start, Node goal, PathfindingSettings settings, float isoLevel, out BucketList <Node> openNodes, out HashSet <Node> closedNodes, int maxIterations = 50000, int nodeCount = 1000) { NodesGenerator.CostHeuristicBalance = settings.greediness; int neighbourChecks = 0; int numIterations = 0; //euclidean distance from start to end float distance = Vector3.Distance(start.pos, goal.pos); //full length of path float pathLength = 0; System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); if (settings.benchmark) { sw.Start(); } var startCapacity = nodeCount / 100; Stack <Vector3> path = new Stack <Vector3>(startCapacity); openNodes = new BucketList <Node>(distance / 100, Mathf.Min(settings.Heuristic(start.pos, goal.pos) * settings.greediness, settings.CostIncrease(start.pos, goal.pos) * (1 - settings.greediness))); //openNodes = new MinHeap<Node>(startCapacity * 10); closedNodes = new HashSet <Node>(); Node current = null; start.cost = 0; start.parent = start; start.heuristic = settings.Heuristic(start.pos, goal.pos); openNodes.Add(start); while (openNodes.Count != 0 && !closedNodes.Contains(goal)) { if (++numIterations == maxIterations) { break; } current = openNodes.ExtractMin(); closedNodes.Add(current); foreach (var neighbour in current.neighbours) { neighbourChecks++; if (neighbour.isoValue <= isoLevel) { continue; } if (closedNodes.Contains(neighbour)) { continue; } var newCost = current.cost + settings.CostIncrease(current.pos, neighbour.pos); if (openNodes.Contains(neighbour)) { if (newCost >= neighbour.cost) { continue; } openNodes.Remove(neighbour); } neighbour.parent = current; neighbour.heuristic = settings.Heuristic(neighbour.pos, goal.pos); neighbour.cost = newCost; openNodes.Add(neighbour); } } if (!closedNodes.Contains(goal)) { Debug.Log("no goal, " + numIterations + " iterations, closed: " + closedNodes.Count + ", opened: " + openNodes.Count); return(path); } path.Push(goal.pos); Node temp = goal.parent; while (temp != null) { pathLength += Vector3.Distance(path.Peek(), temp.pos); path.Push(temp.pos); if (temp == start) { break; } temp = temp.parent; } if (settings.benchmark) { sw.Stop(); Debug.Log("A*, Heuristic: " + settings.heuristic + ", Cost increase: " + settings.costIncrease + ", Path length: " + pathLength * 100 / distance + "%, ms: " + sw.Elapsed.TotalMilliseconds + ", closed: " + closedNodes.Count + ", opened: " + openNodes.Count + ", Neighbour checks: " + neighbourChecks); } return(path); }
public override void CalculateLoss(SimulationMsg cdlMsg, bool bDebug) { if (bDebug) { cdlMsg.SendMessage(string.Format("Calculate Loss TermNode: intId={0}, begin {1}", this.m_intId, this.CalcState)); } //aggregate losses from children for (int cIdx = 0; cIdx < this.m_vChildNode.Count; ++cIdx) { TermNode child = (TermNode)this.m_vChildNode[cIdx]; child.CalculateLoss(cdlMsg, bDebug); if (bDebug) { cdlMsg.SendMessage(string.Format("For TermNode: intId={0} initial {1}, Adding Child TermNode: intId={2}, {3}", this.m_intId, this.m_calcState, child.IntId, child.CalcState)); } } if (BucketList != null) { List <int> overlapBuckets = new List <int>(); for (int b0 = 0; b0 < bucketList.Count; b0++) { List <int> bucket = bucketList[b0]; for (int b1 = 0; b1 < bucket.Count - 1; b1++) { for (int b2 = 1; b2 < bucket.Count; b2++) { if (IsOverlap(bucket[b1], bucket[b2])) { if (!overlapBuckets.Contains(b0)) { overlapBuckets.Add(b0); } } } } } foreach (int ob in overlapBuckets) { BucketList.Remove(bucketList[ob]); } int b = 0; CalcState[] calcStateArray = new CalcState[BucketList.Count]; foreach (List <int> bucket in BucketList) { calcStateArray[b] = new CalcState(); calcStateArray[b].X = 0; calcStateArray[b].S = 0; calcStateArray[b].D = 0; foreach (int intId in bucket) { if (MapIntIdToNode.ContainsKey(intId)) { TermNode tn = MapIntIdToNode[intId]; _Schedule sar = tn.Subject.Schedule; foreach (RiskItem riskItem in sar.SetSchedule) { calcStateArray[b].X += riskItem.CalcState.X; calcStateArray[b].S += riskItem.CalcState.S; calcStateArray[b].D += riskItem.CalcState.D; } } else if (MapIntIdToRit.ContainsKey(intId)) { RiskItem ri = MapIntIdToRit[intId]; calcStateArray[b].X += ri.CalcState.X; calcStateArray[b].S += ri.CalcState.S; calcStateArray[b].D += ri.CalcState.D; } } foreach (TermObject termObj in this.m_sortTermObj) { termObj.ApplyTermObject(calcStateArray[b]); } b++; } this.m_calcState = FindWinningBucket(calcStateArray, BucketList); } else { _Schedule sar = this.m_subject.Schedule; foreach (RiskItem riskItem in sar.SetSchedule) { this.m_calcState.X += riskItem.CalcState.X; this.m_calcState.S += riskItem.CalcState.S; this.m_calcState.D += riskItem.CalcState.D; } //apply term objects to the term node.. foreach (TermObject termObj in this.m_sortTermObj) { termObj.ApplyTermObject(this.m_calcState); } } if (bDebug) { cdlMsg.SendMessage(string.Format("Calculate Loss TermNode: intId={0}, final {1}", this.m_intId, this.CalcState)); } }