/
ComposedMaps.jl
111 lines (93 loc) · 2.94 KB
/
ComposedMaps.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
## TODO: roll into InducedMap work?
struct ComposedMarkovMap{T<:Tuple,D<:Domain,R<:Domain} <: AbstractMarkovMap{D,R}
maps::T
domain::D
rangedomain::R
end
(∘)(f::AbstractMarkovMap,g::AbstractMarkovMap) = ComposedMarkovMap(f,g)
function ComposedMarkovMap(maps...)
ran = rangedomain(maps[1])
mps = isa(maps[1],ComposedMarkovMap) ? maps[1].maps : (maps[1],)
for i = 1:length(maps)-1
@assert rangedomain(maps[i+1]) == domain(maps[i])
mps = isa(maps[i+1],ComposedMarkovMap) ? (mps...,maps[i+1].maps...) : (mps...,maps[i+1])
end
dom = domain(maps[end])
ComposedMarkovMap(mps,dom,ran)
end
complength(c::ComposedMarkovMap) = length(c.maps)
function (c::ComposedMarkovMap)(x)
f = c.maps[end](x)
for i = complength(c)-1:-1:1
f = c.maps[i](f)
end
f
end
function mapP(c::ComposedMarkovMap,x)
f,dfdx = mapP(c.maps[end],x)
for i = complength(c)-1:-1:1
f,dfdxs = mapP(c.maps[i],f)
dfdx *= dfdxs
end
f,dfdx
end
mapD(c::ComposedMarkovMap,x) = mapP(c,x)[2]
function mapinv(c::ComposedMarkovMap,b,x)
v = mapinv(c.maps[1],b[1],x)
for i = 2:complength(c)
v = mapinv(c.maps[i],b[i],v)
end
v
end
function mapinvP(c::ComposedMarkovMap,b,x)
v,dvdx = mapinvP(c.maps[1],b[1],x)
for i = 2:complength(c)
v,dvdxs = mapinvP(c.maps[i],b[i],v)
dvdx *= dvdxs
end
v,dvdx
end
mapinvD(c::ComposedMarkovMap,b,x) = mapinvP(c,b,x)[2]
# TODO: map(P,D)(c,b,x)
function getbranchind(m::ComposedMarkovMap,x)
x ∈ m.domain || error("DomainError: $x ∉ $(m.domain)")
fx = x
br = getbranchind(m.maps[end],fx)
for i = complength(c)-1:-1:1
fx = m.maps[i+1](fx)
br = (getbranchind(m.maps[i],fx),br...)
end
br
end
nbranches(C::ComposedMarkovMap) = prod(nbranches(mm for mm in C.maps))
eachbranchindex(C::ComposedMarkovMap) = product(eachbranchindex(mm) for mm in C.maps)
branchindtype(C::ComposedMarkovMap) = Array{promote_type([branchindtype(mm) for mm in C.maps]...),1}
nneutral(C::ComposedMarkovMap) = 0 # assume we can't do this
neutralfixedpoints(C::ComposedMarkovMap) = []
#TODO: must be faster??
function transferfunction(x,m::ComposedMarkovMap{Tuple{M}},f) where {M<:AbstractMarkovMap}
transferfunction(x,m.maps[1],f)
end
struct TransferCall{M<:AbstractMarkovMap,ff}
m::M
f::ff
end
# TransferCall(m,f) = TransferCall{typeof(m),typeof(f),T}(m,f)
(t::TransferCall)(x) = transferfunction(x,t.m,t.f)
function transferfunction(x,m::ComposedMarkovMap,f)
m2 = ComposedMarkovMap(m.maps[2:end],domain(m.maps[end]),rangedomain(m.maps[2]))
transferfunction(x,m.maps[1],#x->transferfunction(x,m2,f))
TransferCall(m2,f))
end
# TODO: transferfunction_int
# TODO
struct ComposedCircleMap{M<:AbstractMarkovMap,D<:Domain,R<:Domain} <: AbstractMarkovMap{D,R}
maps::NTuple{M}
domain::D
rangedomain::R
end
# stuff you can do for both
ComposedMap{M,D<:Domain,R<:Domain} = Union{ComposedMarkovMap{M,D,R},ComposedCircleMap{M,D,R}}
for FUN in (:domain,:rangedomain)
@eval ($FUN)(c::ComposedMarkovMap) = c.$FUN
end