Приклади кінцевих державних машин [закрито]


25

Я шукаю гарні приклади кінцевих державних машин; мова не особливо важлива, лише хороші приклади.

Реалізація коду є корисною (узагальнений псевдо-код), але також дуже корисно збирати різні способи використання FSM.

Приклади не обов'язково повинні базуватися на комп’ютері, наприклад, наприклад, «Железнодорожние сети Майка Данлай», дуже корисні.


12
Регулярні вирази - це машини з кінцевим станом.
chrisaycock

5
Я не розумію, чому це питання позначено як "неконструктивне". Враховуючи, що минуло майже 2 роки, як я вперше представив відповідь, що це закрито, я стверджую, що це насправді було дуже конструктивним та тематичним.
аква

2
@aqua - це справді більше проблеми зі стеком. Програмісти, його мандат - відповідати на запитання, дуже конкретні запитання, на які є одна відповідь. Однак такі питання, як цінні, не вважаються "конструктивними" (дуже поганим визначенням цього терміна в IMNSHO.) На основі визначення сайтів Stack взагалі. Відверто кажучи, програмісти справді корисні, воно повинно сприйняти менш ревне дотримання цього конкретного правила, але я старий, втомлений і іншим чином займаюся, щоб докласти необхідні зусилля, щоб "намагатися виправити дурних".
ocodo

1
Фактично справжньою проблемою є те, що сайти Stack, відверто кажучи, один з дуже небагатьох високоякісних ресурсів, які добре відомі та спільні, і мають хороший читабельний формат. Здається, що цей редукціонізм на Stack справді вказує на необхідність формату сайту, який відповідає навчальним "питанням" (можливо, без використання слова E)
ocodo

3
Я б все-таки закликав людей знову відкривати це питання, тому що більше прикладів було б чудово. Сумний факт, якби не було додано нових відповідей, питання залишилося б відкритим.
ocodo

Відповіді:


28

Безпечний (подія запущена)

  • Штати : кілька "заблокованих" станів, одне "незамкнено" стан
  • Переходи : Правильні комбінації / клавіші переміщують вас від початкових заблокованих станів до заблокованих станів ближче до розблокованих, поки ви нарешті не дістаєтесь до розблокованих. Неправильні комбінації / клавіші повертають вас у початковий заблокований стан (іноді відомий як простоювати) .

Світлофор (час спрацьовує | датчик [подія] спрацьовує)

  • Штати : ЧЕРВОН, ЖОВТИЙ, ЗЕЛЕНИЙ (найпростіший приклад)
  • Переходи : Після зміни таймера ЧЕРВЕНИЙ на ЗЕЛЕНИЙ, ЗЕЛЕНИЙ на ЖОВТИЙ, а ЖОВТИЙ на КРАСНИЙ. Це також може спрацьовувати на автомобілях зондування в різних (більш складних) станах.

Торговий автомат (подія запущена, зміна сейфу )

  • Штати : IDLE, 5_CENTS, 10_CENTS, 15_CENTS, 20_CENTS, 25_CENTS тощо, VEND, CHANGE
  • Переходи : зміни держави після вставки монет, рахунків, переходу на VEND при правильній сумі покупки (або більше), а потім переходу до ЗМІНИ або IDLE (залежно від того, наскільки етичний ваш торговий автомат)

+1 і більше, якщо я міг. Все добре виглядає, окрім останнього. Це повинно бути, БЕЗКОШТОВНО, ВІДПРИЄМСТВО та ЗМІНА Значення є умовними і повинні бути представлені як перехід між IDLE і самим собою. Ви також хочете, щоб стан, що представляє, вибраний елемент.
Еван Плейс

@EvanPlaice: Чи не вибір елемента просто стане подією, яка викликає перехід від IDLE до VEND? Якщо ви не запропонували спосіб підтвердження вибору перед продажем.
Місько

Будь-який шанс діаграми для цих двох?
ocodo

Це такі самі, як приклади, наведені на сторінці Вікіпедії FSM , яка також включає ліфти: "Прості приклади - торгові машини , які відпускають продукцію, коли належна комбінація монет відкладається, ліфти , послідовність зупинок яких визначається запитуваними поверхами. водіями, світлофорами , які змінюють послідовність, коли автомобілі чекають, та комбінованими замками , які потребують введення комбінованих номерів у належному порядку ".
icc97

