Skip to content

Commit 5480cd9

Browse files
committed
Handle trees properly. More graphs
1 parent 6d25ba6 commit 5480cd9

File tree

1 file changed

+219
-14
lines changed

1 file changed

+219
-14
lines changed

pymathics/graph/graph_generators.py

Lines changed: 219 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,135 @@
11
from pymathics.graph.__main__ import _NetworkXBuiltin, nx, Graph
22
from mathics.core.expression import String
33

4+
class BalancedTree(_NetworkXBuiltin):
5+
"""
6+
<dl>
7+
<dt>'BalancedTree[$r$, $h$]'
8+
<dd>Returns the perfectly balanced $r$-ary tree of height $h$.
9+
10+
In this tree produced, all non-leaf nodes will have $r$ children and the height of
11+
the path from root $r$ to any leaf will be $h$.
12+
</dl>
13+
14+
>> BalancedTree[2, 3]
15+
= -Graph-
16+
17+
"""
18+
19+
messages = {
20+
"ilsmp": "Expected a non-negative integer at position 1 in ``.",
21+
"ilsmp2": "Expected a non-negative integer at position 2 in ``.",
22+
"mem": "Out of memory",
23+
}
24+
25+
def apply(self, r, h, expression, evaluation, options):
26+
"%(name)s[r_Integer, h_Integer, OptionsPattern[%(name)s]]"
27+
py_r = r.get_int_value()
28+
29+
if py_r < 0:
30+
evaluation.message(self.get_name(), "ilsmp", expression)
31+
return
32+
33+
py_h = h.get_int_value()
34+
if py_h < 0:
35+
evaluation.message(self.get_name(), "ilsmp2", expression)
36+
return
37+
38+
try:
39+
G = nx.balanced_tree(py_r, py_h)
40+
except MemoryError:
41+
evaluation.message(self.get_name(), "mem", expression)
42+
return
43+
44+
45+
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("tree")
46+
g = Graph(G, options=options)
47+
g.r = r
48+
g.h = h
49+
G.root = g.root = 0
50+
return g
51+
52+
53+
class BarbellGraph(_NetworkXBuiltin):
54+
"""
55+
<dl>
56+
<dt>'BarbellGraph[$m1$, $m2$]'
57+
<dd>Barbell Graph: two complete graphs connected by a path.
58+
</dl>
59+
60+
>> BarBellGraph[2, 3]
61+
= -Graph-
62+
63+
"""
64+
65+
messages = {
66+
"ilsmp": "Expected a non-negative integer at position 1 in ``.",
67+
"ilsmp2": "Expected a non-negative integer at position 2 in ``.",
68+
}
69+
70+
def apply(self, m1, m2, expression, evaluation, options):
71+
"%(name)s[m1_Integer, m2_Integer, OptionsPattern[%(name)s]]"
72+
py_m1 = m1.get_int_value()
73+
74+
if py_m1 < 0:
75+
evaluation.message(self.get_name(), "ilsmp", expression)
76+
return
77+
78+
py_m2 = m2.get_int_value()
79+
if py_m2 < 0:
80+
evaluation.message(self.get_name(), "ilsmp", expression)
81+
return
82+
83+
G = nx.barbell_graph(py_m1, py_m2)
84+
85+
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("spring")
86+
g = Graph(G, options=options)
87+
g.m1 = m1
88+
g.m2 = m2
89+
return g
90+
91+
92+
class BinomialTree(_NetworkXBuiltin):
93+
"""
94+
<dl>
95+
<dt>'BinomialTree[$n$]'
96+
<dd>Returns the Binomial Tree of order $n$.
97+
98+
The binomial tree of order $n$ with root $R$ is defined as:
99+
100+
If $k$=0, $B[k]$ = $B[0]$ = {$R$}. i.e., the binomial tree of order zero consists of a single node, $R$.
101+
102+
If $k>0$, B[k] = {$R$, $B[0$], $B[1]$ .. $B[k]$, i.e., the binomial tree of order $k$>0 comprises the root $R$, and $k$ binomial subtrees, $B[0] to $B[k].
103+
104+
Binomial trees the underlying datastructre in Binomial Heaps.
105+
</dl>
106+
107+
>> BinomialTree[3]
108+
= -Graph-
109+
110+
"""
111+
112+
messages = {
113+
"ilsmp": "Expected a non-negative integer at position 1 in ``.",
114+
}
115+
116+
def apply(self, n, expression, evaluation, options):
117+
"%(name)s[n_Integer, OptionsPattern[%(name)s]]"
118+
py_n = n.get_int_value()
119+
120+
if py_n < 0:
121+
evaluation.message(self.get_name(), "ilsmp", expression)
122+
return
123+
124+
G = nx.binomial_tree(py_n)
125+
126+
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("tree")
127+
g = Graph(G, options=options)
128+
g.n = n
129+
G.root = g.root = 0
130+
return g
131+
132+
4133
class CompleteGraph(_NetworkXBuiltin):
5134
"""
6135
<dl>
@@ -30,7 +159,10 @@ def apply(self, n, expression, evaluation, options):
30159

31160
G = nx.complete_graph(py_n)
32161

33-
return Graph(G)
162+
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("circular")
163+
g = Graph(G, options=options)
164+
g.n = n
165+
return g
34166

35167
def apply_multipartite(self, n, evaluation, options):
36168
"%(name)s[n_List, OptionsPattern[%(name)s]]"
@@ -40,14 +172,17 @@ def apply_multipartite(self, n, evaluation, options):
40172
)
41173

42174

43-
class BalancedTree(_NetworkXBuiltin):
44-
"""
45-
<dl>
46-
<dt>'BalancedTree[$r$, $h$]'
47-
<dd>Returns the perfectly balanced r-ary tree of height h.
175+
class FullRAryTree(_NetworkXBuiltin):
176+
"""<dl>
177+
<dt>'FullRAryTree[$r$, $n$]'
178+
<dd>Creates a full $r$-ary tree of $n$ vertices.
48179
</dl>
49180
50-
>> BalancedTree[2, 3]
181+
In the returned tree, with $n$ nodes, the from root $R$ to any
182+
leaf will differ by most 1, the height of the tree from any root
183+
to a leaf is O(log($n, $r$)).
184+
185+
>> FullRAryTree[2, 10]
51186
= -Graph-
52187
53188
"""
@@ -57,23 +192,27 @@ class BalancedTree(_NetworkXBuiltin):
57192
"ilsmp2": "Expected a non-negative integer at position 2 in ``.",
58193
}
59194

