Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two classes, same code, one gets StackOverflow

I'm in a project that does DFS recursively over a graph.

The issue is that I have the exact same code in two different classes (with different names) and while one manages to do the recursion effectively, the other fails and throws StackOverflowError. It's the same calculation and the same process with the same code they are trying to solve. Is there any reason for this?

EDIT

Here's the code:

package mundo.ParteA;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.Set;

import estructuras.GrafoDirigidoLAdy;
import estructuras.HashTable;
import estructuras.ListaDoble;
import estructuras.Dijkstra.DijkstrasSP;
import mundo.PesosProyecto3;
import mundo.ProcessCSV;
import mundo.Punto;
import mundo.VerticeBogota;

public class ParteAA {

    //-----------------------------------------------------------------
    // Constantes
    //-----------------------------------------------------------------

    /**
     * Constante que establece la ubicación del archivo kml que se produce al calcular la
     * ruta entre dos puntos del grafo
     */
    private static final String OUTPUT_FILE = "./data/outputParteA";

    //-----------------------------------------------------------------
    // Atributos
    //-----------------------------------------------------------------

    private HashTable<String, String> definitions;

    private GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota;

    private HashTable<String, Set<Integer>> diccionarioNombres;

    private HashTable<Punto, VerticeBogota> diccionarioCoordenadas;

    private int numArchivo;

    //-----------------------------------------------------------------
    // Constructor
    //-----------------------------------------------------------------

    public ParteAA()
    {
        numArchivo = 0;
        cargarDatos();
    }

    //-----------------------------------------------------------------
    // Métodos
    //-----------------------------------------------------------------

    public static void main(String... args)
    {
        ParteAA x = new ParteAA();
        for(Integer i : x.centrosAcopioEnRango(4277, 70)){
            System.out.println(i);
        }

//      try {
//          for(Integer i: x.calcularRutaMasCortaDistanciaYMostrarlaEnMaps(3077, 123512, 3, 7))
//              System.out.println(i);
//      } catch (Exception e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }
    }

    /**
     * Método que carga los datos para la inicialización.
     */
    public void cargarDatos()
    {
        ProcessCSV csv = new ProcessCSV(PesosProyecto3.TipoPesos.DISTANCIA);
        definitions = csv.getDefinitions();
        grafoVerticesBogota = csv.getGrafo();
        diccionarioNombres = csv.getDiccionarioNombres();
        diccionarioCoordenadas = csv.getDiccionarioCoordenadas();
    }

    /**
     * Método que se encarga de calcular la ruta más corta entre dos nodos y representarla en GoogleMaps
     * @param origen
     * @param destino
     * @param espacioBusquedaOrigen
     * @param espacioBusquedaDestino
     * @return 
     */
    public Iterable<Integer> calcularRutaMasCortaDistanciaYMostrarlaEnMaps(int idOrigen, int idDestino, double espacioBusquedaOrigen , double espacioBusquedaDestino) throws Exception
    {
        VerticeBogota origen = grafoVerticesBogota.getVertice(idOrigen);
        VerticeBogota destino = grafoVerticesBogota.getVertice(idDestino);
        if(origen==null||destino==null){ 
            System.out.println("No existe alguno de los dos vertices ingresados por parámetro. \nHasta Luego!");
            System.exit(0);
        }
        ListaDoble<Integer> listaSalida = (ListaDoble<Integer>) centrosAcopioEnRango(idOrigen, espacioBusquedaOrigen);
        ListaDoble<Integer> listaLlegada = (ListaDoble<Integer>) centrosAcopioEnRango(idDestino, espacioBusquedaDestino);

        if(listaSalida.isEmpty() || listaLlegada.isEmpty())
        {
            throw new Exception("No hay ningún centro de acopio en alguno de los rangos dados. \nPor favor incremente el área de busqueda");
        }

        double distMenor = Double.POSITIVE_INFINITY;
        Iterable<Integer> rutaOptima = null;

        for(Integer i : listaSalida)
        {
            DijkstrasSP sp = new DijkstrasSP(grafoVerticesBogota, i);
            for(Integer j : listaLlegada)
            {
                if(sp.distTo(j)<distMenor)
                {
                    distMenor = sp.distTo(j);
                    if(distMenor==0)
                    {
                        distMenor = 0;
                    }
                    rutaOptima = sp.caminoA(j);
                }
            }
        }

        System.out.println(distMenor);
        getShortestPathFile(rutaOptima);
        return rutaOptima;
    }