1
@ icc97 Прикладів FSM є безліч і поширений у повсякденному житті. До речі, пост обміну стеками попередньо включає інформацію про приклад на сторінку Вікіпедії :)
aqua

14

Приклад протоколу прикордонного шлюзу

BGP - це протокол, який підтримує основні рішення щодо маршрутизації в Інтернеті. Він підтримує таблицю для визначення доступності хостів із заданого вузла і зробив Інтернет справді децентралізованим.

У мережі кожен вузол BGP є одноранговим і використовує машину з кінцевим станом, з одним із шести станів: Idle , Connect , Active , OpenSent , OpenConfirm та Established . Кожне однорангове з'єднання в мережі підтримує один з цих станів.

Протокол BGP визначає повідомлення, які надсилаються одноліткам, щоб змінити їх стан.

Бюро державних діаграм.

Бюджетна схема BGP

Холостий

Перший стан простою . У цьому стані BGP ініціалізує ресурси та відмовляється від спроб вхідного з'єднання та ініціює з'єднання з одноранговим.

Підключення

Другий стан Підключення . У такому стані маршрутизатор чекає завершення з'єднання та переходу до стану OpenSent у разі успіху. Якщо не вдалося, він скидає таймер ConnectRetry і після закінчення переходить до активного стану.

Активний

У активному стані маршрутизатор скидає таймер ConnectRetry до нуля і повертається в стан підключення .

OpenSent

У стані OpenSent маршрутизатор відправляє відкрите повідомлення і чекає його натомість. Повідомлення Keepalive обмінюються, і після успішного отримання маршрутизатор переходить у встановлений стан.

Встановлено

У встановленому стані маршрутизатор може відправляти / отримувати: Keepalive; Оновлення; і Повідомлення повідомлень до / від свого колеги.

Більше інформації про BGP можна знайти на wikipedia


@tcrosley - це з wikipedia, тому насправді не заслуговує на кредит.
окудо

1
Ок, +1 для включення діаграми. :)
tcrosley

Я спробував зафіксувати мітку діаграми на BGP, але це не дозволило мені - недостатньо символів :)
Майк Данлаве

Має бути кращий спосіб зробити це.
Робота

1
@Job - трохи пізня відповідь, вибачте, але зараз я думаю, що це занадто езотеричний приклад, Безпечний, Торговий автомат і т. Д. Є набагато кориснішим, на мою думку.
ocodo

7

Вони корисні для моделювання будь-яких речей. Наприклад, виборчий цикл може бути змодельований штатами за принципом (нормальний уряд) - вибори, які називаються -> (дострокова агітація) - розпущений парламент -> (жорстка агітація) --вибори -> (підрахунок голосів ). Тоді або (підрахунок голосів) - без більшості -> (коаліційні переговори) - досягнута домовленість -> (нормальний уряд) або (підрахунок голосів) - величина -> (нормальний уряд). Я реалізував варіант за цією схемою в грі з політичною підгруппою.

Вони використовуються і в інших аспектах ігор: AI часто заснований на державних; переходи між меню та рівнями та переходи після смерті чи завершеного рівня часто добре моделюються FSM.


++ Хороший приклад.
Майк Данлаве

1
+1 Хороший приклад DFM (детермінованої машини з кінцевим станом), оскільки шляхи.
Еван Плейс

4

CSV аналізатор використовується в JQuery-CSV плагін

Це базовий аналізатор граматики Чомського типу III .

Для оцінювання даних на основі принципу «Чар-за-Чар» використовується токенізатор-регекс. Якщо виникає контрольна графіка, код передається в оператор перемикання для подальшої оцінки на основі стартового стану. Символи без контролю групуються та копіюються масово, щоб зменшити кількість необхідних операцій копіювання рядків.

Токенізатор:

var tokenizer = /("|,|\n|\r|[^",\r\n]+)/;

