Exemplo n.º 1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="problem"></param>
 /// <param name="heuristic">An estimate of the cost to reach the goal from the given state</param>
 public GreedyBestFirstSearch(ISearchProblem <TState, TAction> problem, Func <TState, int> heuristic) : base(problem)
 {
     _heuristic = heuristic;
     // todo: this should be in BestFirst Init function.. or something. have to call same frontier push
     //       in all subclasses
     Frontier.Push(new SearchNode <TState, TAction>(problem.InitialState, null, default(TAction), 0));
 }
Exemplo n.º 2
0
 protected override void AddToFrontier(Node <S, A> node)
 {
     if (!_explored.Contains(node.State))
     {
         Frontier.Add(node);
     }
 }
        private Node <T> RemoveFront()
        {
            var node = Frontier[0];

            Frontier.Remove(node);
            return(node);
        }
Exemplo n.º 4
0
        public SearchResult <T> Search()
        {
            T        state = Problem.InitialState;
            Node <T> node  = new Node <T>(state);

            if (Problem.GoalTest(state))
            {
                return(new SearchResult <T>(node));
            }
            Frontier.Put(node);
            OpenList.Add(state);

            while (!Frontier.IsEmpty)
            {
                node  = Frontier.Take();
                state = node.State;
                ClosedList.Add(state);
                foreach (IAction <T> action in Problem.Actions(state))
                {
                    Node <T> childNode  = node.ChildNode(Problem, action);
                    T        childState = childNode.State;
                    if (!ClosedList.Contains(childState) && !OpenList.Contains(childState))
                    {
                        if (Problem.GoalTest(childState))
                        {
                            return(new SearchResult <T>(childNode));
                        }
                        Frontier.Put(childNode);
                        OpenList.Add(childState);
                    }
                }
            }
            return(new SearchResult <T>(null));
        }
Exemplo n.º 5
0
 private void CleanUpFrontier()
 {
     while (!Frontier.Empty() && _explored.Contains(Frontier.Peek().State))
     {
         Frontier.Remove();
     }
 }
Exemplo n.º 6
0
        protected override Node <S, A> RemoveFromFrontier()
        {
            var res = Frontier.Remove();

            _explored.Add(res.State);
            _frontierStates.Remove(res.State);
            return(res);
        }
Exemplo n.º 7
0
        protected override Node <S, A> RemoveFromFrontier()
        {
            CleanUpFrontier();
            var result = Frontier.Remove();

            _explored.Add(result.State);
            return(result);
        }
Exemplo n.º 8
0
        public List <IPlan> Search(IPlanner IP, int k, float cutoff)
        {
            var Solutions = new List <IPlan>();

            var watch = System.Diagnostics.Stopwatch.StartNew();

            while (Frontier.Count > 0)
            {
                var plan = Frontier.Dequeue();
                IP.Expanded++;
                var flaw = plan.Flaws.Next();
                Console.WriteLine(plan.Decomps);
                if (IP.Console_log)
                {
                    Console.WriteLine(plan.ToStringOrdered());
                    Console.WriteLine(flaw);
                }

                // Termination criteria
                if (flaw == null)
                {
                    watch.Stop();
                    var elapsedMs = watch.ElapsedMilliseconds;

                    Solutions.Add(plan);
                    if (Solutions.Count >= k)
                    {
                        IP.WriteToFile(elapsedMs, plan as Plan);

                        return(Solutions);
                    }
                    continue;
                }

                if (watch.ElapsedMilliseconds > cutoff)
                {
                    watch.Stop();
                    IP.WriteToFile(watch.ElapsedMilliseconds, plan as Plan);
                    return(null);
                }

                var frontierCount = Frontier.Count;

                if (flaw.Ftype == Enums.FlawType.Link)
                {
                    IP.RepairThreat(plan, flaw as ThreatenedLinkFlaw);
                }

                else if (flaw.Ftype == Enums.FlawType.Condition)
                {
                    IP.AddStep(plan, flaw as OpenCondition);
                    IP.Reuse(plan, flaw as OpenCondition);
                }
            }

            return(null);
        }
