public override void Refine(SSA <SYMBOL> m, SSA <SYMBOL> x)
        {
            int inc;

            if (boundInc == Config.BoundInc.One)
            {
                inc = 1;
            }
            else
            {
                SSA <SYMBOL> ssa;
                if (boundInc == Config.BoundInc.M)
                {
                    ssa = m;
                }
                else
                {
                    ssa = x;
                }
                inc = ssa.States.Count();
                if (halveBoundInc)
                {
                    inc /= 2;
                }
            }

            bound += inc;
        }
Beispiel #2
0
 /// <summary>
 /// ARMC constructor.
 /// </summary>
 /// <param name="config">Configuration.</param>
 public ARMC(Config config)
     : this(SSA <SYMBOL> .Parse(config.InitFilePath),
            SSA <SYMBOL> .Parse(config.BadFilePath),
            config.TauFilePaths.Select(path => SST <SYMBOL> .Parse(path)).ToArray(),
            config)
 {
 }
        public FiniteLengthAbstraction(Config config, SSA <SYMBOL> init = null, SSA <SYMBOL> bad = null, SST <SYMBOL>[] tau = null)
        {
            if (config.InitialBound == Config.InitBound.One)
            {
                bound = 1;
            }
            else
            {
                SSA <SYMBOL> ssa;
                if (config.InitialBound == Config.InitBound.Init)
                {
                    ssa = init ?? SSA <SYMBOL> .Parse(config.InitFilePath);
                }
                else
                {
                    ssa = bad ?? SSA <SYMBOL> .Parse(config.BadFilePath);
                }
                bound = ssa.States.Count();
                if (config.HalveInitialBound)
                {
                    bound /= 2;
                }
            }

            forward       = (config.LanguageDirection == Config.Direction.Forward);
            trace         = config.TraceLanguages;
            boundInc      = config.BoundIncrement;
            halveBoundInc = config.HalveBoundIncrement;
        }
        public override bool StatesAreEquivalent(SSA <SYMBOL> m, int q1, int q2)
        {
            Func <int, int, SSA <SYMBOL> > boundedLang = trace ?
                                                         (forward ? (Func <int, int, SSA <SYMBOL> >)m.BoundedForwardTraceLanguage : m.BoundedBackwardTraceLanguage) :
                                                         (forward ? (Func <int, int, SSA <SYMBOL> >)m.BoundedForwardStateLanguage : m.BoundedBackwardStateLanguage);

            return(boundedLang(q1, bound) == boundedLang(q2, bound));
        }
Beispiel #5
0
 /// <summary>
 /// Checks if L(M1) does not equal L(M2).
 /// </summary>
 /// <remarks>
 /// Compares references if either SSA is null.
 /// </remarks>
 public static bool operator !=(SSA <SYMBOL> m1, SSA <SYMBOL> m2)
 {
     if (object.ReferenceEquals(m1, null) || object.ReferenceEquals(m2, null))
     {
         return(!object.ReferenceEquals(m1, m2));
     }
     return(!SSA <SYMBOL> .Equivalent(m1, m2));
 }
Beispiel #6
0
        public override bool Equals(object obj)
        {
            SSA <SYMBOL> m = obj as SSA <SYMBOL>;

            if (m != null)
            {
                return(this.automaton.Equals(m.automaton));
            }
            return(this.automaton.Equals(obj));
        }
Beispiel #7
0
        public SSA <SYMBOL> BoundedLanguage(int n)
        {
            var m = new SSA <SYMBOL>(
                0,
                Enumerable.Range(0, n + 1),
                Enumerable.Range(0, n).Select(s => new Move <Predicate <SYMBOL> >(s, s + 1, Predicate <SYMBOL> .True)),
                new Set <SYMBOL>(Alphabet)
                );

            return(Product(this, m));
        }