Перший набір збігів - це контрольні символи: роздільник значень роздільника значення (") (,) та роздільник введення (усі варіанти нового рядка). Останній збіг обробляє групування символів без контролю.

Є 10 правил, яким повинен відповідати аналізатор:

  • Правило №1 - один запис на рядок, кожен рядок закінчується новим рядком
  • Правило №2 - пропуск нового рядка в кінці файлу опущений
  • Правило №3 - Перший рядок містить дані заголовка
  • Правило №4 - Проміжки вважаються даними, а записи не повинні містити коду в кінці
  • Правило № 5 - рядки можуть бути, а можуть і не бути обмежені подвійними лапками
  • Правило № 6 - поля, що містять розриви рядків, подвійні лапки та коми, повинні бути укладені у подвійні лапки
  • Правило № 7 - Якщо для укладання полів використовуються подвійні лапки, то подвійну цитату, що з’являється всередині поля, необхідно уникнути, передуючи їй ще однією подвійною цитатою
  • Поправка №1 - поле, яке не котирується, може або може
  • Поправка №2 - Поле, яке цитується, може чи не може
  • Поправка №3 - Останнє поле в записі може містити або не містити нульового значення

Примітка. Найпопулярніші 7 правил отримані безпосередньо з IETF RFC 4180 . Останні 3 були додані, щоб охопити крайові регістри, запроваджені сучасними програмами електронних таблиць (Excel, Google Spreadsheet), які не розмежовують (тобто цитують) усі значення за замовчуванням. Я намагався внести зміни до RFC, але ще не почув відповіді на мій запит.

Досить з вітром, ось схема:

CSV аналізатор кінцевого стану аналізатора

Штати:

  1. початковий стан для запису та / або значення
  2. зустрічається вступна цитата
  3. зустрічається друга цитата
  4. зустрічається значення без котирування

Переходи:

  • а. перевіряє як цитовані значення (1), цінні без котирування (3), нульові значення (0), нульові записи (0) та нові записи (0)
  • б. чеки на другу графіку (2)
  • c. перевіряє наявність процитованої цитати (1), кінця значення (0) та кінця запису (0)
  • г. перевіряє кінець значення (0) та кінець запису (0)

Примітка. Насправді відсутній стан. Повинно бути рядок із "c" -> "b", позначений станом "1", оскільки другий відмежувач, який уникнув, означає, що перший роздільник ще відкритий. Насправді, мабуть, було б краще представити це як інший перехід. Створювати це - мистецтво, немає єдиного правильного способу.

Примітка. У ньому також відсутній стан виходу, але на дійсних даних аналізатор завжди закінчується на переході 'a', і жоден із станів не можливий, тому що для розбору не залишається нічого.

Різниця між державами та переходами:

Стан є кінцевим, тобто можна зробити висновок лише про одне.

Перехід являє собою потік між станами, тому він може означати багато речей.

В основному, перехідний стан -> 1 -> * (тобто один на багато). Держава визначає "що це таке", а перехід визначає "як це обробляти".

Примітка. Не хвилюйтесь, якщо застосування станів / переходів не відчуває себе інтуїтивно, це не інтуїтивно. Було потрібно кілька обширних відповідей з кимось набагато розумнішим за мене, перш ніж я нарешті отримав концепцію дотримуватися.

Псевдокод:

csv = // csv input string

// init all state & data
state = 0
value = ""
entry = []
output = []

endOfValue() {
  entry.push(value)
  value = ""
}

endOfEntry() {
  endOfValue()
  output.push(entry)
  entry = []
}

tokenizer = /("|,|\n|\r|[^",\r\n]+)/gm