Exemplo n.º 9
0
        public static List <Node> GetPath(Node start, Node end)
        {
            List <Node> path = new List <Node>();

            Frontier <Node> frontier = new Frontier <Node>();
            // hashing
            Dictionary <Node, Node> cameFrom = new Dictionary <Node, Node>();

            // Dijkstra
            Dictionary <Node, int> costSoFar = new Dictionary <Node, int>();

            frontier.Enqueue(start, 0);
            cameFrom[start]  = null;
            costSoFar[start] = 0;

            while (!frontier.IsEmpty)
            {
                Node currentNode = frontier.Dequeue();

                if (currentNode == end)
                {
                    break;
                }

                foreach (Node neighbour in currentNode.Neighbours)
                {
                    int newCost = costSoFar[currentNode] + neighbour.Cost;
                    if (!costSoFar.ContainsKey(neighbour) || newCost < costSoFar[neighbour])
                    {
                        costSoFar[neighbour] = newCost;
                        int priority = newCost;
                        frontier.Enqueue(neighbour, priority);
                        // for each neighbour, store its parent
                        cameFrom[neighbour] = currentNode;
                    }
                }
            }

            // build the list of node to traverse
            Node currentStep = end;

            while (currentStep != start && currentStep != null)
            {
                if (!cameFrom.ContainsKey(currentStep))
                {
                    return(null);
                }
                path.Add(currentStep);
                currentStep = cameFrom[currentStep];
            }
            //path.Add(start);

            path.Reverse();

            return(path);
        }
Exemplo n.º 10
0
        public int RunAlgorithm()
        {
            bool firstNode = true;

            // initialize the min spanning tree and frontier
            // Pick first node to put into the min spanning tree
            // add the other nodes into the frontier

            MinSpanningTree mst         = null;
            Frontier        frontier    = new Frontier();
            int             initialNode = -1;

            foreach (int node in graph.Nodes)
            {
                if (firstNode)
                {
                    initialNode = node;
                    mst         = new MinSpanningTree(node);
                    firstNode   = false;
                }
                else
                {
                    int weight = graph.GetWeight(node, initialNode);
                    frontier.Add(weight, node, initialNode);
                }
            }

            while (frontier.GetMinimumCut() != null)
            {
                // pick the node with the lowest weight and add it to the mst
                // remove node from frontier
                Tuple <int, int, int> nextEdge = frontier.GetMinimumCut();
                frontier.Remove(nextEdge.Item1, nextEdge.Item2);
                mst.Add(nextEdge);

                // adjust connecting nodes
                foreach (KeyValuePair <int, int> nodeWeightPair in graph.GetConnection(nextEdge.Item2))
                {
                    frontier.AdjustWeight(nodeWeightPair.Key, nextEdge.Item2, nodeWeightPair.Value);
                }
            }

            // cost of the mst
            int cost = 0;

            foreach (Tuple <int, int, int> triplet in mst.Edges)
            {
                cost += triplet.Item1;
            }

            return(cost);  //-3612829
        }
Exemplo n.º 11
0
 public Frontier FulfillConstraints(Frontier frontier)
 {
     foreach (var m in members)
     {
         // Console.WriteLine("First Layer {0}", m.name);
         var workingFront = m.CanFulfillConstraints(frontier.AddFoundPairs(this, m));
         if (workingFront != null)
         {
             return(workingFront);
         }
     }
     return(null);
 }
Exemplo n.º 12
0
        private void Init()
        {
            int[] firstTriIdxs;
            var   pts    = D.Points;
            var   ptsCnt = pts.Length;

            m_Origin = CalcOrigin(out firstTriIdxs);
            Func <float, int> keyHash;
            var thetaGroups = Frontier.ThetaGroup.BuildThetaGroups(ptsCnt, out keyHash);
            var grpsCnt     = thetaGroups.Length;

            m_PolPos      = new PolartPt[ptsCnt]; //TODO make this dynamic to save memory?
            m_VertIdxsByR = new int[ptsCnt - 3];
            var idxOffset = 0;

            for (var pIdx = 0; pIdx < ptsCnt; ++pIdx)
            {
                //Store polar position
                var polPos = new PolartPt(pts[pIdx], m_Origin);
                m_PolPos[pIdx] = polPos;
                var theta = polPos.Theta;

                //Reference theta group
                var grpIdx = keyHash(theta);
                if (grpIdx >= grpsCnt) //Floating point error check TODO
                {
                    grpIdx--;
                }

                polPos.thetaGroup = thetaGroups[grpIdx];

                //Prepare r index reference (to be sorted later)
                if (firstTriIdxs.Contains(pIdx))
                {
                    idxOffset++;
                    continue;
                }

                m_VertIdxsByR[pIdx - idxOffset] = pIdx;
            }

            //Sort points by distance to origin
            //Array.Sort(m_VertIdxsByR, (_a, _b) => m_PolPos[_a].r.CompareTo(m_PolPos[_b].r));
            Array.Sort(m_VertIdxsByR, (_a, _b) => ComparePol(m_PolPos[_a], m_PolPos[_b]));

            //Init Frontier
            var firstTri = new Delaunay.Triangle(firstTriIdxs[0], firstTriIdxs[1], firstTriIdxs[2], D);

            m_Frontier = new Frontier(firstTri, this);
        }
