// // Prim.java // A simple java applet to display the prim algorithm. // import java.awt.*; import java.applet.*; import java.awt.event.*; import java.util.Vector; import java.util.Enumeration; import java.lang.Integer; class Edge { public int V1; public int V2; public int Weight; public int DrawStatus; String V1Prefix = "V1: "; String V2Prefix = " V2: "; String WeightPrefix = " C: "; String DrawStatusPrefix = " DrawStatus: "; public Edge(int x, int y, int z) { V1 = x; V2 = y; Weight = z; DrawStatus = 0; } public Edge(String ListString) { int V1Start = ListString.indexOf(V1Prefix) + V1Prefix.length(); int V1End = ListString.indexOf(V2Prefix); int V2Start = V1End + V2Prefix.length(); int V2End = ListString.indexOf(WeightPrefix); int WeightStart = V2End + WeightPrefix.length(); V1 = Integer.parseInt( ListString.substring(V1Start, V1End).trim() ); V2 = Integer.parseInt( ListString.substring(V2Start, V2End).trim() ); Weight = Integer.parseInt( ListString.substring(WeightStart, ListString.length()).trim() ); DrawStatus = 0; System.out.println("Made: " + toString()); } public boolean equals(Object o) { Edge other = (Edge) o; //System.out.println("Comparing: " + other.toString() + "\n With: " + this.toString()+"\n"); if ( ( other.V1 == V1 ) && ( other.V2 == V2 ) ) return true; return false; } public String toString() { return ("Edge From: " + V1 + " To: " + V2 + " Weight: " + Weight + " DrawStatus: " + DrawStatus); } public String toListString() { return(V1Prefix + V1 + V2Prefix + V2 + WeightPrefix + Weight); } } public class Prim extends Applet { //static final String message = "Hello World!"; private Font font = new Font("serif", Font.ITALIC + Font.BOLD, 36); private Button Start_Button; private Button Step_Button; private Button Show_Button; private Button Edit_Button; public TextField ProofText = new TextField(); final int PRIM_COMPLETE = 0; final int PRIM_READY = 1; final int PRIM_RUNNING = 2; final int CONSIDERED_STATE = 0; final int CHOSEN_STATE = 1; final int ORIGINAL = 0; final int CONSIDERED = 1; final int CHOSEN = 2; /* int sizeG = 9; //number of vertices int GEdges[][] = { {0,1,2}, {0,2,4}, {0,3,5}, {0,4,7}, {0,5,9}, {0,6,3}, {0,7,5}, {0,8,12}, {1,4,34}, {2,5,56}, {3,6,5}, {3,5,45}, {4,7,8}, {4,6,4}, {5,8,10}, {5,7,12}, {6,8,20} }; */ int sizeG = 6; int GEdges[][] = { {0,1,2}, {0,2,4}, {1,3,4}, {1,2,3}, {1,4,6}, {3,4,7}, {3,5,1}, {4,5,2} }; public Vector GTest = new Vector(GEdges.length + 1); /* int TEdges[][] = new int[sizeG-1][3]; //this has to hold for it to be a tree!!! :-) int G[][] = new int[sizeG][sizeG]; //allocate for adjacency matrix. int T[][] = new int[sizeG][sizeG]; //allocate for tree adjacency matrix. */ int GLocations[][]; int TLocations[][]; boolean unused_vertices[]; int unused_count; boolean DrawBoth = false; int PrimStatus = PRIM_READY; int RunningState = -1; private EditWindow EditFrame; public PrimFrame MainFrame; boolean[][] GraphSettings = { {true,false}, {true,false}, {true,true} }; public void init() { setLayout(new GridLayout(1,1)); Show_Button = new Button("Open Algorithm Window"); Show_Button.addActionListener(new MainButtonListener()); add(Show_Button); setGraphSize(sizeG); //populate GTest for(int x =0; x < GEdges.length; x++) GTest.addElement(new Edge(GEdges[x][0],GEdges[x][1],GEdges[x][2])); MainFrame = new PrimFrame("Prim's Algorithm"); InitPrim(); //must be after mainFrame is created. EditFrame = new EditWindow(this); EditFrame.hide(); /* //zero the adjacency matrix for G for(int y=0; y < sizeG; y++) for(int x=0; x < sizeG; x++) {G[x][y]=0;T[x][y]=0;} //printf("%i\n\n", sizeof(GEdges)/sizeof(int[3]) ); //fill adjacency matrix for(int x=0; x < GEdges.length; x++) { //printf("adding #%i:{%i,%i,%i}\n",x,GEdges[x][0],GEdges[x][1],GEdges[x][2]); G[ GEdges[x][0] ][ GEdges[x][1] ] = GEdges[x][2]; G[ GEdges[x][1] ][ GEdges[x][0] ] = GEdges[x][2]; } */ } void setGraphSize(int NewSize) { sizeG = NewSize; GLocations = new int[sizeG][2]; TLocations = new int[sizeG][2]; unused_vertices = new boolean[sizeG]; } void setPrimStatus(int NewStatus) { System.out.println("entering primstatus"); switch(NewStatus) { case PRIM_COMPLETE : Start_Button.setLabel("Reset the Algorithm"); Step_Button.setEnabled(false); PrimStatus = PRIM_COMPLETE; break; case PRIM_READY : System.out.println("primready"); Start_Button.setLabel("Run Prim's Algorithm"); Step_Button.setEnabled(true); PrimStatus = PRIM_READY; break; case PRIM_RUNNING : //Start_Button.setLable("Finish the Algorithm"); PrimStatus = PRIM_RUNNING; break; default: System.out.println("Error with setPrimStatus " + NewStatus); } } public void resizeGraph() { double degrees =2.0 * java.lang.Math.PI / (sizeG); //it uses radians!!! int width = MainFrame.getBounds().width - 40; int height = MainFrame.getBounds().height - 60; if (DrawBoth) width /= 2; int temp = java.lang.Math.min(width,height); double radius = temp/2 - 30; int initx = (int)radius + 25; int initx2 = initx + width; if (!DrawBoth) initx = width/2; int inity = (int)radius + 63; for (int x=0; x < sizeG; x++) { GLocations[x][0] = initx + (int)(radius * java.lang.Math.cos(x*degrees)); GLocations[x][1] = inity + (int)(radius * java.lang.Math.sin(x*degrees)); TLocations[x][0] = initx2 + (int)(radius * java.lang.Math.cos(x*degrees)); TLocations[x][1] = inity + (int)(radius * java.lang.Math.sin(x*degrees)); } MainFrame.repaint(); } private class PrimFrame extends Frame { public PrimFrame(String Title) { super(Title); addWindowListener(new MainWindowListener()); addComponentListener(new MainComponentListener()); Panel SouthPanel = new Panel(); SouthPanel.setLayout(new GridLayout(1,3)); setLayout (new BorderLayout()); add(SouthPanel, "South"); Start_Button = new Button("Run Prim's Algorithm"); SouthPanel.add(Start_Button,"South"); Start_Button.addActionListener(new MainButtonListener()); Step_Button = new Button("Step though Algorithm"); SouthPanel.add(Step_Button,"South"); Step_Button.addActionListener(new MainButtonListener()); Edit_Button = new Button("Edit the Graph"); SouthPanel.add(Edit_Button,"South"); Edit_Button.addActionListener(new MainButtonListener()); ProofText.setEditable(false); add(ProofText, "North"); setSize(new Dimension(640,480)); } public void paint (Graphics g) { System.out.println("Painting...\n"); g.setColor(Color.blue); g.setFont(font); //g.drawString("TEST",30,30); drawGraph(g, GLocations, GTest, 0); if (DrawBoth) drawGraph(g, TLocations, GTest, 1); } } public void start() { MainFrame.show(); } private void drawGraph(Graphics g, int VertexLocations[][],Vector Edges,int GraphNum) { g.setColor(Color.blue); if (VertexLocations[0][0]!=0){ Enumeration them = Edges.elements(); Edge temp; while (them.hasMoreElements()) { temp = (Edge)them.nextElement(); int x1 = VertexLocations[temp.V1][0], y1= VertexLocations[temp.V1][1]; int x2 = VertexLocations[temp.V2][0], y2= VertexLocations[temp.V2][1]; switch (temp.DrawStatus) { case ORIGINAL: if(GraphSettings[ORIGINAL][GraphNum]) drawEdgeWithWeight(g,x1,y1,x2,y2,temp.Weight, Color.blue); //System.out.println("Original " + GraphSettings[ORIGINAL][GraphNum] +" "+ ORIGINAL +" "+ GraphNum); break; case CONSIDERED: if(GraphSettings[CONSIDERED][GraphNum]) drawEdgeWithWeight(g,x1,y1,x2,y2,temp.Weight, Color.green); else if(GraphSettings[ORIGINAL][GraphNum]) drawEdgeWithWeight(g,x1,y1,x2,y2,temp.Weight, Color.blue); //System.out.println("Considered"); break; case CHOSEN: if(GraphSettings[CHOSEN][GraphNum]) drawEdgeWithWeight(g,x1,y1,x2,y2,temp.Weight, Color.orange); else if(GraphSettings[ORIGINAL][GraphNum]) drawEdgeWithWeight(g,x1,y1,x2,y2,temp.Weight, Color.blue); //System.out.println("Chosen"); break; default: System.out.println("ERROR, with drawgraph"); } } for(int x = 0; x < VertexLocations.length; x++) { g.setColor(Color.blue); g.drawString(""+ x, VertexLocations[x][0], VertexLocations[x][1]); if (!unused_vertices[x]) g.setColor(Color.orange); g.fillOval(VertexLocations[x][0]-4,VertexLocations[x][1]-4,8,8); //System.out.println("drawing " + x + " at " + VertexLocations[x][0] + "," + VertexLocations[x][1]); } } } private void drawEdgeWithWeight(Graphics g, int x1, int y1, int x2, int y2, int weight, Color c) { //System.out.println("in draw..."); g.setColor(c); g.drawLine(x1,y1,x2,y2); g.setColor(Color.red); g.drawString("" + weight, x2 + (x1-x2)/2, y2 + (y1-y2)/2); } /* private void drawGraph(Graphics g, int VertexLocations[][],int Edges[][]) { g.setColor(Color.blue); if (VertexLocations[0][0]!=0){ for(int x = 0; x < VertexLocations.length; x++) { g.drawString(""+ x, VertexLocations[x][0], VertexLocations[x][1]); //System.out.println("drawing " + x + " at " + VertexLocations[x][0] + "," + VertexLocations[x][1]); } if(Edges[Edges.length - 1][2]!=0)//if is it cleared... (this is a bad way to do it.) { for (int x = 0; x < Edges.length; x++) { if(Edges[x][2]!=0) //redundant??? { int x1 = VertexLocations[Edges[x][0]][0], y1= VertexLocations[Edges[x][0]][1]; int x2 = VertexLocations[Edges[x][1]][0], y2= VertexLocations[Edges[x][1]][1]; g.setColor(Color.blue); g.drawLine(x1,y1,x2,y2); g.setColor(Color.red); g.drawString(""+Edges[x][2], x2 + (x1-x2)/2, y2 + (y1-y2)/2); } } } else System.out.println("Not drawing edges...\n"); } } */ private class MainButtonListener implements ActionListener{ public MainButtonListener() {} public void actionPerformed(ActionEvent e) { if ( ( (Button)e.getSource() ).equals(Start_Button) ) { if (PrimStatus == PRIM_COMPLETE) { System.out.println("Resetting prim"); InitPrim(); MainFrame.repaint(); //needed? } //if(PrimStatus == PRIM_READY) else { System.out.println("running prim"); //pick some arbitrary vertex. int first_vertex = 0; //call prim's algorithm. Prim(first_vertex); MainFrame.repaint(); //needed? } } else if ( ( (Button)e.getSource() ).equals(Step_Button) ) { System.out.println("Hit Step button...\n"); if (PrimStatus != PRIM_RUNNING) { InitPrim(); Start_Button.setLabel("Finish the Algorithm"); } PrimStep(); MainFrame.repaint(); } else if ( ( (Button)e.getSource() ).equals(Show_Button) ) { MainFrame.show(); } else if ( ( (Button)e.getSource() ).equals(Edit_Button) ) { EditFrame.show(); } } } private class MainComponentListener implements ComponentListener { public void componentHidden(ComponentEvent e) {} public void componentMoved(ComponentEvent e) {} public void componentResized(ComponentEvent e) { System.out.println("Resize!!\n"); resizeGraph(); } public void componentShown(ComponentEvent e) { System.out.println("Shown!!\n"); resizeGraph(); } } private class MainWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { MainFrame.hide(); } } private void InitPrim() { unused_count = sizeG; //setting it /* for(int x=0; x < sizeG; x++) for(int y=0; y < sizeG; y++) Tree[x][y]=0; for(int x=0; x < TEdges.length; x++) TEdges[x][0]=TEdges[x][1]=TEdges[x][2]=0; */ Enumeration EnuTemp = GTest.elements(); while (EnuTemp.hasMoreElements()) ( (Edge)EnuTemp.nextElement() ).DrawStatus = ORIGINAL; //set all vertices unused. for(int y = 0; y < sizeG; y++) unused_vertices[y] = true; //System.out.println("Calculating lightest edges...\n"); ProofText.setText("Given a connected, weighted graph G, with n verticies."); setPrimStatus(PRIM_READY); } private void FindAdjacent (Vector TheEdges) // find all adjacent edges to new vertices { Enumeration Edges; Edges = TheEdges.elements(); while(Edges.hasMoreElements()) { Edge temp = (Edge) Edges.nextElement(); if ( ( !unused_vertices[temp.V1] || !unused_vertices[temp.V2] ) && !( !unused_vertices[temp.V1] && !unused_vertices[temp.V2] ) ) temp.DrawStatus = CONSIDERED; } Step_Button.setLabel("Find the Lightest Edge"); ProofText.setText("Choose the least weighted frontier edge e from this tree."); RunningState = CONSIDERED_STATE; } private void FindLightest (Vector TheEdges) // choose the lightest edge { Enumeration Edges; //set the lightest edge to nothing value Edge lightest_edge = new Edge(-1,-1,-1); Edges = TheEdges.elements(); while(Edges.hasMoreElements()) { Edge temp = (Edge) Edges.nextElement(); if (temp.DrawStatus == CONSIDERED) { System.out.println("Considering: " + temp.toString()); if ( (lightest_edge.Weight == -1) || (temp.Weight < lightest_edge.Weight) ) lightest_edge = temp; temp.DrawStatus = ORIGINAL; } } int tempindex = GTest.indexOf(lightest_edge); if (tempindex >= 0) ( (Edge) GTest.elementAt( tempindex ) ).DrawStatus = CHOSEN; else System.out.println("Error finding" + lightest_edge.V1 + " to " + lightest_edge.V2 + " weight: " + lightest_edge.Weight); unused_vertices[lightest_edge.V2] = unused_vertices[lightest_edge.V1] = false; unused_count--; Step_Button.setLabel("Find Adjacent Edges"); ProofText.setText("T = (T U {e}) remains a tree."); RunningState = CHOSEN_STATE; } private void PrimStep() { if (PrimStatus != PRIM_RUNNING) { //set the first vertex used. //System.out.println("Starting with vertex #" + vertex +"\n"); unused_vertices[0] = false; unused_count--; ProofText.setText("Choose some arbitrary vertex, v. Let T be a tree with E(T) empty and V(T) = {v}."); RunningState = CHOSEN_STATE; setPrimStatus(PRIM_RUNNING); } else { if (RunningState == CHOSEN_STATE) FindAdjacent(GTest); else FindLightest(GTest); } if (unused_count <= 0) setPrimStatus(PRIM_COMPLETE); } /* for(int x = 0; x < sizeG; x++) //go through all the used vertices {//open for x if (!unused_vertices[x]) {//open if for(int y = 0; y < sizeG; y++) //then go through all vertices adjacent {//open for y if (unused_vertices[y] && ((lightest_edge.Weight == -1) || (Graph[x][y] < lightest_edge.Weight)) && (Graph[x][y] > 0) ) { lightest_edge.V1 = x; lightest_edge.V2 = y; lightest_edge.Weight = Graph[y][x]; System.out.println("new lightest edge, from " + x + " to " + y + " weight: " + Graph[y][x]); } }//close for y }//close if }//close for x System.out.println("setting vertex #" + lightest_edge.V2 +" used\n"); //add the edge to the tree. Tree[lightest_edge.V1][lightest_edge.V2]=Tree[lightest_edge.V2][lightest_edge.V1]=lightest_edge.Weight; System.out.println("chosen edge, from " + lightest_edge.V1 + " to " + lightest_edge.V2 + " weight: " + lightest_edge.Weight); TEdges[unused_count][0] = lightest_edge.V1; TEdges[unused_count][1] = lightest_edge.V2; TEdges[unused_count][2] = lightest_edge.Weight; //java.lang.System.arraycopy(lightest_edge,0,TEdges[unused_count],0,lightest_edge.length); System.out.println("wrote edge #" + unused_count + ", from " + TEdges[unused_count][0] + " to " + TEdges[unused_count][1] + " weight: " + TEdges[unused_count][2] + "\n"); //delete lightestedge?? */ private void Prim(int vertex) {//open prim //if (PrimStatus != PRIM_RUNNING) InitPrim(); //pass more? while (unused_count > 0) //until we've used them all { PrimStep(); }//close while /* System.out.println("Adjacency of G:"); for(int x = 0; x < sizeG; x++) { for(int y = 0; y < sizeG; y++) { if (G[x][y] < 10) System.out.print(" " + G[x][y]); else System.out.print(" " + G[x][y]); } System.out.println("\n"); } System.out.println("Adjacency of T:"); for(int x = 0; x < sizeG; x++) { for(int y = 0; y < sizeG; y++) { if (T[x][y] < 10) System.out.print(" " + T[x][y]); else System.out.print(" " + T[x][y]); } System.out.println("\n"); } System.out.println("Edges of T:"); for(int x = 0; x < TEdges.length; x++) { for(int y = 0; y < 3; y++) { if (TEdges[x][y] < 10) System.out.print(" " + TEdges[x][y]); else System.out.print(" " + TEdges[x][y]); } System.out.println("\n"); } */ }//close prim public void tellToRepaint() { MainFrame.repaint(); } } class EditWindow extends Frame { Prim MainApp; Choice PopOne; Choice PopTwo; Button Add_Button; Button Delete_Button; TextField WeightField; List EdgeList; CheckboxGroup GraphNumber = new CheckboxGroup(); String SettingNames[] = {"Original","Considered","Final"}; boolean[][] CheckSettings; private class MyCheck extends Checkbox { int WhichGraph; int WhichSetting; public MyCheck(int x,int y,boolean b) { super("",b); WhichGraph=y; WhichSetting=x; enableEvents(java.awt.AWTEvent.ITEM_EVENT_MASK); } public void processItemEvent(ItemEvent e) { System.out.println("Processsing event!!!\n"); MyCheck temp; temp = (MyCheck)e.getSource(); System.out.println("setting: " + temp.WhichSetting + " " + temp.WhichGraph + " to " + temp.getState()); MainApp.GraphSettings[temp.WhichSetting][temp.WhichGraph] = temp.getState(); MainApp.tellToRepaint(); } } public EditWindow(Prim theApp) { super("Edit Graph"); setSize(new Dimension(320,240)); setResizable(false); MainApp = theApp; CheckSettings = MainApp.GraphSettings; addWindowListener(new MainWindowListener()); setLayout (new BorderLayout()); EdgeList = new List(10,false); add(EdgeList,"West"); EdgeList.addItemListener(new MainItemListener()); Panel SettingsPanel = new Panel(); SettingsPanel.setLayout(new GridLayout(4,3)); Checkbox temp; SettingsPanel.add(new Label("")); temp = new Checkbox("1", GraphNumber,true); temp.addItemListener(new MainItemListener()); SettingsPanel.add(temp); temp = new Checkbox("2", GraphNumber,false); temp.addItemListener(new MainItemListener()); SettingsPanel.add(temp); for(int x=0; x<3;x++) { SettingsPanel.add(new Label(SettingNames[x])); for(int y=0;y<2;y++) SettingsPanel.add(new MyCheck(x,y,CheckSettings[x][y])); } add(SettingsPanel, "East"); Panel SouthPanel = new Panel(); SouthPanel.setLayout(new GridLayout(2,3)); PopOne = new Choice(); for(int x = 0; x < MainApp.sizeG; x++) PopOne.addItem(""+x); SouthPanel.add(PopOne); PopOne.addItemListener(new MainItemListener()); PopTwo = new Choice(); for(int x = 0; x < MainApp.sizeG; x++) PopTwo.addItem(""+x); SouthPanel.add(PopTwo); //PopTwo.addItemListener(new MainItemListener()); WeightField = new TextField(2); SouthPanel.add(WeightField); Add_Button = new Button("Add"); SouthPanel.add(Add_Button); Add_Button.addActionListener(new MainButtonListener()); Delete_Button = new Button("Delete"); SouthPanel.add(Delete_Button); Delete_Button.addActionListener(new MainButtonListener()); add(SouthPanel, "South"); generateList(MainApp.GTest); } public void generateList(Vector EdgeVector) { EdgeList.removeAll(); Enumeration Edges = EdgeVector.elements(); while (Edges.hasMoreElements()) { Edge temp = (Edge) Edges.nextElement(); EdgeList.addItem(temp.toListString()); } } private class MainWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { hide(); } public void windowOpened(WindowEvent e) { generateList(MainApp.GTest); } } private class MainItemListener implements ItemListener { public void itemStateChanged(ItemEvent e) { Class x = e.getClass(),y = e.getClass(), z = e.getClass(); try{ x = java.lang.Class.forName("java.awt.List"); y = java.lang.Class.forName("java.awt.Checkbox"); z = java.lang.Class.forName("java.awt.Choice"); } catch (Exception ex){System.out.println("VERY BAD. COULDN'T FIND CLASS.");} if (e.getSource().getClass() == x) { switch (e.getStateChange()) { case ItemEvent.DESELECTED: Delete_Button.setEnabled(false); break; case ItemEvent.SELECTED: Delete_Button.setEnabled(true); break; default: } } else if (e.getSource().getClass() == y) { int WhichNumber = Integer.parseInt( ( (Checkbox)e.getSource() ).getLabel() ); if (WhichNumber == 2) { MainApp.DrawBoth = true; MainApp.resizeGraph(); } else if (WhichNumber == 1) { MainApp.DrawBoth = false; MainApp.resizeGraph(); } } else if (e.getSource().getClass() == z) { //int WhichNumber = Integer.parseInt( ( (Choice)e.getSource() ).getLabel() ); //careful... int WhichVertex = ( (Choice)e.getSource() ).getSelectedIndex(); //generate the PopTwo } } } private class MainButtonListener implements ActionListener { public void actionPerformed(ActionEvent e) { if ( ( (Button)e.getSource() ).equals(Add_Button) ) { //no checking... just do it. Edge temp = new Edge( PopOne.getSelectedIndex(), PopTwo.getSelectedIndex(), Integer.parseInt( WeightField.getText() ) ); MainApp.GTest.add(temp); EdgeList.add(temp.toListString()); MainApp.tellToRepaint(); } else if ( ( (Button)e.getSource() ).equals(Delete_Button) ) { //safe way, find it , not just by index. MainApp.GTest.remove( new Edge( EdgeList.getSelectedItem() ) ); EdgeList.remove(EdgeList.getSelectedIndex()); MainApp.tellToRepaint(); } } } }