public Network(NetworkBuilder builder, StateOptimizer optimizer, IEnumerable <RuleBinding> rules, Dictionary <int, RuleBinding> stateRules, Dictionary <int, RuleBinding> contextRules)
        {
            Contract.Requires <ArgumentNullException>(builder != null, "builder");
            Contract.Requires <ArgumentNullException>(optimizer != null, "optimizer");
            Contract.Requires <ArgumentNullException>(rules != null, "rules");

            _builder = builder;
            _rules   = new List <RuleBinding>(rules);

            //Dictionary<int, string> stateRules = new Dictionary<int, string>();
            //foreach (var rule in _rules)
            //{
            //    stateRules[rule.StartState.Id] = rule.Name;
            //    stateRules[rule.EndState.Id] = rule.Name;
            //}

            HashSet <State>      states      = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default);
            HashSet <Transition> transitions = new HashSet <Transition>(ObjectReferenceEqualityComparer <Transition> .Default);

            foreach (var rule in _rules)
            {
                ExtractStatesAndTransitions(optimizer, rule, rule.StartState, states, transitions, stateRules, contextRules);
                //ExtractStatesAndTransitions(rule.Name, rule.EndState, states, transitions, stateRules, contextRules);
            }

            _states       = states.ToDictionary(i => i.Id);
            _transitions  = new List <Transition>(transitions);
            _stateRules   = stateRules;
            _contextRules = contextRules;
            _optimizer    = optimizer;
        }
        protected virtual void GetRuleStates(StateOptimizer optimizer, RuleBinding ruleName, State state, Dictionary <int, RuleBinding> stateRules)
        {
            if (stateRules.ContainsKey(state.Id))
            {
                return;
            }

            stateRules[state.Id] = ruleName;

            foreach (var transition in state.OutgoingTransitions)
            {
                if (transition is PopContextTransition)
                {
                    continue;
                }

                PushContextTransition contextTransition = transition as PushContextTransition;
                if (contextTransition != null)
                {
                    foreach (var popTransition in optimizer.GetPopContextTransitions(contextTransition))
                    {
                        GetRuleStates(optimizer, ruleName, popTransition.TargetState, stateRules);
                    }
                }
                else
                {
                    GetRuleStates(optimizer, ruleName, transition.TargetState, stateRules);
                }
            }
        }
Beispiel #3
0
        public Network([NotNull] NetworkBuilder builder, [NotNull] StateOptimizer optimizer, [NotNull] IEnumerable <RuleBinding> rules, Dictionary <int, RuleBinding> stateRules, Dictionary <int, RuleBinding> contextRules)
        {
            Requires.NotNull(builder, nameof(builder));
            Requires.NotNull(optimizer, nameof(optimizer));
            Requires.NotNull(rules, nameof(rules));

            _builder = builder;
            _rules   = new List <RuleBinding>(rules);

            //Dictionary<int, string> stateRules = new Dictionary<int, string>();
            //foreach (var rule in _rules)
            //{
            //    stateRules[rule.StartState.Id] = rule.Name;
            //    stateRules[rule.EndState.Id] = rule.Name;
            //}

            HashSet <State>      states      = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default);
            HashSet <Transition> transitions = new HashSet <Transition>(ObjectReferenceEqualityComparer <Transition> .Default);

            foreach (var rule in _rules)
            {
                ExtractStatesAndTransitions(optimizer, rule, rule.StartState, states, transitions, stateRules, contextRules);
                //ExtractStatesAndTransitions(rule.Name, rule.EndState, states, transitions, stateRules, contextRules);
            }

            _states       = states.ToDictionary(i => i.Id);
            _transitions  = new List <Transition>(transitions);
            _stateRules   = stateRules;
            _contextRules = contextRules;
            _optimizer    = optimizer;
        }
Beispiel #4
0
        public Network(NetworkBuilder builder, StateOptimizer optimizer, IEnumerable<RuleBinding> rules, Dictionary<int, RuleBinding> stateRules, Dictionary<int, RuleBinding> contextRules)
        {
            Contract.Requires<ArgumentNullException>(builder != null, "builder");
            Contract.Requires<ArgumentNullException>(optimizer != null, "optimizer");
            Contract.Requires<ArgumentNullException>(rules != null, "rules");

            _builder = builder;
            _rules = new List<RuleBinding>(rules);

            //Dictionary<int, string> stateRules = new Dictionary<int, string>();
            //foreach (var rule in _rules)
            //{
            //    stateRules[rule.StartState.Id] = rule.Name;
            //    stateRules[rule.EndState.Id] = rule.Name;
            //}

            HashSet<State> states = new HashSet<State>(ObjectReferenceEqualityComparer<State>.Default);
            HashSet<Transition> transitions = new HashSet<Transition>(ObjectReferenceEqualityComparer<Transition>.Default);

            foreach (var rule in _rules)
            {
                ExtractStatesAndTransitions(optimizer, rule, rule.StartState, states, transitions, stateRules, contextRules);
                //ExtractStatesAndTransitions(rule.Name, rule.EndState, states, transitions, stateRules, contextRules);
            }

            _states = states.ToDictionary(i => i.Id);
            _transitions = new List<Transition>(transitions);
            _stateRules = stateRules;
            _contextRules = contextRules;
            _optimizer = optimizer;
        }
