├── g5 ├── bin ├── apps │ └── Friends.class ├── Structures │ ├── Graph.class │ ├── Graph$Edge.class │ ├── Graph$Friend.class │ └── Graph$Person.class └── structures │ ├── Graph.class │ ├── Graph$Friend.class │ └── Graph$Person.class ├── g4 ├── g3 ├── todo.txt ├── .classpath ├── g2 ├── README.md ├── .project ├── g1 ├── .settings └── org.eclipse.jdt.core.prefs ├── src ├── apps │ └── Friends.java ├── Structures │ └── Graph.java └── structures │ └── Graph.java └── prog4.html /g5: -------------------------------------------------------------------------------- 1 | 3 2 | a|n 3 | b|n 4 | c|n 5 | a|b 6 | b|c -------------------------------------------------------------------------------- /bin/apps/Friends.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/apps/Friends.class -------------------------------------------------------------------------------- /bin/Structures/Graph.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/Structures/Graph.class -------------------------------------------------------------------------------- /bin/structures/Graph.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/structures/Graph.class -------------------------------------------------------------------------------- /bin/Structures/Graph$Edge.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/Structures/Graph$Edge.class -------------------------------------------------------------------------------- /bin/Structures/Graph$Friend.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/Structures/Graph$Friend.class -------------------------------------------------------------------------------- /bin/Structures/Graph$Person.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/Structures/Graph$Person.class -------------------------------------------------------------------------------- /bin/structures/Graph$Friend.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/structures/Graph$Friend.class -------------------------------------------------------------------------------- /bin/structures/Graph$Person.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/i/friendship/master/bin/structures/Graph$Person.class -------------------------------------------------------------------------------- /g4: -------------------------------------------------------------------------------- 1 | 6 2 | D|n 3 | B|n 4 | C|n 5 | A|n 6 | E|n 7 | F|n 8 | A|b 9 | B|c 10 | B|e 11 | C|d 12 | E|d 13 | D|f 14 | -------------------------------------------------------------------------------- /g3: -------------------------------------------------------------------------------- 1 | 14 2 | a|n 3 | b|n 4 | c|n 5 | d|n 6 | e|n 7 | f|n 8 | g|n 9 | h|n 10 | i|n 11 | j|n 12 | k|n 13 | l|n 14 | m|n 15 | q|n 16 | a|b 17 | b|c 18 | c|d 19 | d|e 20 | a|g 21 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | todo: 2 | shortest path (liz) 3 | connected islands (cliques) started? 4 | connectors 70% done 5 | fix atschool 6 | 7 | completed: 8 | interface 9 | build 10 | subgraph 11 | 12 | **efficiency** 13 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /g2: -------------------------------------------------------------------------------- 1 | 23 2 | q|n 3 | w|n 4 | e|n 5 | r|n 6 | t|n 7 | y|n 8 | u|n 9 | i|n 10 | o|n 11 | p|y|la 12 | a|y|la 13 | s|y|la 14 | d|y|la 15 | f|y|la 16 | g|y|la 17 | h|y|la 18 | j|y|la 19 | k|y|la 20 | l|y|la 21 | z|y|la 22 | x|y|la 23 | c|y|la 24 | b|y|la 25 | q|w 26 | w|e 27 | e|r 28 | r|t 29 | t|y 30 | y|h 31 | h|g 32 | g|b 33 | g|f 34 | f|d 35 | d|e -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CS112 Data Structures Project 2 | Fall 2012 3 | Ian Lozinski / Elizabeth Gao 4 | ================================== 5 | Creates a graph from a given input file of friends and schools and performs the following operations: 6 | shortest path of friends between two people 7 | calculates cliques 8 | determines who the connectors are 9 | creates new graph of all people at a particular school 10 | prints graph 11 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Friendship 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /g1: -------------------------------------------------------------------------------- 1 | 15 2 | jane|y|rutgers 3 | sam|y|rutgers 4 | michele|y|cornell 5 | sergei|y|rutgers 6 | ricardo|y|penn state 7 | kaitlin|y|rutgers 8 | samir|n 9 | aparna|y|rutgers 10 | ming|y|penn state 11 | nick|y|penn state 12 | bob|y|rutgers 13 | heather|y|penn state 14 | rachel|n 15 | rich|y|ucla 16 | tom|y|ucla 17 | sam|jane 18 | jane|bob 19 | jane|kaitlin 20 | kaitlin|nick 21 | bob|samir 22 | sergei|aparna 23 | samir|aparna 24 | aparna|ricardo 25 | nick|ricardo 26 | ming|nick 27 | heather|nick 28 | michele|rachel 29 | michele|tom 30 | tom|rich -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.6 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.6 12 | -------------------------------------------------------------------------------- /src/apps/Friends.java: -------------------------------------------------------------------------------- 1 | //Ian Lozinski 2 | //Elizabeth Gao 3 | 4 | package apps; 5 | import java.io.File; 6 | import java.io.FileNotFoundException; 7 | import java.util.ArrayList; 8 | import java.util.Scanner; 9 | 10 | import structures.Graph; 11 | 12 | 13 | 14 | public class Friends { 15 | 16 | 17 | static Scanner userin = new Scanner(System.in); 18 | 19 | static char getOption() { 20 | System.out.print("Choose action: \n"); 21 | System.out.print("\t1) Students at school\n"); 22 | System.out.print("\t2) Shortest intro chain\n"); 23 | System.out.print("\t3) Cliques at school\n"); 24 | System.out.print("\t4) Connectors\n"); 25 | System.out.print("\tq) Quit\n"); 26 | char response = userin.nextLine().toLowerCase().charAt(0); 27 | while (response != '1' && response != '2' && response != '3' && response != '4' && response != 'q') { 28 | System.out.print("\tYou must enter one of 1, 2, 3, 4, 5, or q! "); 29 | response = userin.nextLine().toLowerCase().charAt(0); 30 | } 31 | return response; 32 | } 33 | 34 | /** 35 | * @param args 36 | * @throws FileNotFoundException 37 | */ 38 | public static void main(String[] args) throws FileNotFoundException { 39 | // TODO Auto-generated method stub 40 | System.out.println("Enter graph file name: "); 41 | String graphFile = userin.nextLine(); 42 | Graph graph; 43 | try{ 44 | graph = new Graph(new Scanner(new File(graphFile))); 45 | 46 | char option; 47 | while((option = getOption()) != 'q'){ 48 | if(option == '1'){ 49 | System.out.println("Enter school name: "); 50 | Graph school = graph.atSchool(userin.nextLine().toLowerCase()); 51 | school.printGraph(); 52 | } 53 | else if(option == '2'){ 54 | System.out.println("Enter name of person:"); 55 | String sName = userin.nextLine().toLowerCase(); 56 | System.out.println("Enter name of person they want to meet:"); 57 | String eName = userin.nextLine().toLowerCase(); 58 | graph.shortestChain(sName, eName); 59 | } 60 | else if(option == '3'){ 61 | System.out.println("Enter school name: "); 62 | Graph subgraph = graph.atSchool(userin.nextLine().toLowerCase()); 63 | ArrayList cliques = subgraph.cliques(); 64 | for(int k = 1; k < cliques.size()+1; k++){ 65 | System.out.println("Clique " + k + ":"); 66 | cliques.get(k-1).printGraph(); 67 | } 68 | } 69 | else if(option == '4'){ 70 | graph.connectors(); 71 | // do connectors 72 | } 73 | } 74 | }catch(Exception FileNotFoundException){ 75 | System.err.println("Not valid file! Closing program!"); 76 | 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Structures/Graph.java: -------------------------------------------------------------------------------- 1 | //Ian Lozinski 2 | //Elizabeth Gao 3 | 4 | package Structures; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Hashtable; 8 | import java.util.Scanner; 9 | import java.util.Stack; 10 | 11 | import Structures.Graph.Friend; 12 | 13 | public class Graph { 14 | 15 | int size; //number of vertices 16 | ArrayList people; 17 | Hashtable hash; 18 | int dfscount; 19 | int sccount; 20 | String schoolname; 21 | 22 | 23 | public Graph(Scanner sc) { 24 | this.size = Integer.parseInt(sc.nextLine().trim()); 25 | this.people = new ArrayList(this.size); 26 | this.hash = new Hashtable(this.size); 27 | this.dfscount = 1; 28 | this.sccount = 1; 29 | this.schoolname = null; 30 | 31 | //Creates vertex for each student and fills 'people' array 32 | for(int i=0; i people){ 60 | this.dfscount = 1; 61 | this.sccount = 1; 62 | this.size = people.size(); 63 | this.people = people; 64 | try{ 65 | this.schoolname = people.get(0).school; 66 | }catch (Exception indexOutOfBoundsException){ 67 | System.out.println("Invalid school name!"); 68 | return; 69 | } 70 | this.hash = new Hashtable(this.size); 71 | for(int i = 0; i < people.size(); i++) { 72 | this.hash.put(people.get(i).name, i); 73 | } 74 | this.dfscount = 1; 75 | for(int i = 0; i students = new ArrayList(); 148 | 149 | for (int i = 0; i < people.size(); i++){ 150 | Person p = people.get(i); 151 | if(p.school != null && p.school.equals(schoolName)){ 152 | students.add(new Person(p.name, schoolName, p.friends)); 153 | } 154 | } 155 | Graph subgraph = new Graph(students); 156 | return subgraph; 157 | } 158 | 159 | /** 160 | * Finds the shortest path between two people. 161 | * Prints the sequence of names. 162 | * Greedy Algorithm maybe? 163 | */ 164 | public void shortestChain(String sname, String ename){ 165 | if(indexForName(sname) == -1 || indexForName(ename) == -1){ 166 | System.out.println("invalid name!"); 167 | return; 168 | } 169 | Stack chain = new Stack(); 170 | int snum = indexForName(sname); 171 | Person start = people.get(snum); 172 | Person end = people.get(indexForName(ename)); 173 | boolean[] visited = new boolean[size]; 174 | 175 | people.get(indexForName(sname)).scnum = 0; 176 | scdfs(indexForName(sname), visited); 177 | if(end.scnum == -1){ 178 | System.out.println("They can NEVER be friends!!!"); 179 | return; 180 | } 181 | Person ptr = end; 182 | while(ptr.scnum != 0){ 183 | chain.push(ptr.name); 184 | Friend t = ptr.friends; 185 | int min = ptr.scnum; 186 | while(t != null){ 187 | if(people.get(t.index).scnum < min){ 188 | ptr = people.get(t.index); 189 | break; 190 | } 191 | t = t.next; 192 | } 193 | } 194 | chain.push(start.name); 195 | String ret = ""; 196 | while(chain.size() > 1){ 197 | ret = ret + chain.pop() + ", "; 198 | } 199 | ret = "Shortest path: " + ret + chain.pop() + "."; 200 | System.out.println(ret); 201 | 202 | //resets scnumbers 203 | for(int i = 0; i < people.size(); i++){ 204 | people.get(i).scnum = -1; 205 | } 206 | } 207 | private void scdfs(int v, boolean[] visited){ 208 | visited[v] = true; 209 | for (Friend e = people.get(v).friends; e != null; e=e.next){ 210 | if(!visited[e.index]){ 211 | people.get(e.index).scnum = sccount; 212 | sccount++; 213 | scdfs(e.index, visited); 214 | sccount--; 215 | people.get(v).scnum = Math.min(people.get(v).scnum, people.get(e.index).scnum + 1); 216 | } 217 | else{//already visited 218 | people.get(v).scnum = Math.min(people.get(e.index).scnum + 1, people.get(v).scnum); 219 | } 220 | } 221 | } 222 | 223 | /** 224 | * Prints a textual representation of the graph 225 | */ 226 | public void printGraph(){ 227 | System.out.println(people.size()); 228 | for(int v = 0; v < people.size(); v++){ 229 | if(people.get(v).school != null){ 230 | System.out.println(people.get(v).name + "|y|" + people.get(v).school); 231 | } 232 | else{ 233 | System.out.println(people.get(v).name + "|n"); 234 | } 235 | } 236 | for(int v = 0; v < people.size(); v++){ 237 | Friend ptr = people.get(v).friends; 238 | while(ptr != null){ 239 | if(v < ptr.index){ 240 | System.out.println(people.get(v).name + "|" + nameForIndex(ptr.index)); 241 | } 242 | ptr = ptr.next; 243 | } 244 | 245 | } 246 | } 247 | 248 | /** 249 | * finds cliques (separate groups) at a particular school. 250 | * prints the subgraphs in format of input file. 251 | */ 252 | public ArrayList cliques(){ 253 | ArrayList cliqueslist = new ArrayList(); 254 | boolean[] visited = new boolean[size]; 255 | boolean[] vtemp = new boolean[size]; 256 | 257 | for(int i=0; i clique = new ArrayList(); 259 | if (!visited[i]){ 260 | System.out.println("Starting on new clique"); 261 | cliquedfs(vtemp, i, visited); 262 | for(int j=0; j= 0; n--){ 301 | if(people.get(n).back == 1 && n != 0){ 302 | min++; 303 | if(min >= 2){knex[0] = true;} 304 | } 305 | } 306 | System.out.print("Connectors:"); 307 | String s = ""; 308 | for(int i=0; i people.get(w.index).back) { 331 | people.get(v).back = Math.min(people.get(v).back , people.get(w.index).back); 332 | } 333 | if(people.get(v).dfsnum <= people.get(w.index).back && v != 0){ 334 | knex[v]=true; 335 | } 336 | } 337 | else{//w is already visited 338 | people.get(v).back = Math.min(people.get(v).back, people.get(w.index).dfsnum); 339 | //System.out.println(people.get(w.index).name + " " + people.get(w.index).dfsnum + "/" + people.get(w.index).back); 340 | } 341 | } 342 | 343 | } 344 | 345 | } 346 | -------------------------------------------------------------------------------- /src/structures/Graph.java: -------------------------------------------------------------------------------- 1 | //Ian Lozinski 2 | //Elizabeth Gao 3 | 4 | package structures; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Hashtable; 8 | import java.util.Scanner; 9 | import java.util.Stack; 10 | 11 | import structures.Graph.Friend; 12 | 13 | 14 | public class Graph { 15 | 16 | int size; //number of vertices 17 | ArrayList people; 18 | Hashtable hash; 19 | int dfscount; 20 | int sccount; 21 | String schoolname; 22 | 23 | 24 | public Graph(Scanner sc) { 25 | this.size = Integer.parseInt(sc.nextLine().trim()); 26 | this.people = new ArrayList(this.size); 27 | this.hash = new Hashtable(this.size); 28 | this.dfscount = 1; 29 | this.sccount = 1; 30 | this.schoolname = null; 31 | 32 | //Creates vertex for each student and fills 'people' array 33 | for(int i=0; i people){ 61 | this.dfscount = 1; 62 | this.sccount = 1; 63 | this.size = people.size(); 64 | this.hash = new Hashtable(this.size); 65 | this.people = people; 66 | try{ 67 | this.schoolname = people.get(0).school; 68 | }catch (Exception indexOutOfBoundsException){ 69 | System.out.println("Invalid school name!"); 70 | return; 71 | } 72 | 73 | for(int i = 0; i < people.size(); i++) { 74 | this.hash.put(people.get(i).name, i); 75 | } 76 | for(int i = 0; i students = new ArrayList(); 150 | 151 | for (int i = 0; i < people.size(); i++){ 152 | Person p = people.get(i); 153 | if(p.school != null && p.school.equals(schoolName)){ 154 | Friend newfriends = null; 155 | Friend temp = p.friends; 156 | while(temp != null){ 157 | if(temp.school != null && temp.school.equals(schoolName)){ 158 | newfriends = new Friend(temp.index, newfriends); 159 | } 160 | temp = temp.next; 161 | } 162 | students.add(new Person(p.name, schoolName, newfriends)); 163 | } 164 | } 165 | Graph subgraph = new Graph(students); 166 | return subgraph; 167 | } 168 | 169 | /** 170 | * Finds the shortest path between two people. 171 | * Prints the sequence of names. 172 | * Greedy Algorithm maybe? 173 | */ 174 | public void shortestChain(String sname, String ename){ 175 | if(indexForName(sname) == -1 || indexForName(ename) == -1){ 176 | System.out.println("invalid name!"); 177 | return; 178 | } 179 | Stack chain = new Stack(); 180 | int snum = indexForName(sname); 181 | Person start = people.get(snum); 182 | Person end = people.get(indexForName(ename)); 183 | boolean[] visited = new boolean[size]; 184 | 185 | people.get(indexForName(sname)).scnum = 0; 186 | scdfs(indexForName(sname), visited); 187 | if(end.scnum == -1){ 188 | System.out.println("They can NEVER be friends!!!"); 189 | return; 190 | } 191 | Person ptr = end; 192 | while(ptr.scnum != 0){ 193 | chain.push(ptr.name); 194 | Friend t = ptr.friends; 195 | int min = ptr.scnum; 196 | while(t != null){ 197 | if(people.get(t.index).scnum < min){ 198 | ptr = people.get(t.index); 199 | break; 200 | } 201 | t = t.next; 202 | } 203 | } 204 | chain.push(start.name); 205 | String ret = ""; 206 | while(chain.size() > 1){ 207 | ret = ret + chain.pop() + ", "; 208 | } 209 | ret = "Shortest path: " + ret + chain.pop() + "."; 210 | System.out.println(ret); 211 | 212 | //resets scnumbers 213 | for(int i = 0; i < people.size(); i++){ 214 | people.get(i).scnum = -1; 215 | } 216 | } 217 | private void scdfs(int v, boolean[] visited){ 218 | visited[v] = true; 219 | for (Friend e = people.get(v).friends; e != null; e=e.next){ 220 | if(!visited[e.index]){ 221 | people.get(e.index).scnum = sccount; 222 | sccount++; 223 | scdfs(e.index, visited); 224 | sccount--; 225 | people.get(v).scnum = Math.min(people.get(v).scnum, people.get(e.index).scnum + 1); 226 | } 227 | else{//already visited 228 | people.get(v).scnum = Math.min(people.get(e.index).scnum + 1, people.get(v).scnum); 229 | } 230 | } 231 | } 232 | 233 | /** 234 | * Prints a textual representation of the graph 235 | */ 236 | public void printGraph(){ 237 | if(size == 0){ 238 | System.out.println("Empty graph."); 239 | return; 240 | } 241 | System.out.println(size); 242 | for(int v = 0; v < size; v++){ 243 | if(people.get(v).school != null){ 244 | System.out.println(people.get(v).name + "|y|" + people.get(v).school); 245 | } 246 | else{ 247 | System.out.println(people.get(v).name + "|n"); 248 | } 249 | } 250 | for(int v = 0; v < size; v++){ 251 | Friend ptr = people.get(v).friends; 252 | while(ptr != null){ 253 | if(v < ptr.index){ 254 | System.out.println(people.get(v).name + "|" + nameForIndex(ptr.index)); 255 | } 256 | ptr = ptr.next; 257 | } 258 | } 259 | } 260 | 261 | /** 262 | * finds cliques (separate groups) at a particular school. 263 | * prints the subgraphs in format of input file. 264 | */ 265 | public ArrayList cliques(){ 266 | ArrayList cliqueslist = new ArrayList(); 267 | boolean[] visited = new boolean[size]; 268 | boolean[] vtemp = new boolean[size]; 269 | 270 | for(int i=0; i clique = new ArrayList(); 272 | if (!visited[i]){ 273 | System.out.println("Starting on new clique"); 274 | cliquedfs(vtemp, i, visited); 275 | for(int j=0; j= 0; n--){ 314 | if(people.get(n).back == 1 && n != 0){ 315 | min++; 316 | if(min >= 2){knex[0] = true;} 317 | } 318 | } 319 | System.out.print("Connectors:"); 320 | String s = ""; 321 | for(int i=0; i people.get(w.index).back) { 344 | people.get(v).back = Math.min(people.get(v).back , people.get(w.index).back); 345 | } 346 | if(people.get(v).dfsnum <= people.get(w.index).back && v != 0){ 347 | knex[v]=true; 348 | } 349 | } 350 | else{//w is already visited 351 | people.get(v).back = Math.min(people.get(v).back, people.get(w.index).dfsnum); 352 | //System.out.println(people.get(w.index).name + " " + people.get(w.index).dfsnum + "/" + people.get(w.index).back); 353 | } 354 | } 355 | 356 | } 357 | 358 | } 359 | -------------------------------------------------------------------------------- /prog4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CS112 Fall 2012 - Friendship Graph Algorithms 5 | 18 | 19 |
20 |

