Передача конечного состояния и межфазная сигнализация
Рекомендации для языков с родными (без каких-либо средств генерации FSM) поддержка разработки и выполнения государственных машин и передачи сообщений/сигналов. Это для телекоммуникационных компаний, например, внедрение FSM такого уровня сложности.
Я рассмотрел Erlang, но мне понравилась бы некоторая обратная связь, предложения, указатель на учебники, альтернативы, в частности, на основе Java. Может быть, Scala?
Только с открытым исходным кодом. Я не ищу решения UML или регулярных выражений.
Как это делается для реализации протоколов телекоммуникаций, FSM могут быть нетривиальными. Многие состояния, многие переходы, основанные на сигналах, входные ограничения/охранники. Динамическая инстанция будет плюсом. Выводы операторов не могут быть и речи, он быстро гнездится к непригодным. Это вряд ли лучше, если /else.
Я бы предпочел не зависеть от графического дизайна; описание формата FSM должно быть понятным для человека/редактируемым/управляемым.
-
Я решил сосредоточиться на основанном на актере решении для С++
Например, структура Theron обеспечивает отправную точку http://theron.ashtonmason.net/ и во избежание операторов switch в обработчике событий на основе FSM этот шаблон С++ FSM Framework выглядит полезным http://satsky.spb.ru/articles/fsm/fsmEng.php
Ответы
Ответ 1
Я согласен с тем, что операторы switch не должны быть в стороне... они в конечном итоге приводят к кошмарам обслуживания. Вы не можете использовать State Pattern для реализации вашего FSM? В зависимости от вашей реальной реализации вы можете использовать актеров (если у вас есть несколько FSM-сотрудничающих - хм... это возможно?). Самое приятное в актерах в том, что рамки для передачи сообщений уже есть.
Пример использования состояния:
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)
}
}
}
}
Это очень простой код, но, поскольку я не знаю больше требований, я могу больше всего думать. Преимущество государства состоит в том, что каждое состояние самодостаточно в одном классе.
Ответ 2
Это конкретное приложение, реализация протокола telco, является тем, для чего был создан Erlang. Первоначальными приложениями Erlang в Ericsson были телефонные коммутаторы, а самыми ранними коммерческими продуктами были коммутаторы ATM, поддерживающие все протоколы telco.
OTP имеет стандартное поведение для реализации FSM, называемых gen_fsm
. Вот пример его использования в нетривиальном FSM в некоторой документации OTP.
OSERL является открытой реализацией SMPP в Erlang и демонстрирует, как вы можете реализовать протокол telco с помощью gen_fsm
s. Хорошим примером для этого будет gen_esme_session.
Пока я не могу указать на код, я знаю, что существует немало компаний Erlang, продающих продукты, ориентированные на телекоммуникации: Corelatus, Synapse, Motivity и другие.
Ответ 3
Я не согласен, что FSM тривиально реализовать. Это очень недальновидно и демонстрирует либо незнание альтернатив, либо отсутствие опыта со сложными государственными машинами.
Основная проблема заключается в том, что граф конечной машины очевиден, но код FSM - нет. Как только вы выйдете за пределы дюжины состояний и перечислите количество переходов, код FSM становится уродливым и трудным для подражания.
Есть инструменты, в которых вы рисуете конечный автомат и генерируете для него Java-код. Однако я не знаю о каких-либо инструментах с открытым исходным кодом.
Теперь, возвращаясь к Erlang/ Scala, Scala, есть и Actors и передача сообщений, и основана на JVM, поэтому это может быть лучшей альтернативой, чем Erlang с учетом ваших ограничений.
Там есть библиотека DFA/NFA на Scala, хотя она не особенно хорошая. Он поддерживает преобразование из произвольных регулярных выражений (т.е. Литералы не обязательно должны быть символами) в 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 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)
}
Ответ 4
Я с трудом могу думать о любом языке, где реализация FSM нетривиальна. Возможно этот.
...
if (currentState == STATE0 && event == EVENT0) return STATE1;
if (currentState == STATE1 && event == EVENT0) return STATE2;
...
Ответ 5
Шаблон состояния (с использованием перечислений 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();
}
}
Ответ 6
FSM должен быть тривиальным для реализации на любом языке с аргументом case. Ваш выбор языка должен основываться на том, что должен делать конечный конечный автомат.
Например, вы заявляете, что вам нужно сделать это для развития телекоммуникаций и указать сообщения. Я бы посмотрел на системы/языки, поддерживающие передачу распределенных сообщений. Erlang делает это, и я уверен, что любой другой общий язык поддерживает это через API/библиотеку для языка.