    /**
     * Calcula la distancia entre dos puntos.
     * @param origen - Punto inicial.
     * @param destino - Punto de llegada.
     * @return distKm - La distancia en kilometros entre los dos puntos.
     */
    private static double haversineDist(Punto origen, Punto destino)
    {
        long radioTierra = 6371;
        double rad = Math.PI/180;
        return Math.acos(
                Math.sin(origen.getLatitude()*rad) * Math.sin(destino.getLatitude()*rad)
                +   Math.cos(origen.getLatitude()*rad) * Math.cos(destino.getLatitude()*rad)
                *   Math.cos(destino.getLongitude()*rad - origen.getLongitude()*rad)
                ) * radioTierra;
    }

    /**
     * Método que busca los centros de acopio que están dentro del radio de búsqueda dada una ubicación
     */
    private Iterable<Integer> centrosAcopioEnRango(int origen, double distKm)
    {
        BitSet marked = new BitSet(grafoVerticesBogota.getNumVertices());
        ListaDoble<Integer> verticesEnRango = new ListaDoble<Integer>();

        haversineDFS(verticesEnRango, marked, origen, origen, distKm);

        return verticesEnRango;
    }

    private void haversineDFS(ListaDoble<Integer> verticesEnRango, BitSet marked, int orig, int actual, double distKm) {
        marked.set(actual);
        if(grafoVerticesBogota.getVertice(actual).isCentroDeAcopio()){ verticesEnRango.add(actual); }
        for(GrafoDirigidoLAdy<Integer, VerticeBogota>.Arco arc : grafoVerticesBogota.getAdy(actual))
        {
            double dis = haversineDist(grafoVerticesBogota.getVertice(orig).getUbicacion(), arc.getTo().getUbicacion());
            if(dis<=distKm && !marked.get(arc.getTo().getId()))
            {
                haversineDFS(verticesEnRango, marked, orig, arc.getTo().getId(), distKm);
            }
        }
    }

    //-----------------------------------------------------------------
    // KML Output
    //-----------------------------------------------------------------

