-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathcontractor.jl
130 lines (91 loc) · 3.17 KB
/
contractor.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
doc"""
`Contractor` represents a `Contractor` from $\mathbb{R}^N$ to $\mathbb{R}^N$.
Nout is the output dimension of the forward part.
"""
immutable Contractor{N, Nout, F1<:Function, F2<:Function}
variables::Vector{Symbol} # input variables
forward::F1
backward::F2
forward_code::Expr
backward_code::Expr
expression::Expr
end
function Contractor(variables::Vector{Symbol}, top, forward, backward, forward_code, backward_code, expression)
# @show variables
# @show top
N = length(variables) # input dimension
local Nout # number of outputs
if isa(top, Symbol)
Nout = 1
elseif isa(top, Expr) && top.head == :tuple
Nout = length(top.args)
else
Nout = length(top)
end
Contractor{N, Nout, typeof(forward), typeof(backward)}(variables, forward, backward, forward_code, backward_code, expression)
end
function Base.show{N,Nout,F1,F2}(io::IO, C::Contractor{N,Nout,F1,F2})
println(io, "Contractor in $(N) dimensions:")
println(io, " - forward pass contracts to $(Nout) dimensions")
println(io, " - variables: $(C.variables)")
print(io, " - expression: $(C.expression)")
end
function (C::Contractor{N,Nout,F1,F2}){N,Nout,F1,F2,T}(
A::IntervalBox{Nout,T}, X::IntervalBox{N,T})
output, intermediate = C.forward(X)
# @show output
# @show intermediate
output_box = IntervalBox(output)
constrained = output_box ∩ A
# if constrained is already empty, eliminate call to backward propagation:
if isempty(constrained)
return emptyinterval(X)
end
# @show X
# @show constrained
# @show intermediate
# @show C.backward(X, constrained, intermediate)
return IntervalBox{N,T}(C.backward(X, constrained, intermediate) )
end
# allow 1D contractors to take Interval instead of IntervalBox for simplicty:
(C::Contractor{N,1,F1,F2}){N,F1,F2,T}(A::Interval{T}, X::IntervalBox{N,T}) = C(IntervalBox(A), X)
function make_contractor(expr::Expr)
# println("Entering Contractor(ex) with ex=$ex")
# expr, constraint_interval = parse_comparison(ex)
# if constraint_interval != entireinterval()
# warn("Ignoring constraint; include as first argument")
# end
top, linear_AST = flatten(expr)
# @show expr
# @show top
# @show linear_AST
forward_code, backward_code = forward_backward(linear_AST)
# @show top
if isa(top, Symbol)
top = [top]
elseif isa(top, Expr) && top.head == :tuple
top = top.args
end
# @show forward_code
# @show backward_code
:(Contractor($(linear_AST.variables),
$top,
$forward_code,
$backward_code,
$(Meta.quot(forward_code)),
$(Meta.quot(backward_code)),
$(Meta.quot(expr))))
end
doc"""Usage:
```
C = @contractor(x^2 + y^2)
A = -∞..1 # the constraint interval
x = y = @interval(0.5, 1.5)
C(A, x, y)
`@contractor` makes a function that takes as arguments the variables contained in the expression, in lexicographic order
```
TODO: Hygiene for global variables, or pass in parameters
"""
macro contractor(ex)
make_contractor(ex)
end