Пример конечного автомата

Может ли кто-нибудь привести хороший пример использования State machine в программном обеспечении (кроме компиляторов и парсеров)? Есть примеры большой практической важности, и использование конечного автомата должно упростить программное обеспечение :-)

Я хочу написать приложение .NET.

Спасибо.


person evgeny-i    schedule 20.04.2012    source источник


Ответы (9)


Вы можете думать о каждом пользовательском интерфейсе, который вы видите, как об одной большой машине состояний. Каждое событие пользовательского интерфейса (например, нажатие кнопки, выбор меню и т. д.) приводит к переходу в другое состояние, что может означать новую страницу.

person duffymo    schedule 20.04.2012

Планировщик/диспетчер ядра ОС является конечным автоматом. Потоки имеют состояния: работает, готово, спящий, ожидание события, приостановлено, завершено. События — это аппаратные прерывания от драйверов устройств ввода-вывода и программные прерывания от запущенных потоков.

person Martin James    schedule 20.04.2012

Дизайн веб-сайта, показывающий типичные пути навигации (аналогично ответу @duffymo). Вот неполный пример (вдохновленный «Применением UML и шаблонов» (Крейг Ларман)):

введите здесь описание изображения

person Fuhrmanator    schedule 21.04.2012

Другой сценарий — заказ. Новый заказ (в новом состоянии) может быть отменен или изменен, но не возвращен. Но, как только вы получите его в завершенном состоянии, его нельзя будет отменить, но он может быть возвращен.

person AD.Net    schedule 20.04.2012

Генератор случайных чисел можно как-то рассматривать и как конечный автомат. У вас есть набор входных данных, таких как сдвиг влево, добавление константы, умножение на константу и т. д. Состояние — это фактическое текущее случайное значение. Поскольку количество таких случайных чисел конечно, их можно рассматривать как своего рода конечный автомат.

person user1339260    schedule 20.04.2012

Для некоторых примеров конечных автоматов (представленных в Umple) см.:

Программное обеспечение для блокировки канала: http://cruise.eecs.uottawa.ca/umpleonline/?example=CanalLockStateMachine&diagramtype=state

Обработка телекоммуникационных вызовов: http://cruise.eecs.uottawa.ca/umpleonline/?example=Phone&diagramtype=state

Программное обеспечение для гаражных ворот: http://cruise.eecs.uottawa.ca/umpleonline/?example=GarageDoor&diagramtype=state

Бронирование в системе бронирования авиабилетов: http://cruise.eecs.uottawa.ca/umpleonline/?example=Booking&diagramtype=state

person Timothy C. Lethbridge    schedule 14.01.2014

Библиотека opengl — это конечный автомат. Он сохраняет статус, который меняется в зависимости от вызовов библиотечных функций. Вы можете увидеть это здесь: http://www.cs.tufts.edu/research/graphics/resources/OpenGL/OpenGL.htm

Еще одна область применения конечных автоматов — видеоигры. Представьте себе одного врага, который относительно умен. У этого врага будет несколько статусов: атакующий, прячущийся, умирающий, бегущий и т. д. Это может контролироваться состояниями и событиями. Когда я писал видеоигру в качестве своего дипломного проекта, я использовал две машины состояний: одну для игрового процесса (экран презентации, игра, параметры и т. д.), а другую — для самой игры (задание вопроса, бросок кубика, перемещение игрока и т. д.). )

person Community    schedule 17.01.2014

Вот пример игрушечного консольного приложения базового FSM.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//  DESC: QAD-FSM (Quick And Dirty Finite State Machine)
//  
//  Notes: In its simplest form a state machine is
//       • A set of states
//       • A set of events
//       • A set of transitions that define 
//           the next state given the current state and event.
//       • A method of tracking current state
// 
//  Example:
// 
//       I want to create a different kind of door lock that
//           has the following states:
//          
//               1. LBS - Locked_Both_Sides
//               2. UBS - Unlocked_Both_Sides
//               3. LFO - Locked_From_Outside
// 
//           and has the following events:
//          
//               1. OKT - Outside Key Turn
//               2. IKT - Inside Key Turn
//              
//       Transistions will be as follows:
//      
//       CurrState  Event   NextState   Desc
//       ========================================================
//       LBS            OKT     UBS         When both sides locked, outside key turn unlocks both sides
//       LBS            IKT     LFO         When both sides locked, inside key turn unlocks inside
//       UBS            OKT     LFO         When both sides unlocked, outside key turn locks outside
//       UBS            IKT     LBS         When both sides unlocked, inside key turn locks both sides
//       LFO            OKT     UBS         When only outside locked, outside key turn unlocks outside
//       LFO            IKT     LBS         When only outside locked, inside key turn locks both sides.

