private void SetupGenerator()
        {
            var mapping       = mapDescription.GetMapping();
            var chainsGeneric = configuration.Chains;

            // Create chain decomposition
            if (chainsGeneric == null)
            {
                var chainDecomposition = new TwoStageChainDecomposition <TNode>(mapDescriptionOriginal, new BreadthFirstChainDecomposition <TNode>(configuration.ChainDecompositionConfiguration ?? new ChainDecompositionConfiguration()));
                chainsGeneric = chainDecomposition.GetChains(mapDescriptionOriginal.GetGraph());
            }

            var chains = chainsGeneric
                         .Select(x => new Chain <int>(x.Nodes.Select(y => mapping[y]).ToList(), x.Number)
            {
                IsFromFace = x.IsFromFace
            })
                         .ToList();

            // Create generator planner
            var generatorPlanner = new GeneratorPlanner <Layout <Configuration <CorridorsData> >, int>(configuration.SimulatedAnnealingMaxBranching);

            // Create configuration spaces
            var configurationSpacesGenerator = new ConfigurationSpacesGenerator(
                new PolygonOverlap(),
                DoorHandler.DefaultHandler,
                new OrthogonalLineIntersection(),
                new GridPolygonUtils());

            var configurationSpaces         = configurationSpacesGenerator.GetConfigurationSpaces <Configuration <CorridorsData> >(mapDescription);
            var corridorConfigurationSpaces = configurationSpaces;

            var averageSize    = configurationSpaces.GetAverageSize();
            var polygonOverlap = new FastPolygonOverlap();

            // Create generator constraints
            var stageOneConstraints =
                new List <INodeConstraint <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>,
                                           CorridorsData> >
            {
                new BasicConstraint <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>,
                                     CorridorsData, IntAlias <PolygonGrid2D> >(
                    new FastPolygonOverlap(),
                    averageSize,
                    configurationSpaces
                    ),
                new CorridorConstraints <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, CorridorsData, IntAlias <PolygonGrid2D> >(
                    mapDescription,
                    averageSize,
                    corridorConfigurationSpaces
                    ),
            };

            if (!configuration.RoomsCanTouch)
            {
                stageOneConstraints.Add(new TouchingConstraints <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, CorridorsData, IntAlias <PolygonGrid2D> >(
                                            mapDescription,
                                            polygonOverlap
                                            ));
            }

            var stageOneConstraintsEvaluator = new ConstraintsEvaluator <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, IntAlias <PolygonGrid2D>, CorridorsData>(stageOneConstraints);

            var roomShapesHandler = new RoomShapesHandler <int, Configuration <CorridorsData> >(
                configurationSpaces,
                configurationSpaces.GetIntAliasMapping(),
                mapDescription,
                configuration.RepeatModeOverride
                );

            // Create layout operations
            var layoutOperations = new LayoutOperations <Layout <Configuration <CorridorsData> >, int, Configuration <CorridorsData>, IntAlias <PolygonGrid2D>, CorridorsData>(corridorConfigurationSpaces, configurationSpaces.GetAverageSize(), mapDescription, stageOneConstraintsEvaluator, stageOneConstraintsEvaluator, roomShapesHandler, configuration.ThrowIfRepeatModeNotSatisfied);

            var initialLayout   = new Layout <Configuration <CorridorsData> >(mapDescription.GetGraph());
            var layoutConverter =
                new BasicLayoutConverter <Layout <Configuration <CorridorsData> >, TNode,
                                          Configuration <CorridorsData> >(mapDescription, configurationSpaces,
                                                                          configurationSpaces.GetIntAliasMapping());

            // Create simulated annealing evolver
            var layoutEvolver =
                new SimulatedAnnealingEvolver <Layout <Configuration <CorridorsData> >, int,
                                               Configuration <CorridorsData> >(layoutOperations, configuration.SimulatedAnnealingConfiguration, true);

            // Create the generator itself
            generator = new ChainBasedGenerator <Layout <Configuration <CorridorsData> >, MapLayout <TNode>, int>(initialLayout, generatorPlanner, chains, layoutEvolver, layoutConverter);

            // Register event handlers
            generator.OnRandomInjected += (random) =>
            {
                ((IRandomInjectable)configurationSpaces).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutOperations).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutEvolver).InjectRandomGenerator(random);
                ((IRandomInjectable)layoutConverter).InjectRandomGenerator(random);
            };

            generator.OnCancellationTokenInjected += (token) =>
            {
                ((ICancellable)generatorPlanner).SetCancellationToken(token);
                ((ICancellable)layoutEvolver).SetCancellationToken(token);
            };

            layoutEvolver.OnEvent              += (sender, args) => OnSimulatedAnnealingEvent?.Invoke(sender, args);
            layoutEvolver.OnPerturbed          += (sender, layout) => OnPerturbed?.Invoke(layoutConverter.Convert(layout, false));
            layoutEvolver.OnPerturbed          += (sender, layout) => OnPerturbedInternal?.Invoke(layout);
            layoutEvolver.OnValid              += (sender, layout) => OnPartialValid?.Invoke(layoutConverter.Convert(layout, true));
            generatorPlanner.OnLayoutGenerated += layout => OnValid?.Invoke(layoutConverter.Convert(layout, true));
        }
        /// <summary>
        /// Benchmark our speed improvements.
        /// </summary>
        public static void CompareOldAndNew()
        {
            //var mapDescriptions = GetMapDescriptionsSet(new IntVector2(1, 1), false);
            var mapDescriptions = GetMapDescriptionsForThesis(false);

            var layoutGenerator = LayoutGeneratorFactory.GetDefaultChainBasedGenerator <int>();
            var benchmark       = Benchmark.CreateFor(layoutGenerator);

            layoutGenerator.InjectRandomGenerator(new Random(0));
            layoutGenerator.SetLayoutValidityCheck(false);

            var scenario = BenchmarkScenario.CreateScenarioFor(layoutGenerator);

            scenario.SetRunsCount(1);

            // Measure the difference between old and new approaches
            {
                var setups = scenario.MakeSetupsGroup();

                setups.AddSetup("Old", (generator) =>
                {
                    //generator.SetChainDecompositionCreator(mapDescription => new OriginalChainDecomposition());
                    generator.SetChainDecompositionCreator(mapDescription => new OldChainDecomposition <int>(new GraphDecomposer <int>()));
                    //generator.SetGeneratorPlannerCreator(mapDescription => new SlowGeneratorPlanner<Layout<Configuration<EnergyData>, BasicEnergyData>>());
                    //generator.SetLayoutEvolverCreator((mapDescription, layoutOperations) =>
                    //{
                    //	var evolver =
                    //		new SimulatedAnnealingEvolver<Layout<Configuration<EnergyData>, BasicEnergyData>, int,
                    //			Configuration<EnergyData>>(layoutOperations);
                    //	evolver.Configure(50, 500);
                    //	evolver.SetRandomRestarts(true, SimulatedAnnealingEvolver<Layout<Configuration<EnergyData>, BasicEnergyData>, int, Configuration<EnergyData>>.RestartSuccessPlace.OnAccepted, false, 0.5f);

                    //	return evolver;
                    //});

                    generator.SetGeneratorPlannerCreator(mapDescription => new BasicGeneratorPlanner <Layout <Configuration <EnergyData>, BasicEnergyData> >());
                    generator.SetLayoutEvolverCreator((mapDescription, layoutOperations) =>
                    {
                        var evolver =
                            new SimulatedAnnealingEvolver <Layout <Configuration <EnergyData>, BasicEnergyData>, int,
                                                           Configuration <EnergyData> >(layoutOperations);

                        return(evolver);
                    });

                    generator.InjectRandomGenerator(new Random(0));
                });
                setups.AddSetup("New", (generator) =>
                {
                    generator.SetChainDecompositionCreator(mapDescription =>
                                                           new BreadthFirstChainDecomposition <int>(new GraphDecomposer <int>()));
                    generator.SetGeneratorPlannerCreator(mapDescription => new BasicGeneratorPlanner <Layout <Configuration <EnergyData>, BasicEnergyData> >());
                    generator.SetLayoutEvolverCreator((mapDescription, layoutOperations) =>
                    {
                        var evolver =
                            new SimulatedAnnealingEvolver <Layout <Configuration <EnergyData>, BasicEnergyData>, int,
                                                           Configuration <EnergyData> >(layoutOperations);

                        return(evolver);
                    });

                    generator.InjectRandomGenerator(new Random(0));
                });
            }

            Benchmark.WithDefaultFiles((sw, dw) =>
            {
                benchmark.Execute(layoutGenerator, scenario, mapDescriptions, 80, 1, sw, dw);
            });
        }