From 6cb013214e9f393bd6d2c5fa3b50de567e9efac1 Mon Sep 17 00:00:00 2001 From: Kamila Szewczyk Date: Thu, 13 Apr 2023 10:23:00 +0200 Subject: [PATCH] chinese postman algorithm --- .../runtime/graph/ChinesePostman.java | 25 +++++++++ .../kamilalisp/runtime/graph/GraphPath.java | 52 +++++++++++++++++++ .../kamilalisp/runtime/lib/AlgorithmLib.java | 1 + 3 files changed, 78 insertions(+) create mode 100644 src/main/java/palaiologos/kamilalisp/runtime/graph/ChinesePostman.java create mode 100644 src/main/java/palaiologos/kamilalisp/runtime/graph/GraphPath.java diff --git a/src/main/java/palaiologos/kamilalisp/runtime/graph/ChinesePostman.java b/src/main/java/palaiologos/kamilalisp/runtime/graph/ChinesePostman.java new file mode 100644 index 00000000..2d27792d --- /dev/null +++ b/src/main/java/palaiologos/kamilalisp/runtime/graph/ChinesePostman.java @@ -0,0 +1,25 @@ +package palaiologos.kamilalisp.runtime.graph; + +import org.jgrapht.alg.cycle.BergeGraphInspector; +import org.jgrapht.graph.DefaultEdge; +import palaiologos.kamilalisp.atom.Atom; +import palaiologos.kamilalisp.atom.Environment; +import palaiologos.kamilalisp.atom.Lambda; +import palaiologos.kamilalisp.atom.PrimitiveFunction; + +import java.util.List; + +public class ChinesePostman extends PrimitiveFunction implements Lambda { + @Override + public Atom apply(Environment env, List args) { + assertArity(args, 1); + GraphWrapper wp = args.get(0).getUserdata(GraphWrapper.class); + var inspector = new org.jgrapht.alg.cycle.ChinesePostman(); + return new Atom(new GraphPath(inspector.getCPPSolution(wp.getGraph()))); + } + + @Override + protected String name() { + return "graph:chinese-postman"; + } +} diff --git a/src/main/java/palaiologos/kamilalisp/runtime/graph/GraphPath.java b/src/main/java/palaiologos/kamilalisp/runtime/graph/GraphPath.java new file mode 100644 index 00000000..8faec7cc --- /dev/null +++ b/src/main/java/palaiologos/kamilalisp/runtime/graph/GraphPath.java @@ -0,0 +1,52 @@ +package palaiologos.kamilalisp.runtime.graph; + +import org.jgrapht.graph.DefaultEdge; +import palaiologos.kamilalisp.atom.Atom; +import palaiologos.kamilalisp.atom.Userdata; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class GraphPath implements Userdata { + private final org.jgrapht.GraphPath path; + + public GraphPath(org.jgrapht.GraphPath path) { + this.path = path; + } + + @Override + public Atom field(Object key) { + if(!(key instanceof String s)) + throw new IllegalArgumentException("key must be a string"); + switch (s) { + case "length" -> { + return new Atom(BigInteger.valueOf(path.getLength())); + } + case "weight" -> { + return new Atom(BigDecimal.valueOf(path.getWeight())); + } + case "start" -> { + return path.getStartVertex(); + } + case "end" -> { + return path.getEndVertex(); + } + case "vertices" -> { + return new Atom(path.getVertexList()); + } + default -> { + throw new IllegalArgumentException("unknown key: " + key); + } + } + } + + @Override + public String toDisplayString() { + return "graph:path of length " + path.getLength(); + } + + @Override + public String typeName() { + return "graph:path"; + } +} diff --git a/src/main/java/palaiologos/kamilalisp/runtime/lib/AlgorithmLib.java b/src/main/java/palaiologos/kamilalisp/runtime/lib/AlgorithmLib.java index 5e486ea8..971822f5 100644 --- a/src/main/java/palaiologos/kamilalisp/runtime/lib/AlgorithmLib.java +++ b/src/main/java/palaiologos/kamilalisp/runtime/lib/AlgorithmLib.java @@ -138,6 +138,7 @@ public static void register(Environment env) { env.setPrimitive("graph:is-berge-graph", new Atom(new BergeGraphTest())); env.setPrimitive("graph:bron-kerbosch-clique-finder", new Atom(new BronKerboschCliqueFinder())); env.setPrimitive("graph:chordal-graph-maximum-clique-finder", new Atom(new ChordalGraphMaximumCliqueFinder())); + env.setPrimitive("graph:chinese-postman", new Atom(new ChinesePostman())); env.setPrimitive("regex:matches?", "⍫⊖∊?", new Atom(new RegexMatches())); env.setPrimitive("regex:replace", "⍫⊖⍆", new Atom(new RegexReplace()));