コード例 #1
0
        public void TestChessboard(ModelConstraintAlgorithm algorithm)
        {
            var model = new PatternModel
            {
                Frequencies = new double[] { 1, 1 },
                Propagator  = new int[][][]
                {
                    new int[][] { new int[] { 1 }, new int[] { 1 }, new int[] { 1 }, new int[] { 1 }, },
                    new int[][] { new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, },
                }
            };
            var width    = 10;
            var height   = 10;
            var topology = new GridTopology(width, height, true);
            var options  = new WavePropagatorOptions {
                ModelConstraintAlgorithm = algorithm
            };
            var propagator = new WavePropagator(model, topology, options);
            var status     = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);
            var a       = propagator.ToTopoArray().ToArray2d();
            var topLeft = a[0, 0];

            for (var x = 0; x < width; x++)
            {
                for (var y = 0; y < height; y++)
                {
                    Assert.IsTrue((a[x, y] == topLeft) ^ (x % 2 == 0) ^ (y % 2 == 0));
                }
            }

            // Should be impossible with an odd sized region
            topology   = new GridTopology(width + 1, height + 1, true);
            propagator = new WavePropagator(model, topology, options);
            status     = propagator.Run();
            Assert.AreEqual(Resolution.Contradiction, status);

            // Should be possible with an odd sized region, if we have the right mask
            var mask = new bool[(width + 1) * (height + 1)];

            for (var x = 0; x < width; x++)
            {
                for (var y = 0; y < height; y++)
                {
                    mask[x + y * (width + 1)] = true;
                }
            }
            topology   = new GridTopology(width + 1, height + 1, true).WithMask(mask);
            propagator = new WavePropagator(model, topology, options);
            status     = propagator.Run();
            Assert.AreEqual(Resolution.Decided, status);
        }
コード例 #2
0
        public void TestMemoizeIndices()
        {
            var model = new PatternModel
            {
                Frequencies = new double[] { 1, 1 },
                // Free model
                Propagator = new int[][][]
                {
                    new int[][] { new int[] { 0, 1 }, new int[] { 0, 1 }, new int[] { 0, 1 }, new int[] { 0, 1 }, },
                    new int[][] { new int[] { 0, 1 }, new int[] { 0, 1 }, new int[] { 0, 1 }, new int[] { 0, 1 }, },
                }
            };
            var width           = 10;
            var height          = 10;
            var topology        = new GridTopology(width, height, true);
            var indexPicker     = new CustomIndexPicker();
            var memoIndexPicker = new MemoizeIndexPicker(indexPicker);
            var options         = new WavePropagatorOptions {
                BacktrackPolicy = new ConstantBacktrackPolicy(1),
                IndexPicker     = memoIndexPicker,
                PatternPicker   = new SimpleOrderedPatternPicker(),
                Constraints     = new[] { new  DontBanOneConstraint() },
            };
            var propagator = new WavePropagator(model, topology, options);

            // Attempts to pick pattern 0 at index 0, should contradict and backtrack
            var status = propagator.Step();

            Assert.AreEqual(Resolution.Undecided, status);
            Assert.AreEqual(1, propagator.BacktrackCount);
            CollectionAssert.AreEqual(propagator.GetPossiblePatterns(0), new[] { 1 });
            Assert.AreEqual(1, indexPicker.Count);
            // Should re-attempt index zero, with no effect.
            propagator.Step();
            Assert.AreEqual(Resolution.Undecided, status);
            Assert.AreEqual(1, propagator.BacktrackCount);
            CollectionAssert.AreEqual(propagator.GetPossiblePatterns(0), new[] { 1 });
            Assert.AreEqual(1, indexPicker.Count);
            // Attempts to pick pattern 0 at index 1, should contradict and backtrack
            propagator.Step();
            Assert.AreEqual(Resolution.Undecided, status);
            Assert.AreEqual(2, propagator.BacktrackCount);
            CollectionAssert.AreEqual(propagator.GetPossiblePatterns(1), new[] { 1 });
            Assert.AreEqual(2, indexPicker.Count);
            // etc
        }