Beispiel #5
0
        public void RemoveTransition(Transition transition, StateOptimizer optimizer = null)
        {
            Requires.NotNull(transition, nameof(transition));
            Requires.Argument(transition.SourceState == this, nameof(transition), "The transition source state must be the current instance.");
            Verify.Operation(OutgoingTransitions.Contains(transition), "Expected the state to contain the transition.");

            RemoveTransitionInternal(transition, optimizer);
        }
Beispiel #6
0
        public void AddTransition(Transition transition, StateOptimizer optimizer = null)
        {
            Contract.Requires <ArgumentNullException>(transition != null, "transition");
            Contract.Requires <InvalidOperationException>(transition.SourceState == null);
            Contract.Requires <InvalidOperationException>(!OutgoingTransitions.Contains(transition));
            Contract.Requires <InvalidOperationException>(!transition.TargetState.IncomingTransitions.Contains(transition));

            AddTransitionInternal(transition, optimizer);
        }
Beispiel #7
0
        public void AddTransition(Transition transition, StateOptimizer optimizer = null)
        {
            Requires.NotNull(transition, nameof(transition));
            Verify.Operation(transition.SourceState == null, "Expected the transition to not be associated with a source state.");
            Verify.Operation(!OutgoingTransitions.Contains(transition), "Expected the state to not already contain the transition.");
            Verify.Operation(!transition.TargetState.IncomingTransitions.Contains(transition), "Expected the target state to not already contain the incoming transition.");

            AddTransitionInternal(transition, optimizer);
        }
Beispiel #8
0
        public void RemoveTransition(Transition transition, StateOptimizer optimizer = null)
        {
            Contract.Requires <ArgumentNullException>(transition != null, "transition");
            Contract.Requires <ArgumentException>(transition.SourceState == this);
            Contract.Requires <InvalidOperationException>(OutgoingTransitions.Contains(transition));

            Contract.Ensures(transition.SourceState == null);
            Contract.Ensures(!Contract.OldValue(transition.SourceState).OutgoingTransitions.Contains(transition));
            Contract.Ensures(!transition.TargetState.IncomingTransitions.Contains(transition));

            RemoveTransitionInternal(transition, optimizer);
        }
Beispiel #9
0
        public void Optimize([NotNull] StateOptimizer optimizer)
        {
            Requires.NotNull(optimizer, nameof(optimizer));
            Verify.Operation(IsRecursiveAnalysisComplete, "Expected recursive analysis to be complete.");

            if (IsOptimized)
            {
                return;
            }

            OptimizeOutgoingTransitions(optimizer);
            _isOptimized = true;
        }
Beispiel #10
0
        public void Optimize(StateOptimizer optimizer)
        {
            Contract.Requires <ArgumentNullException>(optimizer != null, "optimizer");
            Contract.Requires <InvalidOperationException>(IsRecursiveAnalysisComplete);

            if (IsOptimized)
            {
                return;
            }

            OptimizeOutgoingTransitions(optimizer);
            _isOptimized = true;
        }
Beispiel #11
0
        internal void RemoveTransitionInternal(Transition transition, StateOptimizer optimizer)
        {
            Contract.Requires(transition != null, "transition");
            Contract.Requires(transition.SourceState == this);
#if ALL_CHECKS
            Contract.Requires(OutgoingTransitions.Contains(transition));
#endif

            Contract.Ensures(transition.SourceState == null);
#if ALL_CHECKS
            Contract.Ensures(!Contract.OldValue(transition.SourceState).OutgoingTransitions.Contains(transition));
            Contract.Ensures(!transition.TargetState.IncomingTransitions.Contains(transition));

            Contract.Assert(transition.TargetState.IncomingTransitions.Contains(transition));
#endif

            //PopContextTransition popContextTransition = transition as PopContextTransition;
            //if (popContextTransition != null)
            //{
            //    foreach (var pushTransition in popContextTransition.PushTransitions)
            //    {
            //        Contract.Assert(pushTransition.PopTransitions.Contains(transition));
            //        pushTransition.PopTransitions.Remove(popContextTransition);
            //    }
            //}

            //PushContextTransition pushContextTransition = transition as PushContextTransition;
            //if (pushContextTransition != null)
            //{
            //    foreach (var popTransition in pushContextTransition.PopTransitions)
            //    {
            //        Contract.Assert(popTransition.PushTransitions.Contains(transition));
            //        popTransition.PushTransitions.Remove(pushContextTransition);
            //    }
            //}

            if (optimizer != null)
            {
                optimizer.RemoveTransition(transition);
            }

            OutgoingTransitions.Remove(transition);
            transition.TargetState.IncomingTransitions.Remove(transition);

            _followSet          = null;
            _isForwardRecursive = null;
            transition.TargetState._sourceSet           = null;
            transition.TargetState._isBackwardRecursive = null;
            transition.SourceState = null;
        }
