/// <summary>
        /// Run the machine
        /// </summary>
        /// <param name="x">The input to run the machine on.</param>
        /// <returns>True if the machine halts in the accept state.</returns>
        /// <remarks>The first move the machine makes is to fill the first tape (tape 0) with the blank symbol followed by the input.</remarks>
        public new bool Run(IEnumerable <char> x)
        {
            var tapes = Enumerable.Range(0, Tapes).Select(n => new List <char>(Alphabet.Blank)).ToList();

            // Fill the first tape with the input
            foreach (var c in x)
            {
                if (!Alphabet.Contains(c))
                {
                    return(false);
                }
                if (c == Alphabet.EmptyString)
                {
                    continue;
                }
                tapes[0].Add(c);
            }

            try {
                return(Run(tapes, InitialState, Enumerable.Range(0, Tapes).Select(n => 0).ToArray()).Result);
            }
            catch (StackOverflowException) {
                return(false);                // infinite loop, reject
            }
        }
Пример #2
0
        /// <summary>
        /// Run the machine
        /// </summary>
        /// <param name="x">The input to run the machine on.</param>
        /// <param name="o">The completed tape contents</param>
        /// <returns>True if the machine halts in the accept state.</returns>
        /// <remarks>The first move the machine makes is to fill the tape with the blank symbol followed by the input.</remarks>
        public bool Run(IEnumerable <char> x, out char[] o)
        {
            var tape = new List <char>()
            {
                Alphabet.Blank
            };

            // Fill the tape with the input
            foreach (var c in x)
            {
                if (!Alphabet.Contains(c))
                {
                    o = new char[0];
                    return(false);
                }
                if (c == Alphabet.EmptyString)
                {
                    continue;
                }
                tape.Add(c);
            }

            try {
                var res = Run(tape, InitialState, 0).Result;
                o = res.Item2;
                return(res.Item1);
            }
            catch (StackOverflowException) {
                o = new char[0];
                return(false); // infinite loop, reject
            }
        }
Пример #3
0
        /// <param name="q">The set of states</param>
        /// <param name="a">The language alphabet</param>
        /// <param name="g">The stack alphabet</param>
        /// <param name="d">The transition function containing Transition and PushdownTransition objects</param>
        /// <param name="q0">The initial state</param>
        /// <param name="f">The set of accepting states</param>
        /// <exception cref="ArgumentException"></exception>
        public PushdownAutomaton(States q, Alphabet a, StackAlphabet g, PushdownTransitionFunction d, State q0, AcceptingStates f)
        {
            States          = q;
            Alphabet        = a;
            StackAlphabet   = g;
            Transitions     = d;
            InitialState    = q0;
            AcceptingStates = f;

            if (States.Count == 0)
            {
                throw new ArgumentException("The set of states cannot be empty.");
            }
            if (!States.Contains(InitialState))
            {
                throw new ArgumentException("The inital state does not exist in the set of states!");
            }

            foreach (var s in AcceptingStates)
            {
                if (!States.Contains(s))
                {
                    throw new ArgumentException($"The accepting state {s} is not in the set of states!");
                }
            }

            foreach (var t in Transitions)
            {
                if (!States.Contains(t.P) || !States.Contains(t.Q) ||
                    (!Alphabet.Contains(t.A) && t.A != Alphabet.EmptyString) ||
                    (!StackAlphabet.Contains(t.Top) && t.Top != Alphabet.Wildcard && t.Top != Alphabet.EmptyString))
                {
                    throw new ArgumentException($"Invalid transition {t}");
                }
                if (t.Replace.Length == 1 && ((t.Replace[0] != Alphabet.Wildcard && t.Replace[0] != Alphabet.EmptyString) && !StackAlphabet.Contains(t.Replace[0])))
                {
                    throw new ArgumentException($"Invalid replace char for transition {t}");
                }
                if (t.Replace.Length > 1 && Array.Exists(t.Replace, x => !StackAlphabet.Contains(x)))
                {
                    throw new ArgumentException($"Invalid replace char sequence for transition {t}");
                }
            }
        }
        private async Task <bool> Run(char[] x, State p, int i)
        {
            for (; i < x.Length; i++)
            {
                if (!Alphabet.Contains(x[i]))
                {
                    return(false);
                }
                if (x[i] == Alphabet.EmptyString)
                {
                    continue;
                }

                // get possible transitions
                var q = Transitions[p, x[i]];

                if (q.Length == 0)                // nothing to do, stop
                {
                    return(false);
                }

                if (q.Length == 1)
                {
                    p = q[0].Q;                     // switch states
                    if (q[0].A == Alphabet.EmptyString)
                    {
                        i--;                                                    // Don't increment on null transition!
                    }
                }

                else                   // we have a choice
                {
                    var tasks = new Task <bool> [q.Length];
                    // check each path asynchronously
                    for (var j = 0; j < q.Length; j++)
                    {
                        tasks[j] = Run(x, q[j].Q, q[j].A == Alphabet.EmptyString ? i : i + 1);
                    }

                    var result = false;
                    // check the result
                    foreach (var t in tasks)
                    {
                        result = result || await t;
                    }
                    return(result);                    // if one of them is successful, this branch accepts
                }
            }

            // No more moves!
            if (p.Accepting)
            {
                return(true);
            }

            // check for lambda transitions
            var r       = Transitions[p, Alphabet.EmptyString];
            var lambdas = new Task <bool> [r.Length];

            for (var k = 0; k < r.Length; k++)
            {
                lambdas[k] = Run(x, r[k].Q, i);
            }
            var accept = false;

            foreach (var t in lambdas)
            {
                accept = accept || await t;
            }
            return(accept);
        }
