2009-09-17 13 views
14

राज्य मशीन विकास और निष्पादन के लिए देशी (इसलिए कोई एफएसएम पीढ़ी उपकरण) समर्थन के साथ भाषाओं के लिए सिफारिशें और संदेश/संकेतों को पारित करना। यह दूरसंचार के लिए है, उदाहरण के जटिलता के इस स्तर के एफएसएम के कार्यान्वयन।फिनिट स्टेट मशीन और इंटर-एफएसएम सिग्नलिंग

मैंने एरलांग माना है, लेकिन ट्यूटोरियल, विकल्प, विशेष रूप से जावा आधारित ढांचे के लिए कुछ प्रतिक्रिया, सुझाव, सूचक से प्यार होगा। शायद स्कैला?

केवल ओपन सोर्स। मैं यूएमएल या नियमित अभिव्यक्ति से संबंधित समाधान की तलाश नहीं कर रहा हूं।

चूंकि यह दूरसंचार प्रोटोकॉल के कार्यान्वयन के लिए है, इसलिए एफएसएम गैर-तुच्छ हो सकता है। कई राज्य, कई संक्रमण, संकेत आधारित, इनपुट बाधाओं/गार्ड। गतिशील त्वरण एक प्लस होगा। स्विच कथन प्रश्न से बाहर हैं, यह जल्दी से अनुपयोगी के लिए घोंसला। यह मुश्किल से बेहतर है कि अगर/else।

मैं ग्राफिकल डिज़ाइन पर निर्भर करता हूं; प्रारूप एफएसएम विवरण मानव पठनीय/संपादन योग्य/प्रबंधनीय होना चाहिए।

-

मैं के लिए सी ++

उदाहरण के लिए एक अभिनेता आधारित समाधान पर ध्यान केंद्रित करने का फैसला किया है, थेरॉन ढांचा एक प्रारंभिक बिंदु http://theron.ashtonmason.net/ और FSM आधारित ईवेंट हैंडलर इस सी में स्विच बयानों से बचने के लिए प्रदान करता है ++ एफएसएम टेम्पलेट फ्रेमवर्क उपयोगी दिखता है http://satsky.spb.ru/articles/fsm/fsmEng.php

+0

अपने आवश्यक वस्तुएँ क्या _are_? और आपकी बाधाएं? –

+5

अब मैं फ्लाइंग स्पेगेटी राक्षस की मानसिक छवि के साथ अटक गया हूं। संदेश पासिंग को नूडली एपेंडेज में लागू किया जा सकता है। –

उत्तर

8

मैं मानता हूं कि स्विच स्टेटमेंट प्रश्न से बाहर होना चाहिए ... अंततः वे रखरखाव दुःस्वप्न का कारण बनते हैं। क्या आप अपने एफएसएम को लागू करने के लिए State Pattern का उपयोग नहीं कर सकते? आपके वास्तविक कार्यान्वयन के आधार पर, आप अभिनेताओं का उपयोग कर सकते हैं (यदि आपके पास एकाधिक एफएसएम सहयोग है - एचएम ... क्या यह संभव है?)। अभिनेताओं के बारे में अच्छी बात यह है कि संदेश पास करने के लिए ढांचा पहले से ही है।

राज्य का उपयोग कर किया जाएगा का एक उदाहरण:

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) 
     } 
    } 
    } 
} 

यह बहुत ही बुनियादी कोड है, लेकिन जैसा कि मैंने आवश्यकताओं की अधिक पता नहीं है, कि ज्यादातर मैं के बारे में सोच सकते हैं। राज्य का लाभ यह है कि प्रत्येक राज्य एक वर्ग में आत्मनिर्भर है।

+0

धन्यवाद। एक अच्छा उदाहरण है। – hplbsh

+2

रिकॉर्ड के लिए, अक्का एफएसएम इसके लिए एक अच्छा समाधान है। – ron

-1

