package hdgl.db.query.stm;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import hdgl.db.query.condition.AbstractCondition;
import hdgl.db.query.condition.NoRestriction;
import hdgl.db.query.stm.StateMachine.Condition;
import hdgl.db.query.stm.StateMachine.State;
import hdgl.db.query.stm.StateMachine.Transition;
import hdgl.db.query.stm.StateMachine.TransitionType;
public class SimpleStateMachine {
AbstractCondition[] edgeAlphabet;
AbstractCondition[] vertexAlphabet;
int maxstate=1;
Set<Integer> states = new HashSet<Integer>();
Map<Integer, int[]> transitions = new HashMap<Integer, int[]>();
Map<Integer, Boolean> success = new HashMap<Integer, Boolean>();
public SimpleStateMachine(AbstractCondition[] edgeAlphabet,
AbstractCondition[] vertexAlphabet) {
super();
this.edgeAlphabet = edgeAlphabet;
this.vertexAlphabet = vertexAlphabet;
}
public AbstractCondition[] getVertexAlphabet() {
return vertexAlphabet;
}
public void setVertexAlphabet(AbstractCondition[] vertexAlphabet) {
this.vertexAlphabet = vertexAlphabet;
}
public AbstractCondition[] getEdgeAlphabet() {
return edgeAlphabet;
}
public void setEdgeAlphabet(AbstractCondition[] edgeAlphabet) {
this.edgeAlphabet = edgeAlphabet;
}
public int getStates() {
return states.size();
}
public int addState(boolean isSuccess) {
int nstate = maxstate;
transitions.put(nstate,new int[vertexAlphabet.length+edgeAlphabet.length]);
success.put(nstate,isSuccess);
states.add(nstate);
maxstate++;
return nstate;
}
public void addTransition(int inState, int toState, int input, boolean isVertex){
if(!isVertex){
input += vertexAlphabet.length;
}
transitions.get(inState)[input] = toState;
}
public void print(PrintStream out){
out.print("states\t");
for (AbstractCondition ac : vertexAlphabet) {
out.print(ac+"\t");
}
out.print("|");
for (AbstractCondition ac : edgeAlphabet) {
out.print("\t"+ac);
}
out.println();
for(int i:states){
out.print(i+(success.get(i)?"!":"")+"\t");
for (int j = 0; j < vertexAlphabet.length; j++) {
out.print(transitions.get(i)[j]+"\t");
}
out.print("|");
for (int j = 0; j < edgeAlphabet.length; j++) {
out.print("\t"+transitions.get(i)[j+vertexAlphabet.length]);
}
out.println();
}
}
public void minimize(){
boolean doing = true;
w:while (doing) {
doing = false;
for (Map.Entry<Integer, int[]> tr1 : transitions.entrySet()) {
for (Map.Entry<Integer, int[]> tr2 : transitions.entrySet()) {
if(!tr1.getKey().equals(tr2.getKey())){
if(success.get(tr1.getKey()).equals(success.get(tr2.getKey())) &&
Arrays.equals(tr1.getValue(), tr2.getValue())){
compact(tr1.getKey(), tr2.getKey());
doing = true;
continue w;
}
}
}
}
}
}
void compact(int s1, int s2){
for (Map.Entry<Integer, int[]> tr : transitions.entrySet()) {
int[] r=tr.getValue();
for (int i = 0; i < r.length; i++) {
if(r[i]==s2)r[i]=s1;
}
}
success.remove(s2);
transitions.remove(s2);
states.remove(s2);
}
public StateMachine buildStateMachine(){
StateMachine stm = new StateMachine();
Map<Integer, Integer> newStateIds = new HashMap<Integer, Integer>();
Queue<Integer> states =new LinkedList<Integer>();
Set<Integer> closedStateSet = new HashSet<Integer>();
states.offer(-1);
//newStateIds.put(-1, 1);
while (states.size()>0) {
int stateId = states.poll();
closedStateSet.add(stateId);
int newStateId;
StateMachine.State state = stm.getState(newStateId = stm.addState());
newStateIds.put(stateId, newStateId);
List<StateMachine.Condition> conds = buildConditions(-stateId);
for(Condition cond:conds){
for(Transition t:cond.getTransitions()){
int next = t.getToState();
if(newStateIds.containsKey(next)){
next = newStateIds.get(next);
t.setToState(next);
}
if(next<0 && !states.contains(next) && !closedStateSet.contains(next)){
states.offer(next);
}
}
state.addCondition(cond);
}
}
for(State s:stm.getStates()){
for(Condition c:s.getConditions()){
for(Transition t:c.getTransitions()){
int next = t.getToState();
if(next<0){
t.setToState(newStateIds.get(next));
}
}
}
}
return stm;
}
List<StateMachine.Condition> buildConditions(int startState){
ArrayList<Condition> conditions = new ArrayList<StateMachine.Condition>();
int[] trans = this.transitions.get(startState);
int prevTrans = -1;
AbstractCondition prevCondition = null;
for(int i = 0;i < vertexAlphabet.length;i++){
if(trans[i] != prevTrans ||
!prevCondition.require(vertexAlphabet[i])){
if(prevCondition!=null && prevTrans!=0){
StateMachine.Condition cond= new StateMachine.Condition(prevCondition);
for(Transition t:buildTransitions(prevTrans)){
cond.addTransition(t);
}
conditions.add(cond);
}
prevTrans = trans[i];
prevCondition = vertexAlphabet[i];
}else{
prevCondition = vertexAlphabet[i];
}
}
if(prevCondition!=null&&prevTrans!=0){
StateMachine.Condition cond= new StateMachine.Condition(prevCondition);
for(Transition t:buildTransitions(prevTrans)){
cond.addTransition(t);
}
conditions.add(cond);
}
return conditions;
}
List<StateMachine.Transition> buildTransitions(int startState){
ArrayList<StateMachine.Transition> transitions = new ArrayList<StateMachine.Transition>();
int[] trans = this.transitions.get(startState);
if(success.get(startState)){
StateMachine.Transition transition = new Transition(TransitionType.Success, NoRestriction.I, 0);
transitions.add(transition);
}
int prevTrans = -1;
AbstractCondition prevCondition = null;
for(int i = 0;i < edgeAlphabet.length;i++){
if(trans[i+vertexAlphabet.length] != prevTrans ||
!prevCondition.require(edgeAlphabet[i])){
if(prevCondition!=null && prevTrans!=0){
StateMachine.Transition transition= new Transition(TransitionType.Out, prevCondition, -prevTrans);
transitions.add(transition);
}
prevTrans = trans[i+vertexAlphabet.length];
prevCondition = edgeAlphabet[i];
}else{
prevCondition = edgeAlphabet[i];
}
}
if(prevCondition != null && prevTrans!=0){
StateMachine.Transition transition = new Transition(TransitionType.Out, prevCondition, -prevTrans);
transitions.add(transition);
}
return transitions;
}
}