Exemplo n.º 13
0
    private Frontier InitialFrontier(List <Category> cats, Dictionary <string, string> existingConstraints)
    {
        foreach (var cat in cats)
        {
            cat.Shuffle();
        }

        var frontier = new Frontier(cats, new Dictionary <Category, Element>(), new HashSet <int>());

        foreach (var k in existingConstraints.Keys)
        {
            frontier.foundPairs.Add(symbolToCategory[k], shortNameToElement[existingConstraints[k]]);
        }
        return(frontier);
    }
Exemplo n.º 14
0
    public Frontier CanFulfillConstraints(Frontier frontier)
    {
        // Console.WriteLine("In member {0}", this.name);

        if (CatCatToId.data.ContainsKey(memberOf))
        {
            foreach (var cat in CatCatToId.data[memberOf].Keys)
            {
                var currentId = CatCatToId.data[this.memberOf][cat];
                if (frontier.usedConstraintIds.Contains(currentId))
                {
                    continue;
                }
                if (!to.ContainsKey(cat) || to.Count == 0)
                {
                    // Console.WriteLine("{0} has no {1}!", this.name, cat.symbol);
                    return(null);
                }
                if (frontier.foundPairs.ContainsKey(cat))
                {
                    foreach (var el in to[cat])
                    {
                        // Console.WriteLine("  TRY {0}", el.name);
                        if (el == frontier.foundPairs[cat])
                        {
                            // Console.WriteLine("! TRY {0}", el.name);
                            return(frontier.AddUsedConstraintId(currentId));
                        }
                        // Console.WriteLine("X TRY {0}", el.name);
                    }
                    return(null);
                }
            }
        }

        List <Category> reachable = new List <Category>();

        foreach (var cat in frontier.missingCats)
        {
            if (CatCatToId.data.ContainsKey(memberOf) && CatCatToId.data[memberOf].ContainsKey(cat))
            {
                reachable.Add(cat);
            }
        }
        return(this.CanReachAll(frontier, reachable));
    }
Exemplo n.º 15
0
    private Frontier CanReachAll(Frontier frontier, List <Category> reachable)
    {
        // Console.Write("canReachAll {0}", this.name);
        // reachable.ForEach(r => Console.Write(r.symbol + ", "));
        // Console.WriteLine();
        if (reachable.Count == 0)
        {
            return(frontier);
        }
        var cat           = reachable.First();
        var nextReachable = new List <Category>(reachable);

        nextReachable.Remove(cat);
        var currentId = CatCatToId.data[this.memberOf][cat];

        if (frontier.usedConstraintIds.Contains(currentId))
        {
            return(CanReachAll(frontier, nextReachable));
        }
        if (!to.ContainsKey(cat))
        {
            // Console.WriteLine("{0} has no {1}.", this.name, cat.symbol);
            return(null);
        }

        // Console.WriteLine("adding catcatId {0}", currentId);
        var nextFront = frontier.AddUsedConstraintId(currentId).RemoveMissingCat(cat);

        foreach (var el in to[cat])
        {
            // Console.WriteLine("  try {0} -> {1}", cat.symbol, el.name);
            var nextFront2   = nextFront.AddFoundPairs(cat, el);
            var workingFront = el.CanFulfillConstraints(nextFront2);
            if (workingFront != null)
            {
                // Console.WriteLine("! try {0}", el.name);
                var workingFront2 = CanReachAll(workingFront, nextReachable);
                if (workingFront2 != null)
                {
                    return(workingFront2);
                }
            }
            // Console.WriteLine("X try {0} -> {1}", cat.symbol, el.name);
        }
        return(null);
    }
