public void LSystemSelectsRuleToApplyBasedOnConditional()
    {
        var globalParameters = new string[] { "global" };

        LSystemState <float> state = new DefaultLSystemState("A(0)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A(x) : x < global -> A(x + 1)",
            "A(x) : x >= global -> A(x - 1)",
        }, globalParameters);

        var defaultGlobalParams = new float[] { 3 };

        Assert.AreEqual("A(0)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAppliesReplacementBasedOnGlobalParameters()
    {
        var globalParameters = new string[] { "global" };

        LSystemState <float> state = new DefaultLSystemState("A(1, 1)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A(x, y) -> A((x + y) - global, x * y + global)",
        }, globalParameters);

        var defaultGlobalParams = new float[] { 5 };

        Assert.AreEqual("A(1, 1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(-3, 6)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(-2, -13)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(-20, 31)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(6, -615)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(-614, -3685)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemChecksContidionalBasedOnGlobalParameters()
    {
        var globalParameters = new string[] { "global" };

        LSystemState <float> state = new DefaultLSystemState("A(0)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A(x) : x < global -> A(x + 1)",
        }, globalParameters);

        var defaultGlobalParams = new float[] { 3 };

        Assert.AreEqual("A(0)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());

        var nextGlobalParams = new float[] { 4 };

        state = basicLSystem.StepSystem(state, nextGlobalParams);
        Assert.AreEqual("A(4)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAppliesFlatContextualRules()
    {
        LSystemState <float> state = new DefaultLSystemState("B");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "    A     -> AB",
            "    B     -> A",
            "    A > A ->",
            "A < A     -> B"
        });

        Assert.AreEqual("B", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("AB", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABAAB", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABABA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABAABAAB", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABABABA", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LinksSimpleDependencyAndExecutes()
    {
        var fileSystem = new InMemoryFileProvider();

        fileSystem.RegisterFileWithIdentifier("root.lsystem", @"
#axiom Y
#iterations 10
#symbols XY

#include lib.lsyslib (Exported->X)
Y -> YX
");

        fileSystem.RegisterFileWithIdentifier("lib.lsyslib", @"
#symbols AB
#export Exported B

B -> AB
");
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> currentState = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var X = linkedFiles.GetSymbol("root.lsystem", 'X');
        var Y = linkedFiles.GetSymbol("root.lsystem", 'Y');
        var A = linkedFiles.GetSymbol("lib.lsyslib", 'A');
        var B = linkedFiles.GetSymbol("lib.lsyslib", 'B');

        Assert.AreEqual(B, X);

        var symbolStringMapping = new Dictionary <int, char>()
        {
            { X, 'X' },
            { Y, 'Y' },
            { A, 'A' }
        };

        /**
         * system equivalent with remapped symbol names:
         * Y -> YX
         * X -> AX
         */

        Assert.AreEqual("Y", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("YX", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("YXAX", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("YXAXAAX", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("YXAXAAXAAAX", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState.currentSymbols.DisposeImmediate();
    }
    public void LinksBuiltinLibraryAndExecutes()
    {
        var builtins = new BuiltinLibraries();

        builtins.Add(new DiffusionLibrary());

        var fileSystem = new InMemoryFileProvider(builtins);

        fileSystem.RegisterFileWithIdentifier("root.lsystem", @"
#axiom n(0.5, 0, 10)ST(3)
#iterations 10
#symbols naFTS

#include diffusion (Node->n) (Amount->a)

T(x) : x > 0 -> n(.5, 0, 10)FT(x - 1)
S -> a(3)S
");
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> currentState = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var n = linkedFiles.GetSymbol("root.lsystem", 'n');
        var a = linkedFiles.GetSymbol("root.lsystem", 'a');
        var F = linkedFiles.GetSymbol("root.lsystem", 'F');
        var T = linkedFiles.GetSymbol("root.lsystem", 'T');
        var S = linkedFiles.GetSymbol("root.lsystem", 'S');

        var symbolStringMapping = new Dictionary <int, char>()
        {
            { n, 'n' },
            { a, 'a' },
            { F, 'F' },
            { T, 'T' },
            { S, 'S' },
        };

        Assert.AreEqual("n(0.5, 0, 10)ST(3)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.5, 0, 10)a(3)Sn(0.5, 0, 10)FT(2)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.5, 1.5, 10)aa(3)Sn(0.5, 1.5, 10)Fn(0.5, 0, 10)FT(1)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.5, 3, 10)aa(3)Sn(0.5, 2.25, 10)Fn(0.5, 0.75, 10)Fn(0.5, 0, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.5, 4.125, 10)aa(3)Sn(0.5, 3.375, 10)Fn(0.5, 1.125, 10)Fn(0.5, 0.375, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.5, 5.25, 10)aa(3)Sn(0.5, 4.125, 10)Fn(0.5, 1.875, 10)Fn(0.5, 0.75, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.5, 6.1875, 10)aa(3)Sn(0.5, 5.0625, 10)Fn(0.5, 2.4375, 10)Fn(0.5, 1.3125, 10)FT(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping));

        currentState.currentSymbols.DisposeImmediate();
    }
    public void LinksBuiltinLibraryWithCustomParameterAndExecutes()
    {
        var builtins = new BuiltinLibraries();

        builtins.Add(new DiffusionLibrary());

        var fileSystem = new InMemoryFileProvider(builtins);

        fileSystem.RegisterFileWithIdentifier("root.lsystem", @"
#axiom n(0.25, 18, 20)Fn(0.25, 0, 20)Fn(0.25, 0, 20)
#iterations 10
#symbols naF

#define diffusionStepsPerStep 2
#include diffusion (Node->n) (Amount->a)

");
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> currentState = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var n = linkedFiles.GetSymbol("root.lsystem", 'n');
        var a = linkedFiles.GetSymbol("root.lsystem", 'a');
        var F = linkedFiles.GetSymbol("root.lsystem", 'F');

        var symbolStringMapping = new Dictionary <int, char>()
        {
            { n, 'n' },
            { a, 'a' },
            { F, 'F' },
        };

        Assert.AreEqual("n(0.25, 18, 20)Fn(0.25, 0, 20)Fn(0.25, 0, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 11.25, 20)Fn(0.25, 5.625, 20)Fn(0.25, 1.125, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 8.859375, 20)Fn(0.25, 5.976563, 20)Fn(0.25, 3.164063, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 7.602539, 20)Fn(0.25, 5.998535, 20)Fn(0.25, 4.398926, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 6.901062, 20)Fn(0.25, 5.999908, 20)Fn(0.25, 5.09903, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 6.506824, 20)Fn(0.25, 5.999994, 20)Fn(0.25, 5.493181, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 6.285088, 20)Fn(0.25, 6, 20)Fn(0.25, 5.714913, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 6.160362, 20)Fn(0.25, 6, 20)Fn(0.25, 5.839638, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("n(0.25, 6.090203, 20)Fn(0.25, 6, 20)Fn(0.25, 5.909797, 20)", currentState.currentSymbols.Data.ToString(symbolStringMapping));

        currentState.currentSymbols.DisposeImmediate();
    }
    public void CompilesWithImmaturityMarkers()
    {
        var fileSystem = new InMemoryFileProvider();

        fileSystem.RegisterFileWithIdentifier("root.lsystem", @"
#axiom Y(2)
#iterations 20
#symbols XY

#immature Y
Y(x) : x > 0 -> Y(x - 1)
Y(x) : x <= 0 -> X
");
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> currentState = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var X = linkedFiles.GetSymbol("root.lsystem", 'X');
        var Y = linkedFiles.GetSymbol("root.lsystem", 'Y');

        var symbolStringMapping = new Dictionary <int, char>()
        {
            { X, 'X' },
            { Y, 'Y' }
        };

        /**
         * system equivalent with remapped symbol names:
         * Y -> YX
         * X -> AX
         */

        Assert.AreEqual("Y(2)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(1)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        Assert.IsTrue(currentState.hasImmatureSymbols);

        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        Assert.IsTrue(currentState.hasImmatureSymbols);

        currentState = system.StepSystem(currentState);
        Assert.AreEqual("X", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        Assert.IsFalse(currentState.hasImmatureSymbols);

        currentState = system.StepSystem(currentState);
        Assert.AreEqual("X", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        Assert.IsFalse(currentState.hasImmatureSymbols);

        currentState.currentSymbols.DisposeImmediate();
    }
    public void SymbolStringParsesStringAxiom()
    {
        var systemState = new DefaultLSystemState("B");

        Assert.AreEqual("B", systemState.currentSymbols.Data.ToString());
        Assert.AreEqual(new JaggedIndexing
        {
            index  = 0,
            length = 0
        }, systemState.currentSymbols.Data.parameters.indexing[0]);
        Assert.AreEqual(0, systemState.currentSymbols.Data.parameters.data.Length);
        systemState.currentSymbols.Dispose();
    }
    public void LSystemMatchesParametricWithVariedConditionals()
    {
        var globalParameters = new string[] { "global" };

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A(x, y) > B(z, a) : x <  global && y <= z -> A(x, y)",
            "A(x, y) > B(z, a) : x <  global && y >  z -> B(x, y)",
            "A(x, y) > B(z, a) : x >= global && y <= z -> A(z, a)",
            "A(x, y) > B(z, a) : x >= global && y >  z -> B(z, a)",
            "A(x)    > B(y, z) : x >= global && y <= z -> A(z, x)",
            "A(x)    > B(y, z) : x >= global && y >  z -> B(z, x)",
        }, globalParameters);

        var defaultGlobalParams = new float[] { 3 };

        LSystemState <float> state = new DefaultLSystemState("A(0, 5)B(10, 15)");

        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(0, 5)B(10, 15)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("A(0, 5)B(3, 15)");
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("B(0, 5)B(3, 15)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("A(4, 5)B(10, 15)");
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(10, 15)B(10, 15)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("A(4, 5)B(3, 15)");
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("B(3, 15)B(3, 15)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("A(4)B(5, 10)");
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(10, 4)B(5, 10)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("A(4)B(10, 5)");
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("B(5, 4)B(10, 5)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("A(1)B(10, 5)");
        state = basicLSystem.StepSystem(state, defaultGlobalParams);
        Assert.AreEqual("A(1)B(10, 5)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
Exemple #11
0
    public void TestLSystemFile(
        string fileText,
        IEnumerable <string> expectedSteps)
    {
        var fileSystem = new InMemoryFileProvider();

        fileSystem.RegisterFileWithIdentifier("root.lsystem", fileText);

        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> state = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var symbolStringMapping = linkedFiles.allSymbolDefinitionsLeafFirst
                                  .Where(x => x.sourceFileDefinition == "root.lsystem")
                                  .ToDictionary(x => x.actualSymbol, x => x.characterInSourceFile);

        using var axiom = linkedFiles.GetAxiom();
        Assert.AreEqual(axiom.ToString(symbolStringMapping), state.currentSymbols.Data.ToString(symbolStringMapping));
        try
        {
            foreach (var expectedStep in expectedSteps)
            {
                state = system.StepSystem(state);
                Assert.AreEqual(expectedStep, state.currentSymbols.Data.ToString(symbolStringMapping));
            }
        }
        catch (System.Exception e)
        {
            UnityEngine.Debug.LogException(e);
            UnityEngine.Debug.Log("actual result:");
            state.currentSymbols.DisposeImmediate();
            state = new DefaultLSystemState(
                linkedFiles.GetAxiom(),
                (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));
            for (int i = 0; i < expectedSteps.Count(); i++)
            {
                state = system.StepSystem(state);
                UnityEngine.Debug.Log(state.currentSymbols.Data.ToString(symbolStringMapping));
            }
            throw;
        }
        finally
        {
            state.currentSymbols.DisposeImmediate();
        }
    }
    public void LinkCompilesBranchingSymbolWithContextMatches()
    {
        var fileSystem = new InMemoryFileProvider();

        fileSystem.RegisterFileWithIdentifier("root.lsystem", @"
#axiom AF[FB]
#iterations 10
#symbols FAB
#matches AB

#symbols CD
#matches CD
    A > [B] -> C
A < B     -> D
");
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> currentState = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var lBracket = linkedFiles.GetSymbol("root.lsystem", '[');
        var rBracket = linkedFiles.GetSymbol("root.lsystem", ']');
        var FRoot    = linkedFiles.GetSymbol("root.lsystem", 'F');
        var ARoot    = linkedFiles.GetSymbol("root.lsystem", 'A');
        var BRoot    = linkedFiles.GetSymbol("root.lsystem", 'B');
        var CRoot    = linkedFiles.GetSymbol("root.lsystem", 'C');
        var DRoot    = linkedFiles.GetSymbol("root.lsystem", 'D');


        var symbolStringMapping = new Dictionary <int, char>()
        {
            { lBracket, '[' },
            { rBracket, ']' },
            { FRoot, 'F' },
            { ARoot, 'A' },
            { BRoot, 'B' },
            { CRoot, 'C' },
            { DRoot, 'D' }
        };

        Assert.AreEqual("AF[FB]", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("CF[FD]", currentState.currentSymbols.Data.ToString(symbolStringMapping));


        currentState.currentSymbols.DisposeImmediate();
    }
Exemple #13
0
    public void DiffusionRateCanChangeAtRuntime()
    {
        var testFile = @"
#axiom n(0.5, 0, 10)Fn(0.5, 0, 10)Fn(0.5, 8, 10)
#iterations 10
#symbols Fna
#define diffusionStepsPerStep 1
#include diffusion (Node->n) (Amount->a)
";


        var fileSystem = new InMemoryFileProvider();

        fileSystem.RegisterFileWithIdentifier("root.lsystem", testFile);
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();

        LSystemState <float> state = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var symbolStringMapping = linkedFiles.allSymbolDefinitionsLeafFirst
                                  .Where(x => x.sourceFileDefinition == "root.lsystem")
                                  .ToDictionary(x => x.actualSymbol, x => x.characterInSourceFile);

        using var axiom = linkedFiles.GetAxiom();
        Assert.AreEqual(axiom.ToString(symbolStringMapping), state.currentSymbols.Data.ToString(symbolStringMapping));
        try
        {
            state = system.StepSystem(state);
            Assert.AreEqual("n(0.5, 0, 10)Fn(0.5, 4, 10)Fn(0.5, 4, 10)", state.currentSymbols.Data.ToString(symbolStringMapping));

            system.customSymbols.diffusionConstantRuntimeGlobalMultiplier = 0.5f;
            state = system.StepSystem(state);
            Assert.AreEqual("n(0.5, 1, 10)Fn(0.5, 3, 10)Fn(0.5, 4, 10)", state.currentSymbols.Data.ToString(symbolStringMapping));

            state = system.StepSystem(state);
            Assert.AreEqual("n(0.5, 1.5, 10)Fn(0.5, 2.75, 10)Fn(0.5, 3.75, 10)", state.currentSymbols.Data.ToString(symbolStringMapping));

            system.customSymbols.diffusionConstantRuntimeGlobalMultiplier = 1f;
            state = system.StepSystem(state);
            Assert.AreEqual("n(0.5, 2.125, 10)Fn(0.5, 2.625, 10)Fn(0.5, 3.25, 10)", state.currentSymbols.Data.ToString(symbolStringMapping));
        }
        finally
        {
            state.currentSymbols.DisposeImmediate();
        }
    }
    public void LSystemAppliesContextualRulesWithInitialBranching()
    {
        LSystemState <float> state = new DefaultLSystemState("AF[FB]");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "    A > [B] -> C",
        }, includedCharacters: "AB");

        Assert.AreEqual("AF[FB]", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("CF[FB]", state.currentSymbols.Data.ToString());

        state.currentSymbols.Dispose();
    }
    public void LSystemPrioritizesContextualRulesBySize()
    {
        LSystemState <float> state = new DefaultLSystemState("AABCD");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A -> B",
            "A > A -> C",
            "A > ABCD -> F",
            "A > ABC -> E",
            "A > AB -> D",
        });

        Assert.AreEqual("AABCD", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("FBBCD", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemReproducesStochasticResultFromReplicatedState()
    {
        var globalParameters = new string[] { "global" };

        LSystemState <float> state = new DefaultLSystemState("A(0)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "P(0.5) | A(x) : x < global -> A(x + 1)",
            "P(0.5) | A(x) : x < global -> A(x + 0.5)",
            "P(0.5) | A(x) : x >= global -> A(x - 1)",
            "P(0.5) | A(x) : x >= global -> A(x - 0.5)",
        }, globalParameters);

        var defaultGlobalParams = new float[] { 3 };

        var resultSequence   = new List <string>();
        var resultSampleSize = 12;

        resultSequence.Add(state.currentSymbols.Data.ToString());

        LSystemState <float> systemCopyAt5 = null;

        for (int i = 1; i < resultSampleSize; i++)
        {
            if (i == 5)
            {
                systemCopyAt5 = state;
                state         = basicLSystem.StepSystem(state, defaultGlobalParams, false);
            }
            else
            {
                state = basicLSystem.StepSystem(state, defaultGlobalParams);
            }
            resultSequence.Add(state.currentSymbols.Data.ToString());
        }
        state.currentSymbols.Dispose();

        for (int i = 5; i < resultSampleSize; i++)
        {
            systemCopyAt5 = basicLSystem.StepSystem(systemCopyAt5, defaultGlobalParams);
            Assert.AreEqual(resultSequence[i], systemCopyAt5.currentSymbols.Data.ToString(), $"Index {i}");
        }
        systemCopyAt5.currentSymbols.Dispose();
    }
    public void LSystemAppliesParameterMatches()
    {
        LSystemState <float> state = new DefaultLSystemState("A(1)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A(x) -> A(x + 1)",
        });

        Assert.AreEqual("A(1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(3)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(4)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(5)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAppliesComplexParameterEquations()
    {
        LSystemState <float> state = new DefaultLSystemState("A(1, 1)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A(x, y) -> A(x + y, x * y)",
        });

        Assert.AreEqual("A(1, 1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(2, 1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(3, 2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(5, 6)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(11, 30)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAssumesIdentityRule()
    {
        LSystemState <float> state = new DefaultLSystemState("B");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A -> ACB",
            "B -> A"
        });

        Assert.AreEqual("B", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ACB", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ACBCA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ACBCACACB", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    private void AssertStochasticResults(LSystemStepper system, string axiom, string[] expectedResults, float[] globalParams = null)
    {
        var resultSet     = new HashSet <string>();
        var attemptSeeder = new Unity.Mathematics.Random((uint)axiom.GetHashCode());
        var attempts      = expectedResults.Length * 10;

        for (int attempt = 1; attempt < attempts; attempt++)
        {
            LSystemState <float> state = new DefaultLSystemState(axiom, attemptSeeder.NextUInt());
            state = system.StepSystem(state, globalParams);
            resultSet.Add(state.currentSymbols.Data.ToString());
            state.currentSymbols.Dispose();
        }
        Assert.AreEqual(expectedResults.Length, resultSet.Count);
        for (int i = 0; i < expectedResults.Length; i++)
        {
            var expected = expectedResults[i];
            Assert.IsTrue(resultSet.Contains(expected), $"Generated states should contain stochastic result {expected}");
        }
    }
    public void LSystemAssumesIdentityReplacementWithContextRules()
    {
        LSystemState <float> state = new DefaultLSystemState("B");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "B -> ABA",
            "A > A ->",
            "A < A -> B"
        });

        Assert.AreEqual("B", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("AABAA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("BABAB", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABAAABAAABA", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemDoesAFibbonachi()
    {
        LSystemState <float> state = new DefaultLSystemState("A(1)B(1)");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "       A(x) > B(y) -> A(x + y)",
            "A(x) < B(y)        -> B(x)",
        });

        Assert.AreEqual("A(1)B(1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(2)B(1)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(3)B(2)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(5)B(3)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(8)B(5)", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A(13)B(8)", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAppliesContextualRulesOfEqualComplexityInDefinitionOrder()
    {
        LSystemState <float> state = new DefaultLSystemState("AAA");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "    A > A -> B",
            "A < A     -> C"
        });
        Assert.AreEqual("AAA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("BBC", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();

        state = new DefaultLSystemState("AAA");
        using var basicLSystem2 = LSystemBuilder.FloatSystem(new string[] {
            "A < A     -> C",
            "    A > A -> B"
        });
        Assert.AreEqual("AAA", state.currentSymbols.Data.ToString());
        state = basicLSystem2.StepSystem(state);
        Assert.AreEqual("BCC", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAppliesStochasticRuleDifferently()
    {
        LSystemState <float> state = new DefaultLSystemState("C");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "A -> AC",
            "P(0.9) | C -> A",
            "P(0.1) | C -> AB"
        });

        Assert.AreEqual("C", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("A", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("AC", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ACA", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ACAAC", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ACAACACA", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemIgnoresIgnoredCharatchers()
    {
        LSystemState <float> state = new DefaultLSystemState("B");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "    A     -> A1B2",
            "    B     -> 3A4",
            "    A > A -> 5",
            "A < A     -> 6B7"
        }, includedCharacters: "AB");

        Assert.AreEqual("B", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("3A4", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("3A1B24", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("3A1B213A424", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("3A1B213A4213A1B2424", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("3A1B213A4213542136B713A42424", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LSystemAppliesContextualRulesWithUniqueOrigins()
    {
        LSystemState <float> state = new DefaultLSystemState("A");

        using var basicLSystem = LSystemBuilder.FloatSystem(new string[] {
            "    A     -> AB",
            "    B     -> CDC",
            "    D > C -> A",
            "D < C > D -> B"
        });

        Assert.AreEqual("A", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("AB", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABCDC", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABCDCCAC", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABCDCCACCABC", state.currentSymbols.Data.ToString());
        state = basicLSystem.StepSystem(state);
        Assert.AreEqual("ABCDCCACCABCCABCDCC", state.currentSymbols.Data.ToString());
        state.currentSymbols.Dispose();
    }
    public void LinksDependencyWithContextualMatchesAndIgnoresNonImportedSymbols()
    {
        var fileSystem = new InMemoryFileProvider();

        fileSystem.RegisterFileWithIdentifier("root.lsystem", @"
#axiom Y(0)A(3)
#iterations 10
#symbols XYA
#matches XYA

#include nodes.lsyslib (Node->X) (Root->Y)
A(x) : x > 0 -> I(2)[X(x)]A(x - 1)
A(x) : x <= 0 -> J

#symbols IFJ
#matches IJ
I(x) : x > 0 -> I(x - 1)F
J -> 
I(x) > J -> JI(x)
");

        fileSystem.RegisterFileWithIdentifier("nodes.lsyslib", @"
#symbols AB
#matches AB
#export Node B
#export Root A

A(y) < B(x) : x > 0 -> B(x - 1)
       A(x) > [B(y)] : y > 0 -> A(x + 1)
       A(x) > [B(y)][B(z)] : y > 0 && z > 0 -> A(x + 2)
       A(x) > [B(y)][B(z)][B(a)] : y > 0 && z > 0 && a > 0 -> A(x + 3)
       A(x) > [B(y)][B(z)][B(a)][B(b)] : y > 0 && z > 0 && a > 0 && b > 0 -> A(x + 4)

");
        var linker      = new FileLinker(fileSystem);
        var linkedFiles = linker.LinkFiles("root.lsystem");

        using var system = linkedFiles.CompileSystem();
        LSystemState <float> currentState = new DefaultLSystemState(
            linkedFiles.GetAxiom(),
            (uint)UnityEngine.Random.Range(int.MinValue, int.MaxValue));

        var lBracket = linkedFiles.GetSymbol("root.lsystem", '[');
        var rBracket = linkedFiles.GetSymbol("root.lsystem", ']');
        var XRoot    = linkedFiles.GetSymbol("root.lsystem", 'X');
        var YRoot    = linkedFiles.GetSymbol("root.lsystem", 'Y');
        var ARoot    = linkedFiles.GetSymbol("root.lsystem", 'A');
        var IRoot    = linkedFiles.GetSymbol("root.lsystem", 'I');
        var FRoot    = linkedFiles.GetSymbol("root.lsystem", 'F');
        var JRoot    = linkedFiles.GetSymbol("root.lsystem", 'J');
        var Alib     = linkedFiles.GetSymbol("nodes.lsyslib", 'A');
        var Blib     = linkedFiles.GetSymbol("nodes.lsyslib", 'B');

        Assert.AreEqual(Alib, YRoot);
        Assert.AreEqual(Blib, XRoot);

        var symbolStringMapping = new Dictionary <int, char>()
        {
            { lBracket, '[' },
            { rBracket, ']' },
            { XRoot, 'X' },
            { YRoot, 'Y' },
            { ARoot, 'A' },
            { IRoot, 'I' },
            { FRoot, 'F' },
            { JRoot, 'J' }
        };

        Assert.AreEqual("Y(0)A(3)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(0)I(2)[X(3)]A(2)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(1)I(1)F[X(2)]I(2)[X(2)]A(1)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(3)I(0)FF[X(1)]I(1)F[X(1)]I(2)[X(1)]A(0)", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(6)I(0)FF[X(0)]I(0)FF[X(0)]I(1)F[X(0)]J", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(6)I(0)FF[X(0)]I(0)FF[X(0)]JI(1)F[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(6)I(0)FF[X(0)]JI(0)FF[X(0)]I(0)FF[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(6)JI(0)FF[X(0)]I(0)FF[X(0)]I(0)FF[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping));
        currentState = system.StepSystem(currentState);
        Assert.AreEqual("Y(6)I(0)FF[X(0)]I(0)FF[X(0)]I(0)FF[X(0)]", currentState.currentSymbols.Data.ToString(symbolStringMapping));


        currentState.currentSymbols.DisposeImmediate();
    }