Skip to content

Commit 153d848

Browse files
committed
Add from_dicts and from_edgelist examples to ch 1
1 parent 643fb2a commit 153d848

2 files changed

Lines changed: 106 additions & 6 deletions

File tree

Chapter1/Scene2.py

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
load_dotenv()
88

99
from scene_utils import CHAPTER0_MATRIX_DATA, create_labeled_matrix, hide_zero_entries, setup_scene
10+
from scene_utils.graph_utils import create_karate_graph
1011

1112

1213
class Scene2(VoiceoverScene, Scene):
@@ -94,30 +95,129 @@ def construct(self):
9495
self.play(FadeIn(matrix_group))
9596
self.wait(1)
9697

98+
# Transition: fade out COO code, keep matrix
99+
self.play(FadeOut(matrix_code))
100+
101+
# Section 4: from_dicts constructor
102+
with self.voiceover(
103+
"""For more Pythonic construction, GraphBLAS supports
104+
dictionary format. Nested dictionaries map row indices to
105+
column-value pairs. This is intuitive for representing
106+
adjacency lists where each row describes outgoing edges."""
107+
):
108+
dict_code = Code(
109+
code_string="""# Matrix from nested dictionaries
110+
A = gb.Matrix.from_dicts({
111+
0: {1: 1, 3: 2},
112+
1: {2: 5},
113+
3: {4: 2, 5: 9},
114+
4: {2: 5},
115+
5: {4: 2}
116+
}, nrows=6, ncols=6)""",
117+
language="python",
118+
background="window"
119+
).scale(0.65)
120+
dict_code.to_edge(LEFT, buff=0.3).shift(DOWN * 0.5)
121+
self.play(FadeIn(dict_code))
122+
self.wait(1)
123+
124+
# Transition to edgelist
125+
self.play(FadeOut(dict_code))
126+
127+
# Section 5: from_edgelist constructor
128+
with self.voiceover(
129+
"""Edge lists are common in graph data. GraphBLAS can build
130+
matrices directly from sequences of row-column pairs or
131+
triples that include values. This mirrors how graph edges
132+
are often stored in files."""
133+
):
134+
edgelist_code = Code(
135+
code_string="""# Matrix from edge list
136+
edges = [
137+
(0, 1, 1), (0, 3, 2),
138+
(1, 2, 5),
139+
(3, 4, 2), (3, 5, 9),
140+
(4, 2, 5),
141+
(5, 4, 2)
142+
]
143+
A = gb.Matrix.from_edgelist(
144+
edges, nrows=6, ncols=6
145+
)""",
146+
language="python",
147+
background="window"
148+
).scale(0.65)
149+
edgelist_code.to_edge(LEFT, buff=0.3).shift(DOWN * 0.5)
150+
self.play(FadeIn(edgelist_code))
151+
self.wait(1)
152+
153+
# Transition to mmread - clear the small matrix
154+
self.play(FadeOut(edgelist_code), FadeOut(matrix_group))
155+
156+
# Section 6: Matrix Market file reading
157+
with self.voiceover(
158+
"""Real-world graphs are often stored in Matrix Market format.
159+
GraphBLAS can read these files directly. Here we load the
160+
Zachary karate club network, a classic 34-node social network
161+
from 1977."""
162+
):
163+
mmread_code = Code(
164+
code_string="""# Read Matrix Market file
165+
import graphblas.io as gbio
166+
167+
A = gbio.mmread("karate.mtx")
168+
print(A) # 34x34 matrix, 78 edges""",
169+
language="python",
170+
background="window"
171+
).scale(0.7)
172+
mmread_code.to_edge(LEFT, buff=0.5).shift(DOWN * 0.5)
173+
self.play(FadeIn(mmread_code))
174+
175+
# Show the karate graph
176+
karate_graph = create_karate_graph(scale=0.08, node_radius=0.2)
177+
karate_graph.to_edge(RIGHT, buff=0.5).shift(DOWN * 0.3)
178+
self.play(FadeIn(karate_graph))
179+
180+
# Add info label
181+
info_label = Tex("34 nodes, 78 edges").scale(0.7)
182+
info_label.next_to(karate_graph, DOWN, buff=0.3)
183+
self.play(FadeIn(info_label))
184+
self.wait(1)
185+
186+
# Transition back to sparse philosophy - recreate the 6x6 matrix
187+
self.play(FadeOut(mmread_code), FadeOut(karate_graph), FadeOut(info_label))
188+
189+
# Recreate matrix for sparse philosophy section
190+
matrix2, row_labels2, col_labels2 = create_labeled_matrix(
191+
matrix_data, scale=1.5, v_buff=0.5, h_buff=0.5
192+
)
193+
matrix_group2 = VGroup(matrix2, *row_labels2, *col_labels2)
194+
matrix_group2.move_to(ORIGIN)
195+
self.play(FadeIn(matrix_group2))
196+
97197
with self.voiceover(
98198
"""Notice how most entries in this matrix are zero. In
99199
GraphBLAS, these zeros are not stored at all - they simply
100200
don't exist in the sparse representation. This is what makes
101201
GraphBLAS efficient for large, sparse graphs."""
102202
):
103203
# Hide zero entries to show sparse nature
104-
hide_anims = hide_zero_entries(matrix, matrix_data)
204+
hide_anims = hide_zero_entries(matrix2, matrix_data)
105205
self.play(*hide_anims)
106206

107207
# Highlight non-zero positions (matching Chapter 0 matrix)
108208
nz_positions = [(0, 1), (0, 3), (1, 2), (3, 4), (3, 5), (4, 2), (5, 4)]
109-
nz_highlights = [
209+
nz_highlights2 = [
110210
SurroundingRectangle(
111-
matrix.get_entries()[i * 6 + j], color=YELLOW, buff=0.1
211+
matrix2.get_entries()[i * 6 + j], color=YELLOW, buff=0.1
112212
)
113213
for i, j in nz_positions
114214
]
115-
self.play(*[Create(h) for h in nz_highlights])
215+
self.play(*[Create(h) for h in nz_highlights2])
116216
self.wait(2)
117217

118218
# Cleanup
119219
self.play(
120-
FadeOut(title), FadeOut(matrix_code),
121-
FadeOut(matrix_group), *[FadeOut(h) for h in nz_highlights]
220+
FadeOut(title),
221+
FadeOut(matrix_group2), *[FadeOut(h) for h in nz_highlights2]
122222
)
123223
self.wait(0.5)

docs/Chapter1_480p15.mp4

1.59 MB
Binary file not shown.

0 commit comments

Comments
 (0)