// using the match extension of string.replace. string.exec can also be used in a similar manner
csv.replace(tokenizer, function (match) {
  switch(state) {
    case 0:
      if(opening delimiter)
        state = 1
        break
      if(new-line)
        endOfEntry()
        state = 0
        break
      if(un-delimited data)
        value += match
        state = 3
        break
    case 1:
      if(second delimiter encountered)
        state = 2
        break
      if(non-control char data)
        value += match
        state = 1
        break
    case 2:
      if(escaped delimiter)
        state = 1
        break
      if(separator)
        endOfValue()
        state = 0
        break
      if(newline)
        endOfEntry()
        state = 0
        break
    case 3:
      if(separator)
        endOfValue()
        state = 0
        break
      if(newline)
        endOfEntry()
        state = 0
        break
  }
}

Примітка. Це суть, на практиці є ще багато, що слід врахувати. Наприклад, перевірка помилок, нульових значень, кінцевий порожній рядок (тобто, що є дійсним) тощо.

У цьому випадку стан є умовою речей, коли блок відповідності регулярних виразів закінчує ітерацію. Перехід представлений як випадок випадку.

Як люди, ми маємо тенденцію до спрощення операцій низького рівня на більш високі автореферати рівня , але робота з FSM буде працювати з операціями низького рівня. Хоча зі станами та переходами дуже легко працювати з окремими, по суті важко візуалізувати ціле все одночасно. Мені було найпростіше дотримуватися окремих шляхів виконання знову і знову, поки я не зміг зрозуміти, як відбувається перехід. Це король, як вивчити основну математику, ви не зможете оцінити код з більш високого рівня, поки деталі з низьким рівнем не стануть автоматичними.

Убік: Якщо ви подивитесь на фактичну реалізацію, то багато деталей не вистачає. По-перше, всі неможливі шляхи будуть кидати конкретні винятки. Ударити їх не можна, але якщо щось порушиться, вони абсолютно спричинить винятки в тестовому бігуні. По-друге, правила аналізатора того, що дозволено в "легальному" рядку даних CSV, досить вільні, тому код необхідний для обробки багатьох конкретних крайових випадків. Незалежно від цього факту, це був процес, який використовується для знущання над FSM перед усіма виправленнями помилок, розширеннями та тонкою настройкою.

Як і у більшості конструкцій, це не точно представлення реалізації, але воно окреслює важливі частини. На практиці є фактично 3 різні функції парсера, отримані від цієї конструкції: сплітковий лінійний спліттер, однорядний аналізатор і повний багаторядковий аналізатор. Всі вони діють аналогічно, вони відрізняються тим, як обробляють нові рядки.


1
о! дуже приємний внесок.
окудо

@Slomojo Спасибі, я раді поділитися. Я не ходив до школи на CS, тому мені довелося самостійно вивчити цей матеріал. Справді важко знайти додатки в реальному світі, які б висвітлювали такі теми CS високого рівня, як ці в Інтернеті. Я планую врешті детально задокументувати алгоритм синтаксичного аналізу, щоб він міг бути корисним іншим, як я. Це вдалий старт.
Еван Плейс

Я також самоучка, але я почав 30 років тому, тому до цього часу я вже висвітлював навчальну програму CS :) Я опублікував це питання для таких людей, як ти і я. Я думаю, що тоді було значно простіше вивчити теорію дуже низького рівня, просто тому, що було менше відволікань та більше можливостей працювати поруч із металом, хоча інтернету насправді не було, і ми всі жили в печерах.
окудо

3

Простий FSM на Java

int i=0;

while (i<5) {
 switch(i) {
   case 0:
     System.out.println("State 0");
     i=1;
     break;
   case 1:
     System.out.println("State 1");
     i=6;
     break;
   default:
     System.out.println("Error - should not get here");
     break;      
  }

} 

Ось так. Гаразд, це не геніально, але це показує ідею.

Ви часто знаходите FSM в телекомунікаційних продуктах, оскільки вони пропонують просте рішення інакше складної ситуації.


3
Вони також є важливою частиною побудови укладача у лексичному аналізі.
jmq

@jmquigley, ви можете додати відповідь, будь ласка?
ocodo

1
Я додав окрему відповідь з парою посилань для вас.
jmq

3

Я виявив, що думка про / моделювання ліфта (ліфта) - хороший приклад машини з кінцевим станом. Це не потребує способу введення, але забезпечує далеко не тривіальну ситуацію для втілення.

Держави є, наприклад, на першому поверсі, на першому поверсі і т. Д., І пересуваються на перший поверх, або переміщуються з третього на перший поверх, але зараз між 3 та 2 поверхами тощо.

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

На кожному поверсі, окрім верхнього та нижнього, будуть встановлені дві кнопки: одна вимагає, щоб ліфт піднявся вгору, а другий спустився вниз.


