silicium 0.0.20 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -3
- data/.gitignore +13 -13
- data/.rakeTasks +8 -0
- data/.travis.yml +28 -25
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +8 -8
- data/LICENSE.txt +21 -21
- data/Makefile +269 -269
- data/README.md +588 -46
- data/Rakefile +16 -16
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/docs/Object.html +117 -117
- data/docs/README_md.html +142 -142
- data/docs/Silicium/Combinatorics.html +270 -270
- data/docs/Silicium/Dice/Polyhedron.html +315 -315
- data/docs/Silicium/Dice/PolyhedronSet.html +321 -321
- data/docs/Silicium/Dice.html +99 -99
- data/docs/Silicium/Error.html +106 -106
- data/docs/Silicium/Geometry/Line2dCanon.html +243 -243
- data/docs/Silicium/Geometry/VariablesOrderException.html +106 -106
- data/docs/Silicium/Geometry.html +940 -940
- data/docs/Silicium/GraphVisualizer.html +226 -0
- data/docs/Silicium/Graphs/GraphError.html +106 -106
- data/docs/Silicium/Graphs/OrientedGraph.html +901 -775
- data/docs/Silicium/Graphs/UnorientedGraph.html +237 -284
- data/docs/Silicium/Graphs.html +374 -164
- data/docs/Silicium/IntegralDoesntExistError.html +106 -106
- data/docs/Silicium/NumericalIntegration.html +521 -521
- data/docs/Silicium/Optimization.html +629 -639
- data/docs/Silicium/Plotter/Image.html +297 -297
- data/docs/Silicium/Plotter.html +186 -186
- data/docs/Silicium.html +101 -101
- data/docs/created.rid +9 -9
- data/docs/css/fonts.css +167 -167
- data/docs/css/rdoc.css +619 -619
- data/docs/index.html +134 -132
- data/docs/js/darkfish.js +84 -84
- data/docs/js/navigation.js +105 -105
- data/docs/js/search.js +110 -110
- data/docs/js/search_index.js +1 -1
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js +229 -229
- data/docs/table_of_contents.html +697 -608
- data/lib/algebra.rb +452 -0
- data/lib/algebra_diff.rb +258 -0
- data/lib/geometry/figure.rb +62 -0
- data/lib/geometry.rb +290 -236
- data/lib/geometry3d.rb +270 -0
- data/lib/graph/dfs.rb +42 -0
- data/lib/graph/kruskal.rb +36 -0
- data/lib/graph/scc.rb +97 -0
- data/lib/graph.rb +350 -164
- data/lib/graph_visualizer.rb +287 -0
- data/lib/ml_algorithms.rb +181 -0
- data/lib/numerical_integration.rb +184 -147
- data/lib/optimization.rb +209 -144
- data/lib/plotter.rb +256 -96
- data/lib/polynomial_division.rb +132 -0
- data/lib/polynomial_interpolation.rb +94 -0
- data/lib/regression.rb +120 -0
- data/lib/silicium/adding.rb +37 -0
- data/lib/silicium/conversions.rb +23 -0
- data/lib/silicium/multi.rb +82 -0
- data/lib/silicium/sparse.rb +76 -0
- data/lib/silicium/sugar.rb +37 -0
- data/lib/silicium/trans.rb +26 -0
- data/lib/silicium/version.rb +3 -3
- data/lib/silicium.rb +5 -5
- data/lib/theory_of_probability.rb +240 -226
- data/lib/topological_sort.rb +50 -0
- data/oriented_graph.png +0 -0
- data/plot.png +0 -0
- data/silicium.gemspec +38 -39
- metadata +38 -16
data/lib/geometry3d.rb
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'geometry/figure'
|
4
|
+
|
5
|
+
module Silicium
|
6
|
+
|
7
|
+
module Geometry3d
|
8
|
+
##
|
9
|
+
# Represents a point as three coordinates
|
10
|
+
# in three-dimensional space
|
11
|
+
Point3d = Struct.new(:x, :y, :z)
|
12
|
+
|
13
|
+
##
|
14
|
+
# Calculates the distance from given points in three-dimensional space
|
15
|
+
def distance_point_to_point3d(a, b)
|
16
|
+
Math.sqrt((b.x - a.x)**2 + (b.y - a.y)**2 + (b.z - a.z)**2)
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Class represents a plane as equation Ax + By + Cz+D = 0
|
21
|
+
# in two-dimensional space
|
22
|
+
class Plane3d
|
23
|
+
attr_reader :x_coefficient
|
24
|
+
attr_reader :y_coefficient
|
25
|
+
attr_reader :z_coefficient
|
26
|
+
attr_reader :free_coefficient
|
27
|
+
|
28
|
+
# Initializes with three objects of type Point
|
29
|
+
def initialize(point1, point2, point3)
|
30
|
+
vector1 = Vector3d.new(point1)
|
31
|
+
norm = vector1.norm_vector(point2, point3)
|
32
|
+
@x_coefficient = norm.x
|
33
|
+
@y_coefficient = norm.y
|
34
|
+
@z_coefficient = norm.z
|
35
|
+
@free_coefficient = -point1.x * norm.x + (-point1.y * norm.y) + (-point1.z * norm.z)
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Initializes with coefficients
|
40
|
+
def initialize_with_coefficients(a, b, c, d)
|
41
|
+
raise ArgumentError, 'All coefficients cannot be 0 ' if a.equal?(0) && b.equal?(0) && c.equal?(0) && (d.equal?(0) || !d.equal?(0))
|
42
|
+
|
43
|
+
@x_coefficient = a
|
44
|
+
@y_coefficient = b
|
45
|
+
@z_coefficient = c
|
46
|
+
@free_coefficient = d
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# check if the points isn't on the same line
|
51
|
+
def point_is_on_line?(point1, point2, point3)
|
52
|
+
check_p1 = @x_coefficient * point1.x + @y_coefficient * point1.y + @z_coefficient * point1.z + @free_coefficient
|
53
|
+
check_p2 = @x_coefficient * point2.x + @y_coefficient * point2.y + @z_coefficient * point2.z + @free_coefficient
|
54
|
+
check_p3 = @x_coefficient * point3.x + @y_coefficient * point3.y + @z_coefficient * point3.z + @free_coefficient
|
55
|
+
check_p1.equal?(0) && check_p2.equal?(0) && check_p3.equal?(0)
|
56
|
+
end
|
57
|
+
|
58
|
+
# check if the point isn't on the plane
|
59
|
+
def point_is_on_plane?(point)
|
60
|
+
(@x_coefficient * point.x + @y_coefficient * point.y + @z_coefficient * point.z + @free_coefficient).equal?(0)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Checks if two planes are parallel in 3-dimensional space
|
64
|
+
def parallel?(other_plane)
|
65
|
+
v1 = Vector3d.new(Point3d.new(@x_coefficient, @y_coefficient, @z_coefficient))
|
66
|
+
v2 = Vector3d.new(Point3d.new(other_plane.x_coefficient, other_plane.y_coefficient, other_plane.z_coefficient))
|
67
|
+
v1.collinear?(v2)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Checks if two planes are intersecting in 3-dimensional space
|
72
|
+
def intersecting?(other_plane)
|
73
|
+
check_x = @x_coefficient != other_plane.x_coefficient
|
74
|
+
check_y = @y_coefficient != other_plane.y_coefficient
|
75
|
+
check_z = @z_coefficient != other_plane.z_coefficient
|
76
|
+
check_x || check_y || check_z
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Checks if two planes are perpendicular
|
81
|
+
def perpendicular?(other_plane)
|
82
|
+
check_x = @x_coefficient * other_plane.x_coefficient
|
83
|
+
check_y = @y_coefficient * other_plane.y_coefficient
|
84
|
+
check_z = @z_coefficient * other_plane.z_coefficient
|
85
|
+
(check_x + check_y + check_z).equal?(0)
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# The distance between parallel planes
|
90
|
+
def distance_between_parallel_planes(other_plane)
|
91
|
+
raise 'Planes are not parallel' if !parallel?(other_plane)
|
92
|
+
|
93
|
+
free = (other_plane.free_coefficient - @free_coefficient).abs
|
94
|
+
free / sqrt(@x_coefficient**2 + @y_coefficient**2 + @z_coefficient**2)
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# The distance from a point to a plane
|
99
|
+
#
|
100
|
+
def distance_point_to_plane(point)
|
101
|
+
norm = 1 / Math.sqrt(@x_coefficient**2 + @y_coefficient**2 + @z_coefficient**2)
|
102
|
+
(@x_coefficient * norm * point.x + @y_coefficient * norm * point.y +
|
103
|
+
@z_coefficient * norm * point.z + @free_coefficient * norm).abs
|
104
|
+
end
|
105
|
+
end
|
106
|
+
##
|
107
|
+
# Class represents vector
|
108
|
+
# in three-dimensional space
|
109
|
+
class Vector3d
|
110
|
+
attr_reader :x
|
111
|
+
attr_reader :y
|
112
|
+
attr_reader :z
|
113
|
+
|
114
|
+
##
|
115
|
+
# Initializes with one objects of type Point3d
|
116
|
+
# 2nd point is (0,0,0)
|
117
|
+
def initialize(point)
|
118
|
+
@x = point.x
|
119
|
+
@y = point.y
|
120
|
+
@z = point.z
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# Checks if vector is zero vector
|
125
|
+
def zero_vector?
|
126
|
+
(@x.eql?(0) && @y.eql?(0) && @z.eql?(0)).eql?(true) ? true : false
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Returns length of the vector
|
131
|
+
def length
|
132
|
+
Math.sqrt(@x**2 + @y**2 + @z**2)
|
133
|
+
end
|
134
|
+
|
135
|
+
##
|
136
|
+
# Add one vector to another
|
137
|
+
def addition!(other_vector)
|
138
|
+
@x += other_vector.x
|
139
|
+
@y += other_vector.y
|
140
|
+
@z += other_vector.z
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Sub one vector from another
|
145
|
+
def subtraction!(other_vector)
|
146
|
+
@x -= other_vector.x
|
147
|
+
@y -= other_vector.y
|
148
|
+
@z -= other_vector.z
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Mult vector by number
|
153
|
+
def multiplication_by_number!(r)
|
154
|
+
@x *= r
|
155
|
+
@y *= r
|
156
|
+
@z *= r
|
157
|
+
end
|
158
|
+
|
159
|
+
##
|
160
|
+
# Returns scalar multiplication of 2 vectors
|
161
|
+
def scalar_multiplication(other_vector)
|
162
|
+
x * other_vector.x + y * other_vector.y + z * other_vector.z
|
163
|
+
end
|
164
|
+
|
165
|
+
##
|
166
|
+
# Returns cos between two vectors
|
167
|
+
def cos_between_vectors(other_vector)
|
168
|
+
scalar_multiplication(other_vector) / (length * other_vector.length).to_f
|
169
|
+
end
|
170
|
+
|
171
|
+
##
|
172
|
+
# Returns vector multiplication of 2 vectors
|
173
|
+
def vector_multiplication(other_vector)
|
174
|
+
x = @y * other_vector.z - @z * other_vector.y
|
175
|
+
y = @z * other_vector.x - @x * other_vector.z
|
176
|
+
z = @x * other_vector.y - @y * other_vector.x
|
177
|
+
Vector3d.new(Point3d.new(x, y, z))
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Find normal vector
|
182
|
+
##
|
183
|
+
# vector mult
|
184
|
+
def norm_vector(point2, point3)
|
185
|
+
point1 = Point3d.new(@x, @y, @z)
|
186
|
+
# checking if the points isn't on the same line
|
187
|
+
# finding vector between points 1 and 2 ;1 and 3
|
188
|
+
vector12 = Vector3d.new(Point3d.new(point2.x - point1.x, point2.y - point1.y, point2.z - point1.z))
|
189
|
+
vector13 = Vector3d.new(Point3d.new(point3.x - point1.x, point3.y - point1.y, point3.z - point1.z))
|
190
|
+
# vector13=vector1.scalar_multiplication(vector3)
|
191
|
+
x = vector12.y * vector13.z - vector12.z * vector13.y
|
192
|
+
y = -(vector12.x * vector13.z - vector12.z * vector13.x)
|
193
|
+
z = vector12.x * vector13.y - vector12.y * vector13.x
|
194
|
+
Vector3d.new(Point3d.new(x, y, z))
|
195
|
+
end
|
196
|
+
|
197
|
+
##
|
198
|
+
# Function for checking sign of number
|
199
|
+
def sign(integer)
|
200
|
+
integer >= 0 ? 1 : -1
|
201
|
+
end
|
202
|
+
|
203
|
+
##
|
204
|
+
# help function for collinear function
|
205
|
+
def help_check(vector2, x, y, z)
|
206
|
+
check1 = x * sign(vector2.x) * sign(@x) == y * sign(vector2.y) * sign(@y)
|
207
|
+
check2 = x * sign(vector2.x) * sign(@x) == z * sign(vector2.z) * sign(@z)
|
208
|
+
check3 = z * sign(vector2.z) * sign(@z) == y * sign(vector2.y) * sign(@y)
|
209
|
+
check1 && check2 && check3
|
210
|
+
end
|
211
|
+
##
|
212
|
+
# helps to divide correctly
|
213
|
+
def helper(value1, value2)
|
214
|
+
result = 0
|
215
|
+
if value1 > value2
|
216
|
+
result = value1 / value2
|
217
|
+
else
|
218
|
+
result = value2 / value1
|
219
|
+
end
|
220
|
+
result
|
221
|
+
end
|
222
|
+
|
223
|
+
# Check if two vectors are collinear
|
224
|
+
def collinear?(vector2)
|
225
|
+
x1 = (vector2.x).abs
|
226
|
+
y1 = (vector2.y).abs
|
227
|
+
z1 = (vector2.z).abs
|
228
|
+
x = helper(x1,@x.abs)
|
229
|
+
y = helper(y1,@y.abs)
|
230
|
+
z = helper(z1,@z.abs)
|
231
|
+
help_check(vector2, x, y, z)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
##
|
236
|
+
# Creates an array- directing vector in three-dimensional space .
|
237
|
+
# The equation is specified in the canonical form.
|
238
|
+
# Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
|
239
|
+
#
|
240
|
+
# Important: mandatory order of variables: x, y, z
|
241
|
+
def directing_vector3d(line_equation)
|
242
|
+
process_line_by_coordinates(line_equation, :process_cf)
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Creates an array of coordinates of the point ([x, y, z] on the line
|
247
|
+
# given by the equation in the canonical form.
|
248
|
+
# Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
|
249
|
+
#
|
250
|
+
# Important: mandatory order of variables: x, y, z
|
251
|
+
def height_point_3d(line_equation)
|
252
|
+
process_line_by_coordinates(line_equation, :process_free_member)
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# Calculates the distance from a point given by a Point3d structure
|
257
|
+
# to a straight line given by a canonical equation.
|
258
|
+
# Example, (x-0) / 26 = (y + 300) / * (- 15) = (z-200) / 51
|
259
|
+
#
|
260
|
+
# Important: mandatory order of variables: x, y, z
|
261
|
+
def point_to_line_distance_3d(point, line_eq)
|
262
|
+
dir_vector = directing_vector3d(line_eq)
|
263
|
+
line_point = height_point_3d(line_eq)
|
264
|
+
height_vector = [line_point[0] - point.x, line_point[1] - point.y, line_point[2] - point.z]
|
265
|
+
|
266
|
+
height_on_dir = vectors_product(height_vector, dir_vector)
|
267
|
+
vector_length(height_on_dir) / vector_length(dir_vector)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
data/lib/graph/dfs.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'silicium'
|
2
|
+
module Silicium
|
3
|
+
module Graphs
|
4
|
+
|
5
|
+
def depth_first_search?(graph, start, goal)
|
6
|
+
visited = Hash.new(false)
|
7
|
+
stack = [start]
|
8
|
+
until stack.empty?
|
9
|
+
node = stack.pop
|
10
|
+
return true if goal_node?(graph, node, goal)
|
11
|
+
add_to_stack(graph, node, stack, visited)
|
12
|
+
end
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def goal_node?(graph, node, goal)
|
17
|
+
raise ArgumentError if graph.vertices[node].nil?
|
18
|
+
|
19
|
+
node == goal
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_to_stack(graph, node, stack, visited)
|
23
|
+
return if visited[node]
|
24
|
+
|
25
|
+
visited[node] = true
|
26
|
+
graph.vertices[node].each { |child| stack.push(child) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def dfs_traverse(graph, start)
|
30
|
+
visited = Hash.new(false)
|
31
|
+
traversed = []
|
32
|
+
dfs_traverse_recursive(graph, start, visited, traversed)
|
33
|
+
traversed
|
34
|
+
end
|
35
|
+
|
36
|
+
def dfs_traverse_recursive(graph, node, visited, traversed)
|
37
|
+
visited[node] = true
|
38
|
+
traversed.push(node)
|
39
|
+
graph.vertices[node].each { |child| dfs_traverse_recursive(graph, child, visited, traversed) unless visited[child] }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Graphs
|
3
|
+
|
4
|
+
class UnionFind
|
5
|
+
def initialize(graph)
|
6
|
+
@parents = []
|
7
|
+
graph.vertices.keys.each do |vertex|
|
8
|
+
@parents[vertex] = vertex
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def connected?(vertex1, vertex2)
|
13
|
+
@parents[vertex1] == @parents[vertex2]
|
14
|
+
end
|
15
|
+
|
16
|
+
def union(vertex1, vertex2)
|
17
|
+
parent1, parent2 = @parents[vertex1], @parents[vertex2]
|
18
|
+
@parents.map! { |i| i == parent1 ? parent2 : i }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Implements algorithm of Kruskal
|
23
|
+
def kruskal_mst(graph)
|
24
|
+
mst = UnorientedGraph.new
|
25
|
+
uf = UnionFind.new(graph)
|
26
|
+
graph_to_sets(graph).each do |edge, label|
|
27
|
+
unless uf.connected?(edge[0], edge[1])
|
28
|
+
add_edge!(mst, edge, label)
|
29
|
+
uf.union(edge[0], edge[1])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
mst
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/graph/scc.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
module Silicium
|
2
|
+
|
3
|
+
module Graphs
|
4
|
+
class OrientedGraph
|
5
|
+
include Graphs
|
6
|
+
|
7
|
+
##
|
8
|
+
# Finds Strongly Connected Components (SCC) in graph. SCC is a subgraph where every vertex is reachable from every other vertex.
|
9
|
+
# @return Array of SCC. Each component is represented as Array of vertices in decreasing order of their DFS timestamps.
|
10
|
+
# @author vaimon
|
11
|
+
def find_strongly_connected_components
|
12
|
+
# Vertices we have already visited.
|
13
|
+
visited = Hash.new(false)
|
14
|
+
# Timestamps got during depth-first search.
|
15
|
+
order = []
|
16
|
+
# Resulting array of SCC.
|
17
|
+
res = []
|
18
|
+
|
19
|
+
# Step 1: Launch DFS to get order marks
|
20
|
+
@vertices.keys.each do |key|
|
21
|
+
visited, order = scc_dfs_first key, visited, order unless visited[key]
|
22
|
+
end
|
23
|
+
order.uniq!
|
24
|
+
|
25
|
+
# Step 2: Transpose adjacency list
|
26
|
+
transposed = transpose_adjacency_list
|
27
|
+
|
28
|
+
# Step 3: Launch second DFS in reverse order of timestamps from Step 1 to build components.
|
29
|
+
# HACK: In original algorithm, we use *visited* again, but here the code is a bit
|
30
|
+
# optimized using *order* instead of *visited*
|
31
|
+
until order.empty?
|
32
|
+
component = []
|
33
|
+
order, component = scc_dfs_second order.last, component, order, transposed
|
34
|
+
res << component
|
35
|
+
end
|
36
|
+
res
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
##
|
43
|
+
# Processes the first pass of <b>depth-first search</b> as a step of SCC search algorithm.
|
44
|
+
#
|
45
|
+
# Parameters:
|
46
|
+
# +v+: current vertex;
|
47
|
+
# +visited+: array of booleans representing which vertices have been processed;
|
48
|
+
# +order+: array of vertex exit timestamps.
|
49
|
+
#
|
50
|
+
# @return Tuple <code>[visited, order]</code> of params changed during current step of DFS.
|
51
|
+
def scc_dfs_first(v, visited, order)
|
52
|
+
visited[v] = true
|
53
|
+
@vertices[v].each do |adj|
|
54
|
+
visited, order = scc_dfs_first adj, visited, order unless visited[adj]
|
55
|
+
end
|
56
|
+
order << v
|
57
|
+
[visited, order]
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Transposes adjacency list as a step of SCC search algorithm.
|
62
|
+
#
|
63
|
+
# g.vertices #=> {1 => [2,3], 2 => [3], 3 => []}
|
64
|
+
# g.transpose_adjacency_list #=> {2=>[1], 3=>[1, 2]}
|
65
|
+
def transpose_adjacency_list
|
66
|
+
# HACK
|
67
|
+
res = Hash.new { |h, k| h[k] = [] }
|
68
|
+
@vertices.each do |vert, adj|
|
69
|
+
adj.each { |x| res[x] << vert }
|
70
|
+
end
|
71
|
+
res
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Processes the second pass of <b>depth-first search</b> collecting vertices to a component as a step of SCC search algorithm.
|
76
|
+
#
|
77
|
+
# Parameters:
|
78
|
+
# +v+: current vertex;
|
79
|
+
# +component+: component we are building;
|
80
|
+
# +order+: order of timestamps got after first DFS;
|
81
|
+
# +transposed+: transposed adjacency list.
|
82
|
+
#
|
83
|
+
# @return Tuple <code>[order, component]</code> of params changed during current step of DFS.
|
84
|
+
def scc_dfs_second(v, component, order, transposed)
|
85
|
+
order.delete v
|
86
|
+
component << v
|
87
|
+
transposed[v].each do |adj|
|
88
|
+
if order.include? adj
|
89
|
+
order, component = scc_dfs_second adj, component, order, transposed
|
90
|
+
end
|
91
|
+
end
|
92
|
+
[order, component]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|