/* * This file is part of MazeSolver. * * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Copyright (c) 2014 MazeSolver * Sergio M. Afonso Fumero <theSkatrak@gmail.com> * Kevin I. Robayna Hernández <kevinirobaynahdez@gmail.com> */ /** * @file SimulationResults.java * @date 8/11/2014 */ package es.ull.mazesolver.util; import java.util.HashMap; import java.util.Map; import es.ull.mazesolver.agent.Agent; import es.ull.mazesolver.gui.environment.Environment; import es.ull.mazesolver.maze.Maze; /** * Representa los resultados estadísticos de una simulación. También puede * contener los datos de una simulación todavía en ejecución, por lo que se * puede consultar para simulaciones abortadas también. */ public class SimulationResults { /** * Clase de utilidad para contener toda la información de una simulación en un * entorno determinado. */ private class EnvironmentSimulationInfo { public Map <Agent, Integer> steps, iterations; public long first_elapsed, last_elapsed; public Agent winner_agent; /** * Constructor. Crea una nueva instancia de la clase. */ public EnvironmentSimulationInfo () { steps = new HashMap <Agent, Integer>(); iterations = new HashMap <Agent, Integer>(); first_elapsed = last_elapsed = -1; } } private Map <Environment, EnvironmentSimulationInfo> m_info; private long m_acc_time, m_start_time; /** * Constructor por defecto. Inicializa los atributos de la clase. */ public SimulationResults () { m_info = new HashMap <Environment, EnvironmentSimulationInfo>(); // Esta variable mide el tiempo que el temporizador ha estado ejecutándose // incluso tras hacer pausas. m_acc_time = 0; } /** * Elimina toda la información almacenada. */ public void clear () { m_info.clear(); m_acc_time = m_start_time = 0; } /** * Comienza el temporizador para medir el tiempo que tardan los agentes en * encontrar la salida al laberinto. */ public void startTimer () { m_start_time = System.currentTimeMillis(); } /** * Pausa el temporizador. Si se vuelve a iniciar, el tiempo que estuvo antes * ejecutándose seguirá presente. */ public void pauseTimer () { m_acc_time += System.currentTimeMillis() - m_start_time; } /** * Se indica a las estadísticas que un agente ha salido del laberinto. * * @param agent * Agente que salió del laberinto. */ public void agentFinished (Agent agent) { EnvironmentSimulationInfo info = getInfoFromAgentsEnvironment(agent); // Calculamos el tiempo transcurrido para registrar lo que tardó en salir long elapsed = m_acc_time + System.currentTimeMillis() - m_start_time; if (info.winner_agent == null) { info.first_elapsed = elapsed; info.winner_agent = agent; } else info.last_elapsed = elapsed; } /** * Indica a las estadísticas que un agente ha realizado un paso. * * @param agent * Agente que ha realizado el paso. */ public void agentWalked (Agent agent) { EnvironmentSimulationInfo info = getInfoFromAgentsEnvironment(agent); Integer steps = info.steps.getOrDefault(agent, 0); info.steps.put(agent, steps + 1); } /** * Indica a las estadísticas que se ha producido una iteración con el agente * dentro del laberinto. * * @param agent * Agente que ha realizado el paso. */ public void agentIterated (Agent agent) { EnvironmentSimulationInfo info = getInfoFromAgentsEnvironment(agent); Integer iterations = info.iterations.getOrDefault(agent, 0); info.iterations.put(agent, iterations + 1); } /** * Busca el agente que salió antes del laberinto en el entorno, si alguno ha * salido. * * @param env * Entorno en el que buscar al ganador. * @return El agente que salió antes del laberinto en el entorno. */ public Agent getWinner (Environment env) { EnvironmentSimulationInfo info = m_info.get(env); return info != null? info.winner_agent : null; } /** * Busca el agente colocado en el laberinto especificado que salió antes del * mismo, esté en el entorno que esté. * * @param maze * Laberinto del que salió. * @return Agente que salió primero del laberinto, si alguno ha salido. */ public Agent getWinner (Maze maze) { Agent winner = null; int winner_steps = Integer.MAX_VALUE; // Buscamos entre todos los entornos donde el laberinto sea el mismo, aquel // agente que haya llegado el primero al exterior for (Environment env: m_info.keySet()) { if (env.getMaze() == maze) { EnvironmentSimulationInfo info = m_info.get(env); if (info != null) { Agent other_winner = info.winner_agent; if (other_winner != null) { Integer other_steps = info.steps.get(other_winner); if (other_steps == null || winner == null || other_steps < winner_steps) { winner = other_winner; winner_steps = other_steps == null? 0 : other_steps.intValue(); } } } } } return winner; } /** * Obtiene el número de pasos e iteraciones que ha realizado cada agente en el * entorno en la simulación actual. * * @param env * Entorno en el que inspeccionar los agentes. * @return Número de pasos e iteraciones que ha realizado cada agente en el * entorno. */ public Map <Agent, Pair<Integer, Integer>> getSteps (Environment env) { // Utilizamos el nº de agentes guardados en lugar del nº actual en el // entorno porque se pueden añadir y eliminar agentes en tiempo de ejecución EnvironmentSimulationInfo info = m_info.get(env); HashMap <Agent, Pair<Integer, Integer>> steps = new HashMap <Agent, Pair<Integer, Integer>>(); if (info != null) { for (int i = 0; i < env.getAgentCount(); ++i) { Agent agent = env.getAgent(i); Pair <Integer, Integer> agent_info = new Pair <>( info.steps.getOrDefault(agent, 0), info.iterations.getOrDefault(agent, 0)); steps.put(agent, agent_info); } } return steps; } /** * Obtiene el tiempo que tardó el primer agente en salir del laberinto. * * @param env * Entorno en el que evaluar los agentes. * @return Tiempo que le llevó salir del laberinto al primero que salió. */ public long timeTakenFirst (Environment env) { EnvironmentSimulationInfo info = m_info.get(env); return info != null? info.first_elapsed : -1; } /** * Indica la cantidad de tiempo que tardó el agente más rápido en resolver el * laberinto, independientemente del entorno en el que se encontrara. * * @param maze * Laberinto del que salió. * @return Tiempo que le llevó salir del laberinto al primero que salió. */ public long timeTakenFirst (Maze maze) { long min_time = Long.MAX_VALUE; for (Environment env: m_info.keySet()) { if (env.getMaze() == maze) { long time = timeTakenFirst(env); if (time > -1 && time < min_time) min_time = time; } } return min_time != Long.MAX_VALUE? min_time : -1; } /** * Obtiene el tiempo que tardó el último agente en salir del entorno. * * @param env * Entorno en el que evaluar los agentes. * @return Tiempo que le llevó salir del laberinto al último que salió. */ public long timeTakenLast (Environment env) { EnvironmentSimulationInfo info = m_info.get(env); return info != null? info.last_elapsed : -1; } /** * Indica la cantidad de tiempo que tardó el agente más lento en resolver el * laberinto, independientemente del entorno en el que se encontrara. * * @param maze * Laberinto del que salió. * @return Tiempo que le llevó salir del laberinto al último que salió. */ public long timeTakenLast (Maze maze) { long max_time = Long.MIN_VALUE; for (Environment env: m_info.keySet()) { if (env.getMaze() == maze) { long time = timeTakenLast(env); if (time > max_time) max_time = time; } } return max_time != Long.MIN_VALUE? max_time : -1; } /** * Busca en m_info la información del entorno asociado al agente indicado. Si * no lo encuentra, lo crea. * * @param agent * Agente de cuyo entorno se quiere extraer la infomación. * @return Información de la simulación. */ private EnvironmentSimulationInfo getInfoFromAgentsEnvironment (Agent agent) { Environment env = agent.getEnvironment(); EnvironmentSimulationInfo info = m_info.get(env); // Si no hay información almacenada de este agente, lo agregamos a la lista if (info == null) { info = new EnvironmentSimulationInfo(); m_info.put(env, info); } return info; } }