示例#1
0
        public IEnumerable <BasicRule> CompileAllRules(
            Dictionary <string, string> allReplacementDirectives,
            out SystemLevelRuleNativeData ruleNativeData,
            int openSymbol, int closeSymbol
            )
        {
            var allValidRuntimeParameters = allGlobalRuntimeParams.Select(x => x.name).ToArray();
            var parsedRules = allFiles.data
                              .SelectMany((file, index) =>
            {
                Func <char, int> remappingFunction = character => file.GetSymbolInFile(character);
                try
                {
                    return(file.GetRulesWithReplacements(allReplacementDirectives)
                           .Select(x => RuleParser.ParseToRule(x, remappingFunction, (short)index, allValidRuntimeParameters))
                           .ToList());
                }
                catch (SyntaxException ex)
                {
                    ex.fileName = file.fileSource;
                    throw ex;
                }
            })
                              .Where(x => x != null)
                              .ToArray();
            var allRules = RuleParser.CompileAndCheckParsedRules(parsedRules, out ruleNativeData, openSymbol, closeSymbol);

            ruleNativeData.immaturityMarkerSymbols = new NativeHashSet <int>(immaturitySymbolMarkers.Length, Allocator.Persistent);
            foreach (var immature in immaturitySymbolMarkers)
            {
                ruleNativeData.immaturityMarkerSymbols.Add(immature);
            }
            return(allRules);
        }
示例#2
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);
    }
示例#3
0
        public LSystemStepper(
            IEnumerable <BasicRule> rules,
            SystemLevelRuleNativeData nativeRuleData,
            CustomRuleSymbols customSymbols,
            int expectedGlobalParameters = 0,
            ISet <int>[] includedContextualCharactersByRuleIndex = null)
        {
            GlobalParameters = expectedGlobalParameters;

            this.customSymbols = customSymbols;

            includedCharacters = includedContextualCharactersByRuleIndex == null ? new HashSet <int> [0] : includedContextualCharactersByRuleIndex;

            rulesByTargetSymbol = new Dictionary <int, IList <BasicRule> >();
            foreach (var rule in rules)
            {
                var targetSymbols = rule.TargetSymbol;
                if (!rulesByTargetSymbol.TryGetValue(targetSymbols, out var ruleList))
                {
                    rulesByTargetSymbol[targetSymbols] = ruleList = new List <BasicRule>();
                }
                ruleList.Add(rule);
            }

            var maxMemoryRequirementsPerSymbol = new NativeHashMap <int, MaxMatchMemoryRequirements>(rulesByTargetSymbol.Keys.Count(), Allocator.Persistent);

            foreach (var symbol in rulesByTargetSymbol.Keys.ToList())
            {
                rulesByTargetSymbol[symbol] = rulesByTargetSymbol[symbol]
                                              .OrderByDescending(x =>
                                                                 (x.ContextPrefix.IsValid ? x.ContextPrefix.graphNodeMemSpace.length : 0) +
                                                                 (x.ContextSuffix.IsCreated ? x.ContextSuffix.graphNodeMemSpace.length : 0))
                                              .ToList();

                var maxParamCapturedByAnyRule = rulesByTargetSymbol[symbol]
                                                .Select(x => x.CapturedLocalParameterCount)
                                                .DefaultIfEmpty().Max();
                // Greedy estimate for maximum possible parameter match.
                //  there need to be enough space for any rule's parameters to fit, since we don't know which ones will match.
                var maximumPossibleParameterMatch = maxParamCapturedByAnyRule;
                if (maximumPossibleParameterMatch > ushort.MaxValue)
                {
                    throw new LSystemRuntimeException($"Rules with more than {ushort.MaxValue} captured local parameters over all conditional options");
                }
                maxMemoryRequirementsPerSymbol[symbol] = new MaxMatchMemoryRequirements
                {
                    maxParameters = maximumPossibleParameterMatch
                };
            }

            nativeRuleData.blittableRulesByTargetSymbol = NativeOrderedMultiDictionary <BasicRule.Blittable> .WithMapFunction(
                rulesByTargetSymbol,
                rule => rule.AsBlittable(),
                Allocator.Persistent);

            nativeRuleData.maxParameterMemoryRequirementsPerSymbol = maxMemoryRequirementsPerSymbol;
            this.nativeRuleData = new DependencyTracker <SystemLevelRuleNativeData>(nativeRuleData);
        }
示例#4
0
        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]);
            }
        }
    }
示例#6
0
        //TODO: get rid of this function. should only compile from linked files
        public static IEnumerable <BasicRule> CompileRules(
            IEnumerable <string> ruleStrings,
            out SystemLevelRuleNativeData ruleNativeData,
            int branchOpenSymbol, int branchCloseSymbol,
            string[] globalParameters = null)
        {
            var parsedRules = ruleStrings
                              .Select(x => ParseToRule(x, x => x, globalParameters: globalParameters))
                              .Where(x => x != null)
                              .ToArray();
            var rules = CompileAndCheckParsedRules(parsedRules, out ruleNativeData, branchOpenSymbol, branchCloseSymbol);

            ruleNativeData.immaturityMarkerSymbols = new NativeHashSet <int>(0, Allocator.Persistent);
            return(rules);
        }
示例#7
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));
    }
示例#8
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();
        }
    }