Java tutorial
/** * ------------------------------------------------------ * Laboratrio de Linguagens e Tcnicas Adaptativas * Escola Politcnica, Universidade So Paulo * ------------------------------------------------------ * * This program is free software: you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software * Foundation, either version 3 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License * for more details. * **/ package br.usp.poli.lta.cereda.aa.execution; import br.usp.poli.lta.cereda.aa.model.Stack; import br.usp.poli.lta.cereda.aa.model.Transition; import br.usp.poli.lta.cereda.aa.model.Symbol; import br.usp.poli.lta.cereda.aa.model.sets.ActionsSet; import br.usp.poli.lta.cereda.aa.model.sets.SubmachinesSet; import br.usp.poli.lta.cereda.aa.model.sets.Mapping; import br.usp.poli.lta.cereda.aa.utils.RecognitionPath; import com.rits.cloning.Cloner; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.Validate; /** * Implementa o autmato adaptativo propriamente dito. Esta classe definida * como abstrata, forando a redefinio do mtodo de especificao das * transies, submquinas e aes. * @author Paulo Roberto Massa Cereda * @version 1.0 * @since 1.0 */ public abstract class AdaptiveAutomaton { // atributos de classe // elementos a partir da definio formal: conjunto de transies, conjunto // de submquinas, conjunto de aes e pilha protected Mapping transitions; protected SubmachinesSet submachines; protected ActionsSet actions; protected Stack stack; // referncia ao nome da submquina principal e definio de uma constante // que representa a transio em vazio, caso ela seja necessria em uma // transio private String mainSubmachine; public Symbol EPSILON; // lista contendo os smbolos, representando a cadeia de entrada a ser // submetida ao autmato adaptativo private List<Symbol> input; // lista de threads representando cada passo computacional do // autmato, lista de remoo de threads e mapa de caminhos de // recomendao private final List<Kernel> threads; private final List<Integer> removals; private final Map<Integer, RecognitionPath> paths; // varivel que determina se o autmato deve parar ao // encerrar, pelo menos, uma execuo obtendo resultado private boolean stopAtFirstFinishedRecognitionPath; // objeto que representa uma referncia ao autmato // adaptativo corrente private AdaptiveAutomaton reference; /** * Construtor. */ public AdaptiveAutomaton() { // define novos conjuntos transitions = new Mapping(); submachines = new SubmachinesSet(); actions = new ActionsSet(); stack = new Stack(); // inicializa as variveis mainSubmachine = null; EPSILON = null; // cria nova listas auxiliares threads = new ArrayList<>(); removals = new ArrayList<>(); paths = new HashMap<>(); // define que, inicialmente, o autmato s interromper o processo de // reconhecimento quando todas as instncias encerrarem-se stopAtFirstFinishedRecognitionPath = false; // define a referncia inicial do autmato adaptativo reference = null; } /** * Define a configurao inicial do autmato adaptativo. Este mtodo * abstrato e dever ser implementado. */ public abstract void setup(); /** * Define o conjunto de transies do autmato adaptativo. * @param transitions Conjunto de transies do autmato adaptativo. */ public void setTransitions(Mapping transitions) { this.transitions = transitions; } /** * Define o conjunto de submquinas do autmato adaptativo. * @param submachines Conjunto de submquinas do autmato adaptativo. */ public void setSubmachines(SubmachinesSet submachines) { this.submachines = submachines; } /** * Define o conjunto de aes do autmato adaptativo. * @param actions Conjunto de aes do autmato adaptativo. */ public void setActions(ActionsSet actions) { this.actions = actions; } /** * Define a submquina principal. * @param mainSubmachine Nome da submquina principal. */ public void setMainSubmachine(String mainSubmachine) { this.mainSubmachine = mainSubmachine; } /** * Obtm o mapa contendo os caminhos de reconhecimento. * @return Mapa contendo os caminhos de reconhecimento. */ public Map<Integer, RecognitionPath> getRecognitionMap() { return reference.getRecognitionMapOnce(); } /** * Obtm, apenas uma vez, o mapa contendo os caminhos de reconhecimento. * @return Mapa contendo os caminhos de reconhecimento. */ private Map<Integer, RecognitionPath> getRecognitionMapOnce() { return paths; } /** * Obtm a lista contendo todos os caminhos de reconhecimento obtidos * durante a execuo do autmato adaptativo. * @return Lista de todos os caminhos de reconhecimento. */ public List<RecognitionPath> getRecognitionPaths() { return reference.getRecognitionPathsOnce(); } /** * Obtm, apenas uma vez, a lista contendo todos os caminhos de * reconhecimento obtidos * durante a execuo do autmato adaptativo. * @return Lista de todos os caminhos de reconhecimento. */ private List<RecognitionPath> getRecognitionPathsOnce() { List<RecognitionPath> result = new ArrayList<>(); for (int key : paths.keySet()) { result.add(paths.get(key)); } return result; } /** * Reconhece uma lista de smbolos representado a cadeia de entrada. * @param input Lista de smbolos representando a cadeia de entrada. * @return Um valor lgico informando se o autmato adaptativo reconheceu * a cadeia de entrada. */ public boolean recognize(List<Symbol> input) { // cria um objeto de clonagem para realizar // a cpia do autmato adaptativo corrente Cloner dolly = new Cloner(); // cria um clone do autmato corrente reference = dolly.deepClone(this); // inicia o processo de reconhecimento da lista de // smbolos, retornando o resultado return reference.recognizeOnce(input); } /** * Reconhece, apenas uma vez, uma lista de smbolos representado a cadeia * de entrada. * @param input Lista de smbolos representando a cadeia de entrada. * @return Um valor lgico informando se o autmato adaptativo reconheceu * a cadeia de entrada. */ private boolean recognizeOnce(List<Symbol> input) { // realiza a configurao e verifica se a submquina // principal no nula setup(); Validate.notNull(mainSubmachine, "A submquina principal no pode ser nula."); // cria a thread inicial com os conjuntos // do modelo Kernel k = new Kernel(threads, removals, paths); k.setStack(stack); k.setActions(actions); k.setTransitions(transitions); k.setSubmachines(submachines); k.setCurrentSubmachine(mainSubmachine); k.setMainSubmachine(mainSubmachine); k.setInput(input); k.setCursor(0); k.setEnablePriorAction(true); // cria uma transio inicial em vazio que faz o autmato // entrar no estado inicial da submquina principal e ajusta // o cursor de leitura no incio da cadeia Transition t = new Transition(); t.setTransition(null, EPSILON, submachines.getFromName(mainSubmachine).getInitialState()); k.setTransition(t); // cria um novo caminho de reconhecimento e // adiciona a thread inicial na lista de threads paths.put(k.getIdentifier(), new RecognitionPath()); threads.add(k); // enquanto a lista de threads no estiver vazia e o autmato // adaptativo no retornou alguma sada em relao ao processo // de reconhecimento, repete o passo computacional while (!threads.isEmpty() && !atLeastOneRecognitionPathIsDone()) { // verifica se existem threads que j terminaram // e devem ser removidas if (!removals.isEmpty()) { // para cada identificador das threads a serem removidas, // percorre a lista de threads e remove aquelas cujo // identificador igual for (int i : removals) { for (int j = 0; j < threads.size(); j++) { if (threads.get(j).getIdentifier() == i) { threads.remove(j); break; } } // repete a operao no mapa de caminhos de // reconhecimento, mas apenas os reconhecimentos // incompletos so removidos if (!paths.get(i).done()) { paths.remove(i); } } // todas as threads marcadas para remoo foram // devidamente removidas, portanto, agora a lista // de remoo deve ser limpa removals.clear(); } // executa um passo computacional para cada thread // da lista de threads for (int i = 0; i < threads.size(); i++) { // tenta executar, talvez a thread d erro try { threads.get(i).start(); threads.get(i).join(); } catch (InterruptedException exception) { System.err.println("Thread error: " + exception.getMessage()); System.exit(1); } } } // o processo de reconhecimento da cadeia j encerrou, mas ainda // necessrio fazer uma ltima limpeza na lista de threads e no // mapa dos caminhos de reconhecimento if (!removals.isEmpty()) { // para cada identificador das threads a serem removidas, // percorre a lista de threads e remove aquelas cujo // identificador igual for (int i : removals) { for (int j = 0; j < threads.size(); j++) { if (threads.get(j).getIdentifier() == i) { threads.remove(j); break; } } // repete a operao no mapa de caminhos de // reconhecimento, mas apenas os reconhecimentos // incompletos so removidos if (!paths.get(i).done()) { paths.remove(i); } } // todas as threads marcadas para remoo foram // devidamente removidas, portanto, agora a lista // de remoo deve ser limpa removals.clear(); } // verifica se algum caminho de reconhecimento conduziu // aceitao da cadeia e retorna o resultado for (int i : paths.keySet()) { if (paths.get(i).done()) { if (paths.get(i).getResult() == true) { return true; } } } // a cadeia no foi aceita, retorna falso return false; } /** * Verifica se, pelo menos, um caminho de reconhecimento encerrou-se. * @return Um valor lgico que denota se, pelo menos, um caminho de * reconhecimento j encerrou-se. */ private boolean atLeastOneRecognitionPathIsDone() { // se o sinalizador para parar na primeira ocorrncia de um // caminho de reconhecimento for verdadeiro, if (stopAtFirstFinishedRecognitionPath == false) { return false; } // percorre o mapa e verifica se algum caminho j encerrou, // retornando o valor da consulta for (int i : paths.keySet()) { if (paths.get(i).done()) { return true; } } return false; } /** * Retorna uma representao textual do autmato adaptativo. * @return Representao textual do autmato adaptativo. */ @Override public String toString() { String newline = "\n"; StringBuilder sb = new StringBuilder(); sb.append("Autmato adaptativo: {").append(newline); sb.append(submachines).append(newline); sb.append(transitions).append(newline); sb.append(actions).append(newline); sb.append(stack).append(newline); sb.append("Submquina principal: ").append(mainSubmachine != null ? mainSubmachine : "no definida") .append(newline); sb.append("}"); return sb.toString(); } /** * Define a condio de parada do autmato adaptativo tal que este no * prossiga aps o resultado de, pelo menos, um caminho de reconhecimento. * @param flag Valor lgico que determina se o autmato deve continuar o * reconhecimento mesmo que j tenha um resultado disponvel. */ public void setStopAtFirstResult(boolean flag) { this.stopAtFirstFinishedRecognitionPath = flag; } public Mapping getTransitions() { return transitions; } }