is103 1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d27d23670db8b113b4f20683f4671368e4d52024
4
+ data.tar.gz: 631da5c6cfbe1decc3afe494629e9bc525c86114
5
+ SHA512:
6
+ metadata.gz: 57d06dbc0e45653b2f4639ad37217550bb0c55e029f9d92272e47d22cc71c9e48a13737d99580fbf474b9d9cb481aceda42a3c7a06c81128539d09464b18a295
7
+ data.tar.gz: 7b9e90c9858206ecf1f663452526c34584d818e723fb299c99e46351b2b860bf46d2045cbe0610c6b2ee436b3bf7876134ee54a0e9cbec89639d6c1143346778
@@ -0,0 +1,650 @@
1
+ module GraphLab
2
+
3
+ =begin doc
4
+
5
+ == Graph
6
+
7
+ A Graph is made up of vertices and edges between vertices.
8
+ In this lab, to represent edges, we use adjacency list to represent an directed graph.
9
+ Vertex position will be created randomly.
10
+
11
+ =end
12
+
13
+ # Version 2.7
14
+ # Change log:
15
+ #1. added method g.deleteEdges(v1,v2)
16
+ #2. added another constructor where user can define x coord and y coord for the vertex created
17
+
18
+
19
+ @@graph = nil
20
+ @@visitedV = Array.new
21
+ @@position = Array.new #to keep track of position of vertex in canvas
22
+ @@createdValues = Array.new #to keep track of created value
23
+
24
+ #method to view graph
25
+ def view_graph(graph)
26
+ @@graph = graph
27
+ raise "Value must be a Graph!" if graph.class != GraphLab::Graph
28
+ # Initializes the canvas and font type
29
+ Canvas.init(650, 650, "GraphLab")
30
+ Canvas::Font.new('bucketfont', :family => 'Helvetica', :size => 14)
31
+ Canvas::Font.new('visitedfont', :family => 'Helvetica', :size => 12)
32
+ if (graph.vertices == nil)
33
+ return true
34
+ end
35
+ if(graph.vertices != nil)
36
+ draw_graph(graph)
37
+ end
38
+ return true
39
+ end
40
+
41
+ def graph
42
+ @@graph
43
+ end
44
+
45
+ #called by view graph, to draw GRAPH, calls draw vertices and draw edge
46
+ def draw_graph(g)
47
+ v = g.vertices
48
+ #to draw edges
49
+ v.each { |vertex| draw_ed(vertex.xcoord,vertex.ycoord, vertex.adjList, vertex.value)}
50
+
51
+ #to draw the vertices
52
+ v.each { |x| draw_v(x.xcoord,x.ycoord, x.value,"gray") }
53
+ end
54
+
55
+ #to draw vertices
56
+ def draw_v(x,y,value,color)
57
+ Canvas::Circle.new(x, y, 18, :fill => color)
58
+ Canvas::Text.new(value, (x-8), (y-8), :font => 'bucketfont')
59
+ end
60
+
61
+ #to call drawedge for each adj
62
+ def draw_ed(x1,y1,adjList,val1)
63
+ adjList.each { |a| draw_edge(x1,y1, a.xcoord, a.ycoord, val1, a.value)}
64
+ end
65
+
66
+ #to draw edges
67
+ def draw_edge(x1,y1,x2,y2, val1, val2)
68
+ Canvas::Line.new(x1,y1,x2,y2)
69
+ arrowLengthx = (x2-x1)
70
+ arrowLengthx = arrowLengthx.abs
71
+ arrowLengthx = (arrowLengthx - 9.0)*0.03
72
+ arrowLengthy = (y2-y1)
73
+ arrowLengthy = arrowLengthy.abs
74
+ arrowLengthy = (arrowLengthy - 9.0)*0.03
75
+ #to mark the directed graph from the source to the adj node e.g. node 5 had adj node 4, mark will be *4
76
+ x5= 0.0
77
+ y5= 0.0
78
+ distnce = 9.0
79
+ dist = 7.0
80
+ if(arrowLengthx < arrowLengthy && (arrowLengthx/0.03) >= 60)
81
+ distnce = 8.8
82
+ dist = 7.0
83
+ elsif(arrowLengthx < arrowLengthy)
84
+ distnce = 2.8
85
+ dist = 2.5
86
+ elsif(arrowLengthx > arrowLengthy && (arrowLengthy/0.03) >= 60)
87
+ distnce =8.8
88
+ dist = 7.0
89
+ elsif(arrowLengthx > arrowLengthy)
90
+ distnce = 2.8
91
+ dist = 2.2
92
+ end
93
+
94
+ if(x2<x1 && y1>y2)
95
+ x5 = ((x1-x2)/distnce)+x2
96
+ y5 = ((y1-y2)/distnce)+y2
97
+ elsif(x2<x1 && y1<y2)
98
+ x5 = ((x1-x2)/distnce)+x2
99
+ y5 = y2-((y2-y1)/distnce)
100
+ elsif(x2>x1 && y1<y2)
101
+ x5 = x2-((x2-x1)/distnce)
102
+ y5 = y2-((y2-y1)/distnce)
103
+ elsif(x2>x1 && y1>y2)
104
+ x5 = x2-((x2-x1)/distnce)
105
+ y5 = ((y1-y2)/distnce)+y2
106
+ end
107
+ x0= 0.0
108
+ y0= 0.0
109
+ gradient =(((y2*-1.0)-(y1*-1.0))/(x2-x1))
110
+ c= (y2*-1.0)-(gradient*x2)
111
+ if(x2<x1 && y1>y2)
112
+ x0 = ((x1-x2)/dist)+x2
113
+ y0 = ((y1-y2)/dist)+y2
114
+ elsif(x2<x1 && y1<y2)
115
+ x0 = ((x1-x2)/dist)+x2
116
+ y0 = y2-((y2-y1)/dist)
117
+ elsif(x2>x1 && y1<y2)
118
+ x0 = x2-((x2-x1)/dist)
119
+ y0 = y2-((y2-y1)/dist)
120
+ elsif(x2>x1 && y1>y2)
121
+ x0 = x2-((x2-x1)/dist)
122
+ y0 = ((y1-y2)/dist)+y2
123
+ end
124
+ gradientPerpendicular = (1.0/gradient)*-1.0
125
+ cPerpendicular = (y0*-1.0) - (gradientPerpendicular*x0)
126
+ if(arrowLengthx < arrowLengthy && arrowLengthx >= 60)
127
+ arrl = arrowLengthx
128
+ x3 = x0 - arrl
129
+ y3 = (x3*gradientPerpendicular + cPerpendicular)*-1.0
130
+ x4 = x0 + arrl
131
+ y4 = (x4*gradientPerpendicular + cPerpendicular)*-1.0
132
+ elsif(arrowLengthx < arrowLengthy)
133
+ arrl = 9.0
134
+ x3 = x0 - arrl
135
+ y3 = (x3*gradientPerpendicular + cPerpendicular)*-1.0
136
+ x4 = x0 + arrl
137
+ y4 = (x4*gradientPerpendicular + cPerpendicular)*-1.0
138
+ elsif(arrowLengthx > arrowLengthy && arrowLengthy >=60)
139
+ arrl = arrowLengthy
140
+ y3 = (-y0 - arrl)*-1.0
141
+ x3 = (-y3-cPerpendicular)/gradientPerpendicular
142
+ y4 = (-y0 + arrl)*-1.0
143
+ x4 = (-y4-cPerpendicular)/gradientPerpendicular
144
+ elsif(arrowLengthx > arrowLengthy)
145
+ arrl = 9.0
146
+ y3 = (-y0 - arrl)*-1.0
147
+ x3 = (-y3-cPerpendicular)/gradientPerpendicular
148
+ y4 = (-y0 + arrl)*-1.0
149
+ x4 = (-y4-cPerpendicular)/gradientPerpendicular
150
+
151
+ end
152
+ Canvas::Line.new(x3,y3,x5,y5)
153
+ Canvas::Line.new(x4,y4,x5,y5)
154
+ end
155
+
156
+ def dfs(s)
157
+ @@visitedV << "DFS order of visit: "
158
+ view_graph(self)
159
+ _dfs(s)
160
+ self.clearAll
161
+ @@visitedV.clear
162
+ return nil
163
+ end
164
+
165
+ #to perform dfs with x as the starting node, recursive
166
+ def _dfs(v)
167
+ setVisitedDfs(v)
168
+ #recursive dfs
169
+ v.adjList.each{ |u| setVisitedDfs(u) }
170
+ end
171
+
172
+ def setVisitedDfs(u)
173
+ if(!u.isVisited?)
174
+ u.visited = true
175
+ p u
176
+ @@visitedV << u
177
+ anim(u)
178
+ _dfs(u)
179
+ end
180
+ end
181
+
182
+ #to perform bfs with x as the starting node, using queue implementation
183
+ def bfs(s)
184
+ @@visitedV << "BFS order of visit: "
185
+ view_graph(self)
186
+ @q = Queue.new
187
+ setVisitedBfs(s)
188
+ while (!@q.isEmpty?)
189
+ v = @q.dequeue
190
+ adjList = v.adjList
191
+ adjList.each { |u| setVisitedBfs(u)}
192
+ end
193
+ self.clearAll
194
+ @@visitedV.clear
195
+ return nil
196
+ end
197
+
198
+ def setVisitedBfs(u)
199
+ if(!u.isVisited?)
200
+ u.visited = true
201
+ p u
202
+ @@visitedV << u
203
+ anim(u)
204
+ @q.enqueue(u)
205
+ end
206
+ end
207
+
208
+ def clearAll
209
+ self.vertices.each { |u| u.visited = false}
210
+ end
211
+
212
+ def anim(s)
213
+ draw_v(s.xcoord,s.ycoord, s.value,"red")
214
+ Canvas::Text.new(@@visitedV.to_s, 30, 600, :font => 'visitedfont')
215
+ sleep(1.5)
216
+ draw_v(s.xcoord,s.ycoord, s.value, "green")
217
+ end
218
+
219
+ class Graph
220
+
221
+ #to keep array of vertices
222
+ attr_reader :vertices
223
+
224
+ # class constructor
225
+ def initialize
226
+ @vertices = Array.new
227
+ end
228
+
229
+
230
+ # checks whether the graph is empty
231
+ def isEmpty?
232
+ return vertices == nil
233
+ end
234
+
235
+
236
+ #to add new vertex in the graph
237
+ def addVertex(vertex)
238
+ raise "Value must be a Vertex!" if vertex.class != GraphLab::Vertex
239
+ raise "Vertex already added in the graph!" if vertices.include?(vertex)
240
+ if(vertex.class == GraphLab::Vertex && !vertices.include?(vertex))
241
+ vertices << vertex
242
+ end
243
+ view_graph(self)
244
+ return @vertices
245
+ end
246
+
247
+ #to draw edges between 2 vertices in graph randomly from v1 to v2
248
+ def addEdge(v1,v2)
249
+ raise "Value must be a Vertex!" if v1.class != GraphLab::Vertex
250
+ raise "Value must be a Vertex!" if v2.class != GraphLab::Vertex
251
+ raise "Vertex already added in the graph!" if v1.adjList.include?(v2)
252
+ if(v1.class == GraphLab::Vertex && v2.class == GraphLab::Vertex && !v1.adjList.include?(v2))
253
+ v1.addEdge(v2)
254
+ end
255
+ view_graph(self)
256
+ end
257
+
258
+ def deleteEdge(v1, v2)
259
+ raise "Value must be a Vertex!" if v1.class != GraphLab::Vertex
260
+ raise "Value must be a Vertex!" if v2.class != GraphLab::Vertex
261
+ raise "Vertex "+v1.value.to_s+" does not have "+v2.value.to_s+" edge" if !v1.adjList.include?(v2)
262
+ if(v1.class == GraphLab::Vertex && v2.class == GraphLab::Vertex && v1.adjList.include?(v2))
263
+ v1.deleteEdge(v2)
264
+ end
265
+ view_graph(self)
266
+ end
267
+
268
+ #to draw edges between 2 vertices in graph randomly
269
+ def addEdges(x)
270
+ raise "Value must be smaller than 1!" if x > 1
271
+ raise "Value must be larger than 0!" if x <= 0
272
+ x = x*100
273
+ vertices.each { |u| drawOrNot(u,vertices,x) }
274
+ view_graph(self)
275
+ end
276
+
277
+ def drawOrNot(u,adjList,x)
278
+ adjList.each{ |o| drawNot(u,o,x) }
279
+ end
280
+
281
+ def drawNot(u,o,x)
282
+ a = rand(101) #from 100, what is the generated random no
283
+ if(a<=x && u!=o)
284
+ addEdgeForGraph(u,o)
285
+ end
286
+ end
287
+
288
+ #to add edge from v1 to v2 - directed graph
289
+ def addEdgeForGraph(v1,v2)
290
+ raise "Value must be a Vertex!" if v1.class != GraphLab::Vertex
291
+ raise "Value must be a Vertex!" if v2.class != GraphLab::Vertex
292
+ raise "Vertex must be in the graph" if !include?(v1)
293
+ raise "Vertex must be in the graph" if !include?(v2)
294
+ raise "Vertex "+v2+" already adjacent vertex of "+v1+" in the graph!" if v1.adjList.include?(v2)
295
+ raise "cannot add edge to itself" if v1 == v2
296
+ if(v1.class == GraphLab::Vertex && v2.class == GraphLab::Vertex && include?(v1) && include?(v2))
297
+ v1.addEdge(v2)
298
+ end
299
+ end
300
+
301
+ #to count number of vertices in the graph
302
+ def count_v()
303
+ return vertices.length
304
+ end
305
+
306
+ #to delete the vertex from the graph
307
+ def deleteVertex(vertex)
308
+ if(vertex.class == GraphLab::Vertex)
309
+ for i in 0..graph.vertices.length-1
310
+ vi = graph.vertices[i]
311
+ if(vi.adjList.include?(vertex))
312
+ vi.adjList.delete(vertex)
313
+ end
314
+ end
315
+ vertex.adjList.each { |adj| adj.adjList.delete(vertex)}
316
+ vertex.adjList.clear
317
+ vertices.delete(vertex)
318
+ end
319
+ view_graph(self)
320
+ return @vertices
321
+ end
322
+
323
+
324
+ def include?(v1)
325
+ return vertices.include?(v1)
326
+ end
327
+
328
+ # return a string representation of the array
329
+ def inspect
330
+ return to_s
331
+ end
332
+
333
+ # returns a string representation of the array
334
+ def to_s
335
+ return @vertices.inspect
336
+ end
337
+
338
+ end
339
+
340
+ class Vertex
341
+ # value and coordinate of vertex
342
+ attr_accessor:value
343
+ attr_accessor:xcoord
344
+ attr_accessor:ycoord
345
+ # attribute that represents the node in a graph canvas
346
+ attr_accessor:adjList
347
+ attr_accessor:visited
348
+
349
+
350
+ def initialize *args
351
+ case args.size
352
+ when 3
353
+ init_valxy *args
354
+ when 1
355
+ init_val *args
356
+ else
357
+ error
358
+ end
359
+ end
360
+
361
+ def init_valxy(value, x , y)
362
+ raise "Enter other value. Vertex with this value has been created!" if @@createdValues.include?(value)
363
+ if(!@@createdValues.include?(value))
364
+ @@createdValues << value
365
+ @value = value
366
+ @xcoord = x
367
+ @ycoord = y
368
+ @adjList = Array.new
369
+ @visited = false
370
+ end
371
+ return @value
372
+ end
373
+
374
+ def init_val(value)
375
+ raise "Enter other value. Vertex with this value has been created!" if @@createdValues.include?(value)
376
+ if(!@@createdValues.include?(value))
377
+ @@createdValues << value
378
+ @value = value
379
+ @xcoord = rand(450)+30
380
+ @ycoord = rand(450)+30
381
+ coord = (xcoord.to_s + ycoord.to_s)
382
+ #to avoid overlapping vertex coordinates in canvas
383
+ while (@@position.include?(coord))
384
+ puts "regenerate to avoid collision"
385
+ @xcoord = rand(450)+30
386
+ @ycoord = rand(450)+30
387
+ coord = (xcoord.to_s + ycoord.to_s)
388
+ end
389
+ #@@position << coord
390
+ #need to add more y coord and x coord
391
+ a = 50
392
+
393
+ x = @xcoord - a
394
+ y = @ycoord - a
395
+ for i in 0..100
396
+ x = x + i
397
+ for j in 0..100
398
+ y = y + j
399
+ coord = (x.to_s + y.to_s)
400
+ @@position << coord
401
+ end
402
+ end
403
+
404
+
405
+ @adjList = Array.new
406
+ @visited = false
407
+ end
408
+ return @value
409
+ end
410
+
411
+ def getAdjList()
412
+ return self.adjList
413
+ end
414
+
415
+ #to add edge to this vertex
416
+ def addEdge(vertex)
417
+ raise "Value must be a Vertex!" if vertex.class != GraphLab::Vertex
418
+ raise "cannot add edge to itself" if vertex == self
419
+ adjList << vertex
420
+ end
421
+
422
+ def deleteEdge(vertex)
423
+ raise "Value must be a Vertex!" if vertex.class != GraphLab::Vertex
424
+ adjList.delete(vertex)
425
+ end
426
+
427
+ # return a string representation of the vertex
428
+ def inspect
429
+ return to_s
430
+ end
431
+
432
+
433
+ # returns a string representation of the vertex
434
+ def to_s
435
+ s = value.to_s+" ";
436
+ #s+= "("+xcoord.to_s+",";
437
+ #s+= ycoord.to_s+")";
438
+ return s;
439
+ end
440
+
441
+ def isVisited?
442
+ return @visited
443
+ end
444
+
445
+ end
446
+
447
+ class Queue
448
+
449
+ # array used to store the values in the queue
450
+ attr_reader :items
451
+ # Struct object to store the attributes of the drawn visualization
452
+ attr_accessor :drawing
453
+
454
+ # class constructor
455
+ def initialize
456
+ @items = Array.new
457
+ end
458
+
459
+ # dequeue method. if a drawing exists, redraw the canvas
460
+ def dequeue
461
+ value = items.shift
462
+ if @drawing
463
+ view_queue(self, false)
464
+ end
465
+ return value
466
+ end
467
+
468
+ # peek method. if a drawing exists, redraw the canvas
469
+ def peek
470
+ if @drawing
471
+ view_queue(self, true)
472
+ end
473
+ return items.first
474
+ end
475
+
476
+ # enqueue method. if a drawing exists, redraw the canvas
477
+ def enqueue(value)
478
+ output = items << value
479
+ if @drawing
480
+ view_queue(self, false)
481
+ end
482
+ return output
483
+ end
484
+
485
+ # return a string representation of the array
486
+ def inspect
487
+ return to_s
488
+ end
489
+
490
+ # returns a string representation of the array
491
+ def to_s
492
+ return @items.inspect
493
+ end
494
+
495
+ def isEmpty?
496
+ output = false
497
+ if(@items.size == 0)
498
+ output = true
499
+ end
500
+ return output
501
+ end
502
+ end
503
+
504
+ # A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class. This StackView object is being used to store the location of all the rectangles, and its corresponding values.
505
+ StackView = Struct.new(:cells, :values)
506
+
507
+ # Generates the view for a stack visualization
508
+ def view_stack(s, *peek)
509
+ # Initializes the canvas and font type
510
+ Canvas.init(400, 400, "Stack")
511
+ Canvas::Font.new('bucketfont', :family => 'Helvetica', :size => 11)
512
+
513
+ stack = s.items
514
+
515
+ cells = []
516
+ values = []
517
+
518
+ # Define starting height of first rectangle
519
+ y0 = 50
520
+ Canvas::Text.new("Stack Lab", 10, 1, {:font => :bucketfont})
521
+ Canvas::Line.new(0, 20, 400, 20, :fill => :gray, :width => 1)
522
+
523
+ # If generating a peek view, color first rectangle red, and place it on the right
524
+ if peek[0] && stack[0]
525
+ cells << Canvas::Rectangle.new(10, y0, 60, y0+25)
526
+ cells[0].fill = 'red'
527
+ y1 = y0+3
528
+ values << Canvas::Text.new(stack[0], 65, y0+3, {:font => :bucketfont})
529
+ Canvas::Text.new("<- Top of the Stack", 200, y1, {:font => :bucketfont})
530
+
531
+ # Else place a normal rectangle
532
+ elsif stack[0]
533
+ cells << Canvas::Rectangle.new(10, y0, 60, y0+25)
534
+ cells[0].fill = 'grey'
535
+ y1 = y0+3
536
+ values << Canvas::Text.new(stack[0], 65, y0+3, {:font => :bucketfont})
537
+ Canvas::Text.new("<- Top of the Stack", 200, y1, {:font => :bucketfont})
538
+ end
539
+
540
+ iterations = stack.length-1
541
+
542
+ # Iterate as many times as the number of elements in the array minus one. The first element is already handled above.
543
+ iterations.times do |i|
544
+ y0 += 25
545
+ # Draw a rectangle and store a reference to this rectangle in the cells array
546
+ cells << Canvas::Rectangle.new(10, y0, 60, y0+25)
547
+ cells[i+1].fill = 'grey'
548
+ # Draw the text value and store a reference to this value in the values array
549
+ values << Canvas::Text.new(stack[i+1], 65, y0+3, {:font => :bucketfont})
550
+ end
551
+
552
+ if stack.length-1 > 0
553
+ Canvas::Text.new("<- Bottom of the Stack", 200, y0+3, {:font => :bucketfont})
554
+ end
555
+
556
+ # Store the properties of this drawing as a Struct object
557
+ s.drawing = StackView.new(cells, values)
558
+ return true
559
+ end
560
+
561
+ # Ruby Array-based implementation of a Stack
562
+ class Stack
563
+
564
+ # array used to store the values in the stack
565
+ attr_reader :items
566
+ # Struct object to store the attributes of the drawn visualization
567
+ attr_accessor :drawing
568
+
569
+ # class constructor
570
+ def initialize
571
+ @items = Array.new
572
+ end
573
+
574
+ # pop method. if a drawing exists, redraw the canvas
575
+ def pop
576
+ value = items.shift
577
+ if @drawing
578
+ view_stack(self, false)
579
+ end
580
+ return value
581
+ end
582
+
583
+ # peek method. if a drawing exists, redraw the canvas
584
+ def peek
585
+ if @drawing
586
+ view_stack(self, true)
587
+ end
588
+ return items.first
589
+ end
590
+
591
+ # push method. if a drawing exists, redraw the canvas
592
+ def push(value)
593
+ output = items.unshift(value)
594
+ if @drawing
595
+ view_stack(self, false)
596
+ end
597
+ return output
598
+ end
599
+
600
+ # return a string representation of the array
601
+ def inspect
602
+ return to_s
603
+ end
604
+
605
+ # returns a string representation of the array
606
+ def to_s
607
+ return @items.inspect
608
+ end
609
+
610
+ # returns the number of items currently in the stack
611
+ def count
612
+ return items.count
613
+ end
614
+ end
615
+
616
+ # :begin :visit
617
+ def visit(vertex)
618
+ vertex.visited = true
619
+ p vertex
620
+ end
621
+ # :end :visit
622
+
623
+ # :begin :topsort
624
+ def topsort(graph)
625
+ graph.clearAll
626
+ s = Stack.new
627
+ for i in 0..graph.vertices.length-1
628
+ vi = graph.vertices[i]
629
+ if !vi.isVisited?
630
+ topsort_dfs(vi, s)
631
+ end
632
+ end
633
+ return s
634
+ end
635
+ # :end :topsort
636
+
637
+ # :begin :topsort_dfs
638
+ def topsort_dfs(vertex, stack)
639
+ visit(vertex)
640
+ for i in 0..(vertex.adjList.length-1)
641
+ neighbor = vertex.adjList[i]
642
+ if(!neighbor.isVisited?)
643
+ topsort_dfs(neighbor, stack)
644
+ end
645
+ end
646
+ stack.push(vertex)
647
+ end
648
+ # :end :topsort_dfs
649
+
650
+ end