Skip to content

Commit 14105c6

Browse files
committed
Fix docs rendering
1 parent 61291b8 commit 14105c6

File tree

5 files changed

+97
-20
lines changed

5 files changed

+97
-20
lines changed

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ makedocs(;
77
doctest=false,
88
clean=true,
99
format=Documenter.HTML(),
10+
warnonly=true,
1011
)
1112

1213
deploydocs(; repo="github.com/SymbolicML/DynamicExpressions.jl.git")

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
# Contents
33

44
```@contents
5-
Pages = ["types.md", "eval.md"]
5+
Pages = ["utils.md", "types.md", "eval.md"]
66
```

docs/src/utils.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Node utilities
2+
3+
## `Base`
4+
5+
Various functions in `Base` are overloaded to treat an `AbstractNode` as a
6+
collection of its nodes.
7+
8+
```@docs
9+
copy(tree::AbstractExpressionNode; break_sharing::Val=Val(false))
10+
filter(f::Function, tree::AbstractNode; break_sharing::Val=Val(false))
11+
count(f::Function, tree::AbstractNode; init=0, break_sharing::Val=Val(false))
12+
foreach(f::Function, tree::AbstractNode; break_sharing::Val=Val(false))
13+
sum(f::F, tree::AbstractNode; init=0, return_type=Undefined, f_on_shared=_default_shared_aggregation, break_sharing::Val=Val(false)) where {F<:Function}
14+
mapreduce(f::F, op::G, tree::AbstractNode; return_type, f_on_shared, break_sharing) where {F<:Function,G<:Function}
15+
any(f::F, tree::AbstractNode) where {F<:Function}
16+
all(f::F, tree::AbstractNode) where {F<:Function}
17+
map(f::F, tree::AbstractNode, result_type::Type{RT}=Nothing; break_sharing::Val=Val(false)) where {F<:Function,RT}
18+
convert(::Type{<:AbstractExpressionNode{T1}}, n::AbstractExpressionNode{T2}) where {T1,T2}
19+
hash(tree::AbstractExpressionNode{T}, h::UInt; break_sharing::Val=Val(false)) where {T}
20+
```
21+
22+
## Internal utilities
23+
24+
Almost all node utilities are crafted using the `tree_mapreduce` function,
25+
which evaluates a mapreduce over a tree-like (or graph-like) structure:
26+
27+
```@docs
28+
tree_mapreduce
29+
```
30+
31+
Various other utility functions include the following:
32+
33+
```@docs
34+
filter_map
35+
filter_map!
36+
```

src/DynamicExpressions.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ import Reexport: @reexport
2424
copy_node,
2525
set_node!,
2626
tree_mapreduce,
27-
filter_map
27+
filter_map,
28+
filter_map!
2829
import .EquationModule: constructorof, preserve_sharing
2930
@reexport import .EquationUtilsModule:
3031
count_nodes,

src/base.jl

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,9 @@ function count_nodes(tree::AbstractNode; break_sharing=Val(false))
230230
end
231231

