Сигнал конечного автомата и меж-FSM - PullRequest
14 голосов
/ 18 сентября 2009

Рекомендации для языков с родной (так что нет инструментов генерации FSM) поддержкой разработки конечного автомата и выполнения и передачи сообщений / сигналов. Это относится к телекоммуникациям, например, к внедрению автоматов такого уровня сложности.

Я рассмотрел Erlang, но хотел бы получить отзывы, предложения, указатели на учебные пособия, альтернативы, в частности, платформы на основе Java. Может Скала?

Только с открытым исходным кодом. Я не ищу решения, связанные с UML или регулярными выражениями.

Поскольку это касается реализации телекоммуникационных протоколов, автоматы могут быть нетривиальными. Много состояний, много переходов, на основе сигналов, входные ограничения / охранники. Динамическое создание было бы плюсом. О переключателях речи не может быть и речи, он быстро становится непригодным для использования. Едва ли лучше, если / иначе.

Я бы предпочел, чтобы не зависело от графического дизайна; описание формата FSM должно быть читаемым / редактируемым / управляемым.

-

Я решил сосредоточиться на решении на основе Actor для C ++

Например, платформа Theron предоставляет отправную точку http://theron.ashtonmason.net/, и для избежания операторов switch в обработчике событий на основе FSM эта инфраструктура шаблонов C ++ FSM выглядит полезной http://satsky.spb.ru/articles/fsm/fsmEng.php

Ответы [ 6 ]

10 голосов
/ 18 сентября 2009

Именно это приложение, реализация протокола Telco, было разработано для Erlang. Первоначальными приложениями Erlang в Ericsson были телефонные коммутаторы, а самыми ранними коммерческими продуктами были коммутаторы ATM, поддерживающие всевозможные протоколы связи.

OTP имеет стандартное поведение для реализации FSM, называемое gen_fsm. В некоторых документациях OTP .

есть пример его использования в нетривиальном FSM.

OSERL - это открытая реализация SMPP в Erlang, демонстрирующая, как вы можете реализовать протокол связи с использованием gen_fsm s. Хороший пример, на который стоит обратить внимание: gen_esme_session .

Хотя я не могу указать вам код, я знаю, что довольно много Erlang-компаний продают продукты, ориентированные на телекоммуникации: Corelatus , Synapse , Мотивация среди прочих.

8 голосов
/ 18 сентября 2009

Я согласен с тем, что о переключателях не может быть и речи ... в конечном итоге они приводят к кошмарам обслуживания Разве вы не можете использовать State Pattern для реализации своего FSM? В зависимости от вашей реальной реализации, вы можете использовать актеров (если у вас есть несколько сотрудничающих FSM - хм ... это возможно?). Хорошая вещь об актерах - то, что структура для передачи сообщений уже существует.

Примером использования State будет:

trait State {
  def changeState(message: Any): State
}

trait FSM extends Actor {
  var state: State

  def processMessage(message: Any) {
    state = state.changeState(message)
  }

  override def act() {
    loop {
      react {
        case m: Any => processMessage(m)
      }
    }
  }
}

Это очень простой код, но, поскольку я не знаю больше требований, это самое большее, что я могу придумать. Преимущество State состоит в том, что каждое государство автономно в одном классе.

4 голосов
/ 18 сентября 2009

Я не согласен с тем, что FSM тривиально реализовать. Это очень недальновидно и показывает либо недостаточное знакомство с альтернативами, либо отсутствие опыта работы со сложными конечными автоматами.

Основная проблема заключается в том, что конечный автомат graph очевиден, а FSM code - нет. Как только вы преодолеете дюжину состояний и наберете множество переходов, код FSM станет уродливым и трудным для отслеживания.

Существуют инструменты, с помощью которых вы рисуете конечный автомат и генерируете для него Java-код. Однако я не знаю ни одного инструмента с открытым исходным кодом для этого.

Теперь, возвращаясь к Erlang / Scala, в Scala есть также актеры и сообщения, и он основан на JVM, так что это может быть лучшей альтернативой, чем Erlang, учитывая ваши ограничения.

В Scala также есть библиотека DFA / NFA, хотя она не особенно хороша. Он поддерживает преобразование из произвольных регулярных выражений (т.е. литералы не обязательно должны быть символами) в DFA / NFA.

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

import scala.util.regexp._
import scala.util.automata._

