我可以使用Java.util.Set在Java中实现DFA的状态转换吗

我可以使用Java.util.Set在Java中实现DFA的状态转换吗,java,computer-science,set,finite-automata,Java,Computer Science,Set,Finite Automata,我正在实现一个DFA,尽可能接近正式定义,作为一个学习练习(和博客材料) 我计划使用java.util.Set,其中定义中涉及一个集合 该定义涉及一组元组来定义合法状态转换:(state,symbol)->nextState 我有一个成员为state、symbol和nextState的转换类。我实现了equals()和hashCode(),以指示如果两个转换在状态和符号上匹配,则它们是相等的。然后我有一组java.util.Transition实例 在我的处理算法中,当我读取下一个符号时,我具有

我正在实现一个DFA,尽可能接近正式定义,作为一个学习练习(和博客材料)

我计划使用java.util.Set,其中定义中涉及一个集合

该定义涉及一组元组来定义合法状态转换:(state,symbol)->nextState

我有一个成员为state、symbol和nextState的转换类。我实现了equals()和hashCode(),以指示如果两个转换在状态和符号上匹配,则它们是相等的。然后我有一组java.util.Transition实例

在我的处理算法中,当我读取下一个符号时,我具有当前状态。我期望使用这两个函数构建一个Transition对象,从集合中提取匹配的Transition,然后告诉我下一个状态,我可以进行迭代

但是-我看不到任何提取java.util.Set成员以供进一步使用的方法。我可以删除(对象o),但这只是返回布尔值


我做错了什么?

设置可能不是您希望用于此目的的设置。我的建议是使用List,或者可能使用Map。如果不实际构建它并进行一些基准测试,我不确定哪一个更好。

听起来您对equals()和hashCode()的重写是可疑的,因为原始转换与集合中根据equals()的转换匹配,但这两个转换是不可互换的(否则,您只需使用新的过渡代替原始过渡。)


您可能需要一个只包含状态和符号的类,而不包含其他属性,并将其用作映射中的键。或者,您可以使用
映射

我同意Matthew Brubaker的观点,即
设置
可能不是您所需要的。您可能希望尝试使用
枚举
;请参阅示例

如果没有一些外部状态集合,甚至没有Transstion对象,您就不能完成这项工作吗?如果State类的定义如下:

public class State
{
    private Map<Symbol, State> transitions = new HashMap<Symbol, State>();

    public State() { /* populate transitions somehow */ }

    public State nextState(Symbol symbol) { return transitions.get(symbol); }
}

是的,我有点困惑,为什么我甚至需要一个收藏品

对于简单的状态机,您可以使用静态整数和case语句来执行以下状态机操作:

int STATE1 = 1; 
int STATE2 = 2;
int STATE3 = 3;
int STATE4 = 4;

int currentstate = STATE1 ;
int input = nextInput();


while(currentstate != STATE4 ){
   switch(input){
      case STATE1: 
          if(input == 'a') currentstate = STATE2; 
          break;
      case STATE2: 
          if(input == 'b') currentstate = STATE3;
          else currentstate = STATE1;
          break;
      case STATE3: 
          if(input == 'c')  currentstate = STATE4;
          else currentstate = STATE1;
      }
 }
这是一个基本状态机,它将查找任何包含“abc”的字符串。您可以轻松地扩展它,查找ab*c或任何您想要的内容

那么,如果您想要在运行时构建一个动态状态机,该怎么办呢?嗯,我也这么做了。这并不难。我所做的是创建一个包含转换列表的状态类。每个转换都有一个指向下一个状态的指针,以及要链接的条件

例如,STATE1将有一个带有条件“a”的转换和一个指向表示STATE2的某个对象的指针。代码将检查这些条件(可能是一个以int为参数的对象,如果匹配,则返回true或false)如果条件匹配,它会将状态指针移动到转换所指向的状态

代码可能看起来像这样

public void move(int input){
   for(transition t : currentState.transitions){
      if(t.getCriteria().matches(input)){
         currentState = t.getNextState();
         break;
      }
   }
}