Beispiel #12
0
        public void AddRecursiveTransitions(StateOptimizer optimizer)
        {
            if (_recursiveTransitions != null)
            {
                return;
            }

            int originalTransitionCount = OutgoingTransitions.Count;

            HashSet <State> visited = new HashSet <State>(ObjectReferenceEqualityComparer <State> .Default);
            List <int>      trace   = new List <int>();

            AddRecursivePushTransitions(visited, this, new EpsilonTransition(this), trace, optimizer);
            AddRecursivePopTransitions(visited, this, new EpsilonTransition(this), trace, optimizer);

            _recursiveTransitions = OutgoingTransitions.Count != originalTransitionCount;
        }
Beispiel #13
0
        protected virtual int RemoveUnreachableStates(StateOptimizer optimizer, IEnumerable <RuleBinding> rules, HashSet <State> states, HashSet <State> ruleStartStates)
        {
            int removedCount = 0;

            while (true)
            {
                HashSet <State> reachableStates = GetReachableStates(rules);

                bool removed = false;

                foreach (var state in states)
                {
                    // already removed (or a terminal state)
                    if (state.OutgoingTransitions.Count == 0)
                    {
                        continue;
                    }

                    /* if there are no incoming transitions and it's not a rule start state,
                     * then the state is unreachable so we remove it.
                     */
                    if (!reachableStates.Contains(state))
                    {
                        removedCount++;
                        removed = true;
                        foreach (var transition in state.OutgoingTransitions.ToArray())
                        {
                            state.RemoveTransition(transition, optimizer);
                        }
                    }
                }

                if (!removed)
                {
                    break;
                }
            }

#if DEBUG
            int recursiveStates = GetReachableStates(rules).Count(i => i.HasRecursiveTransitions ?? true);
#endif

            return(removedCount);
        }
Beispiel #14
0
        private void OptimizeOutgoingTransitions(StateOptimizer optimizer)
        {
            List <Transition> oldTransitions = new List <Transition>(OutgoingTransitions.Where(i => !i.IsRecursive));

            foreach (var transition in oldTransitions)
            {
                RemoveTransitionInternal(transition, optimizer);
            }

            Contract.Assert(Contract.ForAll(OutgoingTransitions, i => i.IsRecursive));

            foreach (var transition in oldTransitions)
            {
                HashSet <Transition> visited = new HashSet <Transition>(ObjectReferenceEqualityComparer <Transition> .Default);
                visited.Add(transition);
                AddOptimizedTransitions(optimizer, visited, transition, PreventContextType.None);
            }

            Contract.Assert(oldTransitions.Count == 0 || OutgoingTransitions.Count > 0);
        }
Beispiel #15
0
        public void RemoveExtraEpsilonTransitions(StateOptimizer optimizer, bool isStartState)
        {
            if (OutgoingTransitions.Count == 1 && OutgoingTransitions.First().IsEpsilon)
            {
                Transition epsilon = OutgoingTransitions.First();
                foreach (var incoming in IncomingTransitions.ToArray())
                {
                    State sourceState = incoming.SourceState;
                    sourceState.RemoveTransitionInternal(incoming, optimizer);
                    sourceState.AddTransitionInternal(MergeTransitions(incoming, epsilon), optimizer);
                }

                if (!isStartState)
                {
                    RemoveTransitionInternal(epsilon, optimizer);
                }
            }

            if (IncomingTransitions.Count == 1 && IncomingTransitions.First().IsEpsilon)
            {
                Transition epsilon     = IncomingTransitions.First();
                State      sourceState = epsilon.SourceState;

                foreach (var outgoing in OutgoingTransitions.ToArray())
                {
                    if (!isStartState)
                    {
                        this.RemoveTransitionInternal(outgoing, optimizer);
                    }

                    sourceState.AddTransitionInternal(MergeTransitions(epsilon, outgoing), optimizer);
                }

                epsilon.SourceState.RemoveTransitionInternal(epsilon, optimizer);
            }
        }
        protected virtual Network BuildNetworkImpl()
        {
            BindRules();

            HashSet<State> states = GetAllStates(Rules);
            HashSet<State> reachableStates = GetReachableStates(Rules);
            HashSet<State> ruleStartStates = new HashSet<State>(Rules.Where(i => i.IsStartRule).Select(i => i.StartState), ObjectReferenceEqualityComparer<State>.Default);

            StateOptimizer optimizer = new StateOptimizer(states);

            Dictionary<int, RuleBinding> stateRules = new Dictionary<int, RuleBinding>();
            foreach (var rule in Rules)
                GetRuleStates(optimizer, rule, rule.StartState, stateRules);

            Dictionary<int, RuleBinding> contextRules = new Dictionary<int, RuleBinding>();
            foreach (var state in reachableStates)
                GetContextRules(state, stateRules, contextRules);

#if !OLD_OPTIMIZER
            optimizer.Optimize(ruleStartStates);
            RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates);