    /**
     * Escribe el archivo kml de salida con la información de la ruta más corta del nodo idSource al nodo idDestination
     * Este archivo se puede importar a google maps para visualizar la ruta
     * @param idSource int El identificador de la fuente
     * @param idDestination int El identificador del destino
     */
    private void getShortestPathFile(Iterable<Integer> ruta)  {
        numArchivo++;
        File f = new File(OUTPUT_FILE+numArchivo+".kml");
        try {

            if(!f.exists()) {
                f.createNewFile();
            }

            FileWriter fw = new FileWriter(f);
            PrintWriter pw = new PrintWriter(fw);

            writeKMLHeader(pw);

            for(Integer i : ruta)
            {
                pw.println("        " + grafoVerticesBogota.getVertice(i).getUbicacion().getLongitude() + ", " + grafoVerticesBogota.getVertice(i).getUbicacion().getLatitude());
            }

            writeKMLFooter(pw);
            fw.flush();
            fw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Escribe el encabezado de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLHeader(PrintWriter pw) throws IOException
    {

        pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        pw.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
        pw.println("  <Document>");
        pw.println("    <name>Ruta más corta</name>");
        pw.println("    <Placemark>");
        pw.println("      <name>Ruta más corta</name>");
        pw.println("      <LineString>");
        pw.println("      <altitudeMode>absolute</altitudeMode>");
        pw.println("      <coordinates>");
    }

    /**
     * Escribe el pie de pagina de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLFooter(PrintWriter pw) throws IOException
    {
        pw.println("      </coordinates>");
        pw.println("      </LineString>");
        pw.println("    </Placemark>");
        pw.println("  </Document>");
        pw.println("</kml>");
    }

    //-----------------------------------------------------------------
    // Getters y Setters
    //-----------------------------------------------------------------

    public HashTable<String, String> getDefinitions() {
        return definitions;
    }

    public void setDefinitions(HashTable<String, String> definitions) {
        this.definitions = definitions;
    }

    public GrafoDirigidoLAdy<Integer, VerticeBogota> getGrafoVerticesBogota() {
        return grafoVerticesBogota;
    }

    public void setGrafoVerticesBogota(GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota) {
        this.grafoVerticesBogota = grafoVerticesBogota;
    }

    public HashTable<String, Set<Integer>> getDiccionarioNombres() {
        return diccionarioNombres;
    }

    public void setDiccionarioNombres(HashTable<String, Set<Integer>> diccionarioNombres) {
        this.diccionarioNombres = diccionarioNombres;
    }

    public HashTable<Punto, VerticeBogota> getDiccionarioCoordenadas() {
        return diccionarioCoordenadas;
    }

    public void setDiccionarioCoordenadas(HashTable<Punto, VerticeBogota> diccionarioCoordenadas) {
        this.diccionarioCoordenadas = diccionarioCoordenadas;
    }
}

And here's the other:

package mundo.ParteB;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.BitSet;
import java.util.Set;

import estructuras.GrafoDirigidoLAdy;
import estructuras.HashTable;
import estructuras.ListaDoble;
import estructuras.Dijkstra.DijkstrasSP;
import mundo.PesosProyecto3;
import mundo.ProcessCSV;
import mundo.Punto;
import mundo.VerticeBogota;

public class ParteBB{

    //-----------------------------------------------------------------
    // Constantes
    //-----------------------------------------------------------------

    /**
     * Constante que establece la ubicación del archivo kml que se produce al calcular la
     * ruta entre dos puntos del grafo
     */
    private static final String OUTPUT_FILE = "./data/outputParteA";

    //-----------------------------------------------------------------
    // Atributos
    //-----------------------------------------------------------------

    private HashTable<String, String> definitions;

    private GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota;

    private HashTable<String, Set<Integer>> diccionarioNombres;

    private HashTable<Punto, VerticeBogota> diccionarioCoordenadas;

    private int numArchivo;

    //-----------------------------------------------------------------
    // Constructor
    //-----------------------------------------------------------------

    public ParteBB()
    {
        numArchivo = 0;
        cargarDatos();
    }

    //-----------------------------------------------------------------
    // Métodos
    //-----------------------------------------------------------------

    public static void main(String... args)
    {
        ParteBB x = new ParteBB();
        for(Integer i : x.centrosAcopioEnRango(4277, 70)){
            System.out.println(i);
        }

//      try {
//          for(Integer i: x.calcularRutaMasCortaDistanciaYMostrarlaEnMaps(3077, 123512, 3, 7))
//              System.out.println(i);
//      } catch (Exception e) {
//          // TODO Auto-generated catch block
//          e.printStackTrace();
//      }
    }

    /**
     * Método que carga los datos para la inicialización.
     */
    public void cargarDatos()
    {
        ProcessCSV csv = new ProcessCSV(PesosProyecto3.TipoPesos.DISTANCIA);
        definitions = csv.getDefinitions();
        grafoVerticesBogota = csv.getGrafo();
        diccionarioNombres = csv.getDiccionarioNombres();
        diccionarioCoordenadas = csv.getDiccionarioCoordenadas();
    }

    /**
     * Método que se encarga de calcular la ruta más corta entre dos nodos y representarla en GoogleMaps
     * @param origen
     * @param destino
     * @param espacioBusquedaOrigen
     * @param espacioBusquedaDestino
     * @return 
     */
    public Iterable<Integer> calcularRutaMasCortaDistanciaYMostrarlaEnMaps(int idOrigen, int idDestino, double espacioBusquedaOrigen , double espacioBusquedaDestino) throws Exception
    {
        VerticeBogota origen = grafoVerticesBogota.getVertice(idOrigen);
        VerticeBogota destino = grafoVerticesBogota.getVertice(idDestino);
        if(origen==null||destino==null){ 
            System.out.println("No existe alguno de los dos vertices ingresados por parámetro. \nHasta Luego!");
            System.exit(0);
        }
        ListaDoble<Integer> listaSalida = (ListaDoble<Integer>) centrosAcopioEnRango(idOrigen, espacioBusquedaOrigen);
        ListaDoble<Integer> listaLlegada = (ListaDoble<Integer>) centrosAcopioEnRango(idDestino, espacioBusquedaDestino);

        if(listaSalida.isEmpty() || listaLlegada.isEmpty())
        {
            throw new Exception("No hay ningún centro de acopio en alguno de los rangos dados. \nPor favor incremente el área de busqueda");
        }

        double distMenor = Double.POSITIVE_INFINITY;
        Iterable<Integer> rutaOptima = null;

        for(Integer i : listaSalida)
        {
            DijkstrasSP sp = new DijkstrasSP(grafoVerticesBogota, i);
            for(Integer j : listaLlegada)
            {
                if(sp.distTo(j)<distMenor)
                {
                    distMenor = sp.distTo(j);
                    if(distMenor==0)
                    {
                        distMenor = 0;
                    }
                    rutaOptima = sp.caminoA(j);
                }
            }
        }

        System.out.println(distMenor);
        getShortestPathFile(rutaOptima);
        return rutaOptima;
    }

    /**
     * Calcula la distancia entre dos puntos.
     * @param origen - Punto inicial.
     * @param destino - Punto de llegada.
     * @return distKm - La distancia en kilometros entre los dos puntos.
     */
    private static double haversineDist(Punto origen, Punto destino)
    {
        long radioTierra = 6371;
        double rad = Math.PI/180;
        return Math.acos(
                Math.sin(origen.getLatitude()*rad) * Math.sin(destino.getLatitude()*rad)
                +   Math.cos(origen.getLatitude()*rad) * Math.cos(destino.getLatitude()*rad)
                *   Math.cos(destino.getLongitude()*rad - origen.getLongitude()*rad)
                ) * radioTierra;
    }

    /**
     * Método que busca los centros de acopio que están dentro del radio de búsqueda dada una ubicación
     */
    private Iterable<Integer> centrosAcopioEnRango(int origen, double distKm)
    {
        BitSet marked = new BitSet(grafoVerticesBogota.getNumVertices());
        ListaDoble<Integer> verticesEnRango = new ListaDoble<Integer>();

        haversineDFS(verticesEnRango, marked, origen, origen, distKm);

        return verticesEnRango;
    }

    private void haversineDFS(ListaDoble<Integer> verticesEnRango, BitSet marked, int orig, int actual, double distKm) {
        marked.set(actual);
        if(grafoVerticesBogota.getVertice(actual).isCentroDeAcopio()){ verticesEnRango.add(actual); }
        for(GrafoDirigidoLAdy<Integer, VerticeBogota>.Arco arc : grafoVerticesBogota.getAdy(actual))
        {
            double dis = haversineDist(grafoVerticesBogota.getVertice(orig).getUbicacion(), arc.getTo().getUbicacion());
            if(dis<=distKm && !marked.get(arc.getTo().getId()))
            {
                haversineDFS(verticesEnRango, marked, orig, arc.getTo().getId(), distKm);
            }
        }
    }

    //-----------------------------------------------------------------
    // KML Output
    //-----------------------------------------------------------------

    /**
     * Escribe el archivo kml de salida con la información de la ruta más corta del nodo idSource al nodo idDestination
     * Este archivo se puede importar a google maps para visualizar la ruta
     * @param idSource int El identificador de la fuente
     * @param idDestination int El identificador del destino
     */
    private void getShortestPathFile(Iterable<Integer> ruta)  {
        numArchivo++;
        File f = new File(OUTPUT_FILE+numArchivo+".kml");
        try {

            if(!f.exists()) {
                f.createNewFile();
            }

            FileWriter fw = new FileWriter(f);
            PrintWriter pw = new PrintWriter(fw);

            writeKMLHeader(pw);

            for(Integer i : ruta)
            {
                pw.println("        " + grafoVerticesBogota.getVertice(i).getUbicacion().getLongitude() + ", " + grafoVerticesBogota.getVertice(i).getUbicacion().getLatitude());
            }

            writeKMLFooter(pw);
            fw.flush();
            fw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Escribe el encabezado de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLHeader(PrintWriter pw) throws IOException
    {

        pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        pw.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
        pw.println("  <Document>");
        pw.println("    <name>Ruta más corta</name>");
        pw.println("    <Placemark>");
        pw.println("      <name>Ruta más corta</name>");
        pw.println("      <LineString>");
        pw.println("      <altitudeMode>absolute</altitudeMode>");
        pw.println("      <coordinates>");
    }

    /**
     * Escribe el pie de pagina de un archivo kml
     * @param pw El PrintWriter que escribe al archivo
     * @throws IOException En caso de que haya un error a la hora de escribir en el archivo
     */
    private void writeKMLFooter(PrintWriter pw) throws IOException
    {
        pw.println("      </coordinates>");
        pw.println("      </LineString>");
        pw.println("    </Placemark>");
        pw.println("  </Document>");
        pw.println("</kml>");
    }

    //-----------------------------------------------------------------
    // Getters y Setters
    //-----------------------------------------------------------------

    public HashTable<String, String> getDefinitions() {
        return definitions;
    }

    public void setDefinitions(HashTable<String, String> definitions) {
        this.definitions = definitions;
    }

    public GrafoDirigidoLAdy<Integer, VerticeBogota> getGrafoVerticesBogota() {
        return grafoVerticesBogota;
    }

    public void setGrafoVerticesBogota(GrafoDirigidoLAdy<Integer, VerticeBogota> grafoVerticesBogota) {
        this.grafoVerticesBogota = grafoVerticesBogota;
    }

    public HashTable<String, Set<Integer>> getDiccionarioNombres() {
        return diccionarioNombres;
    }

    public void setDiccionarioNombres(HashTable<String, Set<Integer>> diccionarioNombres) {
        this.diccionarioNombres = diccionarioNombres;
    }

    public HashTable<Punto, VerticeBogota> getDiccionarioCoordenadas() {
        return diccionarioCoordenadas;
    }

    public void setDiccionarioCoordenadas(HashTable<Punto, VerticeBogota> diccionarioCoordenadas) {
        this.diccionarioCoordenadas = diccionarioCoordenadas;
    }
}
like image 209
kickingnico Avatar asked Jul 17 '26 12:07

kickingnico


1 Answers

One scenario is you successfully build the code, then you change the code and think that it compiled properly, but it didn't, so I'm guessing that what you think is the same code probably isn't actually the same code.

Also, I assume you are using the same input both times.

like image 195
ajon Avatar answered Jul 20 '26 00:07

ajon