/// <summary> /// Generates a layout. /// </summary> /// <returns></returns> public TOutputLayout GenerateLayout() { IterationsCount = 0; layoutEvolver.OnPerturbed += IterationsCounterHandler; OnRandomInjected?.Invoke(Random); if (CancellationToken.HasValue) { OnCancellationTokenInjected?.Invoke(CancellationToken.Value); } var stopwatch = new Stopwatch(); stopwatch.Start(); var layout = generatorPlanner.Generate(initialLayout, chains, layoutEvolver); stopwatch.Stop(); layoutEvolver.OnPerturbed -= IterationsCounterHandler; LayoutsCount = 1; TimeTotal = stopwatch.ElapsedMilliseconds; // Reset cancellation token if it was already used if (CancellationToken.HasValue && CancellationToken.Value.IsCancellationRequested) { CancellationToken = null; } var convertedLayout = layout != null?layoutConverter.Convert(layout, true) : default(TOutputLayout); return(convertedLayout); }
public IList <TOutputLayout> GetLayouts(TMapDescription mapDescription, int numberOfLayouts) { var graph = mapDescription.GetGraph(); if (graph.VerticesCount < 2) { throw new ArgumentException("Given mapDescription must contain at least two nodes.", nameof(mapDescription)); } if (!graphUtils.IsConnected(graph)) { throw new ArgumentException("Given mapDescription must represent a connected graph.", nameof(mapDescription)); } if (!graphUtils.IsPlanar(graph)) { throw new ArgumentException("Given mapDescription must represent a planar graph.", nameof(mapDescription)); } // Create instances and inject the random generator and the cancellation token if possible configurationSpaces = configurationSpacesCreator(mapDescription); TryInjectRandomAndCancellationToken(configurationSpaces); chainDecomposition = chainDecompositionCreator(mapDescription); TryInjectRandomAndCancellationToken(chainDecomposition); initialLayout = initialLayoutCreator(mapDescription); TryInjectRandomAndCancellationToken(initialLayout); generatorPlanner = generatorPlannerCreator(mapDescription); TryInjectRandomAndCancellationToken(generatorPlanner); layoutOperations = layoutOperationsCreator(mapDescription, configurationSpaces); TryInjectRandomAndCancellationToken(layoutOperations); layoutConverter = layoutConverterCreator(mapDescription, configurationSpaces); TryInjectRandomAndCancellationToken(layoutConverter); layoutEvolver = layoutEvolverCreator(mapDescription, layoutOperations); TryInjectRandomAndCancellationToken(layoutEvolver); // Restart stopwatch stopwatch.Restart(); chains = chainDecomposition.GetChains(graph); context = new GeneratorContext(); RegisterEventHandlers(); // TODO: handle number of layouts to be evolved - who should control that? generator or planner? // TODO: handle context.. this is ugly var layouts = generatorPlanner.Generate(initialLayout, numberOfLayouts, chains.Count, (layout, chainNumber, numOfLayouts) => layoutEvolver.Evolve(AddChain(layout, chainNumber), chains[chainNumber], numOfLayouts), context); // Stop stopwatch and prepare benchmark info stopwatch.Stop(); timeTotal = stopwatch.ElapsedMilliseconds; layoutsCount = layouts.Count; // Reset cancellation token if it was already used if (CancellationToken.HasValue && CancellationToken.Value.IsCancellationRequested) { CancellationToken = null; } return(layouts.Select(x => layoutConverter.Convert(x, true)).ToList()); }