Exemplo n.º 16
0
        public List <IPlan> Search(IPlanner IP, int k, float cutoff)
        {
            var watch     = System.Diagnostics.Stopwatch.StartNew();
            var Solutions = new List <IPlan>();

            while (Frontier.Count > 0)
            {
                var plan = Frontier.Dequeue();

                IP.Expanded++;

                if (IP.Console_log)
                {
                    Console.WriteLine(plan);
                }

                if (plan.CurrentState.Satisfies(plan.Goal.Predicates))
                {
                    // Termination criteria
                    watch.Stop();
                    var elapsedMs = watch.ElapsedMilliseconds;
                    Solutions.Add(plan);
                    if (Solutions.Count >= k)
                    {
                        Console.WriteLine(IP.Open.ToString() + ", " + IP.Expanded.ToString());
                        return(Solutions);
                    }
                    continue;
                }

                if (watch.ElapsedMilliseconds > cutoff)
                {
                    watch.Stop();
                    Console.WriteLine(IP.Open.ToString() + ", " + IP.Expanded.ToString());
                    return(null);
                }

                IP.AddStep(plan);
            }

            return(null);
        }
Exemplo n.º 17
0
        public static long TotalCost <TData> (this DirectedGraph <TData> graph)
        {
            var rand        = new Random(DateTime.UtcNow.Millisecond);
            var pivotVertex = graph.Vertices.ElementAt(rand.Next(0, graph.Vertices.Count - 1));

            var totalCost = 0L;

            var frontier = new Frontier <TData>(graph);

            frontier.AddVertex(pivotVertex);
            while (frontier.SeenSoFar() < graph.Vertices.Count)
            {
                var minOutgoingEdge = frontier.MinEdge();
                totalCost += minOutgoingEdge.Metric;

                var nextVertex = frontier.ExternalVertex(minOutgoingEdge);
                frontier.AddVertex(nextVertex);
            }

            return(totalCost);
        }
Exemplo n.º 18
0
        public static List <Vertex <TData, TMetric> > FindPath <TData, TMetric>
            (Graph <TData, TMetric> graph,
            Vertex <TData, TMetric> start,
            Vertex <TData, TMetric> finish)
        {
            var frontier = new Frontier <TData, TMetric>();

            frontier.AddVertex(start, null);

            while (!frontier.Contains(finish))
            {
                var shortestEdge = frontier.ShortestEdge();
                frontier.AddVertex(shortestEdge.Ending, shortestEdge);

                if (!frontier.HasEdges)
                {
                    break;
                }
            }

            //check whether finish node has been found
            if (!frontier.Contains(finish))
            {
                return(null);
            }

            var path = new List <Vertex <TData, TMetric> >();

            for (var current = finish; current != null;)
            {
                path.Add(current);
                var shortestEdge = frontier.EdgeForVertex(current);
                current = shortestEdge?.Beginning;
            }
            path.Reverse();
            return(path);
        }
Exemplo n.º 19
0
        public override void PerformSearch()
        {
            while (Frontier.Count > 0)
            {
                INode node = Frontier.Pop();
                ExploredNodes.Push(node);

                if (node.IsTarget())
                {
                    SuccessNode = node;
                    return;
                }

                INode[] nextNodes = node.NextNodes();

                foreach (INode n in nextNodes)
                {
                    if (!ExploredNodes.Contains(n) && !Frontier.Contains(n))
                    {
                        Frontier.Push(n);
                    }
                }
            }
        }
Exemplo n.º 20
0
 protected override bool IsFrontierEmpty()
 {
     CleanUpFrontier();
     return(Frontier.Empty());
 }
Exemplo n.º 21
0
 private void AddNodes(IEnumerable <Node <T> > nodes)
 {
     Frontier.AddRange(nodes);
 }
    // Grouping the coordinate in frontier, based on the max distance and number of coordinates allowable
    public void Coordinate2Frontiers()
    {
        // ensure that  the main variablea are ready to use
        points.Clear();
        frontiers.Clear();
        complete = true;

        GetCoordinates();

        if (!complete)
        {
            // dictionary that keep the group of coordinates and the number of the its menber.
            Dictionary <Coordinate, List <Coordinate> > groupCoordinate = new Dictionary <Coordinate, List <Coordinate> >();

            // matrix with distance between the Coordinate as element
            float[,] distanceMatrix = new float[points.Count, points.Count];

            bool next = true;

            // initialize the dictionary
            foreach (Coordinate elem in points)
            {
                groupCoordinate.Add(elem, new List <Coordinate> {
                    elem
                });
            }

            // initialize the matrix of distance with
            for (int i = 0; i < points.Count; i++)
            {
                for (int j = 0; j < i; j++)
                {
                    distanceMatrix[i, j] = ComputeDistance(points[i], points[j]);
                }
            }

            // the process work until there are not any
            while (next)
            {
                int[] ii = FindMinElem(distanceMatrix, groupCoordinate);
                if (ii != null)
                {
                    distanceMatrix = UpdateDistanceMatrix(ii[0], ii[1], distanceMatrix, groupCoordinate);
                }
                else
                {
                    next = false;
                }
            }

            // put into the list of frontier the nearest coordinate to the center of group, with the list contained
            foreach (Coordinate key in groupCoordinate.Keys)
            {
                float      oldDiff      = Frontier.distance;
                Coordinate nearestCoord = new Coordinate(key);

                foreach (Coordinate elem in groupCoordinate[key])
                {
                    if (ComputeDistance(key, elem) < oldDiff)
                    {
                        nearestCoord = new Coordinate(elem);
                        oldDiff      = ComputeDistance(key, elem);
                    }
                }
                Frontier frontier = new Frontier(nearestCoord, groupCoordinate[key]);
                frontiers.Add(frontier);
            }
        }
    }
