/ Published in: Java
URL: http://siwego.net/dev/tsp_java.zip
[start_tsp.bat] file should be made for launching: start "output" java -jar TSP.jar
Expand |
Embed | Plain Text
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; @SuppressWarnings("serial") /* * @author: Michal Sztolcman s3826 * subject: TSP z alg. Kruskala i Prima */ public static int ROUTE_POINTS = 20; Dimension size; double factorX, factorY; Node[] Nodes; // zbior wylosowanych pojedynczych punktow (wezlow) char tmp_ch; TSP.alg last_alg; boolean last_tsp, rolled; char point; int tsp_degree; public Node(char c, int x, int y) { super(x, y); point = c; tsp_degree = 0; } public Node(int i, int x, int y) { this((char)('A'+i), x, y); } public double getDistance(Node n) { } return ""+point; } } public TSPgraphics() { addComponentListener(this); } public void roll() { factorX = factorY = 1; connections = false; printed = false; rollNodes(); repaint(); } public void connect(final TSP.alg alg, final char startNode) { if (alg != last_alg || last_tsp != TSP.TSPselected() || (alg == TSP.alg.PRIM && tmp_ch != startNode)) printed = false; last_alg = alg; last_tsp = TSP.TSPselected(); else return; public void run() { output = new ArrayList<String>(); output.add("\n\n"+(TSP.TSPselected() ? "tsp " : "")+(""+alg).toLowerCase()+" - step log:"); if (alg == TSP.alg.KRUSKAL) { // <-- KRUSKAL // rodzina jednoelementowych zbiorow z kazdym z wezlow // utworzenie uporzadkowanego zbioru segmentow NodePair rosnaco wg. dystansu public int compare(NodePair p1, NodePair p2) { //w przypadku wyniku 0 TreeSet nie dopuscil by roznych polaczen o tej samej odleglosci return p1.distance - p2.distance < 0 ? -1 : 1; } }); // dodanie wszystkich par punktow NodePair wraz z odlegloscia do zbioru for (int i = 0; i < Nodes.length; i++) { for (int j = 0; j < i && i > 0; j++) { routes.add( new NodePair(Nodes[j]+""+Nodes[i], Nodes[j].getDistance(Nodes[i])) ); } // utworzenie zbioru z jednym elementem (wezlem) divList.add(hs1); // dodanie do rodziny zbiorow } // operacja laczenia zbiorow w rodzinie zbiorow i oznaczanie polaczen Set pointSet, leftSet; while(routeIt.hasNext() && divList.size() != 1) { divIt = divList.iterator(); p = (NodePair) routeIt.next(); A = p.segment.charAt(0); B = p.segment.charAt(1); leftSet = null; pointSet = null; while (divIt.hasNext()) { if (TSP.TSPselected() && (Nodes[idx(A)].tsp_degree >= 2 || Nodes[idx(B)].tsp_degree >= 2)) continue; if (pointSet.contains(A) && pointSet.contains(B)) continue; else if (pointSet.contains(A) || pointSet.contains(B)) if (leftSet == null) leftSet = pointSet; else { leftSet.addAll(pointSet); divIt.remove(); p.connection = true; if (TSP.TSPselected()) { Nodes[idx(A)].tsp_degree++; Nodes[idx(B)].tsp_degree++; } break; } } divIt = divList.iterator(); while (divIt.hasNext()) tmp += divIt.next(); output.add(tmp); } if (TSP.TSPselected()) { for (int i = 0; i < Nodes.length; i++) { if (Nodes[i].tsp_degree == 1) segment += Nodes[i]; Nodes[i].tsp_degree = 0; } routeIt = routes.iterator(); while(routeIt.hasNext()) { p = (NodePair) routeIt.next(); if (p.segment.equals(segment)) { p.connection = true; output.add("finally "+segment.charAt(0)+" -> "+segment.charAt(1)); break; } } } } else if (alg == TSP.alg.PRIM) { tmp_ch = startNode; // <-- PRIM routes = new LinkedHashSet(); // zbior do wydruku wybranych polaczen PrimTree ptree = new PrimTree(); // uproszczone drzewo polaczen dla alg tsp double[] distances = new double[Nodes.length]; // tablica odleglosci Node[] parents = new Node[Nodes.length]; // tablica wierzcholkow rodzicow // utworzenie mst prim uzywajac dwoch pomocniczych tablic, przy zalozeniu ze wszystkie punkty sie widza Node curr = Nodes[idx(startNode)]; distances[idx(startNode)] = -1; for (int i = 0; i < Nodes.length; i++) { tmp1+=" "+Nodes[i]; tmp2+="--"; } output.add(tmp1+" take: "+curr+tmp2); for (int min = 0; min != -1;) { min = -1; for (int i = 0; i < Nodes.length; i++) { if (distances[i] == -1) continue; if (distances[i] == 0 || curr.getDistance(Nodes[i]) < distances[i]) { distances[i] = curr.getDistance(Nodes[i]); parents[i] = curr; } if (curr != Nodes[i] && (min == -1 || distances[i] < distances[min])) min = i; } if (min != -1) { tmp1 = ""; for (int i = 0; i < Nodes.length; i++) tmp1 += " "+(distances[i] != -1 ? parents[i] : "."); output.add(tmp1+" next: "+parents[min]+" -> "+Nodes[min]+" ("+((int)distances[min])+"."+(""+distances[min]).charAt((""+distances[min]).indexOf('.')+1)+")"); if (TSP.TSPselected()) ptree.add(parents[min], Nodes[min]); else routes.add( new NodePair(parents[min]+""+Nodes[min], parents[min].getDistance(Nodes[min]), true) ); distances[min] = -1; curr = Nodes[min]; } } if (TSP.TSPselected()) { // wlasna definicja stosu myStack stack = new myStack() { private stnode head; private int count; class stnode { Node node; stnode next; public stnode(Node n) { count++; node = n; next = head; head = this; } }; public myStack push(Set<Node> hs) { if (hs != null) new stnode((Node) it.next()); return this; } public Node pop() { count--; Node n = head.node; head = head.next; popPrint(n); return n; } public Node top() { return head.node; } public boolean empty() { return head == null; } private void popPrint(Node n) { int i; stnode pointer = head; Node[] nod = new Node[count]; for (i = count-1; pointer != null; i--) { nod[i] = pointer.node; pointer = pointer.next; } i = 0; if (print.isEmpty()) { print.add(" "+n); print.add(" ="); for (; i < nod.length-1; i++) print.add(" "+nod[i]); print.add(" "+n); } else { print.set(i, print.get(i++)+" "+n); print.set(i, print.get(i++)+" ="); for (; i < nod.length+2; i++) { if (print.size() > i) print.set(i, print.get(i)+" "+nod[i-2]); } if (print.size() > i) print.set(i, print.get(i)+" "+n); while (i < print.size()) print.set(i, print.get(i++)+" "); } } }; // okreslenie trasy tsp na utworzonym wczesniej minimalnym drzewie rozpinajacym prim Node parent = Nodes[idx(startNode)], next; stack.push(ptree.get(stack.pop())); while (!stack.empty()) { next = stack.pop(); stack.push(ptree.get(next)); routes.add( new NodePair(parent+""+next, parent.getDistance(next), true) ); parent = next; } routes.add( new NodePair(Nodes[idx(startNode)]+""+parent, Nodes[idx(startNode)].getDistance(parent), true) ); print.add("\n\ntsp prim - stack pop log:\n"); for (int i = print.size()-1; i >= 0; i--) output.add(""+print.set(i, null)); output.add("\nfinally "+Nodes[idx(startNode)]+" -> "+parent); } ptree.clear(); } connections = true; repaint(); } }; // obsluga wyjatkow przepelnienia, ktore nie powinno sie zdarzyc } else System.out.println(".\nwarning: "+e.getClass().getSimpleName()+", connecting interrupted..\nplease try again.."); dumped = true; connections = false; routes.clear(); output.clear(); return; } }); connecting.start(); /* (new Thread() { public void run() { progress = 0; while (connecting.isAlive()) { try { this.sleep(1000); } catch(InterruptedException e) { return; } if (connecting.isAlive()) { progress++; if (progress == 2) { System.out.println(".\nwarning: computing connections takes very long, possibility of data overflow"); } else if (progress > 5) { System.out.println(".\noperation aborted.\nhint: use less nodes"); try { connecting.stop(); } catch (SecurityException exc) { } return; } else System.out.print("."); } else if (!connections && !dumped) { System.out.println("\nfatal error: most propably OutOfMemoryError occured: Java heap overflow\n"); System.exit(1); } } } }).start(); try { connecting.join(); } catch (InterruptedException exc) { } */ } int progress; boolean dumped; super.paintComponent(g); if (rolled) { int w = getWidth(); int h = getHeight(); g.drawString("Michael Sztolcman s3826", w - 130, h - 5); for (int i = 0; i < Nodes.length; i++) { g.fillOval(getX(i), getY(i), 6, 6); g.drawOval(getX(i), getY(i), 6, 6); g.drawString(""+Nodes[i], getX(i) + 8, getY(i) + 18); } if (connections) { if (!printed) System.out.println((progress == 0 ? ".." : progress == 1 ? "." : "")+"\n\n connect distance"); NodePair p; Character A, B; while(routeIt.hasNext()) { p = (NodePair) routeIt.next(); if (!printed) System.out.println(p.segment + " = " + p.connection + (p.connection ? " " : "") + " " + p.distance); if (p.connection) { A = p.segment.charAt(0); B = p.segment.charAt(1); g.drawLine(getX(A) + 3, getY(A) + 3, getX(B) + 3, getY(B) + 3); } } if (!printed) printed = true; } } } private int getX(char c) { return getX(idx(c)); } private int getX(int i) { return (int) (Nodes[i].x * factorX); } private int getY(char c) { return getY(idx(c)); } private int getY(int i) { return (int) (Nodes[i].y * factorY); } private void rollNodes() { rolled = false; Nodes = new Node[ROUTE_POINTS]; int x, y, i = 0; boolean ok; while (i < Nodes.length) { x = rnd(getWidth()-24)+6; y = rnd(getHeight()-28)+5; ok = true; for (int j = 0; j < i && i > 0; j++) if (((x <= Nodes[j].x && x > Nodes[j].x - 16) || (x > Nodes[j].x && x < Nodes[j].x + 16)) && ((y <= Nodes[j].y && y > Nodes[j].y - 16) || (y > Nodes[j].y && y < Nodes[j].y + 16))) { ok = false; break; } if (ok) { Nodes[i] = new Node(i, x, y); i++; } } rolled = true; } private static int rnd(int n) { return r.nextInt(n); } for (int i = 0; i < n; i++) s += " "; return s; } private int idx(char c) { return c-'A'; } // uproszczone drzewo polaczen dla alg tsp prima class PrimTree extends HashMap<Node, HashSet> { public void add(Node root, Node child) { if (containsKey(root)) { HashSet<Node> hs = remove(root); hs.add(child); put(root, hs); } else } public HashSet<Node> get(Node node) { return super.remove(node); } }; double x = getWidth(), y = getHeight(); if (size != null) { factorX = x/((double) size.width); factorY = y/((double) size.height); } } //abstract class myStack interface myStack { boolean empty(); Node top(); Node pop(); myStack push(Set<Node> hs); } } class NodePair /*implements Comparable*/ { String segment; double distance; boolean connection; segment = s; distance = d; connection = c; } this(s, d, false); } /* public int compareTo(Object o) { return distance - ((NodePair) o).distance < 0 ? -1 : 1; }*/ } final static int SIZ_X = 600, SIZ_Y = 400; public static enum alg { KRUSKAL, PRIM }; static myRadio RBKruskal, RBPrim; public TSP() { dispose(); } }); } final TSP f = new TSP(); final TSPgraphics t = new TSPgraphics(); //t.setSize(SIZ_X, SIZ_Y); Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new ComponentEvent(t, ComponentEvent.COMPONENT_RESIZED)); } }); t.roll(); } }); b.setFocusPainted(false); j.add(b); // box.setBackground(Color.red); // box.setOpaque(true); box.add(JL = jl); f.setText(""); } f.setText(f.getText().length() > 0 ? f.getText().toUpperCase() : "A"); } }); box.add(JTF = tf); b.setToolTipText(" find 'travelling salesman problem' route "); char ch = tf.getText().charAt(0); if (RBPrim.isSelected() && (ch < 'A' || ch > 'A' + TSPgraphics.ROUTE_POINTS-1)) JOptionPane.showMessageDialog(null, "Route point '"+ tf.getText() +"' not exists!", "route canceled", JOptionPane.WARNING_MESSAGE); else t.connect(RBPrim.isSelected() ? alg.PRIM : alg.KRUSKAL, ch); } }); b.setFocusPainted(false); box.add(BRoute = b); j.add(box); j.add(jl); String tf_tmp; tf_tmp = j.getText(); j.setSelectionStart(0); j.setSelectionEnd(tf_tmp.length()); }; if (j.getText().length() == 0) j.setText(tf_tmp); else try { if (n < 2) { n = 2; j.setText(""+n); } else if (n > 50) { n = 50; j.setText(""+n); } TSPgraphics.ROUTE_POINTS = n; j.setText(tf_tmp); } } }); j.add(tf1); /*JRadioButton rb = new JRadioButton("Kruskal", true) { public void paintComponent(Graphics g) { super.paintComponent(g); if (this.isSelected()) setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); else setCursor(new Cursor(Cursor.HAND_CURSOR)); } }; gr.add(rb);*/ j.add(RBKruskal = new myRadio(f, "Kruskal", gr)); j.add(RBPrim = new myRadio(f, "Prim", gr)); CB_TSP.setFocusPainted(false); CB_TSP.setOpaque(false); f.setTitle((isSet ? "TSP " : "")+(RBPrim.isSelected() ? "PRIM" : "KRUSKAL")); BRoute.setText(isSet ? " TSP ROUTE " : " FIND MST "); BRoute.setToolTipText(" find "+(isSet ? "'travelling salesman problem' route " : "minimum spanning tree using "+(RBPrim.isSelected() ? "Prim's " : "Kruskal's ")+"algorithm ")); } }); j.add(CB_TSP); RBKruskal.doClick(); f.setSize(SIZ_X, SIZ_Y); f.setDefaultCloseOperation(EXIT_ON_CLOSE); f.setLocationRelativeTo(null); f.setVisible(true); t.roll(); } public static boolean TSPselected() { return CB_TSP.isSelected(); } super(n); setFocusPainted(false); setOpaque(false); //((JFrame) getParent().getParent().getParent().getParent().getParent()).setTitle(""); boolean isSet = TSPselected(); f.setTitle((isSet ? "TSP " : "")+getText().toUpperCase()); BRoute.setText(isSet ? " TSP ROUTE " : " FIND MST "); BRoute.setToolTipText(" find "+(isSet ? "'travelling salesman problem' route " : "minimum spanning tree using "+getText()+"'s algorithm ")); JL.setVisible(RBPrim.isSelected()); JTF.setVisible(RBPrim.isSelected()); } }); g.add(this); } super.paintComponent(g); if (this.isSelected()) else } } }
You need to login to post a comment.
