Exemple #1
0
    private void AssertRuleDoesNotMatchCondtitional(
        string ruleText,
        int[] sourceSymbols        = null,
        float[][] sourceParameters = null,
        string axiom = null,
        int ruleParamMemoryStartIndex = 0,
        int matchIndex            = 0,
        int paramTempMemorySize   = 0,
        float[] globalParams      = null,
        string[] globalParamNames = null,
        string includedSymbols    = "[]ABCDE"
        )
    {
        var totalIncluded = new HashSet <int>(includedSymbols.Select(x => (int)x));

        globalParamNames  = globalParamNames ?? new string[0];
        using var symbols = new DependencyTracker <SymbolString <float> >(
                  axiom == null ?
                  new SymbolString <float>(sourceSymbols, sourceParameters)
            : SymbolString <float> .FromString(axiom, Allocator.Persistent)
                  );
        var ruleFromString = new BasicRule(
            RuleParser.ParseToRule(ruleText, x => x, globalParameters: globalParamNames),
            '[', ']');

        using var ruleNativeData = new SystemLevelRuleNativeData(new[] { ruleFromString });
        var nativeWriter = new SymbolSeriesMatcherNativeDataWriter();

        ruleFromString.WriteDataIntoMemory(ruleNativeData, nativeWriter);

        globalParams           = globalParams ?? new float[0];
        using var globalNative = new NativeArray <float>(globalParams, Allocator.Persistent);

        using var paramMemory = new NativeArray <float>(paramTempMemorySize, Allocator.Persistent);
        using var branchCache = new SymbolStringBranchingCache('[', ']', new[] { totalIncluded }, ruleNativeData);
        branchCache.BuildJumpIndexesFromSymbols(symbols);
        var random          = new Unity.Mathematics.Random();
        var matchSingleData = new LSystemSingleSymbolMatchData
        {
            isTrivial = false,
            tmpParameterMemorySpace = JaggedIndexing.GetWithNoLength(ruleParamMemoryStartIndex)
        };

        var potentialMatch = ruleFromString.AsBlittable().PreMatchCapturedParametersWithoutConditional(
            branchCache,
            symbols.Data,
            matchIndex,
            paramMemory,
            matchSingleData.tmpParameterMemorySpace.index,
            ref matchSingleData,
            new TmpNativeStack <SymbolStringBranchingCache.BranchEventData>(5),
            globalNative,
            ruleNativeData.dynamicOperatorMemory,
            ref random,
            ruleNativeData.ruleOutcomeMemorySpace
            );

        Assert.IsFalse(potentialMatch);
    }
        public static IEnumerable <BasicRule> CompileAndCheckParsedRules(
            ParsedRule[] parsedRules,
            out SystemLevelRuleNativeData ruleNativeData,
            int branchOpenSymbol, int branchCloseSymbol)
        {
            var basicRules = parsedRules.Where(r => !(r is ParsedStochasticRule))
                             .Select(x => new BasicRule(x, branchOpenSymbol, branchCloseSymbol)).ToList();

            IEqualityComparer <ParsedRule> ruleComparer = new ParsedRuleEqualityComparer();

#if UNITY_EDITOR
            for (int i = 0; i < parsedRules.Length; i++)
            {
                if (parsedRules[i] is ParsedStochasticRule)
                {
                    continue;
                }
                for (int j = i + 1; j < parsedRules.Length; j++)
                {
                    if (parsedRules[j] is ParsedStochasticRule)
                    {
                        continue;
                    }
                    if (ruleComparer.Equals(parsedRules[i], parsedRules[j]))
                    {
                        throw new LSystemRuntimeException($"Cannot have two non-stochastic rules matching the same symbols. matching rules: {parsedRules[i]} {parsedRules[j]}");
                    }
                }
            }
#endif

            var stochasticRules = parsedRules.Where(r => r is ParsedStochasticRule)
                                  .Select(x => x as ParsedStochasticRule)
                                  .GroupBy(x => x, ruleComparer)
                                  .Select(group =>
            {
                var probabilityDeviation = System.Math.Abs(group.Sum(x => x.probability) - 1);
                if (probabilityDeviation > 1e-5)
                {
                    throw new LSystemRuntimeException($"Error: probability is {probabilityDeviation} away from 1 in rule group {group.Key.TargetSymbolString()}");
                }
                return(new BasicRule(group, branchOpenSymbol, branchCloseSymbol));
            }).ToList();


            var allRules = basicRules.Concat(stochasticRules).ToArray();
            ruleNativeData = new SystemLevelRuleNativeData(allRules);
            var nativeWriter = new SymbolSeriesMatcherNativeDataWriter();

            foreach (var rule in allRules)
            {
                rule.WriteDataIntoMemory(ruleNativeData, nativeWriter);
            }

            return(allRules);
        }
    private void AssertBackwardsMatch(
        string target,
        string matcher,
        bool shouldMatch,
        string includeSymbols              = "[]ABCDEFJ",
        int parameterMemorySize            = 10,
        float[] expectedCapturedParameters = null,
        int indexInTarget = -1)
    {
        var includedSymbolSet = includeSymbols.Select(x => (int)x);

        var prefixBuilder = SymbolSeriesPrefixBuilder.Parse(matcher);

        using var nativeData = new SystemLevelRuleNativeData(new RuleDataRequirements
        {
            prefixNodes = prefixBuilder.RequiredNodeMemorySpace
        });
        var writer = new SymbolSeriesMatcherNativeDataWriter();

        var seriesMatcher = prefixBuilder.BuildIntoManagedMemory(nativeData, writer);

        using var targetString   = new DependencyTracker <SymbolString <float> >(SymbolString <float> .FromString(target));
        using var branchingCache = new SymbolStringBranchingCache(
                  '[', ']',
                  includedSymbolSet == null ? new HashSet <int> [0] : new[] { new HashSet <int>(includedSymbolSet) },
                  nativeData);
        branchingCache.BuildJumpIndexesFromSymbols(targetString);
        using var parameterMemory = new NativeArray <float>(parameterMemorySize, Allocator.Persistent);


        var realIndex  = indexInTarget < 0 ? indexInTarget + targetString.Data.Length : indexInTarget;
        var hasMatched = branchingCache.MatchesBackwards(
            branchingCache.includeSymbols[0],
            realIndex,
            seriesMatcher,
            targetString.Data,
            0,
            parameterMemory,
            out var copiedParams);

        if (shouldMatch != hasMatched)
        {
            Assert.Fail($"Expected '{matcher}' to {(shouldMatch ? "" : "not ")}match backwards from {indexInTarget} in '{target}'");
        }
        if (shouldMatch && expectedCapturedParameters != null)
        {
            Assert.AreEqual(expectedCapturedParameters.Length, copiedParams);
            for (int i = 0; i < expectedCapturedParameters.Length; i++)
            {
                Assert.AreEqual(expectedCapturedParameters[i], parameterMemory[i]);
            }
        }
    }
