Пример #1
0
        private BaseProjectionBuffer PickIndependentBuffer()
        {
            // pick a buffer for which all source buffers have finished participating in the master edit.
            // source buffer could be stable because
            //  1. it is in the source closure of the master buffer -- all those edits are done by now
            //  2. it isn't in the target closure of the master buffer
            //  3. it has already been picked by this method

            // for the moment, we are ignoring #2, and such buffers won't get picked (resulting in an exception).

            foreach (BaseProjectionBuffer projectionBuffer in this.pendingIndependentBuffers)
            {
                bool ok = true;
                foreach (ITextBuffer sourceBuffer in projectionBuffer.SourceBuffers)
                {
                    if (!IsStableDuringIndependentPhase((BaseBuffer)sourceBuffer))
                    {
                        ok = false;
                        break;
                    }
                }
                if (ok)
                {
                    GraphEntry gg = this.graph[(BaseBuffer)projectionBuffer];
                    gg.Dependent = true;    // indicate has been chosen
                    this.pendingIndependentBuffers.Remove(projectionBuffer);
                    return(projectionBuffer);
                }
            }
            throw new InvalidOperationException("Couldn't pick an independent buffer");
        }
Пример #2
0
        private void UpdateGraphList()
        {
            if (m_graphsInProject == null)
            {
                return;
            }

            var guids   = AssetDatabase.FindAssets(Model.Settings.GRAPH_SEARCH_CONDITION);
            var newList = new List <GraphEntry>(guids.Length);

            foreach (var guid in guids)
            {
                var e = m_graphsInProject.Find(v => v.Guid == guid);
                if (e == null)
                {
                    e = new GraphEntry(guid);
                }
                else
                {
                    e.Refresh();
                }
                newList.Add(e);
            }

            m_graphsInProject = newList;
        }
Пример #3
0
        private void ProcessBestEntry(GraphEntry bestEntry)
        {
            // First we should remove the entry from the candidate array
            Assert.IsTrue(_sortedCandidateGraphEntries [0] == bestEntry);
            _sortedCandidateGraphEntries.RemoveAt(0);
            GraphElement bestElement = bestEntry.graphElement;

                        #if !REQUIRE_STRUCT
            Assert.IsTrue(bestElement != null);
                        #endif

            // Now we should add/update all the connected entries.
            if (bestEntry.connectedElements != null)
            {
                foreach (GraphElement currConnectedElement in bestEntry.connectedElements)
                {
                    float      connectionCost        = _graph.getActualCostForMovementBetweenElementsFunc(bestElement, currConnectedElement);
                    float      totalCostToConnection = bestEntry.bestCostToHere + connectionCost;
                    GraphEntry connectedEntry        = GetEntryForElement(currConnectedElement);
                    if (connectedEntry == _startEntry)
                    {
                        // This is the start entry so just ignore it as the best route never returns to the start point!
                    }
                    else if (connectedEntry == _targetEntry)
                    {
                        // We've reached the target entry, add it as a sorted candidate, we're only finished if this route becomes the best possible.
                        if (connectedEntry.bestCostVia == null || totalCostToConnection < connectedEntry.bestCostToHere)
                        {
                            connectedEntry.SetBestCost(bestEntry, totalCostToConnection);
                            AddSortedCandidate(connectedEntry);
                        }
                    }
                    else if (connectedEntry != null && connectedEntry.bestCostVia != null)
                    {
                        // We've already visited this entry so see if this is the optimum route.
                        if (totalCostToConnection < connectedEntry.bestCostToHere)
                        {
                            // This route is shorter than the one we've previously found so replace it.
                            RemoveSortedCandidate(connectedEntry);
                            connectedEntry.SetBestCost(bestEntry, totalCostToConnection);
                            AddSortedCandidate(connectedEntry);
                        }
                    }
                    else
                    {
                        // This is the first time we've seen this entry so just add it
                        Assert.IsTrue(connectedEntry == null || connectedEntry.bestCostVia == null);
                        if (connectedEntry == null)
                        {
                            connectedEntry = CreateGraphEntryFor(currConnectedElement);
                        }
                        connectedEntry.SetBestCost(bestEntry, totalCostToConnection);
                        AddSortedCandidate(connectedEntry);
                    }
                }
            }
        }
