/// <summary> /// Is called by a background thread to "solve" the algorithm with brute force, so to speak. /// </summary> /// <returns></returns> private AlgorithmResult Solve(CancellationToken token) { // Our solver is quite simple: // We try to "solve" the problem with a maximum number of iterations. // If we happen to stumble upon a result that appears stable, then we // break early. TimeSpan dt = TimeSpan.FromMilliseconds(60); for (int i = 0; i < _maxIterations; ++i) { AlgorithmAction action; if (_pendingActions.TryDequeue(out action)) { Execute(action); } AlgorithmResult previous = _algorithm.Result; _algorithm.Update(dt); if (Converges(previous, _algorithm.Result)) { break; } if (token.IsCancellationRequested) { break; } } return(_algorithm.Result); }
internal void Update(TimeSpan dt) { if (_algorithm != null) { _algorithm.Update(dt); _currentPositions = _algorithm.Result; InvalidateArrange(); } }
void INodeLayoutAlgorithm.Update(TimeSpan elapsed) { if (_solver.IsCompleted) { _currentResult = _solver.Result; } else if (_solver.IsFaulted) { _currentResult = AlgorithmResult.Empty; } }
/// <summary> /// Creates a new solver for the given algorithm. /// </summary> /// <param name="algorithm"></param> public SolvingNodeLayoutAlgorithm(INodeLayoutAlgorithm algorithm) { if (algorithm == null) { throw new ArgumentNullException("algorithm"); } _algorithm = algorithm; _pendingActions = new ConcurrentQueue <AlgorithmAction>(); _maxIterations = 100000; _cancellationTokenSource = new CancellationTokenSource(); _currentResult = AlgorithmResult.Empty; _solver = Task.FromResult(_currentResult); }
private bool Converges(AlgorithmResult previous, AlgorithmResult current) { const double maximumDisplacement = 0.1; const double maximumDisplacementSquared = maximumDisplacement * maximumDisplacement; // I define converging as every node moving within 0.1 units / tick. foreach (var node in previous.Keys) { Point previousPosition = previous[node]; Point currentPosition = current[node]; Vector delta = previousPosition - currentPosition; double squaredLength = delta.LengthSquared; if (squaredLength > maximumDisplacementSquared) { return(false); } } return(false); }
static AlgorithmResult() { Empty = new AlgorithmResult(new Dictionary <INode, Point>()); }