From 3baf9d19e40b5b9ef6e31f7deb15413679dcf68e Mon Sep 17 00:00:00 2001 From: dcisse2 Date: Wed, 15 Oct 2025 12:38:44 +0000 Subject: [PATCH 1/2] Initial commit --- README.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec2ac13 --- /dev/null +++ b/README.md @@ -0,0 +1,93 @@ +# M1graphs25 + + + +## Getting started + +To make it easy for you to get started with GitLab, here's a list of recommended next steps. + +Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! + +## Add your files + +- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files +- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: + +``` +cd existing_repo +git remote add origin https://disc.univ-fcomte.fr/cr700-gitlab/dcisse2/m1graphs25.git +git branch -M main +git push -uf origin main +``` + +## Integrate with your tools + +- [ ] [Set up project integrations](https://disc.univ-fcomte.fr/cr700-gitlab/dcisse2/m1graphs25/-/settings/integrations) + +## Collaborate with your team + +- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) +- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) +- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) +- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) +- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) +- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) +- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) +- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) +- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +*** + +# Editing this README + +When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. + +## Suggestions for a good README + +Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + +## Name +Choose a self-explaining name for your project. + +## Description +Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + +## Badges +On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. + +## Visuals +Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + +## Installation +Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. + +## Usage +Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. + +## Support +Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. + +## Roadmap +If you have ideas for releases in the future, it is a good idea to list them in the README. + +## Contributing +State if you are open to contributions and what your requirements are for accepting them. + +For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. + +You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. + +## Authors and acknowledgment +Show your appreciation to those who have contributed to the project. + +## License +For open source projects, say how it is licensed. + +## Project status +If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. -- GitLab From 09b8f9b960a2c80f48a9180dcdf78d3a049aab9a Mon Sep 17 00:00:00 2001 From: adjemaou Date: Wed, 22 Oct 2025 16:29:40 +0200 Subject: [PATCH 2/2] modif --- src/main/java/m1graphs2025/Edge.java | 65 +++-- src/main/java/m1graphs2025/Graph.java | 189 +++++++------ src/main/java/m1graphs2025/Node.java | 4 + src/main/java/m1graphs2025/TestGraphsPW2.java | 248 +++++++++--------- .../java/m1graphs2025/UndirectedGraph.java | 60 ++++- .../m1graphs2025/undirWeightedMultiGraph.gv | 18 ++ 6 files changed, 351 insertions(+), 233 deletions(-) create mode 100644 src/main/java/m1graphs2025/undirWeightedMultiGraph.gv diff --git a/src/main/java/m1graphs2025/Edge.java b/src/main/java/m1graphs2025/Edge.java index 9bb4742..14ef5e0 100644 --- a/src/main/java/m1graphs2025/Edge.java +++ b/src/main/java/m1graphs2025/Edge.java @@ -36,6 +36,12 @@ public class Edge implements Comparable { this.weight = null; } + public Edge() { + this.from = null; + this.to = null; + this.weight = null; + } + /** Arête pondérée */ public Edge(Node from, Node to, Integer weight) { this.from = from; @@ -90,24 +96,47 @@ public class Edge implements Comparable { // Getters / Setters // ====================== - public Node getNodeFrom() { return from; } - public Node getNodeTo() { return to; } - public Integer getWeight() { return weight; } + public Node getNodeFrom() { + return from; + } + + public Node getNodeTo() { + return to; + } + + public Integer getWeight() { + return weight; + } - public void setNodeFrom(Node from) { this.from = from; } - public void setNodeTo(Node to) { this.to = to; } - public void setWeight(Integer weight) { this.weight = weight; } + public void setNodeFrom(Node from) { + this.from = from; + } + + public void setNodeTo(Node to) { + this.to = to; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } // ====================== // Méthodes fonctionnelles // ====================== - public Node from() { return from; } - public Node to() { return to; } + public Node from() { + return from; + } + + public Node to() { + return to; + } /** * Retourne une arête symétrique (inversée) avec la même pondération. - * @return une nouvelle arête inversée ou null si les nœuds n’appartiennent pas au même graphe. + * + * @return une nouvelle arête inversée ou null si les nœuds n’appartiennent pas + * au même graphe. */ public Edge getSymmetric() { Graph g1 = (from != null) ? from.getGraph() : null; @@ -133,12 +162,14 @@ public class Edge implements Comparable { * mais avec un poids différent (arête multiple). */ public boolean isMultiEdge() { - if (from == null || from.getGraph() == null) return false; + if (from == null || from.getGraph() == null) + return false; Graph graph = from.getGraph(); List edges = graph.adjEdList.get(from); - if (edges == null) return false; + if (edges == null) + return false; for (Edge edge : edges) { boolean sameNodes = edge.from.getId() == this.from.getId() @@ -171,10 +202,12 @@ public class Edge implements Comparable { int w2 = (other.weight == null) ? 0 : other.weight; int cmp = Integer.compare(w1, w2); - if (cmp != 0) return cmp; + if (cmp != 0) + return cmp; cmp = Integer.compare(this.from.getId(), other.from.getId()); - if (cmp != 0) return cmp; + if (cmp != 0) + return cmp; return Integer.compare(this.to.getId(), other.to.getId()); } @@ -185,8 +218,10 @@ public class Edge implements Comparable { */ @Override public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof Edge edge)) return false; + if (this == o) + return true; + if (!(o instanceof Edge edge)) + return false; return Objects.equals(from, edge.from) && Objects.equals(to, edge.to) && Objects.equals(weight, edge.weight); diff --git a/src/main/java/m1graphs2025/Graph.java b/src/main/java/m1graphs2025/Graph.java index 7711640..f565262 100644 --- a/src/main/java/m1graphs2025/Graph.java +++ b/src/main/java/m1graphs2025/Graph.java @@ -1,5 +1,7 @@ package m1graphs2025; +import java.io.BufferedReader; +import java.io.FileReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -96,7 +98,8 @@ public class Graph { return null; } for (Node entry : adjEdList.keySet()) { - if (entry != null && entry.getId() == id) return entry; + if (entry != null && entry.getId() == id) + return entry; } System.err.println("Aucun nœud trouvé avec l’id " + id + "."); return null; @@ -170,7 +173,6 @@ public class Graph { } } - public boolean removeNode() { return removeNode(0); } @@ -237,7 +239,8 @@ public class Graph { try { return n.getSuccessors(); } catch (Exception e) { - System.err.println("Erreur lors de la récupération des successeurs du nœud " + n.getId() + ": " + e.getMessage()); + System.err.println( + "Erreur lors de la récupération des successeurs du nœud " + n.getId() + ": " + e.getMessage()); return List.of(); } } @@ -259,7 +262,8 @@ public class Graph { try { return n.getSuccessorsMulti(); } catch (Exception e) { - System.err.println("Erreur lors de la récupération des successeurs multiples du nœud " + n.getId() + ": " + e.getMessage()); + System.err.println("Erreur lors de la récupération des successeurs multiples du nœud " + n.getId() + ": " + + e.getMessage()); return List.of(); } } @@ -281,7 +285,8 @@ public class Graph { try { return u.adjacent(v); } catch (Exception e) { - System.err.println("Erreur lors de la vérification de l’adjacence entre " + u.getId() + " et " + v.getId() + ": " + e.getMessage()); + System.err.println("Erreur lors de la vérification de l’adjacence entre " + u.getId() + " et " + v.getId() + + ": " + e.getMessage()); return false; } } @@ -368,7 +373,8 @@ public class Graph { public int nbEdges() { int count = 0; - for (List edges : adjEdList.values()) count += edges.size(); + for (List edges : adjEdList.values()) + count += edges.size(); return count; } @@ -378,7 +384,8 @@ public class Graph { throw new IllegalArgumentException("Les nœuds ne peuvent pas être null."); } for (Edge e : adjEdList.getOrDefault(u, Collections.emptyList())) { - if (e.getNodeTo().equals(v)) return true; + if (e.getNodeTo().equals(v)) + return true; } return false; } catch (Exception ex) { @@ -451,8 +458,10 @@ public class Graph { if (from == null || to == null) { throw new IllegalArgumentException("Les nœuds source et destination ne peuvent pas être null."); } - if (!usesNode(from)) addNode(from); - if (!usesNode(to)) addNode(to); + if (!usesNode(from)) + addNode(from); + if (!usesNode(to)) + addNode(to); adjEdList.get(from).add(new Edge(from, to)); } catch (Exception ex) { System.err.println("Erreur dans addEdge(Node, Node) : " + ex.getMessage()); @@ -466,8 +475,10 @@ public class Graph { } Node from = getNode(fromId); Node to = getNode(toId); - if (from == null) from = new Node(fromId, this); - if (to == null) to = new Node(toId, this); + if (from == null) + from = new Node(fromId, this); + if (to == null) + to = new Node(toId, this); addEdge(from, to); } catch (Exception ex) { System.err.println("Erreur dans addEdge(int, int) : " + ex.getMessage()); @@ -497,8 +508,10 @@ public class Graph { if (weight < 0) { throw new IllegalArgumentException("Le poids doit être positif ou nul."); } - if (!usesNode(from)) addNode(from); - if (!usesNode(to)) addNode(to); + if (!usesNode(from)) + addNode(from); + if (!usesNode(to)) + addNode(to); adjEdList.get(from).add(new Edge(from, to, weight)); } catch (Exception ex) { System.err.println("Erreur dans addEdge(Node, Node, int) : " + ex.getMessage()); @@ -515,8 +528,10 @@ public class Graph { } Node from = getNode(fromId); Node to = getNode(toId); - if (from == null) from = new Node(fromId, this); - if (to == null) to = new Node(toId, this); + if (from == null) + from = new Node(fromId, this); + if (to == null) + to = new Node(toId, this); addEdge(from, to, weight); } catch (Exception ex) { System.err.println("Erreur dans addEdge(int, int, int) : " + ex.getMessage()); @@ -533,8 +548,10 @@ public class Graph { } Node from = getNode(fromId); Node to = getNode(toId); - if (from == null) from = new Node(fromId, g); - if (to == null) to = new Node(toId, g); + if (from == null) + from = new Node(fromId, g); + if (to == null) + to = new Node(toId, g); addEdge(from, to); } catch (Exception ex) { System.err.println("Erreur dans addEdge(int, int, Graph) : " + ex.getMessage()); @@ -619,7 +636,8 @@ public class Graph { List result = new ArrayList<>(); for (List edges : adjEdList.values()) { for (Edge e : edges) { - if (e.getNodeTo().equals(n)) result.add(e); + if (e.getNodeTo().equals(n)) + result.add(e); } } return result; @@ -682,7 +700,8 @@ public class Graph { } List result = new ArrayList<>(); for (Edge e : adjEdList.getOrDefault(u, Collections.emptyList())) { - if (e.getNodeTo().equals(v)) result.add(e); + if (e.getNodeTo().equals(v)) + result.add(e); } return result; } catch (Exception ex) { @@ -694,7 +713,8 @@ public class Graph { public List getAllEdges() { try { List result = new ArrayList<>(); - for (List edges : adjEdList.values()) result.addAll(edges); + for (List edges : adjEdList.values()) + result.addAll(edges); return result; } catch (Exception ex) { System.err.println("Erreur dans getAllEdges() : " + ex.getMessage()); @@ -732,7 +752,8 @@ public class Graph { public Graph getReverse() { Map> reversed = new HashMap<>(); - for (Node n : adjEdList.keySet()) reversed.put(n, new ArrayList<>()); + for (Node n : adjEdList.keySet()) + reversed.put(n, new ArrayList<>()); for (Node u : adjEdList.keySet()) { for (Edge e : adjEdList.get(u)) { Node from = e.getNodeTo(); @@ -751,7 +772,8 @@ public class Graph { for (Node i : nodes) { for (Node j : nodes) { if (closure.existsEdge(i, k) && closure.existsEdge(k, j)) { - if (!closure.existsEdge(i, j)) closure.addEdge(i, j); + if (!closure.existsEdge(i, j)) + closure.addEdge(i, j); } } } @@ -765,7 +787,8 @@ public class Graph { Set seen = new HashSet<>(); for (Edge e : edges) { Node to = e.getNodeTo(); - if (seen.contains(to)) return true; + if (seen.contains(to)) + return true; seen.add(to); } } @@ -775,7 +798,8 @@ public class Graph { public boolean hasSelfLoops() { for (Node u : adjEdList.keySet()) { for (Edge e : adjEdList.get(u)) { - if (e.getNodeTo().equals(u)) return true; + if (e.getNodeTo().equals(u)) + return true; } } return false; @@ -787,7 +811,8 @@ public class Graph { public Graph toSimpleGraph() { Graph g = new Graph(new HashMap<>()); - for (Node u : adjEdList.keySet()) g.addNode(new Node(u.getId(), g)); + for (Node u : adjEdList.keySet()) + g.addNode(new Node(u.getId(), g)); for (Node u : adjEdList.keySet()) { Set seen = new HashSet<>(); for (Edge e : adjEdList.get(u)) { @@ -805,7 +830,8 @@ public class Graph { Map> copy = new HashMap<>(); for (Node u : adjEdList.keySet()) { List list = new ArrayList<>(); - for (Edge e : adjEdList.get(u)) list.add(new Edge(e.getNodeFrom(), e.getNodeTo(), e.getWeight())); + for (Edge e : adjEdList.get(u)) + list.add(new Edge(e.getNodeFrom(), e.getNodeTo(), e.getWeight())); copy.put(u, list); } return new Graph(copy); @@ -859,7 +885,9 @@ public class Graph { public List getBFS() { List visited = new ArrayList<>(); Map infos = initVisitInfo(); - for (Node s : sortNodes()) if (infos.get(s).getColour() == NodeColour.WHITE) BFSVisit(s, infos, visited); + for (Node s : sortNodes()) + if (infos.get(s).getColour() == NodeColour.WHITE) + BFSVisit(s, infos, visited); return visited; } @@ -900,7 +928,7 @@ public class Graph { // ====================== public List getDFSWithVisitInfo(Map nodeVisit, - Map edgeVisit) { + Map edgeVisit) { List visited = new ArrayList<>(); AtomicInteger time = new AtomicInteger(0); initVisitInfo(nodeVisit); @@ -912,8 +940,8 @@ public class Graph { } public List getDFSWithVisitInfo(Node start, - Map nodeVisit, - Map edgeVisit) { + Map nodeVisit, + Map edgeVisit) { List visited = new ArrayList<>(); AtomicInteger time = new AtomicInteger(0); initVisitInfo(nodeVisit); @@ -922,9 +950,9 @@ public class Graph { } private void DFSVisitEnriched(Node u, AtomicInteger time, - Map nodeVisit, - Map edgeVisit, - List visited) { + Map nodeVisit, + Map edgeVisit, + List visited) { time.incrementAndGet(); nodeVisit.get(u).setDiscoveryTime(time.get()); nodeVisit.get(u).setColour(NodeColour.GRAY); @@ -955,57 +983,35 @@ public class Graph { // DOT I/O // ====================== - public static Graph fromDotFile(String filename) { return fromDotFile(filename, ".gv"); } - - public static Graph fromDotFile(String filename, String ext) { - if (ext == null) ext = ".gv"; - if (!ext.startsWith(".")) ext = "." + ext; - Path path = Path.of(filename + ext); - Map> adj = new HashMap<>(); - - Pattern linePattern = Pattern.compile("^\\s*(\\d+)\\s*(--|->)\\s*(\\d+)\\s*(?:\\[(.*?)\\])?\\s*;?\\s*$"); - - List lines; - try { lines = Files.readAllLines(path, StandardCharsets.UTF_8); } - catch (IOException e) { return new Graph(adj); } - - for (String rawLine : lines) { - String line = rawLine.trim(); - if (line.isEmpty() || line.startsWith("digraph") || line.startsWith("graph") || line.startsWith("{") || line.startsWith("}")) - continue; - Matcher m = linePattern.matcher(line); - if (m.matches()) { - int fromId = Integer.parseInt(m.group(1)); - String op = m.group(2); - int toId = Integer.parseInt(m.group(3)); - String attr = m.group(4); - - Node from = adj.keySet().stream().filter(n -> n.getId() == fromId).findFirst().orElseGet(() -> { - Node nn = new Node(fromId, null); - adj.put(nn, new ArrayList<>()); - return nn; - }); - Node to = adj.keySet().stream().filter(n -> n.getId() == toId).findFirst().orElseGet(() -> { - Node nn = new Node(toId, null); - adj.put(nn, new ArrayList<>()); - return nn; - }); - - Integer weight = null; - if (attr != null) { - Matcher mW = Pattern.compile("len\\s*=\\s*(\\d+)").matcher(attr); - if (mW.find()) weight = Integer.parseInt(mW.group(1)); + public static Graph fromDotFile(String filename) { + BufferedReader dot = new BufferedReader(new FileReader(filename)); + Map> adjEdList = new HashMap<>(); + Graph g = new Graph(adjEdList); + BufferedReader dot = new BufferedReader(new FileReader(filename)); + List nodes = new ArrayList<>(); + + String line = dot.readLine(); + while (line != null) { + int iteration = 0; + Edge edge = new Edge(); + Node nFrom = new Node(); + Node nTo = new Node(); + String[] tokens = line.split("[^0-9]"); + if (!tokens[0].equals("")) { + if (!nodes.contains(Integer.parseInt(tokens[0]))) { + List listEdges = new ArrayList<>(); } - - if (weight == null) adj.get(from).add(new Edge(from, to)); - else adj.get(from).add(new Edge(from, to, weight)); - if (op.equals("--")) { - if (weight == null) adj.get(to).add(new Edge(to, from)); - else adj.get(to).add(new Edge(to, from, weight)); + nFrom.setId(Integer.parseInt(tokens[0])); + edge.setNodeFrom(nFrom); + nTo.setId(Integer.parseInt(tokens[1])); + edge.setNodeTo(nTo); + if (tokens[2] != "") { + edge.setWeight(Integer.parseInt(tokens[2])); } + } + } - return new Graph(adj); } public String toDotString() { @@ -1025,13 +1031,20 @@ public class Graph { return sb.toString(); } - public void toDotFile(String filename) { toDotFile(filename, ".gv"); } + public void toDotFile(String filename) { + toDotFile(filename, ".gv"); + } public void toDotFile(String filename, String ext) { - if (ext == null) ext = ".gv"; - if (!ext.startsWith(".")) ext = "." + ext; - try { Files.writeString(Path.of(filename + ext), toDotString(), StandardCharsets.UTF_8); } - catch (IOException e) { e.printStackTrace(); } + if (ext == null) + ext = ".gv"; + if (!ext.startsWith(".")) + ext = "." + ext; + try { + Files.writeString(Path.of(filename + ext), toDotString(), StandardCharsets.UTF_8); + } catch (IOException e) { + e.printStackTrace(); + } } // ====================== @@ -1040,12 +1053,14 @@ public class Graph { private Map initVisitInfo() { Map map = new HashMap<>(); - for (Node n : adjEdList.keySet()) map.put(n, new NodeVisitInfo()); + for (Node n : adjEdList.keySet()) + map.put(n, new NodeVisitInfo()); return map; } private void initVisitInfo(Map map) { - for (Node n : adjEdList.keySet()) map.put(n, new NodeVisitInfo()); + for (Node n : adjEdList.keySet()) + map.put(n, new NodeVisitInfo()); } private List sortNodes() { diff --git a/src/main/java/m1graphs2025/Node.java b/src/main/java/m1graphs2025/Node.java index ebd69ea..40fa05e 100644 --- a/src/main/java/m1graphs2025/Node.java +++ b/src/main/java/m1graphs2025/Node.java @@ -39,6 +39,10 @@ public class Node implements Comparable { this.id = id; this.graph = graph; } + public Node(){ + this.id = 0; + this.graph = null; + } /** * Construit un nœud avec un identifiant, un graphe et un nom. diff --git a/src/main/java/m1graphs2025/TestGraphsPW2.java b/src/main/java/m1graphs2025/TestGraphsPW2.java index 463c541..6f9fb9b 100644 --- a/src/main/java/m1graphs2025/TestGraphsPW2.java +++ b/src/main/java/m1graphs2025/TestGraphsPW2.java @@ -14,29 +14,30 @@ public class TestGraphsPW2 { System.out.println(">>>>>>>> Creating the subject example graph in G"); Graph g = new Graph(2, 4, 0, 0, 6, 0, 2, 3, 5, 8, 0, 0, 4, 7, 0, 3, 0, 7, 0); System.out.println(">>>> Graph information"); - System.out.println(">> DOT representation\n"+g.toDotString()); - System.out.println(""+g.nbNodes()+" nodes, "+g.nbEdges()+" edges"); + System.out.println(">> DOT representation\n" + g.toDotString()); + System.out.println("" + g.nbNodes() + " nodes, " + g.nbEdges() + " edges"); System.out.println(">> Nodes: "); List nodes = g.getAllNodes(); Collections.sort(nodes); - for (Node n: nodes) - System.out.println("Node "+n+": degree "+g.degree(n)+" (in: "+g.inDegree(n)+"/ out: "+g.outDegree(n)+")"); + for (Node n : nodes) + System.out.println("Node " + n + ": degree " + g.degree(n) + " (in: " + g.inDegree(n) + "/ out: " + + g.outDegree(n) + ")"); List edges; System.out.println(">> Edges: "); System.out.println("---------------------------"); System.out.println("Out-edges per node"); - for (Node n: nodes) { + for (Node n : nodes) { edges = g.getOutEdges(n); Collections.sort(edges); - System.out.println(""+n+": "+edges); + System.out.println("" + n + ": " + edges); } System.out.println("In-edges per node"); - for (Node n: nodes) { + for (Node n : nodes) { edges = g.getInEdges(n); Collections.sort(edges); - System.out.println(""+n+": "+edges); + System.out.println("" + n + ": " + edges); } ///////////////////////////////////////////////////// @@ -46,37 +47,38 @@ public class TestGraphsPW2 { System.out.println("Error: failed to create node 12"); System.out.println("Graph now:"); System.out.println(g.toDotString()); - System.out.println(""+g.nbNodes()+" nodes, "+g.nbEdges()+" edges"); + System.out.println("" + g.nbNodes() + " nodes, " + g.nbEdges() + " edges"); nodes = g.getAllNodes(); Collections.sort(nodes); - System.out.println("Nodes list: "+nodes); + System.out.println("Nodes list: " + nodes); System.out.println("\n>>>>>>>> Removing node 3"); g.removeNode(3); System.out.println("Graph now:"); System.out.println(g.toDotString()); - System.out.println(""+g.nbNodes()+" nodes, "+g.nbEdges()+" edges"); + System.out.println("" + g.nbNodes() + " nodes, " + g.nbEdges() + " edges"); nodes = g.getAllNodes(); Collections.sort(nodes); - System.out.println("Nodes list: "+nodes); + System.out.println("Nodes list: " + nodes); System.out.println(">> Edges: "); System.out.println("---------------------------"); System.out.println("Out-edges per node"); - for (Node n: nodes) { + for (Node n : nodes) { edges = g.getOutEdges(n); Collections.sort(edges); - System.out.println(""+n+": "+edges); + System.out.println("" + n + ": " + edges); } System.out.println("In-edges per node"); - for (Node n: nodes) { + for (Node n : nodes) { edges = g.getInEdges(n); Collections.sort(edges); - System.out.println(""+n+": "+edges); + System.out.println("" + n + ": " + edges); } - System.out.println("\n>>>>>>>> Recreating edges (4, 3), (3, 6), (7, 3), adding edge (12, 3), creating edge (3, 25)"); + System.out.println( + "\n>>>>>>>> Recreating edges (4, 3), (3, 6), (7, 3), adding edge (12, 3), creating edge (3, 25)"); g.addEdge(new Edge(4, 3, g)); g.addEdge(new Edge(3, 6, g)); g.addEdge(new Edge(7, 3, g)); @@ -84,10 +86,10 @@ public class TestGraphsPW2 { g.addEdge(3, 25); System.out.println("Graph now:"); System.out.println(g.toDotString()); - System.out.println(""+g.nbNodes()+" nodes, "+g.nbEdges()+" edges"); + System.out.println("" + g.nbNodes() + " nodes, " + g.nbEdges() + " edges"); nodes = g.getAllNodes(); Collections.sort(nodes); - System.out.println("Nodes list: "+nodes); + System.out.println("Nodes list: " + nodes); System.out.println(""); System.out.println("\n>>>>>>>> Edges removal"); @@ -96,7 +98,8 @@ public class TestGraphsPW2 { g.removeEdge(4, 8); System.out.println(">>>> Removing absent edge (3, 4)"); g.removeEdge(3, 4); - System.out.println(">>>> Removing edges whith 1 or 2 not existing end-points: (-3, 4), (6, 0), (4, 11), (-1, -2), (13, 3), (9, 10)"); + System.out.println( + ">>>> Removing edges whith 1 or 2 not existing end-points: (-3, 4), (6, 0), (4, 11), (-1, -2), (13, 3), (9, 10)"); g.removeEdge(-3, 4); g.removeEdge(6, 0); g.removeEdge(4, 11); @@ -106,49 +109,49 @@ public class TestGraphsPW2 { System.out.println("Graph now:"); System.out.println(g.toDotString()); - System.out.println(""+g.nbNodes()+" nodes, "+g.nbEdges()+" edges"); + System.out.println("" + g.nbNodes() + " nodes, " + g.nbEdges() + " edges"); nodes = g.getAllNodes(); Collections.sort(nodes); - System.out.println("Nodes list: "+nodes); + System.out.println("Nodes list: " + nodes); - System.out.println("\nTesting that getSuccessors and getSuccessorsMulti give the same result for the simple graph:"); + System.out.println( + "\nTesting that getSuccessors and getSuccessorsMulti give the same result for the simple graph:"); boolean same = true; - for (Node u: nodes) { + for (Node u : nodes) { List succs = g.getSuccessors(u), succsMulti = g.getSuccessorsMulti(u); // sort the lists so that nodes always appear in the same order Collections.sort(succs); Collections.sort(succsMulti); same = same && succs.equals(succsMulti); } - System.out.println("\tgetSuccessors and getSuccessorsMulti "+(same?"are identical":"differ")); - - + System.out.println("\tgetSuccessors and getSuccessorsMulti " + (same ? "are identical" : "differ")); System.out.println("\n>>>>>>>> MULTIGRAPH: adding a self-loop on node 6, and a second edge (1, 4)"); g.addEdge(6, 6); g.addEdge(1, 4); System.out.println("Graph now:"); System.out.println(g.toDotString()); - System.out.println(""+g.nbNodes()+" nodes, "+g.nbEdges()+" edges"); + System.out.println("" + g.nbNodes() + " nodes, " + g.nbEdges() + " edges"); nodes = g.getAllNodes(); Collections.sort(nodes); - System.out.println("Nodes list: "+nodes); - System.out.println("Degree of node 6: "+g.degree(6)+" (in: "+g.inDegree(6)+"/ out: "+g.outDegree(6)+")"); + System.out.println("Nodes list: " + nodes); + System.out.println( + "Degree of node 6: " + g.degree(6) + " (in: " + g.inDegree(6) + "/ out: " + g.outDegree(6) + ")"); System.out.println(">> Edges: "); System.out.println("---------------------------"); System.out.println("Out-edges per node"); - for (Node n: nodes) { + for (Node n : nodes) { edges = g.getOutEdges(n); Collections.sort(edges); - System.out.println(""+n+": "+edges); + System.out.println("" + n + ": " + edges); } System.out.println("In-edges per node"); - for (Node n: nodes) { + for (Node n : nodes) { edges = g.getInEdges(n); Collections.sort(edges); - System.out.println(""+n+": "+edges); + System.out.println("" + n + ": " + edges); } System.out.println("\n>>>>>>>>>> Get the reverse graph"); @@ -159,7 +162,7 @@ public class TestGraphsPW2 { System.out.println(">>>>>>>>>> Emptying the graph by removing all its nodes"); nodes = g.getAllNodes(); - for (Node u: nodes) + for (Node u : nodes) g.removeNode(u); System.out.println("Graph now:"); System.out.println(g.toDotString()); @@ -182,7 +185,7 @@ public class TestGraphsPW2 { System.out.println("*------------------------------------------------------------------*"); System.out.println("\n>>> Graph with isolated nodes: reading file 'isolatedNodes.gv'"); Graph gin = Graph.fromDotFile("isolatedNodes"); - if (gin==null) + if (gin == null) System.out.println("Null graph was created from 'isolatedNodes.gv'"); else { System.out.println("Read: OK. The graph with isolated nodes has been read as:"); @@ -193,7 +196,7 @@ public class TestGraphsPW2 { System.out.println(">>> Simple graph: reading file 'simpleGraph.gv'"); Graph sg = Graph.fromDotFile("simpleGraph"); - if (sg==null) + if (sg == null) System.out.println("Null graph was created from 'simpleGraph.gv'"); else { System.out.println("Read: OK. The simple graph has been read as:"); @@ -204,7 +207,7 @@ public class TestGraphsPW2 { System.out.println("\n>>> Multi-graph: reading file 'multiGraph.gv'"); Graph mg = Graph.fromDotFile("multiGraph"); - if (mg==null) + if (mg == null) System.out.println("Null graph was created from 'multiGraph.gv'"); else { System.out.println("Read: OK. The multi-graph has been read as:"); @@ -214,17 +217,15 @@ public class TestGraphsPW2 { } System.out.println("Comparing single and multi successors per node for 'multiGraph.gv'"); - for (Node u: mg.getAllNodes()) { + for (Node u : mg.getAllNodes()) { List succs = mg.getSuccessors(u), succsMulti = mg.getSuccessorsMulti(u); // sort the lists so that nodes always appear in the same order Collections.sort(succs); Collections.sort(succsMulti); - System.out.println(""+u+" single successors: "+succs); - System.out.println(""+u+" multi successors: "+succsMulti); + System.out.println("" + u + " single successors: " + succs); + System.out.println("" + u + " multi successors: " + succsMulti); } - - System.out.println("\n\n"); System.out.println("*----------------------------------------------------------------------*"); System.out.println("************* PART 3. WEIGHTED DIRECTED GRAPHS ***********************"); @@ -234,7 +235,7 @@ public class TestGraphsPW2 { System.out.println("\n>>>>>>>>>>"); System.out.println("Reading a weighted directed simple graph from DOT file 'weightedSimpleGraph.gv'"); Graph wsg = Graph.fromDotFile("weightedSimpleGraph"); - if (wsg==null) + if (wsg == null) System.out.println("Null graph was created from 'weightedSimpleGraph.gv'"); else { System.out.println("Read: OK. The weighted directed simple graph has been read as:"); @@ -242,15 +243,15 @@ public class TestGraphsPW2 { System.out.println(wsg.toDotString()); System.out.println("---------------------"); - for (Edge e: wsg.getAllEdges()) + for (Edge e : wsg.getAllEdges()) totalEdgesWeight += e.getWeight(); - System.out.println("The sum of all edges weights equals "+totalEdgesWeight); + System.out.println("The sum of all edges weights equals " + totalEdgesWeight); } System.out.println("\n>>>>>>>>>>"); System.out.println("Reading a weighted directed multi graph from DOT file 'weightedMultiGraph.gv'"); Graph wmg = Graph.fromDotFile("weightedMultiGraph"); - if (wmg==null) + if (wmg == null) System.out.println("Null graph was created from 'weightedMultiGraph.gv'"); else { System.out.println("Read: OK. The weighted directed multi graph has been read as:"); @@ -259,113 +260,110 @@ public class TestGraphsPW2 { System.out.println("---------------------"); totalEdgesWeight = 0; - for (Edge e: wmg.getAllEdges()) + for (Edge e : wmg.getAllEdges()) totalEdgesWeight += e.getWeight(); - System.out.println("The sum of all edges weights equals "+totalEdgesWeight); + System.out.println("The sum of all edges weights equals " + totalEdgesWeight); } - - - System.out.println("\n\n"); System.out.println("*-------------------------------------------------------------------------*"); System.out.println("************ PART 4. UNDIRECTED UNWEIGHTED GRAPHS ***********************"); System.out.println("*-------------------------------------------------------------------------*"); System.out.println("\nCreating an undirected simple graph 'usg' from scracth"); - UndirectedGraph usg = new UndirectedGraph(2,3,0, 3,4,0, 4,0, 0); + UndirectedGraph usg = new UndirectedGraph(2, 3, 0, 3, 4, 0, 4, 0, 0); System.out.println(usg.toDotString()); - System.out.println("usg has "+usg.nbNodes()+" nodes and "+usg.nbEdges()+" edges."); + System.out.println("usg has " + usg.nbNodes() + " nodes and " + usg.nbEdges() + " edges."); System.out.println("\n>>>>>> usg: Counting degrees and showing successors"); - for (Node u: usg.getAllNodes()) { - System.out.println("Node "+u+". Degree: "+usg.degree(u.getId())+" (In: "+usg.inDegree(u.getId())+" / Out: "+usg.outDegree(u.getId())+")"); - System.out.println("\tSuccessors: "+usg.getSuccessors(u)); + for (Node u : usg.getAllNodes()) { + System.out.println("Node " + u + ". Degree: " + usg.degree(u.getId()) + " (In: " + usg.inDegree(u.getId()) + + " / Out: " + usg.outDegree(u.getId()) + ")"); + System.out.println("\tSuccessors: " + usg.getSuccessors(u)); } System.out.println(">>>>>> usg: Edges of the graph"); System.out.println("// N.B. The edges are printed as though they were directed. This is due to the toString()\n" + "// method that was not overridden. It is possible to do better but not important.\n" + "// What is important is that each edge appears only once per direction."); - System.out.println("All edges of the graph: "+usg.getAllEdges()); + System.out.println("All edges of the graph: " + usg.getAllEdges()); System.out.println("Out-edges per node"); - for (Node u: usg.getAllNodes()) - System.out.println(""+u+": "+usg.getOutEdges(u)); + for (Node u : usg.getAllNodes()) + System.out.println("" + u + ": " + usg.getOutEdges(u)); System.out.println("In-edges per node"); - for (Node u: usg.getAllNodes()) - System.out.println(""+u+": "+usg.getInEdges(u)); + for (Node u : usg.getAllNodes()) + System.out.println("" + u + ": " + usg.getInEdges(u)); System.out.println("Incident edges per node"); - for (Node u: usg.getAllNodes()) - System.out.println(""+u+": "+usg.getIncidentEdges(u)); + for (Node u : usg.getAllNodes()) + System.out.println("" + u + ": " + usg.getIncidentEdges(u)); System.out.println("Creating an undirected multi-graph with self-loops 'umg' from scratch"); - UndirectedGraph umg = new UndirectedGraph(1,1,2,2,3,0, 2,3,0, 0); + UndirectedGraph umg = new UndirectedGraph(1, 1, 2, 2, 3, 0, 2, 3, 0, 0); String dotUMG = umg.toDotString(); System.out.println(dotUMG); - System.out.println("umg has "+umg.nbNodes()+" nodes and "+umg.nbEdges()+" edges."); - + System.out.println("umg has " + umg.nbNodes() + " nodes and " + umg.nbEdges() + " edges."); System.out.println("\n>>>>>> umg: Counting degrees and showing successors"); - for (Node u: umg.getAllNodes()) { - System.out.println("Node "+u+". Degree: "+umg.degree(u.getId())+" (In: "+umg.inDegree(u.getId())+" / Out: "+umg.outDegree(u.getId())+")"); - System.out.println("\tSuccessors: "+umg.getSuccessors(u)); + for (Node u : umg.getAllNodes()) { + System.out.println("Node " + u + ". Degree: " + umg.degree(u.getId()) + " (In: " + umg.inDegree(u.getId()) + + " / Out: " + umg.outDegree(u.getId()) + ")"); + System.out.println("\tSuccessors: " + umg.getSuccessors(u)); } System.out.println(">>>>>> umg: Edges of the graph"); - System.out.println("All edges of the graph: "+umg.getAllEdges()); + System.out.println("All edges of the graph: " + umg.getAllEdges()); System.out.println("Out-edges per node"); - for (Node u: umg.getAllNodes()) - System.out.println(""+u+": "+umg.getOutEdges(u)); + for (Node u : umg.getAllNodes()) + System.out.println("" + u + ": " + umg.getOutEdges(u)); System.out.println("In-edges per node"); - for (Node u: umg.getAllNodes()) - System.out.println(""+u+": "+umg.getInEdges(u)); + for (Node u : umg.getAllNodes()) + System.out.println("" + u + ": " + umg.getInEdges(u)); System.out.println("Incident edges per node"); - for (Node u: umg.getAllNodes()) - System.out.println(""+u+": "+umg.getIncidentEdges(u)); + for (Node u : umg.getAllNodes()) + System.out.println("" + u + ": " + umg.getIncidentEdges(u)); System.out.println("\n>>>>>> umg: Successor Array, Adjacency Matrix, and Graph Reverse"); - System.out.println("umg Successor array\n"+Arrays.toString(umg.toSuccessorArray())); + System.out.println("umg Successor array\n" + Arrays.toString(umg.toSuccessorArray())); System.out.println("umg Adjacency Matrix"); - for (int[] row: umg.toAdjMatrix()) - System.out.println("\t"+Arrays.toString(row)); + for (int[] row : umg.toAdjMatrix()) + System.out.println("\t" + Arrays.toString(row)); System.out.println("Testing via toDotString() the equality with the reverse graph"); String dotRUMG = umg.getReverse().toDotString(); - System.out.println("DOT of the reverse of umg\n"+dotRUMG); - System.out.println("Graph gu and its reverse "+(dotUMG.equals(dotRUMG)?"are identical":"differ")); + System.out.println("DOT of the reverse of umg\n" + dotRUMG); + System.out.println("Graph gu and its reverse " + (dotUMG.equals(dotRUMG) ? "are identical" : "differ")); System.out.println("-----------------\n NOW a disconnected GRAPH \n----------------"); System.out.println("Building 'guDisc', a disconnected undirected graph with multi-edges and self-loops"); - UndirectedGraph guDisc = new UndirectedGraph(1,1,2,2,6,0, 2,3,6,0, 0, 6,0, 6,0, 0, 0, 9,10,0, 0, 0); + UndirectedGraph guDisc = new UndirectedGraph(1, 1, 2, 2, 6, 0, 2, 3, 6, 0, 0, 6, 0, 6, 0, 0, 0, 9, 10, 0, 0, 0); System.out.println(guDisc.toDotString()); // delete -// Graph guDisc2 = new Graph(1,1,2,2,6,0, 2,3,6,0, 0, 6,0, 6,0, 0, 0, 9,10,0, 0, 0); -// System.out.println(guDisc2.toDotString()); -// System.exit(0); - //end delete + // Graph guDisc2 = new Graph(1,1,2,2,6,0, 2,3,6,0, 0, 6,0, 6,0, 0, 0, 9,10,0, 0, + // 0); + // System.out.println(guDisc2.toDotString()); + // System.exit(0); + // end delete System.out.println("Comparing single and multi successors per node for guDisc"); - for (Node u: guDisc.getAllNodes()) { + for (Node u : guDisc.getAllNodes()) { List succs = guDisc.getSuccessors(u), succsMulti = guDisc.getSuccessorsMulti(u); // sort the lists so that nodes always appear in the same order Collections.sort(succs); Collections.sort(succsMulti); - System.out.println(""+u+" single successors: "+succs); - System.out.println(""+u+" multi successors: "+succsMulti); + System.out.println("" + u + " single successors: " + succs); + System.out.println("" + u + " multi successors: " + succsMulti); } - - System.out.println(">>>> DFS of guDisc: "+guDisc.getDFS()); - System.out.println(">>>> BFS of guDisc: "+guDisc.getBFS()); + System.out.println(">>>> DFS of guDisc: " + guDisc.getDFS()); + System.out.println(">>>> BFS of guDisc: " + guDisc.getBFS()); System.out.println(">>>>>>> Computing guDisc's transitive closure"); UndirectedGraph guDiscTC = (UndirectedGraph) guDisc.getTransitiveClosure(); System.out.println(guDiscTC.toDotString()); - System.out.println("\n\n"); System.out.println("*-----------------------------------------------------------------------*"); System.out.println("************ PART 5. UNDIRECTED WEIGHTED GRAPHS ***********************"); @@ -374,8 +372,8 @@ public class TestGraphsPW2 { System.out.println("\n>>>>>> Reading 'uwmg' an undirected weighted multi-graph with self loops\n" + "from file 'undirWeightedMultiGraph.gv'"); - UndirectedGraph uwmg = (UndirectedGraph) UndirectedGraph.fromDotFile("undirWeightedMultiGraph"); - if (uwmg==null) + UndirectedGraph uwmg = (UndirectedGraph) UndirectedGraph.fromDotFile("undirWeightedMultiGraph.gv"); + if (uwmg == null) System.out.println("Null graph was created from 'undirWeightedMultiGraph.gv'"); else { System.out.println("Read: OK. The undirected weighted multi-graph has been read as:"); @@ -384,43 +382,47 @@ public class TestGraphsPW2 { System.out.println("---------------------"); totalEdgesWeight = 0; - for (Edge e: uwmg.getAllEdges()) + for (Edge e : uwmg.getAllEdges()) totalEdgesWeight += e.getWeight(); - System.out.println("The sum of all edges weights equals "+totalEdgesWeight); + System.out.println("The sum of all edges weights equals " + totalEdgesWeight); } System.out.println("\nComparing single and multi successors per node for uwmg"); - for (Node u: uwmg.getAllNodes()) { + for (Node u : uwmg.getAllNodes()) { List succs = uwmg.getSuccessors(u), succsMulti = uwmg.getSuccessorsMulti(u); // sort the lists so that nodes always appear in the same order Collections.sort(succs); Collections.sort(succsMulti); - System.out.println(""+u+" single successors: "+succs); - System.out.println(""+u+" multi successors: "+succsMulti); + System.out.println("" + u + " single successors: " + succs); + System.out.println("" + u + " multi successors: " + succsMulti); } - - /* TO BE CONTINUED ... - System.out.println("\n\n"); - System.out.println("*-----------------------------------------------------------------------*"); - System.out.println("************ PART 6. DFS and Node Visit Info ***********************"); - System.out.println("*-----------------------------------------------------------------------*"); - - - // lecture example but undirected - UndirectedGraph gToVisit = new UndirectedGraph( - 2, 3, 4, 6, 0, //1 - 5, 6, 0, //2 - 4, 0, //3 - 8, 0, //4 - 6, 7, 8, 0, //5 - 7, 0, //6 - 8,0, //7 - 0 //8 - ); - System.out.println("\nAn undirected graph to visit:"); - System.out.println(gToVisit.toDotString()); - */ + /* + * TO BE CONTINUED ... + * System.out.println("\n\n"); + * System.out.println( + * "*-----------------------------------------------------------------------*"); + * System.out. + * println("************ PART 6. DFS and Node Visit Info ***********************" + * ); + * System.out.println( + * "*-----------------------------------------------------------------------*"); + * + * + * // lecture example but undirected + * UndirectedGraph gToVisit = new UndirectedGraph( + * 2, 3, 4, 6, 0, //1 + * 5, 6, 0, //2 + * 4, 0, //3 + * 8, 0, //4 + * 6, 7, 8, 0, //5 + * 7, 0, //6 + * 8,0, //7 + * 0 //8 + * ); + * System.out.println("\nAn undirected graph to visit:"); + * System.out.println(gToVisit.toDotString()); + */ } diff --git a/src/main/java/m1graphs2025/UndirectedGraph.java b/src/main/java/m1graphs2025/UndirectedGraph.java index afd4977..595e22f 100644 --- a/src/main/java/m1graphs2025/UndirectedGraph.java +++ b/src/main/java/m1graphs2025/UndirectedGraph.java @@ -11,9 +11,12 @@ public class UndirectedGraph extends Graph { // ====================== // CONSTRUCTEURS // ====================== + public UndirectedGraph(Map> adjEdList) { + super(adjEdList); + } public UndirectedGraph() { - super(new HashMap<>()); // graphe vide + super(new HashMap<>()); // graphe vide } public UndirectedGraph(int... successorArray) { @@ -38,8 +41,10 @@ public class UndirectedGraph extends Graph { Node u = e.getNodeFrom(); Node v = e.getNodeTo(); if (!existsEdge(v, u)) { - if (e.isWeighted()) addEdge(v, u, e.getWeight()); - else addEdge(v, u); + if (e.isWeighted()) + addEdge(v, u, e.getWeight()); + else + addEdge(v, u); } } } @@ -52,32 +57,37 @@ public class UndirectedGraph extends Graph { public void addEdge(Node from, Node to) { super.addEdge(from, to); // Ajout symétrique - if (!existsEdge(to, from)) super.addEdge(to, from); + if (!existsEdge(to, from)) + super.addEdge(to, from); } @Override public void addEdge(int fromId, int toId) { super.addEdge(fromId, toId); - if (!existsEdge(toId, fromId)) super.addEdge(toId, fromId); + if (!existsEdge(toId, fromId)) + super.addEdge(toId, fromId); } @Override public void addEdge(Node from, Node to, int weight) { super.addEdge(from, to, weight); - if (!existsEdge(to, from)) super.addEdge(to, from, weight); + if (!existsEdge(to, from)) + super.addEdge(to, from, weight); } @Override public void addEdge(int fromId, int toId, int weight) { super.addEdge(fromId, toId, weight); - if (!existsEdge(toId, fromId)) super.addEdge(toId, fromId, weight); + if (!existsEdge(toId, fromId)) + super.addEdge(toId, fromId, weight); } @Override public void addEdge(Edge e) { super.addEdge(e); Edge sym = e.getSymmetric(); - if (sym != null && existsEdge(sym)) super.addEdge(sym); + if (sym != null && existsEdge(sym)) + super.addEdge(sym); } @Override @@ -119,6 +129,40 @@ public class UndirectedGraph extends Graph { return super.isMultiEdge(u, v) || super.isMultiEdge(v, u); } + @Override + public UndirectedGraph copy() { + Map> copy = new HashMap<>(); + for (Node u : adjEdList.keySet()) { + List list = new ArrayList<>(); + for (Edge e : adjEdList.get(u)) + list.add(new Edge(e.getNodeFrom(), e.getNodeTo(), e.getWeight())); + copy.put(u, list); + } + return new UndirectedGraph(copy); + } + + @Override + public UndirectedGraph getTransitiveClosure() { + UndirectedGraph closure = this.copy(); + List nodes = closure.getAllNodes(); + int n = nodes.size(); + for (Node k : nodes) { + for (Node i : nodes) { + for (Node j : nodes) { + if (closure.existsEdge(i, k) && closure.existsEdge(k, j)) { + if (!closure.existsEdge(i, j)) + closure.addEdge(i, j); + } + } + } + } + return closure; + } + + public static UndirectedGraph fromDotFile(String filename) { + return fromDotFile(filename, ".gv"); + } + // ====================== // Utilitaires // ====================== diff --git a/src/main/java/m1graphs2025/undirWeightedMultiGraph.gv b/src/main/java/m1graphs2025/undirWeightedMultiGraph.gv new file mode 100644 index 0000000..ffaa408 --- /dev/null +++ b/src/main/java/m1graphs2025/undirWeightedMultiGraph.gv @@ -0,0 +1,18 @@ +graph { + rankdir=LR + 1 -- 2 [label=4, len=4] + 1 -- 3 [label=3, len=3] + 1 -- 3 [label=6, len=6] + 1 -- 4 [label=0, len=0] + 2 -- 3 [label=1, len=1] + 2 -- 4 [label=2, len=2] + 2 -- 4 [label=50, len=50] + 2 -- 5 [label=3, len=3] + 3 -- 5 [label=2, len=2] + 4 -- 4 [label=14, len=14] + 4 -- 5 [label=2, len=2] + 5 -- 6 [label=7, len=7] + 5 -- 6 [label=10, len=10] + 6 -- 6 [label=5, len=5] + 6 -- 6 [label=8, len=8] +} \ No newline at end of file -- GitLab