2

Добре, ось приклад. Припустимо, ви хочете розібрати ціле число. Це піде щось на зразок dd*де dціла цифра.

state0:
    if (!isdigit(*p)) goto error;
    p++;
    goto state1;
state1:
    if (!isdigit(*p)) goto success;
    p++;
    goto state1;

Звичайно, як сказав @Gary, ви можете замаскувати їх gotoза допомогою оператора переключення та змінної стану. Зауважте, що можна структурувати цей код, який є ізоморфним для початкового регулярного виразу:

if (isdigit(*p)){
    p++;
    while(isdigit(*p)){
        p++;
    }
    // success
}
else {
    // error
}

Звичайно, ви також можете це зробити за допомогою таблиці пошуку.

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

Приклад мережі залізниць

Одним із прикладів FSM є мережа залізниць.

Існує обмежена кількість комутаторів, на яких поїзд може перейти на одну з двох колій.

Існує обмежена кількість доріжок, що з'єднують ці комутатори.

У будь-який час поїзд знаходиться на одній колії, він може бути відправлений на іншу колію, перетинаючи комутатор, виходячи з одного біта вхідної інформації.



@Slomojo: Це добре. Виглядає добре.
Майк Данлаве

2

Кінцева державна машина в Рубі:

module Dec_Acts
 def do_next
    @now = @next
    case @now
    when :invite
      choose_round_partner
      @next = :wait
    when :listen
      @next = :respond
    when :respond
      evaluate_invites
      @next = :update_in
    when :wait
      @next = :update_out
    when :update_in, :update_out
      update_edges
      clear_invites
      @next = :exchange
    when :exchange
      update_colors
      clear_invites
      @next = :choose
    when :choose
      reset_variables
      choose_role
    when :done
      @next = :done
    end
  end
end

Ось така поведінка одного обчислювального вузла в розподіленій системі, встановлення схеми зв'язку на основі зв'язку. Більш-менш. У графічній формі це виглядає приблизно так:

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


+1 Цікаво. На що посилається DGMM?
Еван Плейс

@EvanPlaice, це алгоритм покриття вершинного покриття на основі максимальної відповідності на основі максимальної відповідності (DGMM) ... дещо скорочена абревіатура, не питайте мене, звідки походить G.
ocodo

@slomojo "G" - це "Узагальнений", послідовний алгоритм, з якого це походить, використовує техніку, яку називають узагальненою максимальною відповідністю.
філосопад

@philosodad Я припускав стільки ж, але мені не подобається публікувати припущення.
ocodo


0

На практиці державні машини часто використовуються для:

  • Мета проектування (моделювання різних дій у програмі)
  • Натуральні мовні (граматичні) аналізатори
  • Розбір рядків

Одним із прикладів може бути державна машина, яка сканує рядок, щоб побачити, чи має він правильний синтаксис. Наприклад, голландські поштові індекси відформатовані як "1234 AB". Перша частина може містити лише цифри, друга лише букви. Можливо, може бути записана державна машина, яка відслідковує, перебуває вона у статусі НОМЕРА чи в ПІСЛЯ, і якщо вона зіткнеться з неправильним введенням, відхиліть її.

Ця машина стану приймача має два стани: числовий і альфа. Державна машина запускається в числовому стані і починає читати символи рядка для перевірки. Якщо під час будь-якого з станів зустрічаються недійсні символи, функція повертається з значенням False, відхиляючи введення як недійсне.

Код Python:

import string

STATE_NUMERIC = 1
STATE_ALPHA = 2

CHAR_SPACE = " "

def validate_zipcode(s):
cur_state = STATE_NUMERIC

for char in s:
    if cur_state == STATE_NUMERIC:
        if char == CHAR_SPACE:
            cur_state = STATE_ALPHA
        elif char not in string.digits:
            return False
    elif cur_state == STATE_ALPHA:
        if char not in string.letters:
            return False
return True

zipcodes = [
    "3900 AB",
    "45D6 9A",
]

for zipcode in zipcodes:
    print zipcode, validate_zipcode(zipcode)

Джерело: (Кінцеві) державні машини на практиці

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.