// The goal of this object below is to create a class, MyChar, which will
// be the domain of the tokens used for transitions in the DFA. They could
// be integers, enumerations or even a set of case classes and objects. For
// this particular code, it's just Char.
object MyLang extends WordExp {
  type _regexpT = RegExp
  type _labelT = MyChar

  case class MyChar(c:Char) extends Label
}

// We now need to import the types we defined, as well as any classes we
// created extending Label.    
import MyLang._

// We also need an instance (singleton, in this case) of WordBerrySethi,
// which will convert the regular expression into an automatum. Notice the
// language being used is MyLang.    
object MyBerrySethi extends WordBerrySethi {
  override val lang = MyLang
}

// Last, a function which takes an input in the language we defined,
// and traverses the DFA, returning whether we are at a sink state or
// not. For other uses it will probably make more sense to test against
// both sink states and final states.
def matchDet(pat: DetWordAutom[MyChar], seq: Seq[Char]): Boolean =
  !pat.isSink((0 /: seq) ((state, c) => pat.next(state, MyChar(c))))

// This converts a regular expression to a DFA, with using an intermediary NFA    
def compile(pat: MyLang._regexpT) = 
  new SubsetConstruction(MyBerrySethi.automatonFrom(pat, 100000)).determinize

// Defines a "?" function, since it isn't provided by the library
def Quest(rs: _regexpT*) = Alt(Eps, Sequ(rs: _*)) // Quest(pat) = Eps|pat = (pat)?


// And now, the algorithm proper. It splits the string into words
// converts each character into Letter[MyChar[Char]],
// produce the regular expression desired for each word using Quest and Sequ,
// then the final regular expression by using Sequ with each subexpression.
def words(s : String) = s.split("\\W+")
def wordToRegex(w : String) : Seq[MyLang._regexpT] = w.map(c => Letter(MyChar(c)))
def wordRegex(w : String) = Quest(wordToRegex(w) reduceRight ((a,b) => Sequ(a, Quest(b))))
def phraseRegex(s : String) = Sequ(words(s).map(w => wordRegex(w)) : _*)

// This takes a list of strings, produce a DFA for each, and returns a list of
// of tuples formed by DFA and string.
def regexList(l : List[String]) = l.map(s => compile(phraseRegex(s)) -> s)

// The main function takes a list of strings, and returns a function that will
// traverse each DFA, and return all strings associated with DFAs that did not
// end up in a sink state.
def regexSearcher(l : List[String]) = {
  val r = regexList(l)
  (s : String) => r.filter(t => matchDet(t._1, s)).map(_._2)
}
0 голосов
/ 04 февраля 2011

Шаблон State (с использованием перечислений Java) - это то, что мы используем в нашем телекоммуникационном приложении, однако мы используем небольшие FSM:

public class Controller{
    private State itsState = State.IDLE;

    public void setState(State aState){
        itsState = aState;
    }

    public void action1(){
        itsState.action1(this);
    }

    public void action2(){
        itsState.action2(this);
    }

    public void doAction1(){
        // code
    }

    public void doAction2(){
        // code
    }
}

public enum State{
    IDLE{
        @Override
        public void action1(Controller aCtx){
            aCtx.doAction1();
            aCtx.setState(State.STATE1);
        }
    },

    STATE1{
        @Override
        public void action2(Controller aCtx){
            aCtx.doAction2();
            aCtx.setState(State.IDLE);
        }
    },

    public void action1(Controller aCtx){
        throw new IllegalStateException();
    }

    public void action2(Controller aCtx){
        throw new IllegalStateException();
    }
}
0 голосов
/ 18 сентября 2009

Я с трудом могу придумать какой-либо язык, где реализация FSM нетривиальна. Может быть этот .

...
if (currentState == STATE0 && event == EVENT0) return STATE1;
if (currentState == STATE1 && event == EVENT0) return STATE2;
...
0 голосов
/ 18 сентября 2009

FSM должен быть тривиальным для реализации на любом языке с оператором case. Ваш выбор языка должен основываться на том, что должен делать этот конечный автомат.

Например, вы заявляете, что вам нужно сделать это для развития телекоммуникаций, и упоминать сообщения. Я бы посмотрел на системы / языки, которые поддерживают распределенную передачу сообщений. Эрланг делает это, и я уверен, что почти все другие распространенные языки поддерживают это через API / библиотеку для языка.

...