br.usp.poli.lta.cereda.aa.execution.AdaptiveAutomaton.java Source code

Java tutorial

Introduction

Here is the source code for br.usp.poli.lta.cereda.aa.execution.AdaptiveAutomaton.java

Source

/**
* ------------------------------------------------------
*    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;
    }

}