232232
"""
233-
foreach(f::Function, tree::AbstractNode)
233+
foreach(f::Function, tree::AbstractNode; break_sharing::Val=Val(false))
234234
235-
Apply a function to each node in a tree.
235+
Apply a function to each node in a tree without returning the results.
236236
"""
237237
function foreach(
238238
f::F, tree::AbstractNode; break_sharing::Val=Val(false)
@@ -244,7 +244,7 @@ function foreach(
244244
end
245245

246246
"""
247-
filter_map(filter_fnc::Function, map_fnc::Function, tree::AbstractNode, result_type::Type)
247+
filter_map(filter_fnc::Function, map_fnc::Function, tree::AbstractNode, result_type::Type, break_sharing::Val=Val(false))
248248
249249
A faster equivalent to `map(map_fnc, filter(filter_fnc, tree))`
250250
that avoids the intermediate allocation. However, using this requires
@@ -286,7 +286,7 @@ function filter_map!(
286286
end
287287

288288
"""
289-
filter(f::Function, tree::AbstractNode)
289+
filter(f::Function, tree::AbstractNode; break_sharing::Val=Val(false))
290290
291291
Filter nodes of a tree, returning a flat array of the nodes for which the function returns `true`.
292292
"""
@@ -299,7 +299,7 @@ function collect(tree::AbstractNode; break_sharing::Val=Val(false))
299299
end
300300

301301
"""
302-
map(f::Function, tree::AbstractNode, result_type::Type{RT}=Nothing)
302+
map(f::F, tree::AbstractNode, result_type::Type{RT}=Nothing; break_sharing::Val=Val(false)) where {F<:Function,RT}
303303
304304
Map a function over a tree and return a flat array of the results in depth-first order.
305305
Pre-specifying the `result_type` of the function can be used to avoid extra allocations.
@@ -314,6 +314,11 @@ function map(
314314
end
315315
end
316316

317+
"""
318+
count(f::F, tree::AbstractNode; init=0, break_sharing::Val=Val(false)) where {F<:Function}
319+
320+
Count the number of nodes in a tree for which the function returns `true`.
321+
"""
317322
function count(
318323
f::F, tree::AbstractNode; init=0, break_sharing::Val=Val(false)
319324
) where {F<:Function}
@@ -327,22 +332,44 @@ function count(
327332
) + init
328333
end
329334

335+
"""
336+
sum(f::Function, tree::AbstractNode; init=0, return_type=Undefined, f_on_shared=_default_shared_aggregation, break_sharing::Val=Val(false)) where {F<:Function}
337+
338+
Sum the results of a function over a tree. For graphs with shared nodes
339+
such as `GraphNode`, the function `f_on_shared` is called on the result
340+
of each shared node. This is used to avoid double-counting shared nodes (default
341+
behavior).
342+
"""
330343
function sum(
331344
f::F,
332345
tree::AbstractNode;
333346
init=0,
334347
return_type=Undefined,
335-
f_on_shared=(c, is_shared) -> is_shared ? (false * c) : c,
348+
f_on_shared=_default_shared_aggregation,
336349
break_sharing::Val=Val(false),
337350
) where {F<:Function}
338351
if preserve_sharing(typeof(tree))
339352
@assert typeof(return_type) !== Undefined "Must specify `return_type` as a keyword argument to `sum` if `preserve_sharing` is true."
340353
end
341354
return tree_mapreduce(f, +, tree, return_type; f_on_shared, break_sharing) + init
342355
end
356+
function _default_shared_aggregation(c, is_shared)
357+
return is_shared ? (false * c) : c
358+
end
359+
360+
"""
361+
all(f::Function, tree::AbstractNode)
343362
363+
Reduce a flag function over a tree, returning `true` if the
364+
function returns `true` for all nodes, `false` otherwise.
365+
"""
344366
all(f::F, tree::AbstractNode) where {F<:Function} = !any(t -> !@inline(f(t)), tree)
345367

368+
"""
369+
mapreduce(f::Function, op::Function, tree::AbstractNode; return_type, f_on_shared, break_sharing)
370+
371+
Map a function over a tree and aggregate the result using an operator `op`.
372+
"""
346373
function mapreduce(
347374
f::F,
348375
op::G,
@@ -369,28 +396,32 @@ function length(tree::AbstractNode; break_sharing::Val=Val(false))
369396
return count_nodes(tree; break_sharing)
370397
end
371398

372-
function hash(tree::AbstractExpressionNode{T}) where {T}
399+
"""
400+
hash(tree::AbstractExpressionNode{T}[, h::UInt]; break_sharing::Val=Val(false)) where {T}
401+
402+
Compute a hash of a tree. This will compute a hash differently
403+
if nodes are shared in a tree. This is ignored if `break_sharing` is set to `Val(true)`.
404+
"""
405+
function hash(tree::AbstractExpressionNode{T}, h::UInt=zero(UInt); break_sharing::Val=Val(false)) where {T}
373406
return tree_mapreduce(
374-
t -> t.constant ? hash((0, t.val::T)) : hash((1, t.feature)),
375-
t -> hash((t.degree + 1, t.op)),
376-
(n...) -> hash(n),
407+
t -> t.constant ? hash((0, t.val::T), h) : hash((1, t.feature), h),
408+
t -> hash((t.degree + 1, t.op), h),
409+
(n...) -> hash(n, h),
377410
tree,
378-
UInt64;
411+
UInt;
379412
f_on_shared=(cur_hash, is_shared) ->
380-
is_shared ? hash((:shared, cur_hash)) : cur_hash,
413+
is_shared ? hash((:shared, cur_hash), h) : cur_hash,
414+
break_sharing,
381415
)
382416
end
383417

384418
"""
385-
copy_node(tree::AbstractExpressionNode)
419+
copy_node(tree::AbstractExpressionNode; break_sharing::Val=Val(false))
386420
387421
Copy a node, recursively copying all children nodes.
388422
This is more efficient than the built-in copy.
389423
390-
id_map is a map from `objectid(tree)` to `copy(tree)`.
391-
We check against the map before making a new copy; otherwise
392-
we can simply reference the existing copy.
393-
[Thanks to Ted Hopp.](https://stackoverflow.com/questions/49285475/how-to-copy-a-full-non-binary-tree-including-loops)
424+
If `break_sharing` is set to `Val(true)`, sharing in a tree will be ignored.
394425
"""
395426
function copy_node(
396427
tree::N; break_sharing::Val=Val(false)
@@ -409,12 +440,20 @@ function copy_node(
409440
)
410441
end
411442

443+
"""
444+
copy(tree::AbstractExpressionNode; break_sharing::Val=Val(false))
445+
446+
Copy a node, recursively copying all children nodes.
447+
This is more efficient than the built-in copy.
448+
449+
If `break_sharing` is set to `Val(true)`, sharing in a tree will be ignored.
450+
"""
412451
function copy(tree::AbstractExpressionNode; break_sharing::Val=Val(false))
413452
return copy_node(tree; break_sharing)
414453
end
415454

416455
"""
417-
convert(::Type{AbstractExpressionNode{T1}}, n::AbstractExpressionNode{T2}) where {T1,T2}
456+
convert(::Type{<:AbstractExpressionNode{T1}}, n::AbstractExpressionNode{T2}) where {T1,T2}
418457
419458
Convert a `AbstractExpressionNode{T2}` to a `AbstractExpressionNode{T1}`.
420459
This will recursively convert all children nodes to `AbstractExpressionNode{T1}`,

0 commit comments

Comments
 (0)