Пример #4
0
            public void SetBestCost(GraphEntry viaEntry, float totalCostToHere)
            {
                Assert.IsTrue(totalCostToHere < this.bestCostToHere || bestCostVia == null);
                Assert.IsTrue(totalCostToHere >= 0.0f);
                Assert.IsTrue(viaEntry != null);
                Assert.IsTrue(totalCostToHere >= viaEntry.bestCostToHere);                  // We can't have a smaller cost than our via entry.

                this._bestCostToHere = totalCostToHere;
                this._bestCostVia    = viaEntry;
            }
Пример #5
0
        private void RemoveSortedCandidate(GraphEntry candidateEntry)
        {
            Assert.IsTrue(candidateEntry != null);
            CandidateComparer comparer = new CandidateComparer();
            int findIndex = _sortedCandidateGraphEntries.BinarySearch(candidateEntry, comparer);

            if (findIndex >= 0)
            {
                // Find the lower bound...
                int lowerBound = findIndex;
                while (lowerBound > 0)
                {
                    if (comparer.Compare(_sortedCandidateGraphEntries[lowerBound - 1], _sortedCandidateGraphEntries[findIndex]) == 0)
                    {
                        --lowerBound;
                    }
                    else
                    {
                        break;
                    }
                }

                // Find the upper bound...
                int upperBound = findIndex;
                while (upperBound < (_sortedCandidateGraphEntries.Count - 1))
                {
                    if (comparer.Compare(_sortedCandidateGraphEntries[upperBound + 1], _sortedCandidateGraphEntries[findIndex]) == 0)
                    {
                        ++upperBound;
                    }
                    else
                    {
                        break;
                    }
                }

                // Loop over all possible candidates until we find the one we're looking for.
                for (int currTestIndex = lowerBound; currTestIndex <= upperBound; ++currTestIndex)
                {
                    Assert.IsTrue(comparer.Compare(_sortedCandidateGraphEntries[currTestIndex], _sortedCandidateGraphEntries[findIndex]) == 0);
                    if (_sortedCandidateGraphEntries[findIndex] == candidateEntry)
                    {
                        _sortedCandidateGraphEntries.RemoveAt(findIndex);
                        break;
                    }
                }
            }
        }
Пример #6
0
        private void MarkMasterClosure(BaseBuffer buffer)
        {
            GraphEntry g = this.graph[buffer];

            if (!g.Dependent)
            {
                g.Dependent = true;
                IProjectionBufferBase projectionBuffer = buffer as IProjectionBufferBase;
                if (projectionBuffer != null)
                {
                    foreach (BaseBuffer source in projectionBuffer.SourceBuffers)
                    {
                        MarkMasterClosure(source);
                    }
                }
            }
        }
Пример #7
0
        private bool InTargetClosureOfBuffer(BaseBuffer candidateBuffer, BaseBuffer governingBuffer)
        {
            GraphEntry g = this.graph[governingBuffer];

            foreach (var target in g.Targets)
            {
                if (target == candidateBuffer)
                {
                    return(true);
                }
                if (InTargetClosureOfBuffer(candidateBuffer, (BaseBuffer)target))
                {
                    return(true);
                }
            }
            return(false);
        }
Пример #8
0
 private bool InvulnerableToFutureEdits(GraphEntry graphEntry)
 {
     foreach (IProjectionBufferBase target in graphEntry.Targets)
     {
         BaseBuffer baseTarget  = (BaseBuffer)target;
         GraphEntry targetEntry = this.graph[baseTarget];
         if (targetEntry.EditComplete)
         {
             continue;
         }
         if (InvulnerableToFutureEdits(targetEntry) && !this.buffer2EditMap.ContainsKey(baseTarget))
         {
             targetEntry.EditComplete = true;
             continue;
         }
         return(false);
     }
     return(true);
 }