Exemplo n.º 23
0
 /// <summary>
 /// Initialise the search. Note that lower scores are searched first.
 /// </summary>
 /// <param name="problem">The search problem</param>
 /// <param name="heuristic">An estimate of the cost to reach the goal from the given state</param>
 public AStarSearch(ISearchProblem <TState, TAction> problem, Func <TState, int> heuristic) : base(problem)
 {
     _heuristic = heuristic;
     Frontier.Push(new SearchNode <TState, TAction>(problem.InitialState, null, default(TAction), 0));
 }
Exemplo n.º 24
0
        public override void PerformSearch()
        {
            while (Frontier.Count > 0)
            {
                INode node = Frontier.Pop();
                // we might be back in a parent, don't re-push it into explored
                if (!ExploredNodes.Contains(node))
                {
                    ExploredNodes.Push(node);
                }

                if (node.IsTarget())
                {
                    SuccessNode = node;
                    return;
                }

                // we get the next nodes for our node - given backtracking some of these might have been explored
                INode[] nextNodes = node.NextNodes();

                // the best next node will be the one with the fewest valid, unexplored moves from it
                INode bestNextNode      = null;
                int   bestNextNodeMoves = int.MaxValue;

                INode nextNode;
                int   nextNodeMoves;
                for (int i = 0; i < nextNodes.Length; i++)
                {
                    // for each next node from our current node that we haven't explored, we will look at the number of moves from that node
                    nextNode = nextNodes[i];

                    if (nextNode.IsTarget()) // shortcircuit
                    {
                        SuccessNode = nextNode;
                        return;
                    }
                    // this is an optimisation to pre-recognise leaves that aren't successful as explored
                    if (nextNode.IsLeaf() && !ExploredNodes.Contains(nextNode))
                    {
                        ExploredNodes.Push(nextNode);
                    }

                    // we want the best node we can see out of the next nodes, based on how many moves each has
                    nextNodeMoves = nextNode.NextNodes().Where(n => !ExploredNodes.Contains(n)).Count();
                    if (nextNodeMoves > 0 && nextNodeMoves < bestNextNodeMoves)
                    {
                        bestNextNodeMoves = nextNodeMoves;
                        bestNextNode      = nextNode;
                    }
                }

                // backtrack if we didn't find a node to move forward to
                if (bestNextNode == null)
                {
                    Frontier.Push(node.Parent);
                }
                // if we did find a node, place it onto the stack
                else if (!ExploredNodes.Contains(bestNextNode) && !Frontier.Contains(bestNextNode))
                {
                    Frontier.Push(bestNextNode);
                }
            }
        }
Exemplo n.º 25
0
 protected override bool IsFrontierEmpty()
 {
     return(Frontier.Empty());
 }
