Skip to content

Commit 8508525

Browse files
authored
Merge pull request #345 from ericphanson/eph/maxwidth
Add `MAXWIDTH` for printing
2 parents b877dde + 10543b4 commit 8508525

File tree

4 files changed

+45
-12
lines changed

4 files changed

+45
-12
lines changed

docs/src/advanced.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,18 @@ tree-traversal functions of that package can be used with Convex.jl problems
112112
and structures. This is what allows powers the printing of problems, expressions,
113113
and constraints. The depth to which the tree corresponding to a problem,
114114
expression, or constraint is printed is controlled by the global variable
115-
`MAXDEPTH`, which defaults to 3. This can be changed by e.g. setting
115+
[`Convex.MAXDEPTH`](@ref), which defaults to 3. This can be changed by e.g. setting
116116

117117
```julia
118118
Convex.MAXDEPTH[] = 5
119119
```
120120

121+
Likewise, [`Convex.MAXWIDTH`](@ref), which defaults to 15, controls the "width"
122+
of the printed tree. For example, when printing a problem with 20 constraints,
123+
only the first `MAXWIDTH` of the constraints will be printed. Vertical dots,
124+
"⋮", will be printed indicating that some constraints were omitted in the
125+
printing.
126+
121127
The AbstractTrees methods can also be used to analyze the structure
122128
of a Convex.jl problem. For example,
123129