Пример #9
0
        private void AddSortedCandidate(GraphEntry newCandidateEntry)
        {
            // Only actually add if if it is possible that it will produce a better solution than our existing best solution, and that it's better than the worst cost we're interested in.
            float currBestSolutionCost = _targetEntry.currentBestPossibleTotalCost;

            if (newCandidateEntry.currentBestPossibleTotalCost <= _maxAcceptableRouteLength && (_targetEntry.bestCostVia == null || newCandidateEntry.currentBestPossibleTotalCost < currBestSolutionCost))
            {
                int findIndex = _sortedCandidateGraphEntries.BinarySearch(newCandidateEntry, _candidateComparer);
                if (findIndex < 0)
                {
                    // We didn't find it so insert it at the bitwise compliment of findIndex (see https://msdn.microsoft.com/en-us/library/w4e7fxsh(v=vs.110).aspx)
                    _sortedCandidateGraphEntries.Insert(~findIndex, newCandidateEntry);
                }
                else
                {
                    _sortedCandidateGraphEntries.Insert(findIndex, newCandidateEntry);
                }
            }
        }
Пример #10
0
        private GraphEntry CreateGraphEntryFor(GraphElement graphElement)
        {
            Assert.IsTrue(!_graphEntries.ContainsKey(graphElement));              // We should only be creating a new element if there isn't one already.
            // If the _targetEntry hasn't been setup yet then we must be building it now. Pass null (which evaluates to zero estimated cost as we ARE the target).
            GraphEntry newEntry;

            if (_graphEntryCache.Count == 0)
            {
                newEntry = new GraphEntry(this);
            }
            else
            {
                newEntry = _graphEntryCache.Last();
                _graphEntryCache.RemoveAt(_graphEntryCache.Count - 1);
            }
            newEntry.Setup(graphElement);
            _graphEntries [graphElement] = newEntry;
            return(newEntry);
        }
Пример #11
0
        /// <summary>
        /// Extracts a list of GraphElements representing the shortest route from start to finish.
        /// Returns null if no such route was found.
        /// </summary>
        /// <returns>The solution.</returns>
        /// <param name="targetElement">Target element.</param>
        private List <GraphElement> ExtractSolution(GraphElement targetElement, bool allowPartialSolution)
        {
            List <GraphElement> solutionList = null;

            GraphEntry currEntry           = GetEntryForElement(targetElement);
            bool       hasCompleteSolution = currEntry != null && currEntry.bestCostVia != null;

            if (!hasCompleteSolution && allowPartialSolution)
            {
                // Get a list of all the entries which we did reach in our search.
                var viableEntries = _graphEntries.Values.Where(reachedFilterEntry => (reachedFilterEntry.bestCostVia != null || reachedFilterEntry == _startEntry));
                if (!(viableEntries.Count() == 0))
                {
                    // Filter the list down to the entries which got the closest possible distance away from the target...
                    var   orderedViableEntries      = viableEntries.OrderBy(distFromSolutionEntry => distFromSolutionEntry.bestPossibleCostToTarget);
                    float bestPossibleRemainingCost = orderedViableEntries.First().bestPossibleCostToTarget;
                    viableEntries = viableEntries.Where(filderRemaininCostEntry => filderRemaininCostEntry.bestPossibleCostToTarget == bestPossibleRemainingCost);
                    Assert.IsFalse(viableEntries.Count() == 0);

                    // Order the remaining viable entries by the total cost and pick the smallest...
                    orderedViableEntries = viableEntries.OrderBy(totalCostOrderEntry => totalCostOrderEntry.currentBestPossibleTotalCost);
                    Assert.IsFalse(orderedViableEntries.Count() == 0);

                    // Set the curr entry to be the best possible end entry...
                    currEntry = orderedViableEntries.First();
                }
            }

            // Now we know where the path ends, trace the route back to the start entry.
            if (currEntry != null && (currEntry.bestCostVia != null || currEntry == _startEntry))
            {
                solutionList = new List <GraphElement> ();
                while (currEntry != null)
                {
                    solutionList.Add(currEntry.graphElement);
                    currEntry = currEntry.bestCostVia;
                }
                solutionList.Reverse();
            }

            return(solutionList);
        }