Exemplo n.º 26
0
        public List <IPlan> Search(IPlanner IP, int k, float cutoff)
        {
            var Solutions = new List <IPlan>();

            var watch = System.Diagnostics.Stopwatch.StartNew();

            while (Frontier.Count > 0)
            {
                var plan = Frontier.Dequeue();
                //if (plan.ID.Equals("135a7a13a25a51ri65ri87a189a585a1277a2965a10239d15043a44047r62295ri"))
                //if (plan.ID.Equals("1313a61a76405a") || plan.ID.Equals("1313a61a76407a")
                //    || plan.ID.Equals("1313a61a76409a")
                //    || plan.ID.Equals("1313a61a76411a")
                //    || plan.ID.Equals("1313a61a76413a")
                //    || plan.ID.Equals("1313a61a76415a"))//39709a"))
                //{
                //    Console.WriteLine("Here");
                //}
                if (plan.ID.Equals("016a"))
                {
                    Console.WriteLine("Here");
                }
                IP.Expanded++;
                var flaw = plan.Flaws.Next();
                Console.WriteLine(plan.Decomps);
                if (IP.Console_log)
                {
                    //Console.WriteLine(plan.ToStringOrdered());
                    //Console.WriteLine(plan.ToStringOrdered());
                    //Console.WriteLine(flaw);
                }

                // Termination criteria
                if (flaw == null)
                {
                    if (onlyStopOnDepth)
                    {
                        if (plan.Hdepth == 0)
                        {
                            continue;
                        }
                    }

                    watch.Stop();
                    var elapsedMs = watch.ElapsedMilliseconds;

                    Solutions.Add(plan);
                    if (Solutions.Count >= k)
                    {
                        IP.WriteToFile(elapsedMs, plan as Plan);
                        IP.WriteTimesToFile();
                        return(Solutions);
                    }
                    continue;
                }

                if (watch.ElapsedMilliseconds > cutoff)
                {
                    watch.Stop();
                    IP.WriteToFile(watch.ElapsedMilliseconds, plan as Plan);
                    IP.WriteTimesToFile();
                    return(null);
                }

                var frontierCount = Frontier.Count;

                if (flaw.Ftype == Enums.FlawType.Link)
                {
                    IP.RepairThreat(plan, flaw as ThreatenedLinkFlaw);
                }

                else if (flaw.Ftype == Enums.FlawType.Condition)
                {
                    var beforeAddStep = watch.ElapsedMilliseconds;
                    IP.AddStep(plan, flaw as OpenCondition);
                    IP.LogTime("addStep", watch.ElapsedMilliseconds - beforeAddStep);

                    var beforeReuseStep = watch.ElapsedMilliseconds;
                    IP.Reuse(plan, flaw as OpenCondition);
                    IP.LogTime("reuseStep", watch.ElapsedMilliseconds - beforeReuseStep);
                }
            }

            return(null);
        }
Exemplo n.º 27
0
 private void DetermineRegionNeighbors()
 {
     foreach (Region region in base.Context.Regions.Values)
     {
         List <Frontier> list = new List <Frontier>();
         foreach (District district in region.Districts)
         {
             foreach (HexPos hexPos in district)
             {
                 foreach (HexPos hexPos2 in base.Context.Grid.Adjacents(hexPos))
                 {
                     int      key       = base.Context.DistrictData[hexPos2.Row, hexPos2.Column];
                     District district2 = base.Context.Districts[key];
                     if (district2 != null)
                     {
                         Region neighborRegion = district2.MotherRegion;
                         if (neighborRegion != null && region.Id != neighborRegion.Id)
                         {
                             if (!district.Neighbours.Contains(district2))
                             {
                                 district.Neighbours.Add(base.Context.Districts[key]);
                             }
                             RegionBorder regionBorder;
                             if (region.Borders.ContainsKey(neighborRegion))
                             {
                                 regionBorder = region.Borders[neighborRegion];
                             }
                             else
                             {
                                 regionBorder = new RegionBorder(region, neighborRegion);
                                 region.Borders.Add(neighborRegion, regionBorder);
                             }
                             if (!regionBorder.Contains(hexPos))
                             {
                                 regionBorder.Add(hexPos);
                             }
                             Frontier frontier = list.FirstOrDefault((Frontier tmpFront) => tmpFront.Neighbour == neighborRegion.Id);
                             if (frontier == null)
                             {
                                 frontier = new Frontier
                                 {
                                     Neighbour = neighborRegion.Id,
                                     Points    = new List <Frontier.Point>()
                                 };
                                 list.Add(frontier);
                             }
                             bool flag = false;
                             for (int i = 0; i < frontier.Points.Count; i++)
                             {
                                 if (frontier.Points[i].Hex == hexPos)
                                 {
                                     flag = true;
                                 }
                             }
                             if (!flag)
                             {
                                 frontier.Points.Add(new Frontier.Point
                                 {
                                     From = (int)neighborRegion.Id,
                                     Hex  = hexPos
                                 });
                             }
                         }
                     }
                 }
             }
         }
         region.Frontiers = list.ToArray();
         if (region.Neighbours.Count == 1)
         {
             base.ReportTmx("?NestedRegion");
         }
     }
 }