コード例 #3
0
        public void TestChessboard3d(ModelConstraintAlgorithm algorithm)
        {
            var model = new PatternModel
            {
                Frequencies = new double[] { 1, 1 },
                Propagator  = new int[][][]
                {
                    new int[][] { new int[] { 1 }, new int[] { 1 }, new int[] { 1 }, new int[] { 1 }, new int[] { 1 }, new int[] { 1 }, },
                    new int[][] { new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, },
                }
            };
            var width    = 4;
            var height   = 4;
            var depth    = 4;
            var topology = new GridTopology(width, height, depth, true);
            var options  = new WavePropagatorOptions {
                ModelConstraintAlgorithm = algorithm
            };
            var propagator = new WavePropagator(model, topology, options);
            var status     = propagator.Run();

            Assert.AreEqual(Resolution.Decided, status);
            var a       = propagator.ToTopoArray();
            var topLeft = a.Get(0, 0, 0);

            for (var x = 0; x < width; x++)
            {
                for (var y = 0; y < height; y++)
                {
                    for (var z = 0; z < depth; z++)
                    {
                        Assert.IsFalse((a.Get(x, y, z) == topLeft) ^ (x % 2 == 0) ^ (y % 2 == 0) ^ (z % 2 == 0));
                    }
                }
            }

            // Should be impossible with an odd sized region
            topology   = new GridTopology(width + 1, height + 1, depth + 1, true);
            propagator = new WavePropagator(model, topology, options);
            status     = propagator.Run();
            Assert.AreEqual(Resolution.Contradiction, status);
        }
コード例 #4
0
        public TilePropagator(TileModel tileModel, ITopology topology, TilePropagatorOptions options)
        {
            this.tileModel = tileModel;
            this.topology  = topology;

            var overlapping = tileModel as OverlappingModel;

            tileModelMapping = tileModel.GetTileModelMapping(topology);
            var patternTopology = tileModelMapping.PatternTopology;
            var patternModel    = tileModelMapping.PatternModel;

            var waveConstraints =
                (options.Constraints?.Select(x => new TileConstraintAdaptor(x, this)).ToArray() ?? Enumerable.Empty <IWaveConstraint>())
                .ToArray();


#pragma warning disable CS0618 // Type or member is obsolete
            var randomDouble = options.RandomDouble ?? (options.Random ?? new Random()).NextDouble;
#pragma warning restore CS0618 // Type or member is obsolete

            var(indexPicker, patternPicker) = MakePickers(options);

            var wavePropagatorOptions = new WavePropagatorOptions
            {
                BacktrackPolicy          = MakeBacktrackPolicy(options),
                MaxBacktrackDepth        = options.MaxBacktrackDepth,
                RandomDouble             = randomDouble,
                Constraints              = waveConstraints,
                IndexPicker              = indexPicker,
                PatternPicker            = patternPicker,
                Clear                    = false,
                ModelConstraintAlgorithm = options.ModelConstraintAlgorithm,
            };

            this.wavePropagator = new WavePropagator(
                patternModel,
                patternTopology,
                wavePropagatorOptions);
            wavePropagator.Clear();
        }