Пример #12
0
        private void HandleFrame(LayerSectionFilter filter, DataFrame frame)
        {
            string     name       = GenerateName(filter, frame);
            GraphEntry startEntry = null;

            lock (_graphEntries)
            {
                if (!_shuttingDown)
                {
                    if (_graphEntries.ContainsKey(name))
                    {
                        _graphEntries[name].GetInputAdapter(_direction).Enqueue(frame);
                    }
                    else
                    {
                        LayerSectionDataAdapter clientAdapter = new LayerSectionDataAdapter(this);
                        LayerSectionDataAdapter serverAdapter = new LayerSectionDataAdapter(_linkedNode);

                        if (_direction == LayerSectionGraphDirection.ClientToServer)
                        {
                            LayerSectionDataAdapter temp = clientAdapter;
                            clientAdapter = serverAdapter;
                            serverAdapter = temp;
                        }

                        var clients = filter.Factory.GetNodes <ClientEndpointFactory>();
                        var servers = filter.Factory.GetNodes <ServerEndpointFactory>();

                        if ((clients.Length > 0) && (servers.Length > 0))
                        {
                            MetaDictionary meta = filter.IsolatedGraph ? new MetaDictionary() : Graph.Meta;

                            NetGraph graph = filter.Factory.Create(Graph.Logger, Graph, Graph.GlobalMeta, meta, Graph.ConnectionProperties.AddBag(name));
                            graph.Name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", Name, name);
                            startEntry = new GraphEntry(filter, clientAdapter, serverAdapter,
                                                        graph, clients[0].Id, servers[0].Id, ProxyNetworkService.GetLayerBinding(Graph));
                            startEntry.GetInputAdapter(_direction).Enqueue(frame);

                            _graphEntries[name] = startEntry;
                        }
                        else
                        {
                            throw new ArgumentException(CANAPE.Net.Properties.Resources.LayerSectionNode_InvalidGraph);
                        }
                    }
                }
            }

            // Ensure this is done outside the lock
            if (startEntry != null)
            {
                startEntry.NegotiationThread = new Thread(() =>
                {
                    try
                    {
                        startEntry.Start();
                    }
                    catch (Exception ex)
                    {
                        Graph.Logger.LogException(ex);
                        lock (_graphEntries)
                        {
                            _graphEntries.Remove(name);
                            startEntry.Dispose();
                        }
                    }
                }
                                                          );
                startEntry.NegotiationThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
                startEntry.NegotiationThread.IsBackground     = true;
                startEntry.NegotiationThread.Start();
            }
        }