Exemple #4
0
    public static SymbolSeriesSuffixMatcher GenerateSingleMatcher(
        string matchPattern,
        out SystemLevelRuleNativeData nativeData)
    {
        var builder = SymbolSeriesSuffixBuilder.Parse(matchPattern);

        builder.BuildGraphIndexes('[', ']');

        nativeData = new SystemLevelRuleNativeData(new RuleDataRequirements
        {
            suffixChildren   = builder.RequiredChildrenMemSpace,
            suffixGraphNodes = builder.RequiredGraphNodeMemSpace
        });
        var writer = new SymbolSeriesMatcherNativeDataWriter();

        return(builder.BuildIntoManagedMemory(nativeData, writer));
    }
Exemple #5
0
    public void BasicRuleRejectsApplicationIfAnyParameters()
    {
        var ruleFromString = new BasicRule(
            RuleParser.ParseToRule("A -> AB", x => x),
            '[', ']');
        var totalIncluded = new HashSet <int>("[]AB".Select(x => (int)x));

        using var ruleNativeData = new SystemLevelRuleNativeData(new[] { ruleFromString });
        var nativeWriter = new SymbolSeriesMatcherNativeDataWriter();

        ruleFromString.WriteDataIntoMemory(ruleNativeData, nativeWriter);

        var symbols = new DependencyTracker <SymbolString <float> >(
            new SymbolString <float>(new int[] { 'A' }, new float[][] { new float[0] })
            );

        try
        {
            var globalParams = new float[0];
            using var globalNative = new NativeArray <float>(globalParams, Allocator.Persistent);
            using var paramMemory  = new NativeArray <float>(0, Allocator.Persistent);
            using var branchCache  = new SymbolStringBranchingCache('[', ']', new[] { totalIncluded }, ruleNativeData);
            branchCache.BuildJumpIndexesFromSymbols(symbols);
            var random          = new Unity.Mathematics.Random();
            var matchSingleData = new LSystemSingleSymbolMatchData
            {
                isTrivial = false,
                tmpParameterMemorySpace = JaggedIndexing.GetWithNoLength(0)
            };

            var preMatchSuccess = ruleFromString.AsBlittable().PreMatchCapturedParametersWithoutConditional(
                branchCache,
                symbols.Data,
                0,
                paramMemory,
                matchSingleData.tmpParameterMemorySpace.index,
                ref matchSingleData,
                new TmpNativeStack <SymbolStringBranchingCache.BranchEventData>(5),
                globalNative,
                ruleNativeData.dynamicOperatorMemory,
                ref random,
                ruleNativeData.ruleOutcomeMemorySpace
                );
            Assert.IsTrue(preMatchSuccess);
            Assert.AreEqual(0, matchSingleData.selectedReplacementPattern);
            Assert.AreEqual(0, matchSingleData.tmpParameterMemorySpace.length);
            Assert.AreEqual(2, matchSingleData.replacementSymbolIndexing.length);
            Assert.AreEqual(0, matchSingleData.replacementParameterIndexing.length);

            var symbolRawData = symbols.Data;
            symbolRawData.parameters[0] = new JaggedIndexing
            {
                index  = 0,
                length = 1
            };

            matchSingleData = new LSystemSingleSymbolMatchData
            {
                isTrivial = false,
                tmpParameterMemorySpace = JaggedIndexing.GetWithNoLength(0)
            };
            preMatchSuccess = ruleFromString.AsBlittable().PreMatchCapturedParametersWithoutConditional(
                branchCache,
                symbols.Data,
                0,
                paramMemory,
                matchSingleData.tmpParameterMemorySpace.index,
                ref matchSingleData,
                new TmpNativeStack <SymbolStringBranchingCache.BranchEventData>(5),
                globalNative,
                ruleNativeData.dynamicOperatorMemory,
                ref random,
                ruleNativeData.ruleOutcomeMemorySpace
                );
            Assert.IsFalse(preMatchSuccess);
        }
        finally
        {
            symbols.Dispose();
        }
    }