@@ -100,170 +100,6 @@ Define a new measure in terms of a log-density `f` over some measure `base`.
100
100
"""
101
101
∫exp (f:: Function , μ) = ∫ (logfuncdensity (f), μ)
102
102
103
- """
104
- logdensityof(m::AbstractMeasure, x)
105
-
106
- Compute the log-density of the measure `m` at `x`. Density is always relative,
107
- but `DensityInterface.jl` does not account for this. For compatibility with
108
- this, `logdensityof` for a measure is always implicitly relative to
109
- [`rootmeasure(x)`](@ref rootmeasure).
110
-
111
- `logdensityof` works by first computing `insupport(m, x)`. If this is true, then
112
- `unsafe_logdensityof` is called. If `insupport(m, x)` is known to be `true`, it
113
- can be a little faster to directly call `unsafe_logdensityof(m, x)`.
114
-
115
- To compute log-density relative to `basemeasure(m)` or *define* a log-density
116
- (relative to `basemeasure(m)` or another measure given explicitly), see
117
- `logdensity_def`.
118
-
119
- To compute a log-density relative to a specific base-measure, see
120
- `logdensity_rel`.
121
- """
122
- @inline function logdensityof (μ:: AbstractMeasure , x)
123
- result = dynamic (unsafe_logdensityof (μ, x))
124
- ifelse (insupport (μ, x) == true , result, oftype (result, - Inf ))
125
- end
126
-
127
- export unsafe_logdensityof
128
-
129
- # https://discourse.julialang.org/t/counting-iterations-to-a-type-fixpoint/75876/10?u=cscherrer
130
- """
131
- unsafe_logdensityof(m, x)
132
-
133
- Compute the log-density of the measure `m` at `x` relative to `rootmeasure(m)`.
134
- This is "unsafe" because it does not check `insupport(m, x)`.
135
-
136
- See also `logdensityof`.
137
- """
138
- @inline function unsafe_logdensityof (μ:: M , x) where {M}
139
- ℓ_0 = logdensity_def (μ, x)
140
- b_0 = μ
141
- Base. Cartesian. @nexprs 10 i -> begin # 10 is just some "big enough" number
142
- b_{i} = basemeasure (b_{i - 1 }, x)
143
- if b_{i} isa typeof (b_{i - 1 })
144
- return ℓ_{i - 1 }
145
- end
146
- ℓ_{i} = let Δℓ_{i} = logdensity_def (b_{i}, x)
147
- ℓ_{i - 1 } + Δℓ_{i}
148
- end
149
- end
150
- return ℓ_10
151
- end
152
-
153
- export density_rel
154
-
155
- @inline density_rel (μ, ν, x) = exp (logdensity_rel (μ, ν, x))
156
-
157
- export logdensity_rel
158
-
159
- @inline return_type (f, args:: Tuple ) = Core. Compiler. return_type (f, Tuple{typeof .(args)... })
160
-
161
- unstatic (:: Type{T} ) where {T} = T
162
- unstatic (:: Type{StaticFloat64{X}} ) where {X} = Float64
163
-
164
- """
165
- logdensity_rel(m1, m2, x)
166
-
167
- Compute the log-density of `m1` relative to `m2` at `x`. This function checks
168
- whether `x` is in the support of `m1` or `m2` (or both, or neither). If `x` is
169
- known to be in the support of both, it can be more efficient to call
170
- `unsafe_logdensity_rel`.
171
- """
172
- @inline function logdensity_rel (μ:: M , ν:: N , x:: X ) where {M,N,X}
173
- T = unstatic (
174
- promote_type (
175
- return_type (logdensity_def, (μ, x)),
176
- return_type (logdensity_def, (ν, x)),
177
- ),
178
- )
179
- inμ = insupport (μ, x)
180
- inν = insupport (ν, x)
181
- inμ || return convert (T, ifelse (inν, - Inf , NaN ))
182
- inν || return convert (T, Inf )
183
-
184
- return unsafe_logdensity_rel (μ, ν, x)
185
- end
186
-
187
- """
188
- unsafe_logdensity_rel(m1, m2, x)
189
-
190
- Compute the log-density of `m1` relative to `m2` at `x`, assuming `x` is
191
- known to be in the support of both `m1` and `m2`.
192
-
193
- See also `logdensity_rel`.
194
- """
195
- @inline function unsafe_logdensity_rel (μ:: M , ν:: N , x:: X ) where {M,N,X}
196
- if static_hasmethod (logdensity_def, Tuple{M,N,X})
197
- return logdensity_def (μ, ν, x)
198
- end
199
- μs = basemeasure_sequence (μ)
200
- νs = basemeasure_sequence (ν)
201
- cb = commonbase (μs, νs, X)
202
- # _logdensity_rel(μ, ν)
203
- isnothing (cb) && begin
204
- μ = μs[end ]
205
- ν = νs[end ]
206
- @warn """
207
- No common base measure for
208
- $μ
209
- and
210
- $ν
211
-
212
- Returning a relative log-density of NaN. If this is incorrect, add a
213
- three-argument method
214
- logdensity_def($μ , $ν , x)
215
- """
216
- return NaN
217
- end
218
- return _logdensity_rel (μs, νs, cb, x)
219
- end
220
-
221
- # Note that this method assumes `μ` and `ν` to have the same type
222
- function logdensity_def (μ:: T , ν:: T , x) where {T}
223
- if μ === ν
224
- return zero (logdensity_def (μ, x))
225
- else
226
- return logdensity_def (μ, x) - logdensity_def (ν, x)
227
- end
228
- end
229
-
230
- @generated function _logdensity_rel (
231
- μs:: T μ,
232
- νs:: T ν,
233
- :: Tuple{StaticInt{M},StaticInt{N}} ,
234
- x:: X ,
235
- ) where {Tμ,Tν,M,N,X}
236
- sμ = schema (Tμ)
237
- sν = schema (Tν)
238
-
239
- q = quote
240
- $ (Expr (:meta , :inline ))
241
- ℓ = logdensity_def (μs[$ M], νs[$ N], x)
242
- end
243
-
244
- for i in 1 : M- 1
245
- push! (q. args, :(Δℓ = logdensity_def (μs[$ i], x)))
246
- # push!(q.args, :(println("Adding", Δℓ)))
247
- push! (q. args, :(ℓ += Δℓ))
248
- end
249
-
250
- for j in 1 : N- 1
251
- push! (q. args, :(Δℓ = logdensity_def (νs[$ j], x)))
252
- # push!(q.args, :(println("Subtracting", Δℓ)))
253
- push! (q. args, :(ℓ -= Δℓ))
254
- end
255
-
256
- push! (q. args, :(return ℓ))
257
- return q
258
- end
259
-
260
- export densityof
261
- export logdensityof
262
-
263
- export density_def
264
-
265
- density_def (μ, ν:: AbstractMeasure , x) = exp (logdensity_def (μ, ν, x))
266
- density_def (μ, x) = exp (logdensity_def (μ, x))
267
103
268
104
"""
269
105
rebase(μ, ν)
0 commit comments