Beispiel #8
0
        public PredicateAbstraction(Config config, SSA <SYMBOL> init = null, SSA <SYMBOL> bad = null, SST <SYMBOL>[] taus = null)
        {
            var initPreds = new List <SSA <SYMBOL> >();

            /* add Init? */
            if (config.InitialPredicate == Config.InitPred.Init || config.InitialPredicate == Config.InitPred.Both)
            {
                initPreds.Add(init ?? SSA <SYMBOL> .Parse(config.InitFilePath));
            }
            /* add Bad? */
            if (config.InitialPredicate == Config.InitPred.Bad || config.InitialPredicate == Config.InitPred.Both)
            {
                initPreds.Add(bad ?? SSA <SYMBOL> .Parse(config.BadFilePath));
            }

            /* add transducer domains and/or ranges? */
            SST <SYMBOL>[] ssts = taus ?? config.TauFilePaths.Select(path => SST <SYMBOL> .Parse(path)).ToArray();
            if (config.IncludeGuard)
            {
                foreach (SST <SYMBOL> sst in ssts)
                {
                    initPreds.Add(sst.Domain());
                }
            }
            if (config.IncludeAction)
            {
                foreach (SST <SYMBOL> sst in ssts)
                {
                    initPreds.Add(sst.Range());
                }
            }

            /* ensure that the automata contain no epsilon transitions and have disjunct sets of states */
            predicateAutomata = new Set <SSA <SYMBOL> >();
            int offset = 0;

            foreach (SSA <SYMBOL> pred in initPreds)
            {
                SSA <SYMBOL> normPred = pred.RemoveEpsilons().Normalize(offset);
                predicateAutomata.Add(normPred);
                offset += normPred.States.Count();
            }

            forward       = (config.LanguageDirection == Config.Direction.Forward);
            heuristic     = config.Heuristic;
            ignoredLabels = new Set <int>();  // remains empty if no heuristic used
        }
Beispiel #9
0
        public override SSA <SYMBOL> Collapse(SSA <SYMBOL> m)
        {
            m = m.RemoveEpsilons();

            Dictionary <int, Set <int> > labels = MakeLabels(m);

            if (heuristic.HasValue)
            {
                /* remove ignored states from labels */
                foreach (int state in new List <int>(labels.Keys))
                {
                    labels[state] -= ignoredLabels;
                }
            }

            return(m.Collapse((_, q1, q2) => labels[q1] == labels[q2]));
        }