#else
            foreach (var state in states)
                state.RemoveExtraEpsilonTransitions(optimizer, ruleStartStates.Contains(state));

            foreach (var state in states)
                state.AddRecursiveTransitions(optimizer);

            RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates);

            //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dot");
            //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dgml");


            int skippedCount = 0;
            int optimizedCount = 0;
            foreach (var state in reachableStates)
            {
                bool skip = false;

                /* if there are no incoming transitions and it's not a rule start state,
                 * then the state is unreachable and will be removed so there's no need to
                 * optimize it.
                 */
                if (!ruleStartStates.Contains(state) && state.OutgoingTransitions.Count > 0)
                {
                    if (state.IncomingTransitions.Count == 0)
                        skip = true;

                    if (!skip && state.IncomingTransitions.All(i => i.IsEpsilon))
                        skip = true;

                    if (!skip && !state.IncomingTransitions.Any(i => i.IsMatch) && !state.OutgoingTransitions.Any(i => i.IsMatch))
                    {
                        bool incomingPush = state.IncomingTransitions.Any(i => i is PushContextTransition);
                        bool incomingPop = state.IncomingTransitions.Any(i => i is PopContextTransition);
                        bool outgoingPush = state.OutgoingTransitions.Any(i => i is PushContextTransition);
                        bool outgoingPop = state.OutgoingTransitions.Any(i => i is PopContextTransition);
                        if ((incomingPop && !outgoingPush) || (incomingPush && !outgoingPop))
                            skip = true;
                    }
                }

                if (skip)
                {
                    skippedCount++;
                    continue;
                }

                state.Optimize(optimizer);
                optimizedCount++;
            }

            HashSet<State> reachableOptimizedStates = GetReachableStates(Rules);

            int removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates);

            foreach (var state in reachableOptimizedStates)
            {
                if (!state.IsOptimized && (state.OutgoingTransitions.Count == 0 || state.IncomingTransitions.Any(i => i.IsRecursive)))
                {
                    bool hadTransitions = state.OutgoingTransitions.Count > 0;
                    state.Optimize(optimizer);
                    if (hadTransitions)
                        removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates);
                }
            }

            //RemoveUnreachableStates(Rules, reachableStates, ruleStartStates);

            //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dot");
            //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dgml");

#if false
            foreach (var rule in ruleBindings)
                OptimizeRule(rule, ruleStartStates);
#endif

            reachableOptimizedStates = GetReachableStates(Rules);
            foreach (var state in reachableOptimizedStates)
                state.Optimize(optimizer);

            RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates);
            reachableOptimizedStates = GetReachableStates(Rules);

            //stateRules = RenumberStates(reachableOptimizedStates, reachableStates, stateRules);
#endif

            return new Network(this, optimizer, Rules, stateRules, contextRules);
        }
Beispiel #17
0
        private static void ExtractStatesAndTransitions(StateOptimizer optimizer, RuleBinding currentRule, State currentState, HashSet<State> states, HashSet<Transition> transitions, Dictionary<int, RuleBinding> stateRules, Dictionary<int, RuleBinding> contextRules)
        {
            if (!states.Add(currentState))
                return;

            currentRule = currentRule ?? stateRules[currentState.Id];

            foreach (var transition in currentState.OutgoingTransitions)
            {
                transitions.Add(transition);
                var nextRule = transition.IsContext ? null : currentRule;
                ExtractStatesAndTransitions(optimizer, nextRule, transition.TargetState, states, transitions, stateRules, contextRules);

//                if (transitions.Add(transition))
//                {
//                    if (transition.IsContext)
//                    {
//                        PushContextTransition pushContext = transition as PushContextTransition;
//                        if (pushContext != null)
//                        {
//                            foreach (var popTransition in optimizer.GetPopContextTransitions(pushContext))
//                            {
//                                // the matching pop transitions should always end in this rule
//                                Contract.Assert(popTransition.ContextIdentifiers.Last() == pushContext.ContextIdentifiers.First());
//#if ALL_CHECKS
//                                // matching is symmetric
//                                Contract.Assert(popTransition.PushTransitions.Contains(pushContext));
//#endif
//                                // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition
//                                Contract.Assert(popTransition.SourceState != null);

//                                ExtractStatesAndTransitions(optimizer, currentRule, popTransition.TargetState, states, transitions, stateRules, contextRules);
//                            }

//                            ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules);
//                            continue;
//                        }

//                        PopContextTransition popContext = transition as PopContextTransition;
//                        if (popContext != null)
//                        {
//                            foreach (var pushTransition in optimizer.GetPushContextTransitions(popContext))
//                            {
//                                // the matching push transitions should always start in this rule
//                                Contract.Assert(pushTransition.ContextIdentifiers.First() == popContext.ContextIdentifiers.Last());
//#if ALL_CHECKS
//                                // matching is symmetric
//                                Contract.Assert(pushTransition.PopTransitions.Contains(popContext));
//#endif
//                                // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition
//                                Contract.Assert(pushTransition.SourceState != null);
//                            }

//                            ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules);
//                            continue;
//                        }

//                        throw new InvalidOperationException("Unrecognized context transition.");
//                    }
//                    else
//                    {
//                        ExtractStatesAndTransitions(optimizer, currentRule, transition.TargetState, states, transitions, stateRules, contextRules);
//                    }
//                }
            }

            foreach (var transition in currentState.IncomingTransitions)
            {
                transitions.Add(transition);
                var nextRule = transition.IsContext ? null : currentRule;
                ExtractStatesAndTransitions(optimizer, nextRule, transition.SourceState, states, transitions, stateRules, contextRules);
            }
        }
