/** * Contruye el AFD equivalente * * @return <b>AFD</b> Automata finito equivalente al AFN recibido */ private AFD buildAFD() { for (Cerradura cerradura : cerraduras) { Estado origen = getState(cerradura); Estado destino = null; for (pol.una.py.model.lexico.Cerradura.Subconjunto conjunto : cerradura.getSubconjuntos()) { String codigoUnico = conjunto.getCodCerradura(); // Conjunto vacio if (codigoUnico.equals("{}")) { destino = getStateError(); } else { destino = getState(getCerradura(codigoUnico)); } origen.addTransition(new Transicion(origen, destino, conjunto.getSymbol())); } automata.addEstado(origen); } // Puede darse el caso de que el estado inicial del AFN no sea mas un // estado inicial, sino un estado de aceptacion. Si no es un estado de // aceptacion, indicamos que es el estado inicial. if (!automata.getInitState().isAcceptation()) { automata.getInitState().setInit(true); } return automata; }
/** * Verifica si el aumata ya posee un estado de error y si no lo tiene crea un estado de error y lo * retorna. * * @return */ private Estado getStateError() { Estado state = null; if (!automata.containState(cerraduras.size())) { state = new Estado(cerraduras.size()); state.setError(true); automata.addEstado(state); } else { state = automata.getState(cerraduras.size()); } return state; }
/** * Obtiene el estado relacionado a la cerradura, esto es, si el estado ya se encuentra en el * automata retorna dicho estado, caso contrario crea un nuevo estado. * * @param cerradura Cerradura de la cual se desea obtener el estado asociado. * @return Estado asociado a la cerradura */ private Estado getState(Cerradura cerradura) { Estado state = null; // Si el estado aun no esta en el automata if (!automata.containState(cerradura.getValue())) { state = new Estado(cerradura.getValue()); state.setAcceptation(cerradura.isAcceptation()); state.setInit(cerradura.isInit()); } else { // Si el estado ya esta en el automata state = automata.getState(cerradura.getValue()); } return state; }
/** * Aplica el algoritmo de construcción de subconjunto para obtener a partir de un AFN su AFD * equivalente. * * @param afn * @return */ public AFD build(AFN afn) { automata.setProduction(afn.getProduction()); // Calculamos la cerradura ε para el estado inicial. Cerradura cerraduraInicial = new Cerradura(0, afn.getInitState(), buildCerradura(afn.getInitState())); cerraduras.add(cerraduraInicial); // Mientras existan cerraduras sin procesar. while (isProcess()) { // Hallamos el subconjunto para cada simbolo for (String symbol : afn.getSymbols()) { if (!symbol.equals(ε)) { List<Estado> states = new ArrayList<>(); for (Estado state : next().getEstadosAcanzables()) { merge(states, buildSubconjuntoBySymbol(state, symbol, new ArrayList<Estado>())); } next().addSubconjunto(symbol, states); } } // Para cada subconjunto calculamos la cerradura for (pol.una.py.model.lexico.Cerradura.Subconjunto subconjunto : next().getSubconjuntos()) { if (!subconjunto.getStates().isEmpty()) { addCerradura(subconjunto.getStates(), buildCerradura(subconjunto.getStates())); } } // Finalizamos el proceso de la cerradura actual. next().setProcess(true); } return buildAFD(); }