CS112 Fall 2012: Programming Assignment 4

21 |

Friendship Graph Algorithms

22 |

Posted Tue, Nov 27. Due Fri, Dec 7, 11:00 PM 23 |

Worth 100 points = 10% of your course grade

24 |
25 |
26 |

In this assignment, you will implement some useful algorithms that apply 27 | to friendship graphs of the Facebook kind. 28 | 29 |

You will work on this assignment in PAIRS. 30 | INDIVIDUAL SUBMISSIONS WILL NOT BE ACCEPTED. 31 | 32 |

Read 33 | DCS Academic Integrity Policy for Programming Assignments - you are responsible for abiding 34 | by the policy. In particular, note that "All Violations of the Academic Integrity Policy will 35 | be reported by the instructor to the appropriate Dean". (For this assignment, each 36 | pair of partners must write its own code.) 37 | 38 |

There will NOT be an extension pass option for this assignment. 39 | 40 |


41 | 42 | 48 | 49 |


50 |

Background

51 | 52 |

In this program, you will implement some useful algorithms for 53 | graphs that represent friendships, such as Facebook. A friendship graph 54 | is an undirected graph without any weights on the edges. It is a simple 55 | graph because there are no self loops (a self loop is an edge from a vertex to 56 | itself), or multiple edges (a multiple edge means more than edge between a 57 | pair of vertices). 58 | 59 |