Beispiel #18
0
        protected virtual Network BuildNetworkImpl()
        {
            BindRules();

            HashSet <State> states          = GetAllStates(Rules);
            HashSet <State> reachableStates = GetReachableStates(Rules);
            HashSet <State> ruleStartStates = new HashSet <State>(Rules.Where(i => i.IsStartRule).Select(i => i.StartState), ObjectReferenceEqualityComparer <State> .Default);

            StateOptimizer optimizer = new StateOptimizer(states);

            Dictionary <int, RuleBinding> stateRules = new Dictionary <int, RuleBinding>();

            foreach (var rule in Rules)
            {
                GetRuleStates(optimizer, rule, rule.StartState, stateRules);
            }

            Dictionary <int, RuleBinding> contextRules = new Dictionary <int, RuleBinding>();

            foreach (var state in reachableStates)
            {
                GetContextRules(state, stateRules, contextRules);
            }

#if !OLD_OPTIMIZER
            optimizer.Optimize(ruleStartStates);
            RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates);
#else
            foreach (var state in states)
            {
                state.RemoveExtraEpsilonTransitions(optimizer, ruleStartStates.Contains(state));
            }

            foreach (var state in states)
            {
                state.AddRecursiveTransitions(optimizer);
            }

            RemoveUnreachableStates(optimizer, Rules, states, ruleStartStates);

            //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dot");
            //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplified.dgml");


            int skippedCount   = 0;
            int optimizedCount = 0;
            foreach (var state in reachableStates)
            {
                bool skip = false;

                /* if there are no incoming transitions and it's not a rule start state,
                 * then the state is unreachable and will be removed so there's no need to
                 * optimize it.
                 */
                if (!ruleStartStates.Contains(state) && state.OutgoingTransitions.Count > 0)
                {
                    if (state.IncomingTransitions.Count == 0)
                    {
                        skip = true;
                    }

                    if (!skip && state.IncomingTransitions.All(i => i.IsEpsilon))
                    {
                        skip = true;
                    }

                    if (!skip && !state.IncomingTransitions.Any(i => i.IsMatch) && !state.OutgoingTransitions.Any(i => i.IsMatch))
                    {
                        bool incomingPush = state.IncomingTransitions.Any(i => i is PushContextTransition);
                        bool incomingPop  = state.IncomingTransitions.Any(i => i is PopContextTransition);
                        bool outgoingPush = state.OutgoingTransitions.Any(i => i is PushContextTransition);
                        bool outgoingPop  = state.OutgoingTransitions.Any(i => i is PopContextTransition);
                        if ((incomingPop && !outgoingPush) || (incomingPush && !outgoingPop))
                        {
                            skip = true;
                        }
                    }
                }

                if (skip)
                {
                    skippedCount++;
                    continue;
                }

                state.Optimize(optimizer);
                optimizedCount++;
            }

            HashSet <State> reachableOptimizedStates = GetReachableStates(Rules);

            int removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates);

            foreach (var state in reachableOptimizedStates)
            {
                if (!state.IsOptimized && (state.OutgoingTransitions.Count == 0 || state.IncomingTransitions.Any(i => i.IsRecursive)))
                {
                    bool hadTransitions = state.OutgoingTransitions.Count > 0;
                    state.Optimize(optimizer);
                    if (hadTransitions)
                    {
                        removed = RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates);
                    }
                }
            }

            //RemoveUnreachableStates(Rules, reachableStates, ruleStartStates);

            //ExportDot(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dot");
            //ExportDgml(AlloyParser.tokenNames, ruleBindings, reachableOptimizedStates, stateRules, @"C:\dev\SimpleC\TestGenerated\AlloySimplifiedOptimized.dgml");

#if false
            foreach (var rule in ruleBindings)
            {
                OptimizeRule(rule, ruleStartStates);
            }
#endif

            reachableOptimizedStates = GetReachableStates(Rules);
            foreach (var state in reachableOptimizedStates)
            {
                state.Optimize(optimizer);
            }

            RemoveUnreachableStates(optimizer, Rules, reachableStates, ruleStartStates);
            reachableOptimizedStates = GetReachableStates(Rules);

            //stateRules = RenumberStates(reachableOptimizedStates, reachableStates, stateRules);
#endif

            return(new Network(this, optimizer, Rules, stateRules, contextRules));
        }