एफएसएम किसी भी भाषा में लागू करने के लिए तुच्छ होना चाहिए जिसमें केस स्टेटमेंट है। भाषा की आपकी पसंद उस परिमित राज्य मशीन को करने की आवश्यकता पर आधारित होना चाहिए।

उदाहरण के लिए, आप बताते हैं कि आपको दूरसंचार विकास के लिए ऐसा करने और संदेशों का उल्लेख करने की आवश्यकता है। मैं सिस्टम/भाषाओं को देखता हूं जो वितरित संदेश को गुजरने का समर्थन करते हैं। Erlang यह करता है, और मुझे यकीन है कि भाषा के लिए एक एपीआई/पुस्तकालय के माध्यम से बस हर दूसरी आम भाषा का समर्थन करता है।

4

मैं असहमत हूं कि एफएसएम लागू करने के लिए तुच्छ हैं। यह बहुत छोटा दिखता है, और या तो दिखाता है विकल्प के साथ परिचित की कमी, या जटिल राज्य मशीनों के साथ अनुभव की कमी।

मौलिक समस्या यह है कि एक राज्य मशीन ग्राफ स्पष्ट है, लेकिन 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

एक एफएसएम का _mechanics_ लागू करने के लिए सरल है (निश्चित रूप से एरलांग में है) लेकिन _logical transitions_ ग्राफ की जटिलता का अधिक कार्य है। – jldupont

+0

मुझे यह मिला जो कि ब्याज का हो सकता है। जावा के लिए पीढ़ी के एफएसएम के लिए ग्रहण आधारित प्लग-इन के साथ एक ढांचा: http://unimod.sourceforge.net – hplbsh

10

यह विशेष अनुप्रयोग, टेलको प्रोटोकॉल कार्यान्वयन, एरलांग के लिए बनाया गया था। एरिक्सन में एरलांग के प्रारंभिक अनुप्रयोग टेलीफोन स्विच थे और सबसे शुरुआती वाणिज्यिक उत्पाद एटीएम स्विच सभी तरह के टेलको प्रोटोकॉल का समर्थन करते थे।

ओटीपी के पास gen_fsm नामक एफएसएम लागू करने के लिए एक मानक व्यवहार है। OTP Documentation में से कुछ में गैर-तुच्छ एफएसएम में इसके उपयोग का एक उदाहरण है।

OSERL एरलांग में एक खुला सॉस एसएमपीपी कार्यान्वयन है और यह दर्शाता है कि आप gen_fsm एस का उपयोग कर एक टेलको प्रोटोकॉल को कैसे कार्यान्वित कर सकते हैं। देखने के लिए एक अच्छा उदाहरण gen_esme_session होगा।

जब मैं कोड के लिए आप बात नहीं कर सकते, मैं जानता हूँ कि वहाँ काफी कुछ Erlang टेल्को उन्मुख उत्पादों की बिक्री कंपनियों के हैं: Corelatus, Synapse, Motivity दूसरों के बीच में।

0

मैं किसी भी भाषा के बारे में शायद ही सोच सकता हूं जहां एफएसएम लागू करना गैर-तुच्छ है। शायद this one

... 
if (currentState == STATE0 && event == EVENT0) return STATE1; 
if (currentState == STATE1 && event == EVENT0) return STATE2; 
... 
0

राज्य पैटर्न (जावा enums का प्रयोग करके) हम क्या हमारे दूरसंचार आवेदन में उपयोग होता है, लेकिन हम छोटे 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

सच है कि यह छोटे राज्य मशीनों के लिए एक व्यवहार्य समाधान हो सकता है जैसा आपने उल्लेख किया है। लेकिन राज्यों की संख्या और घटनाओं में से कोई भी संभावना बमबारी की संभावनाओं को बढ़ाती है, और उस समय enum समाधान एक बड़ा छोड़ दिया जाता है। सबसे पहले सभी एक्शन कोड एक फ़ाइल में होने के कारण, दूसरी बार एनम आईएमओ की स्टेटलेस प्रकृति के कारण। –

संबंधित मुद्दे