From 8d022781eb400b0fbf9fbbd4fcd1472c8a911225 Mon Sep 17 00:00:00 2001 From: L3o15 Date: Thu, 29 May 2025 10:16:59 +0000 Subject: [PATCH] Calcolo spanning tree --- .../arnaldo/rovineperdute/Coordinata.java | 11 +++ src/it/unibs/arnaldo/rovineperdute/Graph.java | 80 ++++++++++++++++++- .../unibs/arnaldo/rovineperdute/Parser.java | 66 ++++++++++++++- .../arnaldo/rovineperdute/RovinaPerduta.java | 8 +- .../rovineperdute/RovinaPerdutaGrafo.java | 19 +++++ 5 files changed, 176 insertions(+), 8 deletions(-) create mode 100644 src/it/unibs/arnaldo/rovineperdute/RovinaPerdutaGrafo.java diff --git a/src/it/unibs/arnaldo/rovineperdute/Coordinata.java b/src/it/unibs/arnaldo/rovineperdute/Coordinata.java index 904f734..f739dae 100644 --- a/src/it/unibs/arnaldo/rovineperdute/Coordinata.java +++ b/src/it/unibs/arnaldo/rovineperdute/Coordinata.java @@ -31,4 +31,15 @@ public class Coordinata { ", altezza=" + altezza + '}'; } + + + public double calcolaDistanza(Coordinata c, TipoVeicolo tipoVeicolo){ + if (tipoVeicolo == TipoVeicolo.METZTLI){ + return Math.abs(altezza - c.getAltezza()); + } else if (tipoVeicolo == TipoVeicolo.TONATIUH){ + return Math.sqrt(Math.pow(x - c.getX(), 2) + Math.pow(y - c.getY(), 2)); + } + + return -1; + } } diff --git a/src/it/unibs/arnaldo/rovineperdute/Graph.java b/src/it/unibs/arnaldo/rovineperdute/Graph.java index 50eb82a..3adca10 100644 --- a/src/it/unibs/arnaldo/rovineperdute/Graph.java +++ b/src/it/unibs/arnaldo/rovineperdute/Graph.java @@ -1,17 +1,25 @@ package it.unibs.arnaldo.rovineperdute; -import java.util.HashMap; -import java.util.List; +import java.util.*; public class Graph { - private final HashMap> graph = new HashMap<>(); + private final HashMap> graph; - public Graph(){} + public Graph(){ + graph = new HashMap<>(); + } + public Graph(HashMap> graph){ + this.graph = graph; + } public void add(RovinaPerduta rp, List links) { graph.put(rp, links); } + public HashMap> getGraph() { + return graph; + } + public List getListaCollegamenti(RovinaPerduta rp){ return graph.get(rp); } @@ -28,4 +36,68 @@ public class Graph { } return ret.toString(); } + + public List calcolaSpanningTree(RovinaPerduta puntoPartenza, TipoVeicolo tipo){ + HashMap distanze = new HashMap<>(); + HashMap predecessori = new HashMap<>(); + HashMap salti = new HashMap<>(); + Queue coda = new PriorityQueue<>(Comparator.comparingDouble(distanze::get)); + + // inizializzazione variabili + for (RovinaPerduta rp : graph.keySet()) { + distanze.put(rp, Double.POSITIVE_INFINITY); + salti.put(rp, Integer.MAX_VALUE); + } + + distanze.put(puntoPartenza, 0.0); + coda.add(puntoPartenza); + salti.put(puntoPartenza, 0); + + // fino a quando non ho visitato tutti i percorsi + while (!coda.isEmpty()){ + RovinaPerduta rp = coda.poll(); + List listaVicine = graph.get(rp); + + for (RovinaPerduta vicina : listaVicine){ + double distanza = rp.getCoordinata().calcolaDistanza(vicina.getCoordinata(), tipo); + double nuovaDistanza = distanze.get(rp) + distanza; + double distanzaAttuale = distanze.get(vicina); + int nuoviSalti = salti.get(rp) + 1; + int saltiAttuali = salti.get(vicina); + + // aggiorno la distanza + if (nuovaDistanza < distanzaAttuale + || (Double.compare(nuovaDistanza, distanzaAttuale) == 0 && nuoviSalti < saltiAttuali) + || (Double.compare(nuovaDistanza, distanzaAttuale) == 0 && nuoviSalti == saltiAttuali && rp.getId() > predecessori.getOrDefault(vicina, rp).getId())) { + + distanze.put(vicina, nuovaDistanza); + predecessori.put(vicina, rp); + salti.put(vicina, nuoviSalti); + coda.add(vicina); + } + } + } + + // trovo la rovina perduta + RovinaPerduta rovinePerdute = null; + int maxId = 0; + + for (RovinaPerduta rp : graph.keySet()) { + if (rp.getId() > maxId) { + maxId = rp.getId(); + rovinePerdute = rp; + } + } + + + // ricostruisce il percorso dal punto di partenza alla rovina perduta + LinkedList percorso = new LinkedList<>(); + RovinaPerduta corrente = rovinePerdute; + while (corrente != null) { + percorso.addFirst(new RovinaPerdutaGrafo(corrente.getCoordinata(), corrente.getNome(), corrente.getId(), distanze.get(corrente))); + corrente = predecessori.get(corrente); + } + + return percorso; + } } diff --git a/src/it/unibs/arnaldo/rovineperdute/Parser.java b/src/it/unibs/arnaldo/rovineperdute/Parser.java index c0a3d27..30cba71 100644 --- a/src/it/unibs/arnaldo/rovineperdute/Parser.java +++ b/src/it/unibs/arnaldo/rovineperdute/Parser.java @@ -2,6 +2,7 @@ package it.unibs.arnaldo.rovineperdute; import javax.xml.stream.*; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -10,7 +11,7 @@ import java.util.List; public class Parser { // rovina = città - public static void parseRovinePerduteXML(String fileName) { + public static Graph parseRovinePerduteXML(String fileName) { XMLInputFactory xmlif; XMLStreamReader xmlr = null; @@ -60,7 +61,7 @@ public class Parser { if (endTag.equals("city")) { mappaCollegamenti.put(cityId, link); link = new ArrayList<>(); - RovinaPerduta rovinaPerduta = new RovinaPerduta(new Coordinata(x, y, h), nome); + RovinaPerduta rovinaPerduta = new RovinaPerduta(new Coordinata(x, y, h), nome, cityId); nome = null; x = -1; y = -1; @@ -94,10 +95,69 @@ public class Parser { grafo.add(rp, listaCollegamenti); } - System.out.println(grafo); + return grafo; } catch (FactoryConfigurationError | XMLStreamException | IOException e) { System.out.println("Error reading the file: " + e.getMessage()); + return null; } } + + public static void generaXML(List minimumTreeTonatium, List minimumTreeMetztli) { + String fileName = "routes.xml"; + + try (FileOutputStream outputStream = new FileOutputStream(fileName)) { + XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); + XMLStreamWriter xmlWriter = xmlOutputFactory.createXMLStreamWriter(outputStream, "UTF-8"); + + xmlWriter.writeStartDocument("UTF-8", "1.0"); + xmlWriter.writeStartElement("routes"); + + // Tonatiuh + double consumoTonatiuh = minimumTreeTonatium.get(minimumTreeTonatium.size() - 1).getDistanza(); + int numeroCittaTonatiuh = minimumTreeTonatium.size(); + + xmlWriter.writeStartElement("route"); + xmlWriter.writeAttribute("team", "Tonatiuh"); + xmlWriter.writeAttribute("cost", String.format("%.0f", consumoTonatiuh)); + xmlWriter.writeAttribute("cities", String.valueOf(numeroCittaTonatiuh)); + + for (RovinaPerdutaGrafo citta : minimumTreeTonatium) { + xmlWriter.writeStartElement("city"); + xmlWriter.writeAttribute("id", String.valueOf(citta.getId())); + xmlWriter.writeAttribute("name", citta.getNome()); + xmlWriter.writeEndElement(); // city + } + + xmlWriter.writeEndElement(); // route + + // Metztli + double consumoMetztli = minimumTreeMetztli.get(minimumTreeMetztli.size() - 1).getDistanza(); + int numeroCittaMetztli = minimumTreeMetztli.size(); + + xmlWriter.writeStartElement("route"); + xmlWriter.writeAttribute("team", "Metztli"); + xmlWriter.writeAttribute("cost", String.format("%.0f", consumoMetztli)); + xmlWriter.writeAttribute("cities", String.valueOf(numeroCittaMetztli)); + + for (RovinaPerdutaGrafo citta : minimumTreeMetztli) { + xmlWriter.writeStartElement("city"); + xmlWriter.writeAttribute("id", String.valueOf(citta.getId())); + xmlWriter.writeAttribute("name", citta.getNome()); + xmlWriter.writeEndElement(); // city + } + + xmlWriter.writeEndElement(); + + xmlWriter.writeEndElement(); + xmlWriter.writeEndDocument(); + xmlWriter.flush(); + + System.out.println("File 'routes.xml' generato correttamente."); + + } catch (XMLStreamException | IOException e) { + System.out.println("Errore durante la scrittura del file XML: " + e.getMessage()); + } + } + } diff --git a/src/it/unibs/arnaldo/rovineperdute/RovinaPerduta.java b/src/it/unibs/arnaldo/rovineperdute/RovinaPerduta.java index baa6c6e..51188d7 100644 --- a/src/it/unibs/arnaldo/rovineperdute/RovinaPerduta.java +++ b/src/it/unibs/arnaldo/rovineperdute/RovinaPerduta.java @@ -3,10 +3,12 @@ package it.unibs.arnaldo.rovineperdute; public class RovinaPerduta { private final Coordinata coordinata; private final String nome; + private final int id; - public RovinaPerduta(Coordinata coordinata, String nome) { + public RovinaPerduta(Coordinata coordinata, String nome, int id) { this.coordinata = coordinata; this.nome = nome; + this.id = id; } public Coordinata getCoordinata() { @@ -17,6 +19,10 @@ public class RovinaPerduta { return nome; } + public int getId(){ + return id; + } + @Override public String toString() { return nome + " (" + coordinata.getX() + ", " + coordinata.getY() + ", " + coordinata.getAltezza() + ")"; diff --git a/src/it/unibs/arnaldo/rovineperdute/RovinaPerdutaGrafo.java b/src/it/unibs/arnaldo/rovineperdute/RovinaPerdutaGrafo.java new file mode 100644 index 0000000..92bb026 --- /dev/null +++ b/src/it/unibs/arnaldo/rovineperdute/RovinaPerdutaGrafo.java @@ -0,0 +1,19 @@ +package it.unibs.arnaldo.rovineperdute; + +public class RovinaPerdutaGrafo extends RovinaPerduta{ + private final double distanza; + + public RovinaPerdutaGrafo(Coordinata coordinata, String nome, int id, double distanza) { + super(coordinata, nome, id); + this.distanza = distanza; + } + + public double getDistanza() { + return distanza; + } + + @Override + public String toString(){ + return getNome() + " (" + getCoordinata().getX() + ", " + getCoordinata().getY() + ", " + getCoordinata().getAltezza() + ") Distanza: " + distanza; + } +}