Beispiel #10
0
        /* Collapse method ignores this in favour of more efficient alternative */
        public override bool StatesAreEquivalent(SSA <SYMBOL> m, int q1, int q2)
        {
            Func <int, SSA <SYMBOL> > stateLang = forward ? (Func <int, SSA <SYMBOL> >)m.ForwardStateLanguage : m.BackwardStateLanguage;
            SSA <SYMBOL> m1 = stateLang(q1);
            SSA <SYMBOL> m2 = stateLang(q2);

            foreach (SSA <SYMBOL> pa in predicateAutomata)
            {
                stateLang = forward ? (Func <int, SSA <SYMBOL> >)pa.ForwardStateLanguage : pa.BackwardStateLanguage;
                foreach (int state in pa.States)
                {
                    SSA <SYMBOL> p = stateLang(state);
                    if (SSA <SYMBOL> .ProductIsEmpty(p, m1) != SSA <SYMBOL> .ProductIsEmpty(p, m2))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #11
0
        /// <summary>
        /// Print the counterexample (SSAs).
        /// </summary>
        /// <param name="counterexample">Counterexample.</param>
        /// <param name="directory">Output directory path.</param>
        public void PrintCounterexample(Counterexample <SYMBOL> counterexample, string directory)
        {
            int i = 0;

            foreach (var pair in counterexample.Ms)
            {
                SSA <SYMBOL> m      = pair.Item1;
                SSA <SYMBOL> mAlpha = pair.Item2;
                PrintAutomaton(m, directory, "M" + i.ToString());
                if (mAlpha != null)
                {
                    PrintAutomaton(mAlpha, directory, "M" + i.ToString() + "+");
                }
                i++;
            }
            i = 0;
            foreach (SSA <SYMBOL> x in counterexample.Xs)
            {
                PrintAutomaton(x, directory, "X" + i.ToString());
                i++;
            }
        }
Beispiel #12
0
 /// <summary>
 /// Checks if L(this) is a superset of L(M).
 /// </summary>
 public bool IsSupersetOf(SSA <SYMBOL> m)
 {
     return(m.IsSubsetOf(this));
 }
Beispiel #13
0
 /// <summary>
 /// Checks if L(this) is a subset of L(M). If not, produces witness.
 /// </summary>
 public bool IsSubsetOf(SSA <SYMBOL> m, out List <Predicate <SYMBOL> > witness)
 {
     return(!(Automaton <Predicate <SYMBOL> > .CheckDifference(this.automaton, m.automaton, 0, out witness)));
 }
Beispiel #14
0
        /// <summary>
        /// Checks if L(this) is a subset of L(M).
        /// </summary>
        public bool IsSubsetOf(SSA <SYMBOL> m)
        {
            List <Predicate <SYMBOL> > witness;

            return(IsSubsetOf(m, out witness));
        }
Beispiel #15
0
 /// <summary>
 /// Checks if L(M1) equals L(M2). If not, produces witness.
 /// </summary>
 public static bool Equivalent(SSA <SYMBOL> m1, SSA <SYMBOL> m2, out List <Predicate <SYMBOL> > witness)
 {
     return(m1.automaton.IsEquivalentWith(m2.automaton, out witness));
 }
Beispiel #16
0
 /// <summary>
 /// ARMC constructor.
 /// </summary>
 /// <param name="init">SSA representing initial states.</param>
 /// <param name="bad">SSA representing bad states.</param>
 /// <param name="tau">SST representing transition.</param>
 /// <param name="configFileName">Configuration file path.</param>
 public ARMC(SSA <SYMBOL> init, SSA <SYMBOL> bad, SST <SYMBOL> tau, string configFileName)
     : this(init, bad, new SST <SYMBOL>[] { tau }, new Config(configFileName))
 {
 }
Beispiel #17
0
 /// <summary>
 /// Checks if the intersection of L(M1) and L(M2) is an empty language. If not, produces witness.
 /// </summary>
 public static bool ProductIsEmpty(SSA <SYMBOL> m1, SSA <SYMBOL> m2, out List <Predicate <SYMBOL> > witness)
 {
     return(!Automaton <Predicate <SYMBOL> > .CheckProduct(m1.automaton, m2.automaton, 0, out witness));
 }
Beispiel #18
0
        /// <summary>
        /// ARMC constructor.
        /// </summary>
        /// <param name="init">SSA representing initial states.</param>
        /// <param name="bad">SSA representing bad states.</param>
        /// <param name="taus">SSTs whose composition represents transition.</param>
        /// <param name="config">Configuration.</param>
        public ARMC(SSA <SYMBOL> init, SSA <SYMBOL> bad, SST <SYMBOL>[] taus, Config config)
        {
            /* merge alphabets */
            Set <SYMBOL> alphabet = init.Alphabet + bad.Alphabet + taus.Select(tau => tau.Alphabet).Aggregate(Set <SYMBOL> .Union);

            init.Alphabet = alphabet;
            bad.Alphabet  = alphabet;
            for (int i = 0; i < taus.Length; i++)
            {
                taus[i].Alphabet = alphabet;
            }

            if (config.PredicateLanguages == config.FiniteLengthLanguages)  // sanity check
            {
                throw ConfigException.AbstractionNotChosen();
            }

            this.init = init;
            this.bad  = bad;
            this.tau  = SST <SYMBOL> .Union(taus);

            this.tauInv = tau.Invert();
            this.abstr  = config.PredicateLanguages ?
                          (Abstraction <SYMBOL>) new PredicateAbstraction <SYMBOL>(config, init, bad, taus) :
                          new FiniteLengthAbstraction <SYMBOL>(config, init, bad, taus);
            this.verbose       = config.Verbose;
            this.printAutomata = config.PrintAutomata;
            this.outputDir     = config.OutputDirectory;
            this.format        = config.AutomataFormat;
            this.imgExt        = (config.ImageFormat == null) ? "" : config.ImageFormat.ToString();
            this.timeout       = config.Timeout.Ticks;
            this.stopwatch     = new Stopwatch();
            this.loops         = 0;

            if (outputDir != "")
            {
                /* clear output directory */
                DirectoryInfo dirInfo = Directory.CreateDirectory(outputDir);
                foreach (FileInfo fi in dirInfo.EnumerateFiles())
                {
                    fi.Delete();
                }
                foreach (DirectoryInfo di in dirInfo.EnumerateDirectories())
                {
                    di.Delete(true);
                }
            }

            if (printAutomata)
            {
                /* print input automata and configuration */
                string dir = Path.Combine(outputDir, "armc-input");
                Directory.CreateDirectory(dir);
                PrintAutomaton(init, dir, "init");
                PrintAutomaton(bad, dir, "bad");
                PrintAutomaton(tau, dir, "tau");
                if (taus.Length > 1)  // no point in only printing tau1
                {
                    for (int i = 0; i < taus.Length; i++)
                    {
                        PrintAutomaton(taus[i], dir, "tau" + (i + 1).ToString());
                    }
                }
                PrintAutomaton(tauInv, dir, "tau-inv");
                config.Write(Path.Combine(dir, "armc.properties"));
            }

            if (config.ComputationDirection == Config.Direction.Backward)
            {
                /* reverse direction, i.e. check if tauInv*(bad) & init is empty */
                this.init   = bad;
                this.bad    = init;
                this.tauInv = tau;
                this.tau    = tau.Invert();
            }

            if (!SSA <SYMBOL> .ProductIsEmpty(init, bad))    // no point in further verification
            {
                if (printAutomata)
                {
                    string dir = Path.Combine(outputDir, "armc-counterexample");
                    Directory.CreateDirectory(dir);
                    PrintAutomaton(init & bad, dir, "initXbad");
                }
                throw ARMCException.InitialPropertyViolation();
            }
        }
Beispiel #19
0
        /* label automaton states by predicate states whose forward/backward languages intersect */
        private Dictionary <int, Set <int> > MakeLabels(SSA <SYMBOL> m)
        {
            var labels = new Dictionary <int, Set <int> >(m.States.Count());

            foreach (int state in m.States)
            {
                labels[state] = new Set <int>();
            }
            var stack = new Stack <Tuple <int, int> >();

            foreach (SSA <SYMBOL> pred in predicateAutomata)
            {
                if (m.Algebra.Alphabet != pred.Algebra.Alphabet)
                {
                    throw SSAException.IncompatibleAlphabets();
                }
            }

            Func <int, IEnumerable <Move <Predicate <SYMBOL> > > > getMoves = forward ?
                                                                              (Func <int, IEnumerable <Move <Predicate <SYMBOL> > > >)m.GetMovesTo : m.GetMovesFrom;

            foreach (SSA <SYMBOL> pred in predicateAutomata)
            {
                if (forward)
                {
                    foreach (int mState in m.FinalStates)
                    {
                        foreach (int pState in pred.FinalStates)
                        {
                            stack.Push(new Tuple <int, int>(mState, pState));
                        }
                    }
                }
                else
                {
                    stack.Push(new Tuple <int, int>(m.InitialState, pred.InitialState));
                }

                while (stack.Count > 0)
                {
                    var pair   = stack.Pop();
                    int mState = pair.Item1;
                    int pState = pair.Item2;
                    labels[mState].Add(pair.Item2);

                    foreach (var mMove in getMoves(mState))
                    {
                        int state = forward ? mMove.SourceState : mMove.TargetState;
                        foreach (var pMove in (forward ? pred.GetMovesTo(pState) : pred.GetMovesFrom(pState)))
                        {
                            if (!m.Algebra.IsSatisfiable(mMove.Label & pMove.Label))
                            {
                                continue;
                            }
                            int stateLabel = forward ? pMove.SourceState : pMove.TargetState;
                            if (!labels[state].Contains(stateLabel))
                            {
                                stack.Push(new Tuple <int, int>(state, stateLabel));
                            }
                        }
                    }
                }
            }

            return(labels);
        }
Beispiel #20
0
        public override void Refine(SSA <SYMBOL> m, SSA <SYMBOL> x)
        {
            int offset = predicateAutomata.Sum(pred => pred.States.Count());

            x = x.RemoveEpsilons().Normalize(offset);

            predicateAutomata.Add(x);

            if (heuristic.HasValue)
            {
                var xStates = new Set <int>(x.States);

                /* find important states (appear in labels) */
                Dictionary <int, Set <int> > labels = MakeLabels(m);
                var importantStates = new Set <int>();
                foreach (int mState in m.States)
                {
                    foreach (int xState in labels[mState])
                    {
                        if (xState < offset || xState >= xStates.Count + offset)
                        {
                            continue;
                        }
                        importantStates.Add(xState);
                    }
                }

                if (((Config.PredHeuristic)heuristic) == Config.PredHeuristic.KeyStates)
                {
                    /* try to find one key state among important states */
                    foreach (int state in importantStates)
                    {
                        /* try ignoring all but one state */
                        ignoredLabels += xStates;
                        ignoredLabels.Remove(state);
                        /* check if the collapsed automaton still intersects */
                        if (SSA <SYMBOL> .ProductIsEmpty(Collapse(m), x))
                        {
                            return;
                        }
                        /* failed, restore temporarily ignored states */
                        ignoredLabels -= xStates;
                    }

                    /* couldn't find just one key state, try to find two */
                    foreach (int state1 in importantStates)
                    {
                        foreach (int state2 in importantStates.Where(s => s != state1))
                        {
                            ignoredLabels += xStates;
                            ignoredLabels.Remove(state1);
                            ignoredLabels.Remove(state2);
                            if (SSA <SYMBOL> .ProductIsEmpty(Collapse(m), x))
                            {
                                return;
                            }
                            ignoredLabels -= xStates;
                        }
                    }

                    /* fall back on important states heuristic */
                }

                /* ignore all unimportant states */
                ignoredLabels += xStates - importantStates;
            }
        }
Beispiel #21
0
 /// <summary>
 /// ARMC constructor.
 /// </summary>
 /// <param name="init">SSA representing initial states.</param>
 /// <param name="bad">SSA representing bad states.</param>
 /// <param name="tau">SST representing transition.</param>
 /// <param name="config">Configuration.</param>
 public ARMC(SSA <SYMBOL> init, SSA <SYMBOL> bad, SST <SYMBOL> tau, Config config)
     : this(init, bad, new SST <SYMBOL>[] { tau }, config)
 {
 }
Beispiel #22
0
 /// <summary>
 /// Checks if L(this) is a superset of L(M). If not, produces witness.
 /// </summary>
 public bool IsSupersetOf(SSA <SYMBOL> m, out List <Predicate <SYMBOL> > witness)
 {
     return(m.IsSubsetOf(this, out witness));
 }
Beispiel #23
0
 /// <summary>
 /// Checks if L(this) is a proper superset of L(M).
 /// </summary>
 public bool IsProperSupersetOf(SSA <SYMBOL> m)
 {
     return(m.IsSubsetOf(this) && !this.IsSubsetOf(m));
 }
Beispiel #24
0
        /// <summary>
        /// Performs one step (inner loop) of ARMC.
        /// </summary>
        /// <returns>Verification result, or <code>null</code> if undecided.</returns>
        /// <param name="counterexample">Counterexample (if encountered, i.e. <code>false</code> returned).</param>
        public bool?VerifyStep(out Counterexample <SYMBOL> counterexample)
        {
            var          ssas = new Stack <Tuple <SSA <SYMBOL>, SSA <SYMBOL> > >();
            SSA <SYMBOL> m;
            SSA <SYMBOL> ml;
            SSA <SYMBOL> mAlpha = null;
            SSA <SYMBOL> x;
            var          xs  = new Stack <SSA <SYMBOL> >();
            int          i   = 0;
            int          l   = 0;
            string       ext = "." + format.ToString().ToLower();
            string       dir = Path.Combine(outputDir, "armc-loop-" + loops.ToString());

            stopwatch.Start();

            if (printAutomata)
            {
                Directory.CreateDirectory(dir);
                abstr.Print(dir, this);
            }

            counterexample = null;

            m = init;
            if (printAutomata)
            {
                PrintAutomaton(m, dir, "M0");
            }

            while (true)
            {
                if (verbose)
                {
                    Log("\r" + loops.ToString() + "." + i.ToString());
                }

                if (i > 0 && !SSA <SYMBOL> .ProductIsEmpty(m, bad))
                {
                    if (verbose)
                    {
                        LogLine(": counterexample encountered");
                    }
                    l      = i;
                    x      = m & bad;
                    x.Name = "<i>X</i><sub>" + l.ToString() + "</sub>";
                    if (printAutomata)
                    {
                        PrintAutomaton(x, dir, "X" + l.ToString());
                    }
                    ml = m;
                    xs.Push(x);
                    break;
                }

                mAlpha      = abstr.Collapse(m).Determinize().Minimize();
                mAlpha.Name = "<i>M</i><sub>" + i.ToString() + "</sub><sup>&alpha;</sup>";
                if (printAutomata)
                {
                    PrintAutomaton(mAlpha, dir, "M" + i.ToString() + "+");
                }

                if (i > 0 && mAlpha == ssas.Peek().Item2)
                {
                    stopwatch.Stop();
                    if (verbose)
                    {
                        LogLine(": fixpoint reached");
                        LogLine("time = " + stopwatch.Elapsed.ToString());
                    }
                    return(true);
                }

                if (timeout > 0 && stopwatch.ElapsedTicks > timeout)
                {
                    stopwatch.Stop();
                    if (verbose)
                    {
                        LogLine(": timeout (" + stopwatch.Elapsed.ToString() + ")");
                    }
                    throw ARMCException.Timeout();
                }

                ssas.Push(Tuple.Create(m, mAlpha));
                i++;

                m      = tau.Apply(mAlpha).Determinize().Minimize();
                m.Name = "<i>M</i><sub>" + i.ToString() + "</sub>";
                if (printAutomata)
                {
                    PrintAutomaton(m, dir, "M" + i.ToString());
                }
            }

            bool spurious = false;

            foreach (var pair in ssas)
            {
                m      = pair.Item1;
                mAlpha = pair.Item2;

                i--;

                if (verbose)
                {
                    Log("\r" + loops.ToString() + "." + l.ToString() + "-" + i.ToString());
                }

                x      = (tauInv.Apply(x) & mAlpha).Determinize().Minimize();
                x.Name = "<i>X</i><sub>" + i.ToString() + "</sub>";
                xs.Push(x);
                if (printAutomata)
                {
                    PrintAutomaton(x, dir, "X" + i.ToString());
                }

                if (SSA <SYMBOL> .ProductIsEmpty(x, m))
                {
                    spurious = true;
                    break;
                }
            }

            stopwatch.Stop();

            if (spurious)
            {
                if (verbose)
                {
                    LogLine(": counterexample is spurious");
                }
                abstr.Refine(m, x);
                return(null);
            }
            else
            {
                if (verbose)
                {
                    LogLine(": counterexample is real");
                    LogLine("time = " + stopwatch.Elapsed.ToString());
                }
                List <Tuple <SSA <SYMBOL>, SSA <SYMBOL> > > ms = ssas.ToList();
                ms.Reverse();
                ms.Add(new Tuple <SSA <SYMBOL>, SSA <SYMBOL> >(ml, null));
                counterexample = new Counterexample <SYMBOL> {
                    Ms = ms,
                    Xs = xs.ToList()
                };
                return(false);
            }
        }
Beispiel #25
0
        /// <summary>
        /// Checks if the intersection of L(M1) and L(M2) is an empty language.
        /// </summary>
        public static bool ProductIsEmpty(SSA <SYMBOL> m1, SSA <SYMBOL> m2)
        {
            List <Predicate <SYMBOL> > witness;

            return(SSA <SYMBOL> .ProductIsEmpty(m1, m2, out witness));
        }
Beispiel #26
0
 /// <summary>
 /// Constructs SSA accepting L(this) minus L(M2).
 /// </summary>
 public SSA <SYMBOL> Minus(SSA <SYMBOL> m)
 {
     return(new SSA <SYMBOL>(this.automaton.Minus(m.automaton)));
 }
Beispiel #27
0
 /// <summary>
 /// Checks if L(M1) equals L(M2).
 /// </summary>
 public static bool Equivalent(SSA <SYMBOL> m1, SSA <SYMBOL> m2)
 {
     return(m1.automaton.IsEquivalentWith(m2.automaton));
 }
Beispiel #28
0
 /// <summary>
 /// ARMC constructor.
 /// </summary>
 /// <param name="init">SSA representing initial states.</param>
 /// <param name="bad">SSA representing bad states.</param>
 /// <param name="tau">SST representing transition.</param>
 public ARMC(SSA <SYMBOL> init, SSA <SYMBOL> bad, SST <SYMBOL> tau)
     : this(init, bad, new SST <SYMBOL>[] { tau }, new Config())
 {
 }
Beispiel #29
0
        /// <summary>
        /// Applies this transducer to automaton M in order to create a new automaton
        /// that accepts the translations of all words in L(M).
        /// </summary>
        public SSA <SYMBOL> Apply(SSA <SYMBOL> m)
        {
            if (this.Algebra.Alphabet != m.Algebra.Alphabet)
            {
                throw SSTException.IncompatibleAlphabets();
            }

            m = m.RemoveEpsilons();

            Automaton <Label <SYMBOL> > tau = this.automaton;
            var stack       = new Stack <Tuple <int, int> >();
            var finalStates = new List <int>();
            var moves       = new List <Move <Predicate <SYMBOL> > >();
            var stateDict   = new Dictionary <Tuple <int, int>, int>();
            int id          = 0;

            var init = new Tuple <int, int>(tau.InitialState, m.InitialState);

            stateDict[init] = id++;              // initial state will be 0
            stack.Push(init);

            Action <Tuple <int, int>, Tuple <int, int>, Predicate <SYMBOL> > addMove = (sourcePair, targetPair, label) => {
                int targetState;
                if (!stateDict.TryGetValue(targetPair, out targetState))
                {
                    stateDict[targetPair] = targetState = id++;
                    stack.Push(targetPair);
                }
                moves.Add(new Move <Predicate <SYMBOL> >(stateDict[sourcePair], targetState, label));
            };

            while (stack.Count > 0)
            {
                Tuple <int, int> sourcePair = stack.Pop();
                int tauState = sourcePair.Item1;
                int mState   = sourcePair.Item2;

                foreach (Move <Label <SYMBOL> > tauMove in tau.GetMovesFrom(tauState))
                {
                    if (tauMove.Label.Input == null)
                    {
                        addMove(
                            sourcePair,
                            new Tuple <int, int>(tauMove.TargetState, mState),
                            tauMove.Label.IsIdentity ? null : tauMove.Label.Output
                            );
                        continue;
                    }

                    foreach (Move <Predicate <SYMBOL> > mMove in m.GetMovesFrom(mState))
                    {
                        if (!m.Algebra.IsSatisfiable(tauMove.Label.Input & mMove.Label))
                        {
                            continue;
                        }
                        Predicate <SYMBOL> newLabel;
                        if (tauMove.Label.IsIdentity)
                        {
                            newLabel = tauMove.Label.Input & mMove.Label;
                        }
                        else
                        {
                            newLabel = tauMove.Label.Output;
                            if (newLabel != null && !m.Algebra.IsSatisfiable(newLabel))
                            {
                                continue;
                            }
                        }
                        addMove(
                            sourcePair,
                            new Tuple <int, int>(tauMove.TargetState, mMove.TargetState),
                            newLabel
                            );
                    }
                }
            }

            foreach (var pair in stateDict)
            {
                if (tau.IsFinalState(pair.Key.Item1) && m.IsFinalState(pair.Key.Item2))
                {
                    finalStates.Add(pair.Value);
                }
            }

            return(new SSA <SYMBOL>(0, finalStates, moves, m.Algebra.Alphabet));
        }
Beispiel #30
0
 /// <summary>
 /// Constructs SSA accepting union of L(M1) and L(M2).
 /// </summary>
 public static SSA <SYMBOL> Sum(SSA <SYMBOL> m1, SSA <SYMBOL> m2)
 {
     return(new SSA <SYMBOL>(Automaton <Predicate <SYMBOL> > .MkSum(m1.automaton, m2.automaton)));
 }