The vertices in the graphs for this assignment represent two kinds of people: 60 | students and non-students. Each vertex will store the name of the person. 61 | If the person is a student, the name of the school will also be stored. 62 | 63 |

Here's a sample friendship graph: 64 |

     (sam,rutgers)---(jane,rutgers)-----(bob,rutgers)   (sergei,rutgers)
 65 |                           |                 |             |
 66 |                           |                 |             |
 67 |                      (kaitlin,rutgers)   (samir)----(aparna,rutgers)
 68 |                           |                            |
 69 |                           |                            |
 70 |   (ming,penn state)----(nick,penn state)----(ricardo,penn state)
 71 |                           |
 72 |                           |
 73 |                      (heather,penn state)
 74 | 
 75 | 
 76 |                    (michele,cornell)----(rachel)     
 77 |                           | 
 78 |                           | 
 79 |      (rich,ucla)---(tom,ucla)
 80 | 
81 | Note that the graph may not be connected, as seen in this example in which there 82 | are two "islands" or cliques that are not connected to each other by any edge. 83 | Also see that all the vertices represent students with names of schools, except for 84 | rachel and samir, who are not students. 85 | 86 |


87 |

Algorithms

88 | 89 |
    90 |
  1. 91 |

    Subgraph: Students at a school

    92 | 93 |

    You want to be able to focus exclusively on students in a particular school, and 94 | all the friendships between them. To do this, you will have to extract an 95 | appropriate subgraph out of the full graph. Here is the subgraph of students at 96 | rutgers, extracted from the original sample graph: 97 | 98 |

         (sam,rutgers)---(jane,rutgers)-----(bob,rutgers)    (sergei,rutgers)
     99 |                           |                                |
    100 |                           |                                |
    101 |                      (kaitlin,rutgers)             (aparna,rutgers)
    102 | 
    103 | 104 |
  2. Shortest path: Intro Chain

    105 | 106 |

    sam wants an intro to aparna through friends and friends 107 | of friends. There are two possible chains of intros: 108 |

      sam--jane--kaitlin--nick--ricardo--aparna
    109 |             or
    110 |   sam--jane-bob--samir--aparna
    111 | 
    112 | The second chain is preferable since it is shorter. 113 | 114 |

    If sam wants to be introduced to michele through a chain of 115 | friends, he is out of luck since there is no chain that leads from sam to 116 | michele in the graph. 117 | 118 |

    Note that this algorithm does NOT have any restriction on the composition of the 119 | vertices: a vertex along the shortest chain need NOT be a student at a particular 120 | school, or even a student. So, for instance, you may have to find the shortest intro 121 | chain from nick to samir, which has the following solution: 122 |

       nick--ricardo--aparana--samir
    123 | 
    124 | which consists of two penn state students, one rutgers student, and one non-student. 125 | 126 |
  3. Connected Islands: Cliques

    127 | 128 |

    Students tend to form cliques with their friends, which creates 129 | islands that do not connect with each other. If these cliques could be identified, 130 | particularly in the student population at a particular school, 131 | introductions could be made between people in different cliques to build larger 132 | networks of friendships at that school. 133 | 134 |

    In the sample graph, there are two island cliques for students at rutgers: 135 |

         (sam,rutgers)---(jane,rutgers)-----(bob,rutgers)    (sergei,rutgers)
    136 |                           |                                |
    137 |                           |                                |
    138 |                      (kaitlin,rutgers)             (aparna,rutgers)
    139 | 
    140 | 141 |

    If we were to look at students at penn state, instead, there is a single clique: 142 |

       (ming,penn state)----(nick,penn state)----(ricardo,penn state)
    143 |                           |
    144 |                           |
    145 |                      (heather,penn state)
    146 | 
    147 |

    And again, a single clique for students at ucla: 148 |

         (rich,ucla)---(tom,ucla)
    149 | 
    150 |

    And one for students at cornell: 151 |

                 (michele,cornell)
    152 | 
    153 |

    From these examples, it should be clear that if there is at least one student 154 | in the graph that goes to a particular school, then there must be at least one 155 | island clique in the graph for students at that school. 156 | 157 |

  4. Connectors: Friends who keep friends together

    158 | 159 |

    If jane were to leave rutgers, sam would no longer be able to 160 | connect with anyone else--jane was the "connector" who could pull 161 | sam in to hang out with her other friends. Similarly, aparna 162 | is a connector, since without her, sergei would not be able to 163 | "reach" anyone else. (And there are more connectors in the graph...) 164 | 165 |

    On the other hand samir is not a connector. Even if he were to leave, 166 | everyone else could still "reach" whoever they could when samir was there, 167 | even though they may have to go through a longer chain. 168 | 169 |

    A precise definition of a connector in any undirected graph is a vertex, v, 170 | such that there are at least two other vertices x and w for which every path 171 | between x and w goes through v. For example, v=jane, 172 | x=sam, and w=bob. 173 | 174 |

    Finding all connectors in an undirected graph can be done using DFS (depth-first search), 175 | but keeping track of a couple more numbers for every vertex v. These are: 176 |

      177 |
    • dfsnum(v): This is the dfs number, assigned when a vertex is visited, dealt out 178 | in increasing order. 179 |
    • back(v): This is a number that is initially assigned when a vertex is 180 | visited, and is equal to dfsnum, but can be changed later based on three conditions: 181 |
        182 |
      • When the DFS backs up from a neighbor, w, to v, 183 | if dfsnum(v) > 184 | back(w), then back(v) is set to min(back(v),back(w)) 185 |
      • If a neighbor, w, is already visited then 186 | back(v) is set to min(back(v),dfsnum(w)) 187 |
      188 |
    189 |

    When the DFS backs up from a neighbor, w, to v, 190 | if dfsnum(v)back(w), then v is identified as 191 | a connector, IF v is NOT the starting point 192 | for the DFS. 193 | (If v is a starting point for DFS, it can be a connector, but 194 | another check must be made - see the examples below. The examples don't tell 195 | you how to identify such cases, that's up to you.) 196 | 197 |

    Here are some examples that show how this works. 198 | 199 |

      200 |
    • Example 1: (B is a connector) 201 |
          A--B--C
      202 | 
      203 | The DFS starts at A. Neighbors for a vertex are stored in REVERSE alphabetical order: 204 |
        
      205 |   A: B
      206 |   B: C,A
      207 |   C: B
      208 | 
      209 |   dfs @ A  1/1  (dfsnum/back)
      210 |       dfs @ B 2/2
      211 |           dfs @ C 3/3
      212 |               neighbor B is already visited => C 3/2
      213 |           dfsnum(B) <= back(C) B is a CONNECTOR
      214 |           nbr A is already visited => B 2/1
      215 |       dfsnum(A) <= back(B) A is starting point of DFS, NOT connector
      216 | 
      217 | 218 |

    • Example 2: (B is a connector) 219 |
         A--B--C
      220 | 
      221 | The same example as the first, except DFS starts at B. This shows how even thought B is 222 | the starting point, it is still identified (correctly) as a connector. The code is 223 | not complete because it does not show HOW B is determined to be a connector 224 | in the last line - that's for you to figure out. Neighbors are 225 | stored in reverse alphabetical order as before. 226 |
        dfs @ B  1/1 
      227 |       dfs @ C 2/2
      228 |           nbr B is already visited => C 2/1
      229 |       dfsnum(B) <= back(C) B is starting point, NOT connector
      230 |       dfs @ A 3/3
      231 |           nbr B is already visited => A 3/1
      232 |       dfsnum(B) <= back(A) B is starting point, but is a CONNECTOR
      233 | 
      234 | 235 |

    • Example 3: (B and D are connectors) 236 |
          A---B---C
      237 |         |   |
      238 |         E---D---F
      239 | 
      240 |

      DFS starts at A. Neighbors stored in reverse alphabetical order again: 241 |

        A: B
      242 |   B: E,C,A
      243 |   C: D,B
      244 |   D: F,E,C
      245 |   E: D,B
      246 |   F: D
      247 | 
      248 |   dfs @ A 1/1
      249 |       dfs @ B 2/2
      250 |           dfs @ E 3/3
      251 |               dfs @ D 4/4
      252 |                   dfs @ F 5/5
      253 |                       nbr D is already visited => F 5/4
      254 |                   dfsnum(D) <= back(F) => D is a CONNECTOR
      255 |                   nbr E already visited => D 4/3
      256 |                   dfs @ C 6/6
      257 |                       nbr D already visited => C 6/4
      258 |                       nbr B already visited => C 6/2
      259 |                   dfsnum(D) > back(C) => D 4/2
      260 |               dfsnum(E) > back(D) => E 3/2
      261 |               nbr B is already visited => E 3/2
      262 |           dfsnum(B) <= back(E) => B is a CONNECTOR
      263 |           nbr C is already visited => B 2/2
      264 |           nbr A is already visited => B 2/1
      265 |       dfsnum(A) <= back(B) A is starting point, NOT connector
      266 | 
      267 | 268 |

    • Example 4: (B and D are connectors) 269 |
          A---B---C
      270 |         |   |
      271 |         E---D---F
      272 | 
      273 |

      Same example as the previous, except DFS starts at D, and neighbors stored 274 | in alphabetical order. Connectors are still correctly identified as B and D. 275 |

        A: B
      276 |   B: A,C,E
      277 |   C: B,D
      278 |   D: C,E,F
      279 |   E: B,D
      280 |   F: D
      281 | 
      282 |   dfs @ D 1/1
      283 |       dfs @ C 2/2
      284 |           dfs @ B 3/3
      285 |               dfs @ A 4/4
      286 |                   nbr B is already visited => A 4/3
      287 |               dfsnum(B) <= back(A) => B is a CONNECTOR
      288 |               nbr C is already visited => B 3/2
      289 |               dfs @ E 5/5
      290 |                   nbr B is already visited => E 5/3
      291 |                   nbr D is already visited => E 5/1
      292 |               dfsnum(B) > back(E) => B 3/1
      293 |           dfsnum(C) > back(B) => C 2/1
      294 |           nbr D is already visited => C 2/1
      295 |       dfsnum(D) <= back(C) D is starting point, NOT connector
      296 |       dfs @ F 6/6
      297 |           nbr D is already visited => F 6/1
      298 |       dfsnum(D) <= back(F) D is starting point, is a CONNECTOR
      299 | 
    300 | 301 |