Пример #5
0
        private async Task <bool> Run(char[] x, State p, int i, Stack <char> stack)
        {
            for (; i < x.Length; i++)
            {
                if (!Alphabet.Contains(x[i]))
                {
                    return(false);
                }
                if (x[i] == Alphabet.EmptyString)
                {
                    continue;
                }

                // Get possible transitions
                var q = Transitions[p, x[i], stack.Peek()];

                if (q.Length == 0)                // nothing to do, stop
                {
                    return(false);
                }

                if (q.Length == 1)
                {
                    // try to update the stack. if we are out of bounds, reject
                    try { stack = updateStack(stack, q[0].Top, q[0].Replace); }
                    catch (Exception) { return(false); }

                    p = q[0].Q;
                    if (q[0].A == Alphabet.EmptyString)
                    {
                        i--;                                                    // Don't increment on null transition!
                    }
                }

                else
                {
                    var tasks = new Task <bool> [q.Length];
                    // check each path asynchronously
                    for (var j = 0; j < q.Length; j++)
                    {
                        var s = new Stack <char>(stack);
                        try { s = updateStack(s, q[j].Top, q[j].Replace); }
                        catch (Exception) { continue; }

                        tasks[j] = Run(x, q[j].Q, q[j].A == Alphabet.EmptyString ? i : i + 1, s);
                    }

                    var result = false;
                    foreach (var t in tasks)
                    {
                        result = result || (t != null && await t);
                    }
                    return(result);
                }
            }

            // No more moves!
            if (p.Accepting)
            {
                return(true);
            }

            // check for lambda transitions
            var r       = Transitions[p, Alphabet.EmptyString, stack.Peek()];
            var lambdas = new Task <bool> [r.Length];

            for (var k = 0; k < r.Length; k++)
            {
                var s = new Stack <char>(stack);
                try { s = updateStack(s, r[k].Top, r[k].Replace); }
                catch (Exception) { continue; }

                lambdas[k] = Run(x, r[k].Q, i, s);
            }
            var accept = false;

            foreach (var t in lambdas)
            {
                accept = accept || (t != null && await t);
            }
            return(accept);
        }