60-
def apply(self, r, h, expression, evaluation, options):
61-
"%(name)s[r_Integer, h_Integer, OptionsPattern[%(name)s]]"
195+
def apply(self, r, n, expression, evaluation, options):
196+
"%(name)s[r_Integer, n_Integer, OptionsPattern[%(name)s]]"
62197
py_r = r.get_int_value()
63198

64199
if py_r < 0:
65200
evaluation.message(self.get_name(), "ilsmp", expression)
66201
return
67202

68-
py_h = h.get_int_value()
69-
if py_h < 0:
203+
py_n = n.get_int_value()
204+
if py_n < 0:
70205
evaluation.message(self.get_name(), "ilsmp", expression)
71206
return
72207

73-
G = nx.balanced_tree(py_r, py_h)
208+
G = nx.full_rary_tree(py_r, py_n)
74209

75210
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("tree")
76-
return Graph(G, options=options)
211+
g = Graph(G, options=options)
212+
g.r = r
213+
g.n = n
214+
G.root = g.root = 0
215+
return g
77216

78217

79218
class GraphAtlas(_NetworkXBuiltin):
@@ -101,4 +240,70 @@ def apply(self, n, expression, evaluation, options):
101240
return
102241

103242
G = nx.graph_atlas(py_n)
104-
return Graph(G)
243+
g = Graph(G)
244+
g.n = n
245+
return g
246+
247+
class RandomTree(_NetworkXBuiltin):
248+
"""
249+
<dl>
250+
<dt>'RandomTree[$n$]'
251+
<dd>Returns a uniformly random tree on $n$ nodes.
252+
</dl>
253+
254+
>> RandomTree[3]
255+
= -Graph-
256+
257+
"""
258+
259+
messages = {
260+
"ilsmp": "Expected a non-negative integer at position 1 in ``.",
261+
}
262+
263+
def apply(self, n, expression, evaluation, options):
264+
"%(name)s[n_Integer, OptionsPattern[%(name)s]]"
265+
py_n = n.get_int_value()
266+
267+
if py_n < 0:
268+
evaluation.message(self.get_name(), "ilsmp", expression)
269+
return
270+
271+
G = nx.random_tree(py_n)
272+
273+
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("tree")
274+
g = Graph(G, options=options)
275+
g.n = n
276+
G.root = g.root = 0
277+
return g
278+
279+
280+
class StarGraph(_NetworkXBuiltin):
281+
"""
282+
<dl>
283+
<dt>'StarGraph[$n$]'
284+
<dd>gives a star graph with $n$ vertices
285+
</dl>
286+
287+
>> StarGraph[8]
288+
= -Graph-
289+
"""
290+
291+
messages = {
292+
"ilsmp": "Expected a positive integer at position 1 in ``.",
293+
}
294+
295+
def apply(self, n, expression, evaluation, options):
296+
"%(name)s[n_Integer, OptionsPattern[%(name)s]]"
297+
py_n = n.get_int_value()
298+
299+
if py_n < 1:
300+
evaluation.message(self.get_name(), "ilsmp", expression)
301+
return
302+
303+
G = nx.star_graph(py_n)
304+
305+
options["PlotTheme"] = options["System`PlotTheme"].get_string_value() or String("spring")
306+
307+
g = Graph(G, options=options)
308+
g.n = n
309+
return g

0 commit comments

Comments
 (0)