302 | 303 |


304 |

Implementation

305 | 306 |

You will write a program called Friends that will read a graph file, 307 | build a graph (using the adjacency linked lists representation), and implement the 308 | four algorithms described above. The following describes the inputs and outputs 309 | for all the functionality you need to implement, as well as point assignment. 310 | 311 |

    312 |
  1. (5 pts) User interface

    313 |
      314 |
    • Your user interface should ask for the input graph file, build the graph, 315 | then spin on five choices--students at a school, shortest intro chain, cliques at 316 | school, connectors, and quit--until the user quits. 317 |
    318 | 319 |

  2. (10 pts) Graph build

    320 |
      321 |
    • Input: file that lists names of all people and edges between them. Here is 322 | the format of the input file for the sample friendship graph given in the 323 | Background section. 324 |
         15
      325 |    sam|y|rutgers
      326 |    jane|y|rutgers
      327 |    michele|y|cornell
      328 |    sergei|y|rutgers
      329 |    ricardo|y|penn state
      330 |    kaitlin|y|rutgers
      331 |    samir|n
      332 |    aparna|y|rutgers
      333 |    ming|y|penn state
      334 |    nick|y|penn state
      335 |    bob|y|rutgers
      336 |    heather|y|penn state
      337 |    rachel|n
      338 |    rich|y|ucla
      339 |    tom|y|ucla
      340 |    sam|jane
      341 |    jane|bob
      342 |    jane|kaitlin
      343 |    kaitlin|nick
      344 |    bob|samir
      345 |    sergei|aparna
      346 |    samir|aparna
      347 |    aparna|ricardo
      348 |    nick|ricardo
      349 |    ming|nick
      350 |    heather|nick
      351 |    michele|rachel
      352 |    michele|tom
      353 |    tom|rich
      354 | 
      355 |

      The first line has the number of people in the graph (15 in this case). 356 | 357 |

      The next set of lines has information about the people in the graph, one line per 358 | person (15 lines in this example), with the '|' used to separate the fields. 359 | In each line, the first field is the name of 360 | the person. Names of people can have any character except '|', and are case 361 | insensitive. The second field is 'y' if 362 | the person is a student, and 'n' if not. The third field is 363 | only present for students, and is the name of the school the student attends. 364 | The name of a school can have any character except '|', and is 365 | case insensitive. 366 | 367 |

      The last set of lines, following the people information, lists the friendships 368 | between people, one friendship per line. Since friendship works both ways, any 369 | friendship is only listed once, and the order in which the names of the friends 370 | is listed does not matter. 371 | 372 |

    • Result: The ajacency linked list representation, along with a data structure 373 | to be able to quickly translate from a person's name to vertex number. There should 374 | also be a quick way to translate from vertex number to the person's 375 | name. 376 |

    • Output: You don't have to print the representation, we 377 | will check your code to see if you are storing the graph in this representation. 378 |
    379 |

  3. (15 pts) Subgraph (students at a school)

    380 |
      381 |
    • Input: Name of school (case insensitive), e.g. "penn state" 382 |
    • Result: Subgraph of original graph, vertices are all students at the given school, 383 | edges are a subset of the edges of the original graph such that both endpoints are 384 | students at the school. The subgraph must be in stored in the adjacency linked 385 | lists form, just as for the original graph. 386 |

    • Output: Print the subgraph in the same format as the 387 | input in the Graph build section above. 388 |
    389 |

  4. (20 pts) Shortest path (Intro chain)

    390 |
      391 |
    • Input: Name of person who wants the intro, and the name of the other person, 392 | e.g. "sam" and "aparna" for the graph in the Background section. 393 | (Neither of these, nor any of the intermediate people are 394 | required to be students, in the same school or otherwise.) 395 |
    • Result: The shortest chain of people in the graph 396 | starting at the first and ending at the second. 397 |

    • Output: Print the chain of people in the shortest path, for example: 398 |
      sam--jane-bob--samir--aparna
      399 | 
      400 | If there is no way to get from the first person to the second person, then the 401 | output should be a message to this effect. 402 |
    403 |

  5. (15 pts) Connected Islands (cliques)

    404 |
      405 |
    • Input: Name of school for which cliques are to be found, e.g. "rutgers" 406 |
    • Result: The subgraphs for each of the cliques. 407 |

    • Output: Print the subgraph for each clique, in the same format as 408 | the input described in the Graph build section. For example: 409 |
      Clique 1:
      410 | 
      411 | <subgraph output>
      412 | 
      413 | Clique 2:
      414 | 
      415 | <subgraph output>
      416 | 
      417 | etc...
      418 | 
      419 | 420 | Note: If there is even one student at the named school in the graph, then 421 | there must be at least 422 | one clique in the output. If the graph has no students at all at that school, 423 | then the output will be empty. 424 |
    425 |

  6. (25 pts) Connectors (Friends who keep friends together)

    426 |
      427 |
    • Input: Nothing 428 |
    • Result: Names of all people who are connectors in the graph 429 |

    • Output: Print names of all people who are connectors in the graph, comma 430 | separated, in any order. 431 |
    432 |

  7. (10 pts) Efficiency

    433 |
      434 |
    • Your program will be assessed for efficiency in space usage and running time. 435 | Assume that the input graph in general can have several tens of thousands 436 | of vertices (people), and that each person will have, on average, about 100 friends. 437 | Think carefully through the algorithms to make sure you implement them as efficiently 438 | as you can. 439 | 440 |

      Remember, translating between a person's name and vertex number, as well as the other 441 | way around, should done efficiently. When implementing the algorithms, you will 442 | need to maintain additional data structures--pay particular attention to the space 443 | you use for the data structures. 444 | 445 |

    446 |