Beispiel #19
0
        internal void AddTransitionInternal(Transition transition, StateOptimizer optimizer)
        {
            Contract.Requires(transition != null);
            Contract.Requires(transition.SourceState == null);
#if ALL_CHECKS
            Contract.Requires(!OutgoingTransitions.Contains(transition));
            Contract.Requires(!transition.TargetState.IncomingTransitions.Contains(transition));
#endif

            if (IsRecursiveAnalysisComplete && !transition.IsMatch && transition.TargetState == this && !transition.IsRecursive)
            {
                throw new InvalidOperationException();
            }

            PopContextTransition  popContextTransition  = transition as PopContextTransition;
            PushContextTransition pushContextTransition = transition as PushContextTransition;

#if false
            if (popContextTransition != null && !transition.IsRecursive)
            {
                foreach (var recursive in OutgoingTransitions.OfType <PopContextTransition>().Where(i => i.IsRecursive))
                {
                    if (popContextTransition.ContextIdentifiers.Take(recursive.ContextIdentifiers.Count).SequenceEqual(recursive.ContextIdentifiers))
                    {
                        if (popContextTransition.ContextIdentifiers.Count > recursive.ContextIdentifiers.Count)
                        {
                            throw new InvalidOperationException();
                        }
                    }
                }
            }
#endif

            if (_outgoingTransitions.Count > 10 && !(_outgoingTransitions is ISet <Transition>))
            {
                _outgoingTransitions = new HashSet <Transition>(_outgoingTransitions, ObjectReferenceEqualityComparer <Transition> .Default);
            }

#if false
            if (transition.IsContext && transition.IsRecursive)
            {
                PopContextTransition first = transition as PopContextTransition;
                if (first != null)
                {
                    foreach (var existing in OutgoingTransitions.OfType <PopContextTransition>().ToArray())
                    {
                        if (existing.TargetState != transition.TargetState)
                        {
                            continue;
                        }

                        if (first.ContextIdentifiers.Take(existing.ContextIdentifiers.Count).SequenceEqual(existing.ContextIdentifiers))
                        {
                            RemoveTransitionInternal(existing, optimizer);
                        }
                    }
                }

                PushContextTransition second = transition as PushContextTransition;
                if (second != null)
                {
                    foreach (var existing in OutgoingTransitions.OfType <PushContextTransition>().ToArray())
                    {
                        if (existing.TargetState != transition.TargetState)
                        {
                            continue;
                        }

                        if (second.ContextIdentifiers.Take(existing.ContextIdentifiers.Count).SequenceEqual(existing.ContextIdentifiers))
                        {
                            RemoveTransitionInternal(existing, optimizer);
                        }
                    }
                }
            }
#endif

            OutgoingTransitions.Add(transition);

            if (transition.TargetState.IncomingTransitions.Count > 10 && !(transition.TargetState.IncomingTransitions is ISet <Transition>))
            {
                transition.TargetState._incomingTransitions = new HashSet <Transition>(transition.TargetState._incomingTransitions, ObjectReferenceEqualityComparer <Transition> .Default);
            }

            transition.TargetState.IncomingTransitions.Add(transition);
            transition.SourceState = this;

            if (optimizer != null)
            {
                optimizer.AddTransition(transition);
            }

            if (popContextTransition != null)
            {
                //if (optimizer != null)
                //    popContextTransition.PushTransitions.UnionWith(optimizer.GetPushContextTransitions(popContextTransition.ContextIdentifiers.Last()));

                //foreach (var pushTransition in popContextTransition.PushTransitions)
                //{
                //    Contract.Assert(pushTransition.ContextIdentifiers.First() == popContextTransition.ContextIdentifiers.Last());
                //    Contract.Assert(pushTransition.SourceState != null);
                //    pushTransition.PopTransitions.Add(popContextTransition);
                //}

#if ALL_CHECKS
                Contract.Assert(Contract.ForAll(OutgoingTransitions.OfType <PushContextTransition>(), i => i.ContextIdentifiers.Last() != popContextTransition.ContextIdentifiers.First() || popContextTransition.PushTransitions.Contains(i)));
#endif
            }
            else if (pushContextTransition != null)
            {
                //if (optimizer != null)
                //    pushContextTransition.PopTransitions.UnionWith(optimizer.GetPopContextTransitions(pushContextTransition.ContextIdentifiers[0]));

                //foreach (var popTransition in pushContextTransition.PopTransitions)
                //{
                //    Contract.Assert(popTransition.ContextIdentifiers.Last() == pushContextTransition.ContextIdentifiers.First());
                //    Contract.Assert(popTransition.SourceState != null);
                //    popTransition.PushTransitions.Add(pushContextTransition);
                //}

#if ALL_CHECKS
                Contract.Assert(Contract.ForAll(OutgoingTransitions.OfType <PopContextTransition>(), i => i.ContextIdentifiers.Last() != pushContextTransition.ContextIdentifiers.First() || pushContextTransition.PopTransitions.Contains(i)));
#endif
            }

            _followSet          = null;
            _isForwardRecursive = null;
            transition.TargetState._sourceSet           = null;
            transition.TargetState._isBackwardRecursive = null;
        }
