From 879c6370d7cba0db4ddf68dd9c0396d970acf335 Mon Sep 17 00:00:00 2001 From: selfsame Date: Mon, 26 Feb 2018 15:03:12 -0500 Subject: [PATCH 01/12] SimpleTiledModel comp uses a Text Asset for xml instead of file path --- SimpleTiledWFC.cs | 8 ++++---- impl/OverlappingModel.cs | 32 +++++++++++++++++++++++++------- impl/SimpleTiledModel.cs | 2 +- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/SimpleTiledWFC.cs b/SimpleTiledWFC.cs index ea97497..3d71e89 100644 --- a/SimpleTiledWFC.cs +++ b/SimpleTiledWFC.cs @@ -9,7 +9,7 @@ [ExecuteInEditMode] public class SimpleTiledWFC : MonoBehaviour{ - public string xmlpath = null; + public TextAsset xml = null; private string subset = ""; public int gridsize = 1; @@ -76,13 +76,13 @@ public void Generate(){ GameObject go = output.transform.GetChild(i).gameObject; if (Application.isPlaying){Destroy(go);} else {DestroyImmediate(go);} } - group = new GameObject(xmlpath).transform; + group = new GameObject(xml.name).transform; group.parent = output.transform; group.position = output.transform.position; group.rotation = output.transform.rotation; group.localScale = new Vector3(1f, 1f, 1f); rendering = new GameObject[width, depth]; - this.model = new SimpleTiledModel(Application.dataPath+"/"+xmlpath, subset, width, depth, periodic); + this.model = new SimpleTiledModel(xml.text, subset, width, depth, periodic); undrawn = true; } @@ -130,7 +130,7 @@ public void Draw(){ public class TileSetEditor : Editor { public override void OnInspectorGUI () { SimpleTiledWFC me = (SimpleTiledWFC)target; - if (me.xmlpath != null){ + if (me.xml != null){ if(GUILayout.Button("generate")){ me.Generate(); } diff --git a/impl/OverlappingModel.cs b/impl/OverlappingModel.cs index 22571c5..583dd39 100644 --- a/impl/OverlappingModel.cs +++ b/impl/OverlappingModel.cs @@ -222,17 +222,35 @@ public override void Clear() { for (int x = 0; x < FMX; x++) { - for (int t = 0; t < T; t++) if (t != foundation) wave[x][0][t] = false; - changes[x][0] = true; - - for (int y = 2; y < FMY; y++) + for (int y = 0; y < FMY; y++) { - wave[x][y][foundation] = false; - changes[x][y] = true; + if (x == 0 || x == FMX-2 || y == 0 || y == FMX-2) { + for (int t = 0; t < T; t++) if (t != foundation) wave[x][y][t] = false; + changes[x][y] = true; + } + if (x > 1 && x < FMX-2 && y > 1 && y < FMY-2) { + wave[x][y][foundation] = false; + changes[x][y] = true; + } } - while (Propagate()); } + // for (int x = 0; x < FMX; x++) + // { + // for (int t = 0; t < T; t++) if (t != foundation) wave[x][0][t] = false; + // changes[x][0] = true; + + // for (int t = 0; t < T; t++) if (t != foundation) wave[x][FMY-2][t] = false; + // changes[x][FMY-2] = true; + + // for (int y = 2; y < FMY-2; y++) + // { + // wave[x][y][foundation] = false; + // changes[x][y] = true; + // } + + // while (Propagate()); + // } } } } \ No newline at end of file diff --git a/impl/SimpleTiledModel.cs b/impl/SimpleTiledModel.cs index 5612ab6..35b1e5d 100644 --- a/impl/SimpleTiledModel.cs +++ b/impl/SimpleTiledModel.cs @@ -22,7 +22,7 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b this.periodic = periodic; var xdoc = new XmlDocument(); - xdoc.Load(name); + xdoc.LoadXml(name); XmlNode xnode = xdoc.FirstChild; bool unique = xnode.Get("unique", false); xnode = xnode.FirstChild; From 6731aa9d1b2970e146c24a114c6ff5ec17003217 Mon Sep 17 00:00:00 2001 From: selfsame Date: Mon, 26 Feb 2018 15:07:01 -0500 Subject: [PATCH 02/12] revert foundation code mis-commit --- impl/OverlappingModel.cs | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/impl/OverlappingModel.cs b/impl/OverlappingModel.cs index 583dd39..22571c5 100644 --- a/impl/OverlappingModel.cs +++ b/impl/OverlappingModel.cs @@ -222,35 +222,17 @@ public override void Clear() { for (int x = 0; x < FMX; x++) { - for (int y = 0; y < FMY; y++) + for (int t = 0; t < T; t++) if (t != foundation) wave[x][0][t] = false; + changes[x][0] = true; + + for (int y = 2; y < FMY; y++) { - if (x == 0 || x == FMX-2 || y == 0 || y == FMX-2) { - for (int t = 0; t < T; t++) if (t != foundation) wave[x][y][t] = false; - changes[x][y] = true; - } - if (x > 1 && x < FMX-2 && y > 1 && y < FMY-2) { - wave[x][y][foundation] = false; - changes[x][y] = true; - } + wave[x][y][foundation] = false; + changes[x][y] = true; } + while (Propagate()); } - // for (int x = 0; x < FMX; x++) - // { - // for (int t = 0; t < T; t++) if (t != foundation) wave[x][0][t] = false; - // changes[x][0] = true; - - // for (int t = 0; t < T; t++) if (t != foundation) wave[x][FMY-2][t] = false; - // changes[x][FMY-2] = true; - - // for (int y = 2; y < FMY-2; y++) - // { - // wave[x][y][foundation] = false; - // changes[x][y] = true; - // } - - // while (Propagate()); - // } } } } \ No newline at end of file From 703ce002cb946ce9f37e06062a0f4e1c9702be18 Mon Sep 17 00:00:00 2001 From: selfsame Date: Thu, 29 Mar 2018 12:05:47 -0400 Subject: [PATCH 03/12] 2017.3 api breaking changes --- TilePainter.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/TilePainter.cs b/TilePainter.cs index 82dc0e5..910638b 100644 --- a/TilePainter.cs +++ b/TilePainter.cs @@ -285,19 +285,19 @@ public void ProcessEvents(){ Event current = Event.current; bool leftbutton = (current.button == 0); switch(current.type){ - case EventType.keyDown: + case EventType.KeyDown: if (current.keyCode == KeyCode.S) operation = TileOperation.Sampling; if (current.keyCode == KeyCode.X) operation = TileOperation.Erasing; current.Use(); return; - case EventType.keyUp: + case EventType.KeyUp: operation = TileOperation.None; if (current.keyCode == KeyCode.Space) me.Turn(); if (current.keyCode == KeyCode.B) me.CycleColor(); current.Use(); return; - case EventType.mouseDown: + case EventType.MouseDown: if (leftbutton) { if (operation == TileOperation.None){ @@ -309,7 +309,7 @@ public void ProcessEvents(){ return; } break; - case EventType.mouseDrag: + case EventType.MouseDrag: if (leftbutton) { if (operation != TileOperation.None){ @@ -320,7 +320,7 @@ public void ProcessEvents(){ return; } break; - case EventType.mouseUp: + case EventType.MouseUp: if (leftbutton) { operation = TileOperation.None; @@ -328,13 +328,13 @@ public void ProcessEvents(){ return; } break; - case EventType.mouseMove: + case EventType.MouseMove: me.Resize(); current.Use(); break; - case EventType.repaint: + case EventType.Repaint: break; - case EventType.layout: + case EventType.Layout: HandleUtility.AddDefaultControl(controlID); break; } From 1e42b83e5034bb83070adbf95202f3a7ef99a338 Mon Sep 17 00:00:00 2001 From: selfsame Date: Sat, 30 Jun 2018 09:55:14 -0400 Subject: [PATCH 04/12] upstream /3bd36bf5fd01f4e3494cc82076aea959540b68a8 --- impl/Model.cs | 167 ++++++++++++++++++++------------------- impl/OverlappingModel.cs | 101 ++++++++++++----------- impl/SimpleTiledModel.cs | 104 ++++++++++++------------ 3 files changed, 187 insertions(+), 185 deletions(-) diff --git a/impl/Model.cs b/impl/Model.cs index fe1513c..7b15213 100644 --- a/impl/Model.cs +++ b/impl/Model.cs @@ -10,98 +10,90 @@ The above copyright notice and this permission notice shall be included in all c public abstract class Model { - public bool[][][] wave; - public bool[][] changes; - public double[] stationary; - protected int[][] observed; + protected bool[][] wave; + protected double[] stationary; + protected int[] observed; protected bool init = false; + protected bool[] changes; + protected int[] stack; + protected int stacksize; + protected System.Random random; - protected int FMX, FMY, T, limit; + protected int FMX, FMY, T; protected bool periodic; double[] logProb; double logT; - protected Model(int width, int height) - { - FMX = width; - FMY = height; - - wave = new bool[FMX][][]; - changes = new bool[FMX][]; - for (int x = 0; x 0 && entropy + noise < min) + for (int t = 0; t < T; t++) if (w[t]) { - min = entropy + noise; - argminx = x; - argminy = y; + amount += 1; + sum += stationary[t]; } + + if (sum == 0) return false; + + double noise = 1E-6 * random.NextDouble(); + + double entropy; + if (amount == 1) entropy = 0; + else if (amount == T) entropy = logT; + else + { + double mainSum = 0; + double logSum = Math.Log(sum); + for (int t = 0; t < T; t++) if (w[t]) mainSum += stationary[t] * logProb[t]; + entropy = logSum - mainSum / sum; } - if (argminx == -1 && argminy == -1) - { - observed = new int[FMX][]; - for (int x = 0; x < FMX; x++) - { - observed[x] = new int[FMY]; - for (int y = 0; y < FMY; y++) for (int t = 0; t < T; t++) if (wave[x][y][t]) - { - observed[x][y] = t; - break; - } - } - return true; - } - - double[] distribution = new double[T]; - for (int t = 0; t < T; t++) distribution[t] = wave[argminx][argminy][t] ? stationary[t] : 0; - int r = Stuff.Random(distribution, random.NextDouble()); - for (int t = 0; t < T; t++) wave[argminx][argminy][t] = t == r; - changes[argminx][argminy] = true; + if (entropy > 0 && entropy + noise < min) + { + min = entropy + noise; + argmin = i; + } + } + + if (argmin == -1) + { + observed = new int[FMX * FMY]; + for (int i = 0; i < wave.Length; i++) for (int t = 0; t < T; t++) if (wave[i][t]) { observed[i] = t; break; } + return true; + } + + double[] distribution = new double[T]; + for (int t = 0; t < T; t++) distribution[t] = wave[argmin][t] ? stationary[t] : 0; + int r = distribution.Random(random.NextDouble()); + for (int t = 0; t < T; t++) wave[argmin][t] = t == r; + Change(argmin); return null; } @@ -112,14 +104,14 @@ public bool Run(int seed, int limit) logProb = new double[T]; for (int t = 0; t < T; t++) logProb[t] = Math.Log(stationary[t]); - if (!this.init){ + if (!this.init) { this.init = true; this.Clear(); } - if (seed==0){ + if (seed==0) { random = new System.Random(); - }else{ + } else { random = new System.Random(seed); } @@ -127,20 +119,29 @@ public bool Run(int seed, int limit) { bool? result = Observe(); if (result != null) return (bool)result; - while (Propagate()); + Propagate(); } return true; } - public virtual void Clear() + protected void Change(int i) { - for (int x = 0; x < FMX; x++) for (int y = 0; y < FMY; y++) - { - for (int t = 0; t < T; t++) wave[x][y][t] = true; - changes[x][y] = false; - } + if (changes[i]) return; + + stack[stacksize] = i; + stacksize++; + changes[i] = true; + } + + protected virtual void Clear() + { + for (int i = 0; i < wave.Length; i++) + { + for (int t = 0; t < T; t++) wave[i][t] = true; + changes[i] = false; + } } - protected abstract bool OnBoundary(int x, int y); -} + protected abstract bool OnBoundary(int i); +} \ No newline at end of file diff --git a/impl/OverlappingModel.cs b/impl/OverlappingModel.cs index 22571c5..4d138d5 100644 --- a/impl/OverlappingModel.cs +++ b/impl/OverlappingModel.cs @@ -15,10 +15,10 @@ class OverlappingModel : Model int N; public byte[][] patterns; - int foundation; + int ground; public List colors; - public OverlappingModel(byte[,] sample, int N, int width, int height, bool periodicInput, bool periodicOutput, int symmetry, int foundation) + public OverlappingModel(byte[,] sample, int N, int width, int height, bool periodicInput, bool periodicOutput, int symmetry, int ground) :base(width, height) { this.N = N; @@ -48,11 +48,7 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio Func, byte[]> pattern = (f) => { byte[] result = new byte[N * N]; - for (int y = 0; y < N; y++){ - for (int x = 0; x < N; x++){ - result[x + y * N] = f(x, y); - } - } + for (int y = 0; y < N; y++) for (int x = 0; x < N; x++) result[x + y * N] = f(x, y); return result; }; @@ -116,7 +112,7 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio } T = weights.Count; - this.foundation = (foundation + T) % T; + this.ground = (ground + T) % T; patterns = new byte[T][]; stationary = new double[T]; @@ -130,7 +126,7 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio counter++; } - for (int x = 0; x < FMX; x++) for (int y = 0; y < FMY; y++) wave[x][y] = new bool[T]; + for (int i = 0; i < wave.Length; i++) wave[i] = new bool[T]; Func agrees = (p1, p2, dx, dy) => { @@ -156,57 +152,58 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio } } - protected override bool OnBoundary(int x, int y){ - return !periodic && (x + N > FMX || y + N > FMY);} + override protected bool OnBoundary(int i) + { + return !periodic && (i % FMX + N > FMX || i / FMX + N > FMY); + } - override protected bool Propagate() + override protected void Propagate() { - bool change = false, b; - int x2, y2; + while (stacksize > 0) + { + int i1 = stack[stacksize - 1]; + stacksize--; + changes[i1] = false; + + bool[] w1 = wave[i1]; + int x1 = i1 % FMX, y1 = i1 / FMX; - for (int x1 = 0; x1 < FMX; x1++) for (int y1 = 0; y1 < FMY; y1++) if (changes[x1][y1]) + for (int dx = -N + 1; dx < N; dx++) for (int dy = -N + 1; dy < N; dy++) { - changes[x1][y1] = false; - for (int dx = -N + 1; dx < N; dx++) for (int dy = -N + 1; dy < N; dy++) - { - x2 = x1 + dx; - if (x2 < 0) x2 += FMX; - else if (x2 >= FMX) x2 -= FMX; + int x2 = x1 + dx; + if (x2 < 0) x2 += FMX; + else if (x2 >= FMX) x2 -= FMX; - y2 = y1 + dy; - if (y2 < 0) y2 += FMY; - else if (y2 >= FMY) y2 -= FMY; + int y2 = y1 + dy; + if (y2 < 0) y2 += FMY; + else if (y2 >= FMY) y2 -= FMY; - if (!periodic && (x2 + N > FMX || y2 + N > FMY)) continue; + if (!periodic && (x2 + N > FMX || y2 + N > FMY)) continue; - bool[] w1 = wave[x1][y1]; - bool[] w2 = wave[x2][y2]; - int[][] p = propagator[N - 1 - dx][N - 1 - dy]; + int i2 = x2 + y2 * FMX; + bool[] w2 = wave[i2]; + int[][] prop = propagator[N - 1 - dx][N - 1 - dy]; - for (int t2 = 0; t2 < T; t2++) + for (int t2 = 0; t2 < T; t2++) if (w2[t2]) + { + bool b = false; + int[] p = prop[t2]; + for (int l = 0; l < p.Length && !b; l++) b = w1[p[l]]; + + if (!b) { - if (!w2[t2]) continue; - b = false; - int[] prop = p[t2]; - for (int i1 = 0; i1 < prop.Length && !b; i1++) b = w1[prop[i1]]; - - if (!b) - { - changes[x2][y2] = true; - change = true; - w2[t2] = false; - } + Change(i2); + w2[t2] = false; } } } - - return change; + } } public byte Sample(int x, int y){ bool found = false; byte res = (byte)99; - for (int t = 0; t < T; t++) if (wave[x][y][t]){ + for (int t = 0; t < T; t++) if (wave[x + y * FMX][t]){ if (found) {return (byte)99;} found = true; res = patterns[t][0]; @@ -214,25 +211,25 @@ public byte Sample(int x, int y){ return res; } - public override void Clear() + protected override void Clear() { base.Clear(); - if (foundation != 0) + if (ground != 0) { for (int x = 0; x < FMX; x++) { - for (int t = 0; t < T; t++) if (t != foundation) wave[x][0][t] = false; - changes[x][0] = true; + for (int t = 0; t < T; t++) if (t != ground) wave[x + (FMY - 1) * FMX][t] = false; + Change(x + (FMY - 1) * FMX); - for (int y = 2; y < FMY; y++) + for (int y = 0; y < FMY - 1; y++) { - wave[x][y][foundation] = false; - changes[x][y] = true; + wave[x + y * FMX][ground] = false; + Change(x + y * FMX); } - - while (Propagate()); } + + Propagate(); } } } \ No newline at end of file diff --git a/impl/SimpleTiledModel.cs b/impl/SimpleTiledModel.cs index 35b1e5d..b06b17d 100644 --- a/impl/SimpleTiledModel.cs +++ b/impl/SimpleTiledModel.cs @@ -138,7 +138,7 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b for (int t = 0; t < T; t++) tempPropagator[d][t] = new bool[T]; } - for (int x = 0; x < FMX; x++) for (int y = 0; y < FMY; y++) wave[x][y] = new bool[T]; + for (int i = 0; i < wave.Length; i++) wave[i] = new bool[T]; foreach (XmlNode xneighbor in xnode.NextSibling.ChildNodes) { @@ -187,75 +187,79 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b } } - protected override bool Propagate() + protected override void Propagate() { - bool change = false, b; - for (int x2 = 0; x2 < FMX; x2++) for (int y2 = 0; y2 < FMY; y2++) for (int d = 0; d < 4; d++) + while (stacksize > 0) + { + int i1 = stack[stacksize - 1]; + changes[i1] = false; + stacksize--; + + bool[] w1 = wave[i1]; + int x1 = i1 % FMX, y1 = i1 / FMX; + + for (int d = 0; d < 4; d++) + { + int x2 = x1, y2 = y1; + if (d == 0) { - int x1 = x2, y1 = y2; - if (d == 0) + if (x1 == FMX - 1) { - if (x2 == 0) - { - if (!periodic) continue; - else x1 = FMX - 1; - } - else x1 = x2 - 1; + if (!periodic) continue; + else x2 = 0; } - else if (d == 1) + else x2 = x1 + 1; + } + else if (d == 1) + { + if (y1 == 0) { - if (y2 == FMY - 1) - { - if (!periodic) continue; - else y1 = 0; - } - else y1 = y2 + 1; + if (!periodic) continue; + else y2 = FMY - 1; } - else if (d == 2) + else y2 = y1 - 1; + } + else if (d == 2) + { + if (x1 == 0) { - if (x2 == FMX - 1) - { - if (!periodic) continue; - else x1 = 0; - } - else x1 = x2 + 1; + if (!periodic) continue; + else x2 = FMX - 1; } - else + else x2 = x1 - 1; + } + else + { + if (y1 == FMY - 1) { - if (y2 == 0) - { - if (!periodic) continue; - else y1 = FMY - 1; - } - else y1 = y2 - 1; + if (!periodic) continue; + else y2 = 0; } + else y2 = y1 + 1; + } + int i2 = x2 + y2 * FMX; + bool[] w2 = wave[i2]; + int[][] prop = propagator[d]; - if (!changes[x1][y1]) continue; - bool[] w1 = wave[x1][y1]; - bool[] w2 = wave[x2][y2]; - - for (int t2 = 0; t2 < T; t2++) + for (int t2 = 0; t2 < T; t2++) if (w2[t2]) { - if (!w2[t2]) continue; - b = false; - int[] prop = propagator[d][t2]; - for (int i1 = 0; i1 < prop.Length && !b; i1++) b = w1[prop[i1]]; + bool b = false; + int[] p = prop[t2]; + for (int l = 0; l < p.Length && !b; l++) b = w1[p[l]]; if (!b) { - changes[x2][y2] = true; - change = true; + Change(i2); w2[t2] = false; } - } - } - - return change; + } + } + } } public string Sample(int x, int y){ bool found = false; string res = "?"; - for (int t = 0; t < T; t++) if (wave[x][y][t]){ + for (int t = 0; t < T; t++) if (wave[x + y * FMX][t]){ if (found) {return "?";} found = true; res = tiles[t]; @@ -263,7 +267,7 @@ public string Sample(int x, int y){ return res; } - protected override bool OnBoundary(int x, int y){ + protected override bool OnBoundary(int i){ return false; } From 9e4a8f8f23f15610901f9e0e9185ddaedd1b7c41 Mon Sep 17 00:00:00 2001 From: selfsame Date: Sat, 30 Jun 2018 12:09:24 -0400 Subject: [PATCH 05/12] Compile in RecordNeighbors (needs to be compiled) --- Training.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Training.cs b/Training.cs index b6083ff..58dd371 100644 --- a/Training.cs +++ b/Training.cs @@ -25,6 +25,7 @@ public int Card(int n){ } public void RecordNeighbors() { + Compile(); neighbors = new Dictionary(); for (int y = 0; y < depth; y++){ for (int x = 0; x < width; x++){ From 782bca55b081d85e634ff9226583509f61e00fd0 Mon Sep 17 00:00:00 2001 From: selfsame Date: Sat, 30 Jun 2018 12:46:06 -0400 Subject: [PATCH 06/12] Model changes from fad1066b5000f7e9fbda0ef81bbea56799686670 --- impl/Model.cs | 174 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 125 insertions(+), 49 deletions(-) diff --git a/impl/Model.cs b/impl/Model.cs index 7b15213..acfe2fc 100644 --- a/impl/Model.cs +++ b/impl/Model.cs @@ -11,35 +11,67 @@ The above copyright notice and this permission notice shall be included in all c public abstract class Model { protected bool[][] wave; - protected double[] stationary; + + protected int[][][] propagator; + int[][][] compatible; protected int[] observed; protected bool init = false; - protected bool[] changes; - protected int[] stack; - protected int stacksize; + Tuple[] stack; + int stacksize; protected System.Random random; protected int FMX, FMY, T; protected bool periodic; - double[] logProb; - double logT; + protected double[] weights; + double[] weightLogWeights; + + int[] sumsOfOnes; + double sumOfWeights, sumOfWeightLogWeights, startingEntropy; + double[] sumsOfWeights, sumsOfWeightLogWeights, entropies; protected Model(int width, int height) { FMX = width; FMY = height; + } + void Init() + { wave = new bool[FMX * FMY][]; - changes = new bool[FMX * FMY]; + compatible = new int[wave.Length][][]; + for (int i = 0; i < wave.Length; i++) + { + wave[i] = new bool[T]; + compatible[i] = new int[T][]; + for (int t = 0; t < T; t++) compatible[i][t] = new int[4]; + } + + weightLogWeights = new double[T]; + sumOfWeights = 0; + sumOfWeightLogWeights = 0; + + for (int t = 0; t < T; t++) + { + weightLogWeights[t] = weights[t] * Math.Log(weights[t]); + sumOfWeights += weights[t]; + sumOfWeightLogWeights += weightLogWeights[t]; + } - stack = new int[FMX * FMY]; + startingEntropy = Math.Log(sumOfWeights) - sumOfWeightLogWeights / sumOfWeights; + + sumsOfOnes = new int[FMX * FMY]; + sumsOfWeights = new double[FMX * FMY]; + sumsOfWeightLogWeights = new double[FMX * FMY]; + entropies = new double[FMX * FMY]; + + stack = new Tuple[wave.Length * T]; stacksize = 0; } - protected abstract void Propagate(); + bool? Observe() { @@ -48,37 +80,20 @@ protected Model(int width, int height) for (int i = 0; i < wave.Length; i++) { - if (OnBoundary(i)) continue; + if (OnBoundary(i % FMX, i / FMX)) continue; - bool[] w = wave[i]; - int amount = 0; - double sum = 0; + int amount = sumsOfOnes[i]; + if (amount == 0) return false; - for (int t = 0; t < T; t++) if (w[t]) + double entropy = entropies[i]; + if (amount > 1 && entropy <= min) + { + double noise = 1E-6 * random.NextDouble(); + if (entropy + noise < min) { - amount += 1; - sum += stationary[t]; + min = entropy + noise; + argmin = i; } - - if (sum == 0) return false; - - double noise = 1E-6 * random.NextDouble(); - - double entropy; - if (amount == 1) entropy = 0; - else if (amount == T) entropy = logT; - else - { - double mainSum = 0; - double logSum = Math.Log(sum); - for (int t = 0; t < T; t++) if (w[t]) mainSum += stationary[t] * logProb[t]; - entropy = logSum - mainSum / sum; - } - - if (entropy > 0 && entropy + noise < min) - { - min = entropy + noise; - argmin = i; } } @@ -90,19 +105,56 @@ protected Model(int width, int height) } double[] distribution = new double[T]; - for (int t = 0; t < T; t++) distribution[t] = wave[argmin][t] ? stationary[t] : 0; + for (int t = 0; t < T; t++) distribution[t] = wave[argmin][t] ? weights[t] : 0; int r = distribution.Random(random.NextDouble()); - for (int t = 0; t < T; t++) wave[argmin][t] = t == r; - Change(argmin); + + bool[] w = wave[argmin]; + for (int t = 0; t < T; t++) if (w[t] != (t == r)) Ban(argmin, t); return null; } + protected void Propagate() + { + while (stacksize > 0) + { + var e1 = stack[stacksize - 1]; + stacksize--; + + int i1 = e1.Item1; + int x1 = i1 % FMX, y1 = i1 / FMX; + bool[] w1 = wave[i1]; + + for (int d = 0; d < 4; d++) + { + int dx = DX[d], dy = DY[d]; + int x2 = x1 + dx, y2 = y1 + dy; + if (OnBoundary(x2, y2)) continue; + + if (x2 < 0) x2 += FMX; + else if (x2 >= FMX) x2 -= FMX; + if (y2 < 0) y2 += FMY; + else if (y2 >= FMY) y2 -= FMY; + + int i2 = x2 + y2 * FMX; + int[] p = propagator[d][e1.Item2]; + int[][] compat = compatible[i2]; + + for (int l = 0; l < p.Length; l++) + { + int t2 = p[l]; + int[] comp = compat[t2]; + + comp[d]--; + if (comp[d] == 0) Ban(i2, t2); + } + } + } + } + public bool Run(int seed, int limit) { - logT = Math.Log(T); - logProb = new double[T]; - for (int t = 0; t < T; t++) logProb[t] = Math.Log(stationary[t]); + if (wave == null) Init(); if (!this.init) { this.init = true; @@ -125,23 +177,47 @@ public bool Run(int seed, int limit) return true; } - protected void Change(int i) + protected void Ban(int i, int t) { - if (changes[i]) return; + wave[i][t] = false; - stack[stacksize] = i; + int[] comp = compatible[i][t]; + for (int d = 0; d < 4; d++) comp[d] = 0; + stack[stacksize] = new Tuple(i, t); stacksize++; - changes[i] = true; + + double sum = sumsOfWeights[i]; + entropies[i] += sumsOfWeightLogWeights[i] / sum - Math.Log(sum); + + sumsOfOnes[i] -= 1; + sumsOfWeights[i] -= weights[t]; + sumsOfWeightLogWeights[i] -= weightLogWeights[t]; + + sum = sumsOfWeights[i]; + entropies[i] -= sumsOfWeightLogWeights[i] / sum - Math.Log(sum); } protected virtual void Clear() { for (int i = 0; i < wave.Length; i++) { - for (int t = 0; t < T; t++) wave[i][t] = true; - changes[i] = false; + for (int t = 0; t < T; t++) + { + wave[i][t] = true; + for (int d = 0; d < 4; d++) compatible[i][t][d] = propagator[opposite[d]][t].Length; + } + + sumsOfOnes[i] = weights.Length; + sumsOfWeights[i] = sumOfWeights; + sumsOfWeightLogWeights[i] = sumOfWeightLogWeights; + entropies[i] = startingEntropy; } } - protected abstract bool OnBoundary(int i); + protected abstract bool OnBoundary(int x, int y); + public abstract System.Drawing.Bitmap Graphics(); + + protected static int[] DX = { -1, 0, 1, 0 }; + protected static int[] DY = { 0, 1, 0, -1 }; + static int[] opposite = { 2, 3, 0, 1 }; } \ No newline at end of file From 4bc7019f22e51aa986986944cbc2020b25a30d74 Mon Sep 17 00:00:00 2001 From: selfsame Date: Sat, 30 Jun 2018 13:09:14 -0400 Subject: [PATCH 07/12] complete fad1066b5000f7e9fbda0ef81bbea56799686670 --- impl/Model.cs | 2 +- impl/OverlappingModel.cs | 83 +++++--------------------- impl/SimpleTiledModel.cs | 78 ++----------------------- impl/Tuple.cs | 107 ++++++++++++++++++++++++++++++++++ impl/Tuple2.cs | 102 ++++++++++++++++++++++++++++++++ impl/Tuple3.cs | 107 ++++++++++++++++++++++++++++++++++ impl/Tuple4.cs | 122 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 459 insertions(+), 142 deletions(-) create mode 100644 impl/Tuple.cs create mode 100644 impl/Tuple2.cs create mode 100644 impl/Tuple3.cs create mode 100644 impl/Tuple4.cs diff --git a/impl/Model.cs b/impl/Model.cs index acfe2fc..49debab 100644 --- a/impl/Model.cs +++ b/impl/Model.cs @@ -7,6 +7,7 @@ The above copyright notice and this permission notice shall be included in all c */ using System; +using Eppy; public abstract class Model { @@ -215,7 +216,6 @@ protected virtual void Clear() } protected abstract bool OnBoundary(int x, int y); - public abstract System.Drawing.Bitmap Graphics(); protected static int[] DX = { -1, 0, 1, 0 }; protected static int[] DY = { 0, 1, 0, -1 }; diff --git a/impl/OverlappingModel.cs b/impl/OverlappingModel.cs index 4d138d5..f161cc6 100644 --- a/impl/OverlappingModel.cs +++ b/impl/OverlappingModel.cs @@ -11,7 +11,7 @@ The above copyright notice and this permission notice shall be included in all c class OverlappingModel : Model { - int[][][][] propagator; + int N; public byte[][] patterns; @@ -115,18 +115,17 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio this.ground = (ground + T) % T; patterns = new byte[T][]; - stationary = new double[T]; - propagator = new int[2 * N - 1][][][]; + base.weights = new double[T]; int counter = 0; foreach (int w in weights.Keys) { patterns[counter] = patternFromIndex(w); - stationary[counter] = weights[w]; + base.weights[counter] = weights[w]; counter++; } - for (int i = 0; i < wave.Length; i++) wave[i] = new bool[T]; + Func agrees = (p1, p2, dx, dy) => { @@ -135,70 +134,26 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio return true; }; - for (int x = 0; x < 2 * N - 1; x++) + propagator = new int[4][][]; + for (int d = 0; d < 4; d++) { - propagator[x] = new int[2 * N - 1][][]; - for (int y = 0; y < 2 * N - 1; y++) + propagator[d] = new int[T][]; + for (int t = 0; t < T; t++) { - propagator[x][y] = new int[T][]; - for (int t = 0; t < T; t++) - { - List list = new List(); - for (int t2 = 0; t2 < T; t2++) if (agrees(patterns[t], patterns[t2], x - N + 1, y - N + 1)) list.Add(t2); - propagator[x][y][t] = new int[list.Count]; - for (int c = 0; c < list.Count; c++) propagator[x][y][t][c] = list[c]; - } + List list = new List(); + for (int t2 = 0; t2 < T; t2++) if (agrees(patterns[t], patterns[t2], DX[d], DY[d])) list.Add(t2); + propagator[d][t] = new int[list.Count]; + for (int c = 0; c < list.Count; c++) propagator[d][t][c] = list[c]; } } } - override protected bool OnBoundary(int i) + protected override bool OnBoundary(int x, int y) { - return !periodic && (i % FMX + N > FMX || i / FMX + N > FMY); + return !periodic && (x + N > FMX || y + N > FMY || x < 0 || y < 0); } - override protected void Propagate() - { - while (stacksize > 0) - { - int i1 = stack[stacksize - 1]; - stacksize--; - changes[i1] = false; - bool[] w1 = wave[i1]; - int x1 = i1 % FMX, y1 = i1 / FMX; - - for (int dx = -N + 1; dx < N; dx++) for (int dy = -N + 1; dy < N; dy++) - { - int x2 = x1 + dx; - if (x2 < 0) x2 += FMX; - else if (x2 >= FMX) x2 -= FMX; - - int y2 = y1 + dy; - if (y2 < 0) y2 += FMY; - else if (y2 >= FMY) y2 -= FMY; - - if (!periodic && (x2 + N > FMX || y2 + N > FMY)) continue; - - int i2 = x2 + y2 * FMX; - bool[] w2 = wave[i2]; - int[][] prop = propagator[N - 1 - dx][N - 1 - dy]; - - for (int t2 = 0; t2 < T; t2++) if (w2[t2]) - { - bool b = false; - int[] p = prop[t2]; - for (int l = 0; l < p.Length && !b; l++) b = w1[p[l]]; - - if (!b) - { - Change(i2); - w2[t2] = false; - } - } - } - } - } public byte Sample(int x, int y){ bool found = false; @@ -219,14 +174,8 @@ protected override void Clear() { for (int x = 0; x < FMX; x++) { - for (int t = 0; t < T; t++) if (t != ground) wave[x + (FMY - 1) * FMX][t] = false; - Change(x + (FMY - 1) * FMX); - - for (int y = 0; y < FMY - 1; y++) - { - wave[x + y * FMX][ground] = false; - Change(x + y * FMX); - } + for (int t = 0; t < T; t++) if (t != ground) Ban(x + (FMY - 1) * FMX, t); + for (int y = 0; y < FMY - 1; y++) Ban(x + y * FMX, ground); } Propagate(); diff --git a/impl/SimpleTiledModel.cs b/impl/SimpleTiledModel.cs index b06b17d..b0a340a 100644 --- a/impl/SimpleTiledModel.cs +++ b/impl/SimpleTiledModel.cs @@ -13,7 +13,6 @@ The above copyright notice and this permission notice shall be included in all c public class SimpleTiledModel : Model { - public int[][][] propagator; public List tiles; public SimpleTiledModel(string name, string subsetName, int width, int height, bool periodic) @@ -127,10 +126,10 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b } T = action.Count; - stationary = tempStationary.ToArray(); + weights = tempStationary.ToArray(); - var tempPropagator = new bool[4][][]; propagator = new int[4][][]; + var tempPropagator = new bool[4][][]; for (int d = 0; d < 4; d++) { tempPropagator[d] = new bool[T][]; @@ -138,8 +137,6 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b for (int t = 0; t < T; t++) tempPropagator[d][t] = new bool[T]; } - for (int i = 0; i < wave.Length; i++) wave[i] = new bool[T]; - foreach (XmlNode xneighbor in xnode.NextSibling.ChildNodes) { string[] left = xneighbor.Get("left").Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); @@ -187,74 +184,7 @@ public SimpleTiledModel(string name, string subsetName, int width, int height, b } } - protected override void Propagate() - { - while (stacksize > 0) - { - int i1 = stack[stacksize - 1]; - changes[i1] = false; - stacksize--; - - bool[] w1 = wave[i1]; - int x1 = i1 % FMX, y1 = i1 / FMX; - for (int d = 0; d < 4; d++) - { - int x2 = x1, y2 = y1; - if (d == 0) - { - if (x1 == FMX - 1) - { - if (!periodic) continue; - else x2 = 0; - } - else x2 = x1 + 1; - } - else if (d == 1) - { - if (y1 == 0) - { - if (!periodic) continue; - else y2 = FMY - 1; - } - else y2 = y1 - 1; - } - else if (d == 2) - { - if (x1 == 0) - { - if (!periodic) continue; - else x2 = FMX - 1; - } - else x2 = x1 - 1; - } - else - { - if (y1 == FMY - 1) - { - if (!periodic) continue; - else y2 = 0; - } - else y2 = y1 + 1; - } - int i2 = x2 + y2 * FMX; - bool[] w2 = wave[i2]; - int[][] prop = propagator[d]; - - for (int t2 = 0; t2 < T; t2++) if (w2[t2]) - { - bool b = false; - int[] p = prop[t2]; - for (int l = 0; l < p.Length && !b; l++) b = w1[p[l]]; - if (!b) - { - Change(i2); - w2[t2] = false; - } - } - } - } - } public string Sample(int x, int y){ bool found = false; @@ -267,8 +197,8 @@ public string Sample(int x, int y){ return res; } - protected override bool OnBoundary(int i){ - return false; + protected override bool OnBoundary(int x, int y){ + return !periodic && (x < 0 || y < 0 || x >= FMX || y >= FMY); } } \ No newline at end of file diff --git a/impl/Tuple.cs b/impl/Tuple.cs new file mode 100644 index 0000000..f480f95 --- /dev/null +++ b/impl/Tuple.cs @@ -0,0 +1,107 @@ +// ---------------------------------------------------------------------------- +// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). +// +// Used Chapter 3 in http://functional-programming.net/ as a starting point. +// +// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. +// ---------------------------------------------------------------------------- + +using System; + +namespace Eppy +{ + /// + /// Utility class that simplifies cration of tuples by using + /// method calls instead of constructor calls + /// + public static class Tuple + { + /// + /// Creates a new tuple value with the specified elements. The method + /// can be used without specifying the generic parameters, because C# + /// compiler can usually infer the actual types. + /// + /// First element of the tuple + /// Second element of the tuple + /// A newly created tuple + public static Tuple Create(T1 item1, T2 second) + { + return new Tuple(item1, second); + } + + /// + /// Creates a new tuple value with the specified elements. The method + /// can be used without specifying the generic parameters, because C# + /// compiler can usually infer the actual types. + /// + /// First element of the tuple + /// Second element of the tuple + /// Third element of the tuple + /// A newly created tuple + public static Tuple Create(T1 item1, T2 second, T3 third) + { + return new Tuple(item1, second, third); + } + + /// + /// Creates a new tuple value with the specified elements. The method + /// can be used without specifying the generic parameters, because C# + /// compiler can usually infer the actual types. + /// + /// First element of the tuple + /// Second element of the tuple + /// Third element of the tuple + /// Fourth element of the tuple + /// A newly created tuple + public static Tuple Create(T1 item1, T2 second, T3 third, T4 fourth) + { + return new Tuple(item1, second, third, fourth); + } + + + /// + /// Extension method that provides a concise utility for unpacking + /// tuple components into specific out parameters. + /// + /// the tuple to unpack from + /// the out parameter that will be assigned tuple.Item1 + /// the out parameter that will be assigned tuple.Item2 + public static void Unpack(this Tuple tuple, out T1 ref1, out T2 ref2) + { + ref1 = tuple.Item1; + ref2 = tuple.Item2; + } + + /// + /// Extension method that provides a concise utility for unpacking + /// tuple components into specific out parameters. + /// + /// the tuple to unpack from + /// the out parameter that will be assigned tuple.Item1 + /// the out parameter that will be assigned tuple.Item2 + /// the out parameter that will be assigned tuple.Item3 + public static void Unpack(this Tuple tuple, out T1 ref1, out T2 ref2, T3 ref3) + { + ref1 = tuple.Item1; + ref2 = tuple.Item2; + ref3 = tuple.Item3; + } + + /// + /// Extension method that provides a concise utility for unpacking + /// tuple components into specific out parameters. + /// + /// the tuple to unpack from + /// the out parameter that will be assigned tuple.Item1 + /// the out parameter that will be assigned tuple.Item2 + /// the out parameter that will be assigned tuple.Item3 + /// the out parameter that will be assigned tuple.Item4 + public static void Unpack(this Tuple tuple, out T1 ref1, out T2 ref2, T3 ref3, T4 ref4) + { + ref1 = tuple.Item1; + ref2 = tuple.Item2; + ref3 = tuple.Item3; + ref4 = tuple.Item4; + } + } +} \ No newline at end of file diff --git a/impl/Tuple2.cs b/impl/Tuple2.cs new file mode 100644 index 0000000..4e979de --- /dev/null +++ b/impl/Tuple2.cs @@ -0,0 +1,102 @@ +// ---------------------------------------------------------------------------- +// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). +// +// Used Chapter 3 in http://functional-programming.net/ as a starting point. +// +// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. +// ---------------------------------------------------------------------------- + +using System; + +namespace Eppy +{ + /// + /// Represents a functional tuple that can be used to store + /// two values of different types inside one object. + /// + /// The type of the first element + /// The type of the second element + public sealed class Tuple + { + private readonly T1 item1; + private readonly T2 item2; + + /// + /// Retyurns the first element of the tuple + /// + public T1 Item1 + { + get { return item1; } + } + + /// + /// Returns the second element of the tuple + /// + public T2 Item2 + { + get { return item2; } + } + + /// + /// Create a new tuple value + /// + /// First element of the tuple + /// Second element of the tuple + public Tuple(T1 item1, T2 item2) + { + this.item1 = item1; + this.item2 = item2; + } + + public override string ToString() + { + return string.Format("Tuple({0}, {1})", Item1, Item2); + } + + public override int GetHashCode() + { + int hash = 17; + hash = hash * 23 + (item1 == null ? 0 : item1.GetHashCode()); + hash = hash * 23 + (item2 == null ? 0 : item2.GetHashCode()); + return hash; + } + + public override bool Equals(object o) + { + if (!(o is Tuple)) { + return false; + } + + var other = (Tuple) o; + + return this == other; + } + + public bool Equals(Tuple other) + { + return this == other; + } + + public static bool operator==(Tuple a, Tuple b) + { + if (object.ReferenceEquals(a, null)) { + return object.ReferenceEquals(b, null); + } + if (a.item1 == null && b.item1 != null) return false; + if (a.item2 == null && b.item2 != null) return false; + return + a.item1.Equals(b.item1) && + a.item2.Equals(b.item2); + } + + public static bool operator!=(Tuple a, Tuple b) + { + return !(a == b); + } + + public void Unpack(Action unpackerDelegate) + { + unpackerDelegate(Item1, Item2); + } + } +} \ No newline at end of file diff --git a/impl/Tuple3.cs b/impl/Tuple3.cs new file mode 100644 index 0000000..b510574 --- /dev/null +++ b/impl/Tuple3.cs @@ -0,0 +1,107 @@ +// ---------------------------------------------------------------------------- +// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). +// +// Used Chapter 3 in http://functional-programming.net/ as a starting point. +// +// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. +// ---------------------------------------------------------------------------- + +using System; + +namespace Eppy +{ + /// + /// Represents a functional tuple that can be used to store + /// two values of different types inside one object. + /// + /// The type of the first element + /// The type of the second element + /// The type of the third element + public sealed class Tuple + { + private readonly T1 item1; + private readonly T2 item2; + private readonly T3 item3; + + /// + /// Retyurns the first element of the tuple + /// + public T1 Item1 + { + get { return item1; } + } + + /// + /// Returns the second element of the tuple + /// + public T2 Item2 + { + get { return item2; } + } + + /// + /// Returns the second element of the tuple + /// + public T3 Item3 + { + get { return item3; } + } + + /// + /// Create a new tuple value + /// + /// First element of the tuple + /// Second element of the tuple + /// Third element of the tuple + public Tuple(T1 item1, T2 item2, T3 item3) + { + this.item1 = item1; + this.item2 = item2; + this.item3 = item3; + } + + public override int GetHashCode() + { + int hash = 17; + hash = hash * 23 + (item1 == null ? 0 : item1.GetHashCode()); + hash = hash * 23 + (item2 == null ? 0 : item2.GetHashCode()); + hash = hash * 23 + (item3 == null ? 0 : item3.GetHashCode()); + return hash; + } + + public override bool Equals(object o) + { + if (!(o is Tuple)) { + return false; + } + + var other = (Tuple)o; + + return this == other; + } + + public static bool operator==(Tuple a, Tuple b) + { + if (object.ReferenceEquals(a, null)) { + return object.ReferenceEquals(b, null); + } + if (a.item1 == null && b.item1 != null) return false; + if (a.item2 == null && b.item2 != null) return false; + if (a.item3 == null && b.item3 != null) return false; + return + a.item1.Equals(b.item1) && + a.item2.Equals(b.item2) && + a.item3.Equals(b.item3); + } + + public static bool operator!=(Tuple a, Tuple b) + { + return !(a == b); + } + + public void Unpack(Action unpackerDelegate) + { + unpackerDelegate(Item1, Item2, Item3); + } + } +} \ No newline at end of file diff --git a/impl/Tuple4.cs b/impl/Tuple4.cs new file mode 100644 index 0000000..6f0bdc3 --- /dev/null +++ b/impl/Tuple4.cs @@ -0,0 +1,122 @@ +// ---------------------------------------------------------------------------- +// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). +// +// Used Chapter 3 in http://functional-programming.net/ as a starting point. +// +// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. +// ---------------------------------------------------------------------------- + +using System; + +namespace Eppy +{ + /// + /// Represents a functional tuple that can be used to store + /// two values of different types inside one object. + /// + /// The type of the first element + /// The type of the second element + /// The type of the third element + /// The type of the fourth element + public sealed class Tuple + { + private readonly T1 item1; + private readonly T2 item2; + private readonly T3 item3; + private readonly T4 item4; + + /// + /// Retyurns the first element of the tuple + /// + public T1 Item1 + { + get { return item1; } + } + + /// + /// Returns the second element of the tuple + /// + public T2 Item2 + { + get { return item2; } + } + + /// + /// Returns the second element of the tuple + /// + public T3 Item3 + { + get { return item3; } + } + + /// + /// Returns the second element of the tuple + /// + public T4 Item4 + { + get { return item4; } + } + + /// + /// Create a new tuple value + /// + /// First element of the tuple + /// Second element of the tuple + /// Third element of the tuple + /// Fourth element of the tuple + public Tuple(T1 item1, T2 item2, T3 item3, T4 item4) + { + this.item1 = item1; + this.item2 = item2; + this.item3 = item3; + this.item4 = item4; + } + + public override int GetHashCode() + { + int hash = 17; + hash = hash * 23 + (item1 == null ? 0 : item1.GetHashCode()); + hash = hash * 23 + (item2 == null ? 0 : item2.GetHashCode()); + hash = hash * 23 + (item3 == null ? 0 : item3.GetHashCode()); + hash = hash * 23 + (item4 == null ? 0 : item4.GetHashCode()); + return hash; + } + + public override bool Equals(object o) + { + if (o.GetType() != typeof(Tuple)) { + return false; + } + + var other = (Tuple)o; + + return this == other; + } + + public static bool operator==(Tuple a, Tuple b) + { + if (object.ReferenceEquals(a, null)) { + return object.ReferenceEquals(b, null); + } + if (a.item1 == null && b.item1 != null) return false; + if (a.item2 == null && b.item2 != null) return false; + if (a.item3 == null && b.item3 != null) return false; + if (a.item4 == null && b.item4 != null) return false; + return + a.item1.Equals(b.item1) && + a.item2.Equals(b.item2) && + a.item3.Equals(b.item3) && + a.item4.Equals(b.item4); + } + + public static bool operator!=(Tuple a, Tuple b) + { + return !(a == b); + } + + public void Unpack(Action unpackerDelegate) + { + unpackerDelegate(Item1, Item2, Item3, Item4); + } + } +} \ No newline at end of file From 15ff49da4bdcb558a92344e05e18865445cd21d8 Mon Sep 17 00:00:00 2001 From: Joseph Parker Date: Wed, 20 Nov 2019 00:43:13 -0500 Subject: [PATCH 08/12] be more specific about Tuple class (was throwing errors) --- impl/Model.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impl/Model.cs b/impl/Model.cs index 49debab..09c52c3 100644 --- a/impl/Model.cs +++ b/impl/Model.cs @@ -19,7 +19,7 @@ public abstract class Model protected bool init = false; - Tuple[] stack; + Eppy.Tuple[] stack; int stacksize; protected System.Random random; @@ -68,7 +68,7 @@ void Init() sumsOfWeightLogWeights = new double[FMX * FMY]; entropies = new double[FMX * FMY]; - stack = new Tuple[wave.Length * T]; + stack = new Eppy.Tuple[wave.Length * T]; stacksize = 0; } @@ -184,7 +184,7 @@ protected void Ban(int i, int t) int[] comp = compatible[i][t]; for (int d = 0; d < 4; d++) comp[d] = 0; - stack[stacksize] = new Tuple(i, t); + stack[stacksize] = new Eppy.Tuple(i, t); stacksize++; double sum = sumsOfWeights[i]; From 777af66a21b88217ed9b878d89ccdacd5795e8a4 Mon Sep 17 00:00:00 2001 From: Joseph Parker Date: Wed, 20 Nov 2019 02:31:13 -0500 Subject: [PATCH 09/12] remove warnings and update some obsolute prefab api calls --- OverlapWFC.cs | 10 ++++++---- TilePainter.cs | 22 ++++++++++++++++++++-- Training.cs | 17 ++++++++--------- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/OverlapWFC.cs b/OverlapWFC.cs index c5360ef..70df2d3 100644 --- a/OverlapWFC.cs +++ b/OverlapWFC.cs @@ -28,9 +28,10 @@ class OverlapWFC : MonoBehaviour{ public static bool IsPrefabRef(UnityEngine.Object o){ #if UNITY_EDITOR - return PrefabUtility.GetPrefabParent(o) == null && PrefabUtility.GetPrefabObject(o) != null; - #endif + return PrefabUtility.GetOutermostPrefabInstanceRoot(o) != null; + #else return true; + #endif } static GameObject CreatePrefab(UnityEngine.Object fab, Vector3 pos, Quaternion rot) { @@ -39,11 +40,12 @@ static GameObject CreatePrefab(UnityEngine.Object fab, Vector3 pos, Quaternion r e.transform.position = pos; e.transform.rotation = rot; return e; - #endif + #else GameObject o = GameObject.Instantiate(fab as GameObject) as GameObject; o.transform.position = pos; o.transform.rotation = rot; return o; + #endif } public void Clear(){ @@ -146,7 +148,7 @@ public void Draw(){ } } } - } catch (IndexOutOfRangeException e) { + } catch (IndexOutOfRangeException) { model = null; return; } diff --git a/TilePainter.cs b/TilePainter.cs index 910638b..6e4e6b9 100644 --- a/TilePainter.cs +++ b/TilePainter.cs @@ -184,12 +184,30 @@ public Vector3 Local(Vector3 p){ return this.transform.TransformPoint(p); } + public UnityEngine.Object PrefabSource(GameObject o){ + if (o == null) + { + return null; + } + UnityEngine.Object fab = PrefabUtility.GetCorrespondingObjectFromSource(o); + if (fab == null) + { + fab = Resources.Load(o.name); + } + if (fab == null) + { + fab = palette[0]; + } + return fab; + } + public void Drag(Vector3 mouse, TileLayerEditor.TileOperation op){ Resize(); if (tileobs == null){Restore();} if (this.ValidCoords((int)cursor.x, (int)cursor.y)){ if (op == TileLayerEditor.TileOperation.Sampling){ - UnityEngine.Object s = PrefabUtility.GetPrefabParent(tileobs[(int)cursor.x, (int)cursor.y]); + UnityEngine.Object s = PrefabSource(tileobs[(int)cursor.x, (int)cursor.y]); + Debug.Log(s); if (s != null){ color = s; color_rotation = tileobs[(int)cursor.x, (int)cursor.y].transform.localRotation; @@ -270,7 +288,7 @@ private bool AmHovering(Event e){ me.focused = true; Renderer rend = me.gameObject.GetComponentInChildren( ); - if( rend ) EditorUtility.SetSelectedWireframeHidden( rend, false ); + if( rend ) EditorUtility.SetSelectedRenderState( rend, EditorSelectedRenderState.Wireframe ); return true; } me.focused = false; diff --git a/Training.cs b/Training.cs index 58dd371..b8a3cf2 100644 --- a/Training.cs +++ b/Training.cs @@ -114,17 +114,16 @@ public void Compile() { (tilepos.y > -0.55f) && (tilepos.y <= depth*gridsize-0.55f)){ UnityEngine.Object fab = tile; #if UNITY_EDITOR - fab = PrefabUtility.GetPrefabParent(tile); - if (fab == null){ - PrefabUtility.ReconnectToLastPrefab(tile); - fab = PrefabUtility.GetPrefabParent(tile); - } + fab = PrefabUtility.GetCorrespondingObjectFromSource(tile); + // if (fab == null){ + // PrefabUtility.RevertPrefabInstance(tile); + // fab = PrefabUtility.GetCorrespondingObjectFromSource(tile); + // } if (fab == null){ fab = (GameObject)Resources.Load(tile.name); - if (fab){ - tile = PrefabUtility.ConnectGameObjectToPrefab(tile, (GameObject)fab); - }else{ - fab = tile;} + if (!fab){ + fab = tile; + } } tile.name = fab.name; From 521905e164089562e7ff8373c57d532ce0d6b482 Mon Sep 17 00:00:00 2001 From: Joseph Parker Date: Wed, 20 Nov 2019 02:36:39 -0500 Subject: [PATCH 10/12] remove Eppy Tuple classes --- impl/Model.cs | 7 ++- impl/Tuple.cs | 107 ------------------------------------------- impl/Tuple2.cs | 102 ----------------------------------------- impl/Tuple3.cs | 107 ------------------------------------------- impl/Tuple4.cs | 122 ------------------------------------------------- 5 files changed, 3 insertions(+), 442 deletions(-) delete mode 100644 impl/Tuple.cs delete mode 100644 impl/Tuple2.cs delete mode 100644 impl/Tuple3.cs delete mode 100644 impl/Tuple4.cs diff --git a/impl/Model.cs b/impl/Model.cs index 09c52c3..a2ff16b 100644 --- a/impl/Model.cs +++ b/impl/Model.cs @@ -7,7 +7,6 @@ The above copyright notice and this permission notice shall be included in all c */ using System; -using Eppy; public abstract class Model { @@ -19,7 +18,7 @@ public abstract class Model protected bool init = false; - Eppy.Tuple[] stack; + Tuple[] stack; int stacksize; protected System.Random random; @@ -68,7 +67,7 @@ void Init() sumsOfWeightLogWeights = new double[FMX * FMY]; entropies = new double[FMX * FMY]; - stack = new Eppy.Tuple[wave.Length * T]; + stack = new Tuple[wave.Length * T]; stacksize = 0; } @@ -184,7 +183,7 @@ protected void Ban(int i, int t) int[] comp = compatible[i][t]; for (int d = 0; d < 4; d++) comp[d] = 0; - stack[stacksize] = new Eppy.Tuple(i, t); + stack[stacksize] = new Tuple(i, t); stacksize++; double sum = sumsOfWeights[i]; diff --git a/impl/Tuple.cs b/impl/Tuple.cs deleted file mode 100644 index f480f95..0000000 --- a/impl/Tuple.cs +++ /dev/null @@ -1,107 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). -// -// Used Chapter 3 in http://functional-programming.net/ as a starting point. -// -// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. -// ---------------------------------------------------------------------------- - -using System; - -namespace Eppy -{ - /// - /// Utility class that simplifies cration of tuples by using - /// method calls instead of constructor calls - /// - public static class Tuple - { - /// - /// Creates a new tuple value with the specified elements. The method - /// can be used without specifying the generic parameters, because C# - /// compiler can usually infer the actual types. - /// - /// First element of the tuple - /// Second element of the tuple - /// A newly created tuple - public static Tuple Create(T1 item1, T2 second) - { - return new Tuple(item1, second); - } - - /// - /// Creates a new tuple value with the specified elements. The method - /// can be used without specifying the generic parameters, because C# - /// compiler can usually infer the actual types. - /// - /// First element of the tuple - /// Second element of the tuple - /// Third element of the tuple - /// A newly created tuple - public static Tuple Create(T1 item1, T2 second, T3 third) - { - return new Tuple(item1, second, third); - } - - /// - /// Creates a new tuple value with the specified elements. The method - /// can be used without specifying the generic parameters, because C# - /// compiler can usually infer the actual types. - /// - /// First element of the tuple - /// Second element of the tuple - /// Third element of the tuple - /// Fourth element of the tuple - /// A newly created tuple - public static Tuple Create(T1 item1, T2 second, T3 third, T4 fourth) - { - return new Tuple(item1, second, third, fourth); - } - - - /// - /// Extension method that provides a concise utility for unpacking - /// tuple components into specific out parameters. - /// - /// the tuple to unpack from - /// the out parameter that will be assigned tuple.Item1 - /// the out parameter that will be assigned tuple.Item2 - public static void Unpack(this Tuple tuple, out T1 ref1, out T2 ref2) - { - ref1 = tuple.Item1; - ref2 = tuple.Item2; - } - - /// - /// Extension method that provides a concise utility for unpacking - /// tuple components into specific out parameters. - /// - /// the tuple to unpack from - /// the out parameter that will be assigned tuple.Item1 - /// the out parameter that will be assigned tuple.Item2 - /// the out parameter that will be assigned tuple.Item3 - public static void Unpack(this Tuple tuple, out T1 ref1, out T2 ref2, T3 ref3) - { - ref1 = tuple.Item1; - ref2 = tuple.Item2; - ref3 = tuple.Item3; - } - - /// - /// Extension method that provides a concise utility for unpacking - /// tuple components into specific out parameters. - /// - /// the tuple to unpack from - /// the out parameter that will be assigned tuple.Item1 - /// the out parameter that will be assigned tuple.Item2 - /// the out parameter that will be assigned tuple.Item3 - /// the out parameter that will be assigned tuple.Item4 - public static void Unpack(this Tuple tuple, out T1 ref1, out T2 ref2, T3 ref3, T4 ref4) - { - ref1 = tuple.Item1; - ref2 = tuple.Item2; - ref3 = tuple.Item3; - ref4 = tuple.Item4; - } - } -} \ No newline at end of file diff --git a/impl/Tuple2.cs b/impl/Tuple2.cs deleted file mode 100644 index 4e979de..0000000 --- a/impl/Tuple2.cs +++ /dev/null @@ -1,102 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). -// -// Used Chapter 3 in http://functional-programming.net/ as a starting point. -// -// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. -// ---------------------------------------------------------------------------- - -using System; - -namespace Eppy -{ - /// - /// Represents a functional tuple that can be used to store - /// two values of different types inside one object. - /// - /// The type of the first element - /// The type of the second element - public sealed class Tuple - { - private readonly T1 item1; - private readonly T2 item2; - - /// - /// Retyurns the first element of the tuple - /// - public T1 Item1 - { - get { return item1; } - } - - /// - /// Returns the second element of the tuple - /// - public T2 Item2 - { - get { return item2; } - } - - /// - /// Create a new tuple value - /// - /// First element of the tuple - /// Second element of the tuple - public Tuple(T1 item1, T2 item2) - { - this.item1 = item1; - this.item2 = item2; - } - - public override string ToString() - { - return string.Format("Tuple({0}, {1})", Item1, Item2); - } - - public override int GetHashCode() - { - int hash = 17; - hash = hash * 23 + (item1 == null ? 0 : item1.GetHashCode()); - hash = hash * 23 + (item2 == null ? 0 : item2.GetHashCode()); - return hash; - } - - public override bool Equals(object o) - { - if (!(o is Tuple)) { - return false; - } - - var other = (Tuple) o; - - return this == other; - } - - public bool Equals(Tuple other) - { - return this == other; - } - - public static bool operator==(Tuple a, Tuple b) - { - if (object.ReferenceEquals(a, null)) { - return object.ReferenceEquals(b, null); - } - if (a.item1 == null && b.item1 != null) return false; - if (a.item2 == null && b.item2 != null) return false; - return - a.item1.Equals(b.item1) && - a.item2.Equals(b.item2); - } - - public static bool operator!=(Tuple a, Tuple b) - { - return !(a == b); - } - - public void Unpack(Action unpackerDelegate) - { - unpackerDelegate(Item1, Item2); - } - } -} \ No newline at end of file diff --git a/impl/Tuple3.cs b/impl/Tuple3.cs deleted file mode 100644 index b510574..0000000 --- a/impl/Tuple3.cs +++ /dev/null @@ -1,107 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). -// -// Used Chapter 3 in http://functional-programming.net/ as a starting point. -// -// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. -// ---------------------------------------------------------------------------- - -using System; - -namespace Eppy -{ - /// - /// Represents a functional tuple that can be used to store - /// two values of different types inside one object. - /// - /// The type of the first element - /// The type of the second element - /// The type of the third element - public sealed class Tuple - { - private readonly T1 item1; - private readonly T2 item2; - private readonly T3 item3; - - /// - /// Retyurns the first element of the tuple - /// - public T1 Item1 - { - get { return item1; } - } - - /// - /// Returns the second element of the tuple - /// - public T2 Item2 - { - get { return item2; } - } - - /// - /// Returns the second element of the tuple - /// - public T3 Item3 - { - get { return item3; } - } - - /// - /// Create a new tuple value - /// - /// First element of the tuple - /// Second element of the tuple - /// Third element of the tuple - public Tuple(T1 item1, T2 item2, T3 item3) - { - this.item1 = item1; - this.item2 = item2; - this.item3 = item3; - } - - public override int GetHashCode() - { - int hash = 17; - hash = hash * 23 + (item1 == null ? 0 : item1.GetHashCode()); - hash = hash * 23 + (item2 == null ? 0 : item2.GetHashCode()); - hash = hash * 23 + (item3 == null ? 0 : item3.GetHashCode()); - return hash; - } - - public override bool Equals(object o) - { - if (!(o is Tuple)) { - return false; - } - - var other = (Tuple)o; - - return this == other; - } - - public static bool operator==(Tuple a, Tuple b) - { - if (object.ReferenceEquals(a, null)) { - return object.ReferenceEquals(b, null); - } - if (a.item1 == null && b.item1 != null) return false; - if (a.item2 == null && b.item2 != null) return false; - if (a.item3 == null && b.item3 != null) return false; - return - a.item1.Equals(b.item1) && - a.item2.Equals(b.item2) && - a.item3.Equals(b.item3); - } - - public static bool operator!=(Tuple a, Tuple b) - { - return !(a == b); - } - - public void Unpack(Action unpackerDelegate) - { - unpackerDelegate(Item1, Item2, Item3); - } - } -} \ No newline at end of file diff --git a/impl/Tuple4.cs b/impl/Tuple4.cs deleted file mode 100644 index 6f0bdc3..0000000 --- a/impl/Tuple4.cs +++ /dev/null @@ -1,122 +0,0 @@ -// ---------------------------------------------------------------------------- -// Tuple structs for use in .NET Not-Quite-3.5 (e.g. Unity3D). -// -// Used Chapter 3 in http://functional-programming.net/ as a starting point. -// -// Note: .NET 4.0 Tuples are immutable classes so they're *slightly* different. -// ---------------------------------------------------------------------------- - -using System; - -namespace Eppy -{ - /// - /// Represents a functional tuple that can be used to store - /// two values of different types inside one object. - /// - /// The type of the first element - /// The type of the second element - /// The type of the third element - /// The type of the fourth element - public sealed class Tuple - { - private readonly T1 item1; - private readonly T2 item2; - private readonly T3 item3; - private readonly T4 item4; - - /// - /// Retyurns the first element of the tuple - /// - public T1 Item1 - { - get { return item1; } - } - - /// - /// Returns the second element of the tuple - /// - public T2 Item2 - { - get { return item2; } - } - - /// - /// Returns the second element of the tuple - /// - public T3 Item3 - { - get { return item3; } - } - - /// - /// Returns the second element of the tuple - /// - public T4 Item4 - { - get { return item4; } - } - - /// - /// Create a new tuple value - /// - /// First element of the tuple - /// Second element of the tuple - /// Third element of the tuple - /// Fourth element of the tuple - public Tuple(T1 item1, T2 item2, T3 item3, T4 item4) - { - this.item1 = item1; - this.item2 = item2; - this.item3 = item3; - this.item4 = item4; - } - - public override int GetHashCode() - { - int hash = 17; - hash = hash * 23 + (item1 == null ? 0 : item1.GetHashCode()); - hash = hash * 23 + (item2 == null ? 0 : item2.GetHashCode()); - hash = hash * 23 + (item3 == null ? 0 : item3.GetHashCode()); - hash = hash * 23 + (item4 == null ? 0 : item4.GetHashCode()); - return hash; - } - - public override bool Equals(object o) - { - if (o.GetType() != typeof(Tuple)) { - return false; - } - - var other = (Tuple)o; - - return this == other; - } - - public static bool operator==(Tuple a, Tuple b) - { - if (object.ReferenceEquals(a, null)) { - return object.ReferenceEquals(b, null); - } - if (a.item1 == null && b.item1 != null) return false; - if (a.item2 == null && b.item2 != null) return false; - if (a.item3 == null && b.item3 != null) return false; - if (a.item4 == null && b.item4 != null) return false; - return - a.item1.Equals(b.item1) && - a.item2.Equals(b.item2) && - a.item3.Equals(b.item3) && - a.item4.Equals(b.item4); - } - - public static bool operator!=(Tuple a, Tuple b) - { - return !(a == b); - } - - public void Unpack(Action unpackerDelegate) - { - unpackerDelegate(Item1, Item2, Item3, Item4); - } - } -} \ No newline at end of file From 655b3e7fb867d364dc5967e3106dcdf09965df46 Mon Sep 17 00:00:00 2001 From: Joseph Parker Date: Sun, 24 Nov 2019 19:47:22 -0500 Subject: [PATCH 11/12] foundation is now on ground, with comments for future 4 sided foundations. Bug fix (adding upstream code that allows higher N with bigger training models) --- impl/OverlappingModel.cs | 43 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/impl/OverlappingModel.cs b/impl/OverlappingModel.cs index f161cc6..f175d28 100644 --- a/impl/OverlappingModel.cs +++ b/impl/OverlappingModel.cs @@ -8,6 +8,7 @@ The above copyright notice and this permission notice shall be included in all c using System; using System.Collections.Generic; +using UnityEngine; class OverlappingModel : Model { @@ -90,7 +91,9 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio }; Dictionary weights = new Dictionary(); - for (int y = 0; y < (periodicInput ? SMY : SMY - N + 1); y++) for (int x = 0; x < (periodicInput ? SMX : SMX - N + 1); x++) + List ordering = new List(); + + for (int y = 0; y < (periodicInput ? SMY : SMY - N + 1); y++) for (int x = 0; x < (periodicInput ? SMX : SMX - N + 1); x++) { byte[][] ps = new byte[8][]; @@ -107,7 +110,10 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio { long ind = index(ps[k]); if (weights.ContainsKey(ind)) weights[ind]++; - else weights.Add(ind, 1); + else { + weights.Add(ind, 1); + ordering.Add(ind); + } } } @@ -118,11 +124,11 @@ public OverlappingModel(byte[,] sample, int N, int width, int height, bool perio base.weights = new double[T]; int counter = 0; - foreach (int w in weights.Keys) + foreach (long w in ordering) { patterns[counter] = patternFromIndex(w); - base.weights[counter] = weights[w]; - counter++; + base.weights[counter] = weights[w]; + counter++; } @@ -169,16 +175,29 @@ public byte Sample(int x, int y){ protected override void Clear() { base.Clear(); - - if (ground != 0) + //here we could actually set ground as all 4 sides possibly, think i need to query which ngram is made from the ground tile index, instead of just using that index into the ngrams + if (ground != 0) { for (int x = 0; x < FMX; x++) { - for (int t = 0; t < T; t++) if (t != ground) Ban(x + (FMY - 1) * FMX, t); - for (int y = 0; y < FMY - 1; y++) Ban(x + y * FMX, ground); - } - - Propagate(); + //top + //for (int t = 0; t < T; t++) if (t != ground) Ban(x + (FMY - 1) * FMX, t); + + //bottom + for (int t = 0; t < T; t++) if (t != ground) Ban(x, t); + + } + + /* for (int y = 0; y < FMY; y++) + { + //right + for (int t = 0; t < T; t++) if (t != ground) Ban((y * FMX) + (FMX - 1), t); + + //left + for (int t = 0; t < T; t++) if (t != ground) Ban(y * FMX, t); + }*/ + + Propagate(); } } } \ No newline at end of file From d1b28923ff3876d211d153e36617195d53c9eeb9 Mon Sep 17 00:00:00 2001 From: Joseph Parker Date: Wed, 4 Nov 2020 20:14:05 -0500 Subject: [PATCH 12/12] use CurrentCulture decimal separator for xml weight floats --- Training.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Training.cs b/Training.cs index b8a3cf2..dc39f8f 100644 --- a/Training.cs +++ b/Training.cs @@ -1,6 +1,7 @@ using System; using System.IO; using UnityEngine; +using System.Globalization; #if UNITY_EDITOR using UnityEditor; #endif @@ -74,7 +75,7 @@ public string NeighborXML(){ if (last == "X" || last == "I" || last == "L" || last == "T" || last == "D"){ sym = last; } - res += "\n"; + res += "\n"; } } res += " \n";