コード例 #5
0
        public TilePropagator(TileModel tileModel, ITopology topology, TilePropagatorOptions options)
        {
            this.tileModel = tileModel;
            this.topology  = topology;

            var overlapping = tileModel as OverlappingModel;

            tileModelMapping = tileModel.GetTileModelMapping(topology);
            var patternTopology = tileModelMapping.PatternTopology;
            var patternModel    = tileModelMapping.PatternModel;

            var waveConstraints =
                (options.Constraints?.Select(x => new TileConstraintAdaptor(x, this)).ToArray() ?? Enumerable.Empty <IWaveConstraint>())
                .ToArray();

            var waveFrequencySets = options.Weights == null ? null : GetFrequencySets(options.Weights, tileModelMapping);

#pragma warning disable CS0618 // Type or member is obsolete
            var randomDouble = options.RandomDouble ?? (options.Random ?? new Random()).NextDouble;
#pragma warning restore CS0618 // Type or member is obsolete

            IPickHeuristic MakePickHeuristic(WavePropagator wavePropagator)
            {
                IRandomPicker randomPicker;

                if (options.PickHeuristicType == PickHeuristicType.Ordered)
                {
                    randomPicker = new OrderedRandomPicker(wavePropagator.Wave, wavePropagator.Frequencies, patternTopology.Mask);
                }
                else if (waveFrequencySets != null)
                {
                    var entropyTracker = new ArrayPriorityEntropyTracker(wavePropagator.Wave, waveFrequencySets, patternTopology.Mask);
                    entropyTracker.Reset();
                    wavePropagator.AddTracker(entropyTracker);
                    randomPicker = entropyTracker;
                }
                else
                {
                    var entropyTracker = new EntropyTracker(wavePropagator.Wave, wavePropagator.Frequencies, patternTopology.Mask);
                    entropyTracker.Reset();
                    wavePropagator.AddTracker(entropyTracker);
                    randomPicker = entropyTracker;
                }
                IPickHeuristic heuristic = new RandomPickerHeuristic(randomPicker, randomDouble);

                var pathConstraint = options.Constraints?.OfType <EdgedPathConstraint>().FirstOrDefault();

                if (pathConstraint != null && pathConstraint.UsePickHeuristic)
                {
                    heuristic = pathConstraint.GetHeuristic(
                        randomPicker,
                        randomDouble,
                        this,
                        tileModelMapping,
                        heuristic);
                }

                var connectedConstraint = options.Constraints?.OfType <ConnectedConstraint>().FirstOrDefault();

                if (connectedConstraint != null && connectedConstraint.UsePickHeuristic)
                {
                    heuristic = connectedConstraint.GetHeuristic(
                        randomPicker,
                        randomDouble,
                        this,
                        tileModelMapping,
                        heuristic);
                }

                return(heuristic);
            }

            var wavePropagatorOptions = new WavePropagatorOptions
            {
                BackTrackDepth       = options.BackTrackDepth,
                RandomDouble         = randomDouble,
                Constraints          = waveConstraints,
                PickHeuristicFactory = MakePickHeuristic,
                Clear = false,
                ModelConstraintAlgorithm = options.ModelConstraintAlgorithm,
            };

            this.wavePropagator = new WavePropagator(
                patternModel,
                patternTopology,
                wavePropagatorOptions);
            wavePropagator.Clear();
        }
コード例 #6
0
        public void TestBacktracking(ModelConstraintAlgorithm algorithm)
        {
            // Reproduces the wang tiles found at
            // https://en.wikipedia.org/wiki/Wang_tile
            // They only have aperiodic tiling, so they are a hard set to put down.
            // Clockwise from top
            var tileBorders = new[]
            {
                "rrrg",
                "brbg",
                "rggg",
                "wbrb",
                "bbwb",
                "wwrw",
                "rgbw",
                "bwbr",
                "brwr",
                "ggbr",
                "rwrg",
            };
            var propagator = tileBorders.Select(tile1 =>

                                                tile1.Select((c, i) =>
            {
                var d = new[] { 3, 0, 2, 1 }[i];
                var o = (i + 2) % 4;
                return(Tuple.Create(d, tileBorders
                                    .Select((tile2, i2) => Tuple.Create(tile2, i2))
                                    .Where(t => t.Item1[o] == c)
                                    .Select(t => t.Item2)
                                    .ToArray()));
            })
                                                .OrderBy(x => x.Item1)
                                                .Select(x => x.Item2)
                                                .ToArray()
                                                ).ToArray();

            var model = new PatternModel
            {
                Frequencies = tileBorders.Select(x => 1.0).ToArray(),
                Propagator  = propagator,
            };
            var topology = new GridTopology(10, 10, false);

            var seed = Environment.TickCount;
            var r    = new Random(seed);

            Console.WriteLine("Seed {0}", seed);

            var options = new WavePropagatorOptions
            {
                BackTrackDepth           = -1,
                RandomDouble             = r.NextDouble,
                ModelConstraintAlgorithm = algorithm,
            };
            var wavePropagator = new WavePropagator(model, topology, options);

            var status = wavePropagator.Run();

            Assert.AreEqual(Resolution.Decided, status);

            Console.WriteLine($"Backtrack Count {wavePropagator.BacktrackCount}");
        }