Пример #13
0
        /// <summary>
        /// Calculates the shortest route through the graph to the target using the given LazyGraph callbacks.
        /// </summary>
        /// <param name="startingElement">Starting element.</param>
        /// <param name="allowPartialSolution">If true, then the closest to complete solution will be used, even if the solution
        /// doesn't actually reacth the target position.</param>
        public IList <GraphElement> Calculate(GraphElement startElement, GraphElement targetElement, bool allowPartialSolution = false, float maxAcceptableRouteLength = float.MaxValue)
        {
                        #if !REQUIRE_STRUCT
            Assert.IsTrue(startElement != null);
            Assert.IsTrue(targetElement != null);
                        #endif
            Assert.IsTrue(0.0f < maxAcceptableRouteLength);

            // Special case for if we are starting our search at the target element.
            if (startElement.Equals(targetElement))
            {
                return(new List <GraphElement> {
                    targetElement
                });
            }

            Assert.IsTrue(_sortedCandidateGraphEntries != null && _sortedCandidateGraphEntries.Count == 0);

            // Clear all the cached data if the search has changed...
            {
                Assert.IsTrue(_graphEntries != null);
                bool hasSearchChanged = false;
                if (_maxAcceptableRouteLength != maxAcceptableRouteLength)
                {
                    _maxAcceptableRouteLength = maxAcceptableRouteLength;
                    hasSearchChanged          = true;
                }

                if (_startEntry != null && !startElement.Equals(_startEntry.graphElement))
                {
                    hasSearchChanged = true;
                }

                // Set the target entry...
                if (_targetEntry != null && !targetElement.Equals(_targetEntry.graphElement))
                {
                    hasSearchChanged = true;
                }

                if (hasSearchChanged)
                {
                    _startEntry  = null;
                    _targetEntry = null;
                    _graphEntries.Clear();
                }
            }

            if (_targetEntry == null)
            {
                _targetEntry = CreateGraphEntryFor(targetElement);
            }
            Assert.IsTrue(_targetEntry.graphElement.Equals(targetElement));

            // Initialise the search graph with the starting element...
            AddStartGraphEntry(startElement);
            while (true)
            {
                if (_sortedCandidateGraphEntries.Count == 0)
                {
                    // We're run out of candidates and haven't found the solution.
                    // There is no route across the graph. :-(.
                    break;
                }
                else
                {
                    GraphEntry currTestEntry = GetCurrBestTestEntry();

                    if (currTestEntry.Equals(targetElement))
                    {
                        // We have a full best solution to the target.
                        break;
                    }
                    else
                    {
                        ProcessBestEntry(currTestEntry);
                    }
                }
            }

            List <GraphElement> solutionList = ExtractSolution(targetElement, allowPartialSolution);
            Assert.IsTrue(solutionList == null || startElement.Equals(solutionList[0]));

            // Reset the working data.
            _sortedCandidateGraphEntries.Clear();

            return(solutionList);
        }
Пример #14
0
        private void HandleFrame(LayerSectionFilter filter, DataFrame frame)
        {
            string name = GenerateName(filter, frame);
            GraphEntry startEntry = null;

            lock (_graphEntries)
            {
                if (!_shuttingDown)
                {
                    if (_graphEntries.ContainsKey(name))
                    {
                        _graphEntries[name].GetInputAdapter(_direction).Enqueue(frame);
                    }
                    else
                    {
                        LayerSectionDataAdapter clientAdapter = new LayerSectionDataAdapter(this);
                        LayerSectionDataAdapter serverAdapter = new LayerSectionDataAdapter(_linkedNode);

                        if (_direction == LayerSectionGraphDirection.ClientToServer)
                        {
                            LayerSectionDataAdapter temp = clientAdapter;
                            clientAdapter = serverAdapter;
                            serverAdapter = temp;
                        }

                        var clients = filter.Factory.GetNodes<ClientEndpointFactory>();
                        var servers = filter.Factory.GetNodes<ServerEndpointFactory>();

                        if ((clients.Length > 0) && (servers.Length > 0))
                        {
                            MetaDictionary meta = filter.IsolatedGraph ? new MetaDictionary() : Graph.Meta;

                            NetGraph graph = filter.Factory.Create(Graph.Logger, Graph, Graph.GlobalMeta, meta, Graph.ConnectionProperties.AddBag(name));
                            graph.Name = String.Format(CultureInfo.InvariantCulture, "{0}.{1}", Name, name);
                            startEntry = new GraphEntry(filter, clientAdapter, serverAdapter,
                                graph, clients[0].Id, servers[0].Id, ProxyNetworkService.GetLayerBinding(Graph));
                            startEntry.GetInputAdapter(_direction).Enqueue(frame);

                            _graphEntries[name] = startEntry;
                        }
                        else
                        {
                            throw new ArgumentException(CANAPE.Net.Properties.Resources.LayerSectionNode_InvalidGraph);
                        }
                    }
                }
            }

            // Ensure this is done outside the lock
            if (startEntry != null)
            {
                startEntry.NegotiationThread = new Thread(() =>
                {
                    try
                    {
                        startEntry.Start();
                    }
                    catch (Exception ex)
                    {
                        Graph.Logger.LogException(ex);
                        lock (_graphEntries)
                        {
                            _graphEntries.Remove(name);
                            startEntry.Dispose();
                        }
                    }
                }
                );
                startEntry.NegotiationThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;
                startEntry.NegotiationThread.IsBackground = true;
                startEntry.NegotiationThread.Start();
            }
        }