@@ -165,3 +171,11 @@ for (i, node) in enumerate(AbstractTrees.StatelessBFS(p))
165171
println("Here's node $i via StatelessBFS: $(summary(node))")
166172
end
167173
```
174+
175+
Reference
176+
---------
177+
178+
```@docs
179+
Convex.MAXDEPTH
180+
Convex.MAXWIDTH
181+
```

src/utilities/show.jl

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ Controls depth of tree printing globally for Convex.jl
1010
"""
1111
const MAXDEPTH = Ref(3)
1212

13+
"""
14+
const MAXWIDTH = Ref(15)
15+
16+
Controls width of tree printing globally for Convex.jl
17+
"""
18+
const MAXWIDTH= Ref(15)
19+
20+
1321
"""
1422
show_id(io::IO, x::Union{AbstractExpr, Constraint}; digits = 3)
1523
@@ -115,7 +123,7 @@ without the final newline. Used for `show` methods which
115123
invoke `print_tree`.
116124
"""
117125
function print_tree_rstrip(io::IO, x)
118-
str = sprint(TreePrint.print_tree, x, MAXDEPTH[])
126+
str = sprint(TreePrint.print_tree, x, MAXDEPTH[], MAXWIDTH[])
119127
print(io, rstrip(str))
120128
end
121129

@@ -134,7 +142,7 @@ struct ConstraintRoot
134142
constraint::Constraint
135143
end
136144

137-
TreePrint.print_tree(io::IO, c::Constraint, maxdepth = 5) = TreePrint.print_tree(io, ConstraintRoot(c), maxdepth)
145+
TreePrint.print_tree(io::IO, c::Constraint, args...; kwargs...) = TreePrint.print_tree(io, ConstraintRoot(c), args...; kwargs...)
138146
AbstractTrees.children(c::ConstraintRoot) = AbstractTrees.children(c.constraint)
139147
AbstractTrees.printnode(io::IO, c::ConstraintRoot) = AbstractTrees.printnode(io, c.constraint)
140148

@@ -143,7 +151,7 @@ show(io::IO, c::Constraint) = print_tree_rstrip(io, c)
143151
struct ExprRoot
144152
expr::AbstractExpr
145153
end
146-
TreePrint.print_tree(io::IO, e::AbstractExpr, maxdepth = 5) = TreePrint.print_tree(io, ExprRoot(e), maxdepth)
154+
TreePrint.print_tree(io::IO, e::AbstractExpr, args...; kwargs...) = TreePrint.print_tree(io, ExprRoot(e), args...; kwargs...)
147155
AbstractTrees.children(e::ExprRoot) = AbstractTrees.children(e.expr)
148156
AbstractTrees.printnode(io::IO, e::ExprRoot) = AbstractTrees.printnode(io, e.expr)
149157

@@ -167,15 +175,15 @@ AbstractTrees.children(p::ProblemConstraintsRoot) = p.constraints
167175
AbstractTrees.printnode(io::IO, p::ProblemConstraintsRoot) = print(io, "subject to")
168176

169177

170-
function TreePrint.print_tree(io::IO, p::Problem, maxdepth = 5)
171-
TreePrint.print_tree(io, ProblemObjectiveRoot(p.head, p.objective), maxdepth)
178+
function TreePrint.print_tree(io::IO, p::Problem, args...; kwargs...)
179+
TreePrint.print_tree(io, ProblemObjectiveRoot(p.head, p.objective), args...; kwargs...)
172180
if !(isempty(p.constraints))
173-
TreePrint.print_tree(io, ProblemConstraintsRoot(p.constraints), maxdepth)
181+
TreePrint.print_tree(io, ProblemConstraintsRoot(p.constraints), args...; kwargs...)
174182
end
175183
end
176184

177185
function show(io::IO, p::Problem)
178-
TreePrint.print_tree(io, p, MAXDEPTH[])
186+
TreePrint.print_tree(io, p, MAXDEPTH[], MAXWIDTH[])
179187
print(io, "\ncurrent status: $(p.status)")
180188
if p.status == "solved"
181189
print(io, " with optimal value of $(round(p.optval, digits=4))")

src/utilities/tree_print.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Dict{String,Any}("b"=>['c','d'],"a"=>"b")
6161
"""
6262
print_tree
6363

64-
function _print_tree(printnode::Function, io::IO, tree, maxdepth = 5; depth = 0, active_levels = Int[],
64+
function _print_tree(printnode::Function, io::IO, tree, maxdepth = 5, maxwidth = Inf; depth = 0, active_levels = Int[],
6565
charset = TreeCharSet(), withinds = false, inds = [], from = nothing, to = nothing, roottree = tree)
6666
nodebuf = IOBuffer()
6767
isa(io, IOContext) && (nodebuf = IOContext(nodebuf, io))
@@ -81,8 +81,10 @@ function _print_tree(printnode::Function, io::IO, tree, maxdepth = 5; depth = 0,
8181
c = isa(treekind(roottree), IndexedTree) ?
8282
childindices(roottree, tree) : children(roottree, tree)
8383
if c !== ()
84+
width = 0
8485
s = Iterators.Stateful(from === nothing ? pairs(c) : Iterators.Rest(pairs(c), from))
85-
while !isempty(s)
86+
while !isempty(s) && width < maxwidth
87+
width += 1
8688
ind, child = popfirst!(s)
8789
ind === to && break
8890
active = false
@@ -96,10 +98,14 @@ function _print_tree(printnode::Function, io::IO, tree, maxdepth = 5; depth = 0,
9698
end
9799
print(io, charset.dash, ' ')
98100
print_tree(depth == maxdepth ? (io, val) -> print(io, charset.ellipsis) : printnode,
99-
io, child, maxdepth; depth = depth + 1,
101+
io, child, maxdepth, maxwidth; depth = depth + 1,
100102
active_levels = child_active_levels, charset = charset, withinds=withinds,
101103
inds = withinds ? [inds; ind] : [], roottree = roottree)
102104
end
105+
if !isempty(s)
106+
print_prefix(io, depth, charset, active_levels)
107+
println(io, "")
108+
end
103109
end
104110
end
105111
print_tree(f::Function, io::IO, tree, args...; kwargs...) = _print_tree(f, io, tree, args...; kwargs...)

test/test_utilities.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,16 @@
4747
vexity: affine
4848
$(Convex.show_id(x))"""
4949

50-
# test `maxdepth`
50+
# test `MAXDEPTH`
5151
x = Variable(2)
5252
y = Variable(2)
5353
p = minimize(sum(x), hcat(hcat(hcat(hcat(x,y), hcat(x,y)),hcat(hcat(x,y), hcat(x,y))),hcat(hcat(hcat(x,y), hcat(x,y)),hcat(hcat(x,y), hcat(x,y)))) == hcat(hcat(hcat(hcat(x,y), hcat(x,y)),hcat(hcat(x,y), hcat(x,y))),hcat(hcat(hcat(x,y), hcat(x,y)),hcat(hcat(x,y), hcat(x,y)))))
5454
@test sprint(show, p) == "minimize\n└─ sum (affine; real)\n └─ 2-element real variable ($(Convex.show_id(x)))\nsubject to\n└─ == constraint (affine)\n ├─ hcat (affine; real)\n │ ├─ hcat (affine; real)\n │ │ ├─ …\n │ │ └─ …\n │ └─ hcat (affine; real)\n │ ├─ …\n │ └─ …\n └─ hcat (affine; real)\n ├─ hcat (affine; real)\n │ ├─ …\n │ └─ …\n └─ hcat (affine; real)\n ├─ …\n └─ …\n\ncurrent status: not yet solved"
55+
56+
# test `MAXWIDTH`
57+
x = Variable()
58+
p = satisfy([ x == i for i = 1:100])
59+
@test sprint(show, p) == "minimize\n└─ 0\nsubject to\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 1\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 2\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 3\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 4\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 5\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 6\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 7\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 8\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 9\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 10\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 11\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 12\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 13\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 14\n├─ == constraint (affine)\n│ ├─ real variable ($(Convex.show_id(x)))\n│ └─ 15\n⋮\n\ncurrent status: not yet solved"
5560
end
5661

5762
@testset "clearmemory" begin

0 commit comments

Comments
 (0)