我可以使用Java.util.Set在Java中实现DFA的状态转换吗
我正在实现一个DFA,尽可能接近正式定义,作为一个学习练习(和博客材料) 我计划使用java.util.Set,其中定义中涉及一个集合 该定义涉及一组元组来定义合法状态转换:(state,symbol)->nextState 我有一个成员为state、symbol和nextState的转换类。我实现了equals()和hashCode(),以指示如果两个转换在状态和符号上匹配,则它们是相等的。然后我有一组java.util.Transition实例 在我的处理算法中,当我读取下一个符号时,我具有当前状态。我期望使用这两个函数构建一个Transition对象,从集合中提取匹配的Transition,然后告诉我下一个状态,我可以进行迭代 但是-我看不到任何提取java.util.Set成员以供进一步使用的方法。我可以删除(对象o),但这只是返回布尔值我可以使用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实例 在我的处理算法中,当我读取下一个符号时,我具有
我做错了什么?设置可能不是您希望用于此目的的设置。我的建议是使用List
您可能需要一个只包含状态和符号的类,而不包含其他属性,并将其用作映射中的键。或者,您可以使用
映射我同意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;
}