namespace FSM
{
    // The FSM states
    enum State
    {
        LBS,
        UBS,
        LFO
    }

    // The FSM events
    enum Event
    {
        IKT,
        OKT
    }

    class Transition
    {
        public State currState { get; set; }
        public Event evnt { get; set; }
        public State nextState { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var fsm = new FSM();

            System.Console.WriteLine("Current State: " + fsm.StateDesc[fsm.CurrentState]);

            string input = "";
            while (input != "x")
            {
                System.Console.Write("Enter key turn [IKT, OKT] or x to exit: ");
                input = System.Console.ReadLine();
                if (input == "x") break;
                Event evnt;
                if (!Enum.TryParse(input, out evnt))
                {
                    System.Console.WriteLine("Invalid input: " + input + ", enter one of [IKT,OKT,x]");
                    continue;
                }
                fsm.ChangeState(evnt);
                System.Console.WriteLine("New State: " + fsm.StateDesc[fsm.CurrentState]);
            }

            System.Console.WriteLine("");
            System.Console.WriteLine("History");
            System.Console.WriteLine("===============================================");
            System.Console.WriteLine("CurrState(Event) => NextState");
            System.Console.WriteLine("===============================================");
            fsm.hist
                .Select(h => h.currState.ToString() + "(" + h.evnt.ToString() + ") => " + h.nextState.ToString())
                .ToList()
                .ForEach(h => System.Console.WriteLine(h));
        }
    }

    class FSM
    {
        public Dictionary<State, String> StateDesc = new Dictionary<State, String>()
                                                { 
                                                    {State.LBS, "Both Sides Locked"},
                                                    {State.LFO, "Locked From Outside"},
                                                    {State.UBS, "Both Sides Unlocked"}
                                                };

        public List<Transition> hist = new List<Transition>();

        // Create FSM transitions.
        List<Transition> trans = new List<Transition>
            {
                new Transition() { currState = State.LBS, evnt = Event.OKT, nextState = State.UBS }, 
                new Transition() { currState = State.LBS, evnt = Event.IKT, nextState = State.LFO }, 
                new Transition() { currState = State.UBS, evnt = Event.OKT, nextState = State.LFO }, 
                new Transition() { currState = State.UBS, evnt = Event.IKT, nextState = State.LBS }, 
                new Transition() { currState = State.LFO, evnt = Event.OKT, nextState = State.UBS }, 
                new Transition() { currState = State.LFO, evnt = Event.IKT, nextState = State.LBS }, 
            };

        public State CurrentState { get { var lt = hist.FirstOrDefault(); return lt == null ? State.UBS : lt.nextState; } }

        public State? ChangeState(Event evnt)
        {
            var t = trans.Find(r => r.currState == CurrentState && r.evnt == evnt);
            if (t == null) return null; // If you don't create transitions that cover all combinations this could happen.
            hist.Insert(0, t);
            return t.nextState;
        }
    }
}
person cyberman    schedule 29.09.2015

Вы можете увидеть мой универсальный конечный автомат в .net, используя аспектно-ориентированное программирование в качестве примера реализации.

Его можно использовать в программном обеспечении, которому требуется некоторая логика рабочего процесса, например рабочий процесс утверждения.

https://github.com/rcarubbi/carubbi.statemachine

Просто создайте свою сущность следующим образом:

    [InitialState("State1")]
    public class Entity : IStatedEntity
    {

        [Transition(From = "State1", To = "State2")]
        [Transition(From = "State3", To = "State1")]
        public void Method1()
        {
            Trace.WriteLine("Method1");
        }

        [Transition(From = "State2", To = "State1")]
        public string Method2()
        {
            Trace.WriteLine("Method2");
            return string.Empty;
        }

        [Transition(From = "State2", To = "State3")]
        [Transition(From = "State3", To = "State4")]
        public int Method3(int p1, int p2)
        {
            Trace.WriteLine("Method3");
            return p1 + p2;
        }


        public StateMachine StateMachine { get; set; }
   }

и используйте его следующим образом:

      [TestMethod]
        public void TestMethod1()
        {
            StateMachine.Configure();
            var ent = new Entity
            {
                StateMachine =
                {
                    IgnoreInvalidOperations = true
                }
            };

            ent.StateMachine.TransitionStarted += StateMachine_TransitionStarted;
            ent.StateMachine.TransitionEnded += StateMachine_TransitionEnded;

            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method1();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method2();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method1();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result = ent.Method3(2, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result2 = ent.Method3(4, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result3 = ent.Method3(4, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
        }

        private void StateMachine_TransitionEnded(object sender, TransitionEventArgs e)
        {

        }


        private void StateMachine_TransitionStarted(object sender, TransitionStartedEventArgs e)
        {

        }
   }
person rcarubbi    schedule 11.10.2018