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 this.wavePropagator = new WavePropagator( patternModel, patternTopology, options.BackTrackDepth, waveConstraints, options.RandomDouble ?? (options.Random == null ? (Func <double>)null : options.Random.NextDouble), waveFrequencySets, clear: false); #pragma warning restore CS0618 // Type or member is obsolete wavePropagator.Clear(); }
public void TestChessboard() { 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 Topology(width, height, true); var propagator = new WavePropagator(model, topology); 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 Topology(width + 1, height + 1, true); propagator = new WavePropagator(model, topology); status = propagator.Run(); Assert.AreEqual(Resolution.Contradiction, status); }
public SelectedTracker(TilePropagator tilePropagator, WavePropagator wavePropagator, TileModelMapping tileModelMapping, TilePropagatorTileSet tileSet) { this.tilePropagator = tilePropagator; this.wavePropagator = wavePropagator; this.tileModelMapping = tileModelMapping; this.tileSet = tileSet; patternCounts = new int[tilePropagator.Topology.IndexCount]; }
public void Init(WavePropagator wavePropagator) { wave = wavePropagator.Wave; this.mask = wavePropagator.Topology.Mask; this.indices = wave.Indicies; }
public void TestBacktracking() { // 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 wavePropagator = new WavePropagator(model, topology, 10, randomDouble: r.NextDouble); var status = wavePropagator.Run(); Assert.AreEqual(Resolution.Decided, status); Console.WriteLine($"Backtrack Count {wavePropagator.BacktrackCount}"); }
internal SelectedChangeTracker(TilePropagator tilePropagator, WavePropagator wavePropagator, TileModelMapping tileModelMapping, TilePropagatorTileSet tileSet, IQuadstateChanged onChange) { this.tilePropagator = tilePropagator; this.wavePropagator = wavePropagator; this.tileModelMapping = tileModelMapping; this.tileSet = tileSet; this.onChange = onChange; patternCounts = new int[tilePropagator.Topology.IndexCount]; values = new Quadstate[tilePropagator.Topology.IndexCount]; }
public void Init(WavePropagator wavePropagator) { mask = wavePropagator.Topology.Mask; wave = wavePropagator.Wave; indices = wave.Indicies; entropyValues = new EntropyValues[indices]; Reset(); wavePropagator.AddTracker(this); }
public void Check(WavePropagator wavePropagator) { foreach (var i in Enumerable.Range(0, wavePropagator.Wave.Indicies)) { if (wavePropagator.Wave.Get(i, 1) == false) { wavePropagator.SetContradiction(); } } }
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); }
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 }
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); }
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(); }
public void Init(WavePropagator wavePropagator) { filteredIndexPicker.Init(wavePropagator); // TODO: It's a pity this isn't shared with the path constraint edgedPathView = (EdgedPathView)edgedPathSpec.MakeView(propagator); }
/// <summary> /// Constructs a TilePropagator. /// </summary> /// <param name="tileModel">The model to guide the generation.</param> /// <param name="topology">The dimensions of the output to generate</param> /// <param name="backtrack">If true, store additional information to allow rolling back choices that lead to a contradiction.</param> /// <param name="constraints">Extra constraints to control the generation process.</param> /// <param name="random">Source of randomness</param> public TilePropagator(TileModel tileModel, Topology topology, bool backtrack = false, ITileConstraint[] constraints = null, Random random = null) { this.tileModel = tileModel; this.topology = topology; var overlapping = tileModel as OverlappingModel; Topology patternTopology; if (!(topology.PeriodicX && topology.PeriodicY && topology.PeriodicZ) && overlapping != null) { // Shrink the topology as patterns can cover multiple tiles. patternTopology = topology.WithSize( topology.PeriodicX ? topology.Width : topology.Width - overlapping.NX + 1, topology.PeriodicY ? topology.Height : topology.Height - overlapping.NY + 1, topology.PeriodicZ ? topology.Depth : topology.Depth - overlapping.NZ + 1); mappingType = MappingType.Overlapping; mappingNX = overlapping.NX; mappingNY = overlapping.NY; mappingNZ = overlapping.NZ; // Compute tilesToPatterns and patternsToTiles var patternArrays = overlapping.PatternArrays; tilesToPatternsByOffset = new Dictionary <int, IReadOnlyDictionary <Tile, ISet <int> > >(); patternsToTilesByOffset = new Dictionary <int, IReadOnlyDictionary <int, Tile> >(); for (int ox = 0; ox < overlapping.NX; ox++) { for (int oy = 0; oy < overlapping.NY; oy++) { for (int oz = 0; oz < overlapping.NZ; oz++) { var o = CombineOffsets(ox, oy, oz); var tilesToPatterns = new Dictionary <Tile, ISet <int> >(); tilesToPatternsByOffset[o] = tilesToPatterns; var patternsToTiles = new Dictionary <int, Tile>(); patternsToTilesByOffset[o] = patternsToTiles; for (var pattern = 0; pattern < patternArrays.Count; pattern++) { var patternArray = patternArrays[pattern]; var tile = patternArray.Values[ox, oy, oz]; patternsToTiles[pattern] = tile; if (!tilesToPatterns.TryGetValue(tile, out var patternSet)) { patternSet = tilesToPatterns[tile] = new HashSet <int>(); } patternSet.Add(pattern); } } } } } else { patternTopology = topology; mappingType = MappingType.OneToOne; tilesToPatternsByOffset = new Dictionary <int, IReadOnlyDictionary <Tile, ISet <int> > >() { { 0, tileModel.TilesToPatterns.ToDictionary(g => g.Key, g => (ISet <int>) new HashSet <int>(g)) } }; patternsToTilesByOffset = new Dictionary <int, IReadOnlyDictionary <int, Tile> > { { 0, tileModel.PatternsToTiles }, }; } // Masks interact a bit weirdly with the overlapping model // We choose a pattern mask that is a expansion of the topology mask // i.e. a pattern location is masked out if all the tile locations it covers is masked out. // This makes the propagator a bit conservative - it'll always preserve the overlapping property // but might ban some layouts that make sense. // The alternative is to contract the mask - that is more permissive, but sometimes will // violate the overlapping property. // (passing the mask verbatim is unacceptable as does not lead to symmetric behaviour) // See TestTileMaskWithThinOverlapping for an example of the problem, and // https://github.com/BorisTheBrave/DeBroglie/issues/7 for a possible solution. if (topology.Mask != null && overlapping != null) { // TODO: This could probably do with some cleanup bool GetTopologyMask(int x, int y, int z) { if (!topology.PeriodicX && x >= topology.Width) { return(false); } if (!topology.PeriodicY && y >= topology.Height) { return(false); } if (!topology.PeriodicZ && z >= topology.Depth) { return(false); } x = x % topology.Width; y = y % topology.Height; z = z % topology.Depth; return(topology.Mask[topology.GetIndex(x, y, z)]); } bool GetPatternTopologyMask(Point p) { for (var oz = 0; oz < overlapping.NZ; oz++) { for (var oy = 0; oy < overlapping.NY; oy++) { for (var ox = 0; ox < overlapping.NX; ox++) { if (GetTopologyMask(p.X + ox, p.Y + oy, p.Z + oz)) { return(true); } } } } return(false); } var patternMask = TopoArray.Create(GetPatternTopologyMask, patternTopology); patternTopology = patternTopology.WithMask(patternMask); } var waveConstraints = (constraints?.Select(x => new TileConstraintAdaptor(x, this)).ToArray() ?? Enumerable.Empty <IWaveConstraint>()) .ToArray(); this.wavePropagator = new WavePropagator(tileModel.GetPatternModel(), patternTopology, backtrack, waveConstraints, random, clear: false); wavePropagator.Clear(); }
/// <summary> /// Constructs a TilePropagator. /// </summary> /// <param name="tileModel">The model to guide the generation.</param> /// <param name="topology">The dimensions of the output to generate</param> /// <param name="backtrack">If true, store additional information to allow rolling back choices that lead to a contradiction.</param> /// <param name="constraints">Extra constraints to control the generation process.</param> /// <param name="random">Source of randomness</param> public TilePropagator(TileModel tileModel, Topology topology, bool backtrack = false, ITileConstraint[] constraints = null, Random random = null) { this.tileModel = tileModel; this.topology = topology; var patternTopology = topology; if (!(topology.PeriodicX && topology.PeriodicY && topology.PeriodicZ) && tileModel is OverlappingModel overlapping) { // Shrink the topology as patterns can cover multiple tiles. patternTopology = topology.WithSize( topology.PeriodicX ? topology.Width : topology.Width - overlapping.NX + 1, topology.PeriodicY ? topology.Height : topology.Height - overlapping.NY + 1, topology.PeriodicZ ? topology.Depth : topology.Depth - overlapping.NZ + 1); mappingType = MappingType.Overlapping; mappingNX = overlapping.NX; mappingNY = overlapping.NY; mappingNZ = overlapping.NZ; // Compute tilesToPatterns and patternsToTiles var patternArrays = overlapping.PatternArrays; tilesToPatternsByOffset = new Dictionary <int, IReadOnlyDictionary <Tile, ISet <int> > >(); patternsToTilesByOffset = new Dictionary <int, IReadOnlyDictionary <int, Tile> >(); for (int ox = 0; ox < overlapping.NX; ox++) { for (int oy = 0; oy < overlapping.NY; oy++) { for (int oz = 0; oz < overlapping.NZ; oz++) { var o = CombineOffsets(ox, oy, oz); var tilesToPatterns = new Dictionary <Tile, ISet <int> >(); tilesToPatternsByOffset[o] = tilesToPatterns; var patternsToTiles = new Dictionary <int, Tile>(); patternsToTilesByOffset[o] = patternsToTiles; for (var pattern = 0; pattern < patternArrays.Count; pattern++) { var patternArray = patternArrays[pattern]; var tile = patternArray.Values[ox, oy, oz]; patternsToTiles[pattern] = tile; if (!tilesToPatterns.TryGetValue(tile, out var patternSet)) { patternSet = tilesToPatterns[tile] = new HashSet <int>(); } patternSet.Add(pattern); } } } } } else { mappingType = MappingType.OneToOne; tilesToPatternsByOffset = new Dictionary <int, IReadOnlyDictionary <Tile, ISet <int> > >() { { 0, tileModel.TilesToPatterns.ToDictionary(g => g.Key, g => (ISet <int>) new HashSet <int>(g)) } }; patternsToTilesByOffset = new Dictionary <int, IReadOnlyDictionary <int, Tile> > { { 0, tileModel.PatternsToTiles }, }; } var waveConstraints = (constraints?.Select(x => new TileConstraintAdaptor(x, this)).ToArray() ?? Enumerable.Empty <IWaveConstraint>()) .ToArray(); this.wavePropagator = new WavePropagator(tileModel.GetPatternModel(), patternTopology, backtrack, waveConstraints, random, clear: false); wavePropagator.Clear(); }
public void Init(WavePropagator wavePropagator) { this.wave = wavePropagator.Wave; this.patternCount = wavePropagator.PatternCount; }
public Resolution Init(WavePropagator wavePropagator) { return(underlying.Init(propagator)); }
public Resolution Check(WavePropagator wp) { var wave = wp.Wave; var indices = wp.Indices; // Initialize couldBePath and mustBePath based on wave possibilities var couldBePath = new bool[indices]; var mustBePath = new bool[indices]; for (int i = 0; i < indices; i++) { var couldBe = false; var mustBe = true; for (int p = 0; p < wp.PatternCount; p++) { if (wave.Get(i, p)) { if (PathPatterns.Contains(p)) { couldBe = true; } if (!PathPatterns.Contains(p)) { mustBe = false; } } } couldBePath[i] = couldBe; mustBePath[i] = mustBe; } // Select relevant cells, i.e. those that must be connected. bool[] relevant; if (EndPoints == null) { relevant = mustBePath; } else { relevant = new bool[indices]; if (EndPoints.Length == 0) { return(Resolution.Undecided); } foreach (var endPoint in EndPoints) { var index = wp.Topology.GetIndex(endPoint.X, endPoint.Y, endPoint.Z); relevant[index] = true; } } var walkable = couldBePath; var isArticulation = PathConstraintUtils.GetArticulationPoints(wp.Topology, walkable, relevant); if (isArticulation == null) { return(Resolution.Contradiction); } // All articulation points must be paths, // So ban any other possibilities for (var i = 0; i < indices; i++) { if (!isArticulation[i]) { continue; } for (int p = 0; p < wp.PatternCount; p++) { if (!PathPatterns.Contains(p) && wave.Get(i, p)) { wp.InternalBan(i, p); } } } return(Resolution.Undecided); }
public void Init(WavePropagator wavePropagator) { filteredIndexPicker.Init(wavePropagator); wavePropagator.AddTracker(this); }
private IPickHeuristic MakePickHeuristic(WavePropagator wavePropagator, TilePropagatorOptions options) { var waveFrequencySets = options.Weights == null ? null : GetFrequencySets(options.Weights, tileModelMapping); var randomDouble = wavePropagator.RandomDouble; var patternTopology = wavePropagator.Topology; var pathConstraint = options.Constraints?.OfType <EdgedPathConstraint>().FirstOrDefault(); var pathPickHeuristic = pathConstraint != null && pathConstraint.UsePickHeuristic; var connectedConstraint = options.Constraints?.OfType <ConnectedConstraint>().FirstOrDefault(); var connectedPickHeuristic = connectedConstraint != null && connectedConstraint.UsePickHeuristic; // Use the appropriate random picker // Generally this is HeapEntropyTracker, but it doesn't support some features // so there's a few slower implementations for that 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 if (pathPickHeuristic || connectedPickHeuristic) { var entropyTracker = new EntropyTracker(wavePropagator.Wave, wavePropagator.Frequencies, patternTopology.Mask); entropyTracker.Reset(); wavePropagator.AddTracker(entropyTracker); randomPicker = entropyTracker; } else { var entropyTracker = new HeapEntropyTracker(wavePropagator.Wave, wavePropagator.Frequencies, patternTopology.Mask, randomDouble); entropyTracker.Reset(); wavePropagator.AddTracker(entropyTracker); randomPicker = entropyTracker; } IPickHeuristic heuristic = new RandomPickerHeuristic(randomPicker, randomDouble); if (pathPickHeuristic) { heuristic = pathConstraint.GetHeuristic( randomPicker, randomDouble, this, tileModelMapping, heuristic); } if (connectedPickHeuristic) { heuristic = connectedConstraint.GetHeuristic( randomPicker, randomDouble, this, tileModelMapping, heuristic); } return(heuristic); }
// Don't run init twice void IPatternPicker.Init(WavePropagator wavePropagator) { }
public void Init(WavePropagator wavePropagator) { underlying.Init(propagator); }
public void Check(WavePropagator wavePropagator) { underlying.Check(propagator); }
public void Init(WavePropagator wavePropagator) { wavePropagator.AddChoiceObserver(this); futureChoices = new Deque <int>(); prevChoices = new Deque <int>(); }
public void Init(WavePropagator wavePropagator) { wave = wavePropagator.Wave; frequencies = wavePropagator.Frequencies; }
public void Init(WavePropagator wavePropagator) { Init(wavePropagator.Wave, wavePropagator.Frequencies, wavePropagator.Topology.Mask); wavePropagator.AddTracker(this); }
public Resolution Init(WavePropagator wp) { return(Check(wp)); }
public void Init(WavePropagator wavePropagator) { this.wave = wavePropagator.Wave; }
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(); }
public Resolution Check(WavePropagator wavePropagator) { return(underlying.Check(propagator)); }