447 | 448 |

Your program MUST be called Friends - in other words, you must have a filed 449 | named Friends.java with a main method. 450 | 451 |

You may implement as many classes as you want, and separate them into packages as needed. 452 | 453 |

You may import any of the classes from java.lang, 454 | java.io and java.util, but you may NOT 455 | import classes from any of the other packages in the standard Java API, and you may NOT 456 | import classes from any external java APIs. (Of course, if you have more than one package in your 457 | application, you can cross-import classes among them.) Note: The java.util.TreeMap 458 | class may be useful--it implements a red-black 459 | tree, which, like the AVL tree, is a balanced binary search tree with O(log n) worst case 460 | insert/delete/search times. 461 | 462 |

Submission

463 | 464 | In the Friends.java file, make sure you write the names of 465 | both members of your team in comment lines at the top. 466 |

Export your entire Eclipse project as a zip archive into a file called 467 | friends.zip, 468 | and upload this file to Sakai. (See the Eclipse page for how to do this.) 469 | 470 |

If you submit an 471 | incorrect/incomplete project, you will lose credit. So before you submit, 472 | you should check that all is well by importing your friends.zip file as a project 473 | into Eclipse (in a different workspace, so it doesn't conflict with your 474 | existing project), and running it. 475 | 476 |

ONLY ONE PERSON per team should submit the assignment. 477 | 478 | 479 |

--------------------------------------------------------------------------------