如果您只想实现模式匹配引擎,可能不需要状态设计模式,因为模式不太可能改变。正如Chad指出的,在这种情况下,使用
开关对转换函数进行编码是完全可以接受的

下面是一个使用集合的不确定模式匹配自动机的示例:

public boolean validate() {
    Set<Integer> currentStates = new HashSet<Integer>();
    final Set<Integer> acceptingStates = new HashSet<Integer>();

    currentStates.add(0); // Initial state.
    acceptingStates.add(1);
    acceptingStates.add(3);
    acceptingStates.add(6);

    for (int i = 0; i < getInput().length(); i++) {
        char c = getInput().charAt(i);
        Set<Integer> newStates = new HashSet<Integer>();

        for (int state : currentStates) {
            switch (state) {
                case 0:
                    if (c == 'a')
                        newStates.add(1);
                    break;
                case 1:
                    if (c == 'b') {
                        newStates.add(2);
                        newStates.add(4);
                    }
                    break;
                case 2:
                    if (c == 'b')
                        newStates.add(3);
                    break;
                case 3:
                    if (c == 'b')
                        newStates.add(2);
                    break;
                case 4:
                    if (c == 'b')
                        newStates.add(5);
                    break;
                case 5:
                    if (c == 'b')
                        newStates.add(6);
                    break;
                case 6:
                    if (c == 'b')
                        newStates.add(4);
                    break;
            }
        }

        if (newStates.size() == 0)
            return false;
        currentStates = newStates;

        System.out.printf("Character read: %c\n", c);
        System.out.printf("Current states: ");
        printStates(currentStates);
    }

    for (int state : acceptingStates)
        if (currentStates.contains(state))
            return true;
    return false;
}
public boolean validate(){
Set currentStates=new HashSet();
最终集合acceptingStates=新HashSet();
currentStates.add(0);//初始状态。
接受状态。添加(1);
接受状态。添加(3);
接受状态。添加(6);
对于(int i=0;i

该自动机识别模式
“a(bb*| bbb*)
”所描述的常规语言的输入字,即“a”后跟2的倍数或3的倍数多个“b”s、

这不是关于性能或任何东西,它只是一个简单易懂的实现。我喜欢Map思想——定义是有一个转换函数,而不是一组转换函数——因此我认为这符合精神……实际上,我在想状态是下一个状态的Map——让我试试。转换/状态对于映射条目也是一个不错的选择。=)您考虑的是确定性有限状态
public boolean validate() {
    Set<Integer> currentStates = new HashSet<Integer>();
    final Set<Integer> acceptingStates = new HashSet<Integer>();

    currentStates.add(0); // Initial state.
    acceptingStates.add(1);
    acceptingStates.add(3);
    acceptingStates.add(6);

    for (int i = 0; i < getInput().length(); i++) {
        char c = getInput().charAt(i);
        Set<Integer> newStates = new HashSet<Integer>();

        for (int state : currentStates) {
            switch (state) {
                case 0:
                    if (c == 'a')
                        newStates.add(1);
                    break;
                case 1:
                    if (c == 'b') {
                        newStates.add(2);
                        newStates.add(4);
                    }
                    break;
                case 2:
                    if (c == 'b')
                        newStates.add(3);
                    break;
                case 3:
                    if (c == 'b')
                        newStates.add(2);
                    break;
                case 4:
                    if (c == 'b')
                        newStates.add(5);
                    break;
                case 5:
                    if (c == 'b')
                        newStates.add(6);
                    break;
                case 6:
                    if (c == 'b')
                        newStates.add(4);
                    break;
            }
        }

        if (newStates.size() == 0)
            return false;
        currentStates = newStates;

        System.out.printf("Character read: %c\n", c);
        System.out.printf("Current states: ");
        printStates(currentStates);
    }

    for (int state : acceptingStates)
        if (currentStates.contains(state))
            return true;
    return false;
}