Beispiel #20
0
        private void AddOptimizedTransitions(StateOptimizer optimizer, HashSet <Transition> visited, Transition transition, PreventContextType preventContextType)
        {
            Contract.Requires(optimizer != null);
            Contract.Requires(visited != null);
            Contract.Requires(transition != null);
            Contract.Requires(transition.SourceState == null);
            Contract.Requires(preventContextType != PreventContextType.PushRecursive && preventContextType != PreventContextType.PopRecursive);

            Contract.Ensures(visited.Count == Contract.OldValue(visited.Count));

            List <Transition> addedTransitions = null;

            if (transition.TargetState == this)
            {
                return;
            }

            try
            {
                while (true)
                {
                    /* Done when we find:
                     *  - a match transition
                     *  - a recursive transition (which should already be analyzed)
                     */

                    if (transition.IsMatch || transition.TargetState.OutgoingTransitions.Count == 0 || transition.IsRecursive)
                    {
                        //if (!transition.IsMatch && transition.TargetState.OutgoingTransitions.Count > 0)
                        //{
                        //    // must be here because it's a recursive state
                        //    transition.IsRecursive = true;
                        //}

                        AddTransitionInternal(transition, optimizer);
                        return;
                    }

                    // inline merge of single epsilon transitions
                    if (transition.TargetState.OutgoingTransitions.Count == 1 && transition.TargetState.OutgoingTransitions.First().IsEpsilon)
                    {
                        if (!visited.Add(transition.TargetState.OutgoingTransitions.First()))
                        {
                            throw new InvalidOperationException();
                        }

                        addedTransitions = addedTransitions ?? new List <Transition>();
                        addedTransitions.Add(transition.TargetState.OutgoingTransitions.First());
                        transition = MergeTransitions(transition, transition.TargetState.OutgoingTransitions.First());
                        continue;
                    }

                    break;
                }

                bool added = false;

                foreach (var nextTransition in transition.TargetState.OutgoingTransitions.ToArray())
                {
                    bool preventMerge = nextTransition.IsRecursive;

                    if (!nextTransition.IsRecursive)
                    {
                        switch (preventContextType)
                        {
                        case PreventContextType.Pop:
                            if (transition is PopContextTransition)
                            {
                                preventMerge = true;
                            }

                            break;

                        case PreventContextType.Push:
                            if (transition is PushContextTransition)
                            {
                                preventMerge = true;
                            }

                            break;

                        default:
                            break;
                        }
                    }

                    if (transition.IsEpsilon)
                    {
                        if (preventMerge && !added)
                        {
                            AddTransitionInternal(transition, optimizer);
                            added = true;
                            continue;
                        }

                        if (!visited.Add(nextTransition))
                        {
                            continue;
                        }

                        try
                        {
                            Contract.Assert(!preventMerge);
                            AddOptimizedTransitions(optimizer, visited, MergeTransitions(transition, nextTransition), preventContextType);
                        }
                        finally
                        {
                            visited.Remove(nextTransition);
                        }
                    }
                    else if (transition.IsContext)
                    {
                        PreventContextType nextPreventContextType = PreventContextType.None;
                        if (!preventMerge && transition.TargetState.IsOptimized)
                        {
                            if (nextTransition is PushContextTransition)
                            {
                                nextPreventContextType = PreventContextType.Push;
                            }
                            else if (nextTransition is PopContextTransition)
                            {
                                nextPreventContextType = PreventContextType.Pop;
                            }
                        }

                        bool canMerge = !preventMerge && !nextTransition.IsMatch;

                        if (canMerge && nextTransition.IsContext)
                        {
                            canMerge = (transition is PopContextTransition && nextTransition is PopContextTransition) ||
                                       (transition is PushContextTransition && nextTransition is PushContextTransition);

#if false
                            if (canMerge)
                            {
                                bool recursive = ((ContextTransition)transition).ContextIdentifiers.Any(((ContextTransition)nextTransition).ContextIdentifiers.Contains);
                                if (recursive)
                                {
                                    transition.IsRecursive = true;
                                    canMerge = false;
                                }
                            }
#endif
                        }

                        if (canMerge)
                        {
                            if (!visited.Add(nextTransition))
                            {
                                continue;
                            }

                            try
                            {
                                AddOptimizedTransitions(optimizer, visited, MergeTransitions(transition, nextTransition), nextPreventContextType);
                            }
                            finally
                            {
                                visited.Remove(nextTransition);
                            }
                        }
                        else if (!added)
                        {
                            AddTransitionInternal(transition, optimizer);
                            added = true;
                        }
                    }
                }
            }
            finally
            {
                if (addedTransitions != null)
                {
                    visited.ExceptWith(addedTransitions);
                }
            }
        }
        protected virtual int RemoveUnreachableStates(StateOptimizer optimizer, IEnumerable<RuleBinding> rules, HashSet<State> states, HashSet<State> ruleStartStates)
        {
            int removedCount = 0;

            while (true)
            {
                HashSet<State> reachableStates = GetReachableStates(rules);

                bool removed = false;

                foreach (var state in states)
                {
                    // already removed (or a terminal state)
                    if (state.OutgoingTransitions.Count == 0)
                        continue;

                    /* if there are no incoming transitions and it's not a rule start state,
                     * then the state is unreachable so we remove it.
                     */
                    if (!reachableStates.Contains(state))
                    {
                        removedCount++;
                        removed = true;
                        foreach (var transition in state.OutgoingTransitions.ToArray())
                            state.RemoveTransition(transition, optimizer);
                    }
                }

                if (!removed)
                    break;
            }

#if DEBUG
            int recursiveStates = GetReachableStates(rules).Count(i => i.HasRecursiveTransitions ?? true);
#endif

            return removedCount;
        }
Beispiel #22
0
        private bool AddRecursivePopTransitions(HashSet <State> visited, State currentState, Transition effectiveTransition, List <int> contexts, StateOptimizer optimizer)
        {
            Contract.Requires(visited != null);
            Contract.Requires(currentState != null);
            Contract.Requires(contexts != null);
            Contract.Ensures(visited.Count == Contract.OldValue(visited.Count));
            Contract.Ensures(contexts.Count == Contract.OldValue(contexts.Count));

            bool foundRecursive = false;

            foreach (var transition in currentState.OutgoingTransitions.Where(i => !i.IsRecursive && (i.IsEpsilon || (i is PopContextTransition))).ToArray())
            {
                ContextTransition contextTransition = transition as ContextTransition;
                try
                {
                    if (contextTransition != null)
                    {
                        contexts.AddRange(contextTransition.ContextIdentifiers);
                    }

                    if (transition.TargetState == this)
                    {
                        foundRecursive = true;

                        if (contexts.Count == 0)
                        {
                            Trace.WriteLine(string.Format("State {0} is self-recursive.", this.Id));
                            continue;
                        }

                        PopContextTransition recursive = new PopContextTransition(this, contexts);
                        recursive.IsRecursive = true;
                        AddTransitionInternal(recursive, optimizer);
                        continue;
                    }

                    if (!visited.Add(transition.TargetState))
                    {
                        continue;
                    }

                    try
                    {
                        AddRecursivePopTransitions(visited, transition.TargetState, MergeTransitions(effectiveTransition, transition), contexts, optimizer);
                    }
                    finally
                    {
                        visited.Remove(transition.TargetState);
                    }
                }
                finally
                {
                    if (contextTransition != null)
                    {
                        contexts.RemoveRange(contexts.Count - contextTransition.ContextIdentifiers.Count, contextTransition.ContextIdentifiers.Count);
                    }
                }
            }

            return(foundRecursive);
        }
        private static void ExtractStatesAndTransitions(StateOptimizer optimizer, RuleBinding currentRule, State currentState, HashSet <State> states, HashSet <Transition> transitions, Dictionary <int, RuleBinding> stateRules, Dictionary <int, RuleBinding> contextRules)
        {
            if (!states.Add(currentState))
            {
                return;
            }

            currentRule = currentRule ?? stateRules[currentState.Id];

            foreach (var transition in currentState.OutgoingTransitions)
            {
                transitions.Add(transition);
                var nextRule = transition.IsContext ? null : currentRule;
                ExtractStatesAndTransitions(optimizer, nextRule, transition.TargetState, states, transitions, stateRules, contextRules);

//                if (transitions.Add(transition))
//                {
//                    if (transition.IsContext)
//                    {
//                        PushContextTransition pushContext = transition as PushContextTransition;
//                        if (pushContext != null)
//                        {
//                            foreach (var popTransition in optimizer.GetPopContextTransitions(pushContext))
//                            {
//                                // the matching pop transitions should always end in this rule
//                                Contract.Assert(popTransition.ContextIdentifiers.Last() == pushContext.ContextIdentifiers.First());
//#if ALL_CHECKS
//                                // matching is symmetric
//                                Contract.Assert(popTransition.PushTransitions.Contains(pushContext));
//#endif
//                                // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition
//                                Contract.Assert(popTransition.SourceState != null);

//                                ExtractStatesAndTransitions(optimizer, currentRule, popTransition.TargetState, states, transitions, stateRules, contextRules);
//                            }

//                            ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules);
//                            continue;
//                        }

//                        PopContextTransition popContext = transition as PopContextTransition;
//                        if (popContext != null)
//                        {
//                            foreach (var pushTransition in optimizer.GetPushContextTransitions(popContext))
//                            {
//                                // the matching push transitions should always start in this rule
//                                Contract.Assert(pushTransition.ContextIdentifiers.First() == popContext.ContextIdentifiers.Last());
//#if ALL_CHECKS
//                                // matching is symmetric
//                                Contract.Assert(pushTransition.PopTransitions.Contains(popContext));
//#endif
//                                // make sure there are no "matching" transitions which were removed by a call to State.RemoveTransition
//                                Contract.Assert(pushTransition.SourceState != null);
//                            }

//                            ExtractStatesAndTransitions(optimizer, null, transition.TargetState, states, transitions, stateRules, contextRules);
//                            continue;
//                        }

//                        throw new InvalidOperationException("Unrecognized context transition.");
//                    }
//                    else
//                    {
//                        ExtractStatesAndTransitions(optimizer, currentRule, transition.TargetState, states, transitions, stateRules, contextRules);
//                    }
//                }
            }

            foreach (var transition in currentState.IncomingTransitions)
            {
                transitions.Add(transition);
                var nextRule = transition.IsContext ? null : currentRule;
                ExtractStatesAndTransitions(optimizer, nextRule, transition.SourceState, states, transitions, stateRules, contextRules);
            }
        }
        protected virtual void GetRuleStates(StateOptimizer optimizer, RuleBinding ruleName, State state, Dictionary<int, RuleBinding> stateRules)
        {
            if (stateRules.ContainsKey(state.Id))
                return;

            stateRules[state.Id] = ruleName;

            foreach (var transition in state.OutgoingTransitions)
            {
                if (transition is PopContextTransition)
                    continue;

                PushContextTransition contextTransition = transition as PushContextTransition;
                if (contextTransition != null)
                {
                    foreach (var popTransition in optimizer.GetPopContextTransitions(contextTransition))
                        GetRuleStates(optimizer, ruleName, popTransition.TargetState, stateRules);
                }
                else
                {
                    GetRuleStates(optimizer, ruleName, transition.TargetState, stateRules);
                }
            }
        }