Skip to content

Commit de48b75

Browse files
committed
Fixes for PR
1 parent 84a1e61 commit de48b75

10 files changed

Lines changed: 74 additions & 48 deletions

File tree

docs/examples/CustomProcesses.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ using Plots
3535
using StatsAPI
3636
using Optim
3737

38+
import PointProcesses: NoMarks, AbstractMarkDistribution, AbstractUnivariateProcess
39+
3840
struct TwoStateModel{R<:Real,D<:PointProcessMarkDistribution} <: AbstractUnivariateProcess
3941
λ::R
4042
Δ::R
@@ -47,7 +49,7 @@ end
4749
# `PointProcessMarkDistribution` encompasses `NoMarks` and any distribution in package
4850
# `Distributions.jl`. In the next chapter we will discuss custom distributions as well.
4951

50-
# > Even if you plan on only using a non-marked process, you should keep the `mark_dist` field. In you really want you can define an inner constructor like `TwoStateModel(λ, Δ, τ) → new(λ, Δ, τ, Nomarks())`.
52+
# > Even if you plan on only using a non-marked process, you should keep the `mark_dist` field. If you really want you can define an inner constructor like `TwoStateModel(λ, Δ, τ) → new(λ, Δ, τ, Nomarks())`.
5153

5254
# Right now you cannot do much more than accessing the fields. The only methods you have
5355
# defined are `ndims`, `DensityKind` and `mark_distribution`. Not too interesting.
@@ -243,10 +245,10 @@ imp = IndependentMultivariateProcess([
243245

244246
sim = simulate(imp, 0.0, 10.0)
245247

246-
print("ground_intensity(imp, 0.0, sim) → $(ground_intensity(imp, 0.0, sim))")
247-
print("ground_intensity(imp, 0.0, sim, 1) → $(ground_intensity(imp, 0.0, sim, 1))")
248-
print("intensity(imp, 0.0, 0.0, sim) → $(intensity(imp, 0.0, 0.0, sim))")
249-
print("intensity(imp, 0.0, nothing, sim, 3) → $(intensity(imp, 0.0, nothing, sim, 3))")
248+
println("ground_intensity(imp, 0.0, sim) → $(ground_intensity(imp, 0.0, sim))")
249+
println("ground_intensity(imp, 0.0, sim, 1) → $(ground_intensity(imp, 0.0, sim, 1))")
250+
println("intensity(imp, 0.0, 0.0, sim) → $(intensity(imp, 0.0, 0.0, sim))")
251+
println("intensity(imp, 0.0, nothing, sim, 3) → $(intensity(imp, nothing, 0.0, sim, 3))")
250252

251253
# Lets end this tutorial with a nice plot of this process.
252254

src/PointProcesses.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ export sample_mark
4545

4646
## Point processes
4747

48-
export PointProcessMarkDistribution, AbstractMarkDistribution, NoMarks
4948
export AbstractPointProcess, AbstractUnivariateProcess, AbstractMultivariateProcess
5049
export BoundedPointProcess
5150
export ground_intensity, mark_distribution

src/history.jl

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ end
169169

170170
function History(h::History, d::Int)
171171
times = event_times(h, d)
172-
marks = event_times(h, d)
172+
marks = event_marks(h, d)
173173
return History(times, min_time(h), max_time(h), marks)
174174
end
175175

@@ -191,8 +191,8 @@ event_times(h::History) = h.times
191191
192192
Return the sorted vector of event times for `h` in dimension `d`.
193193
"""
194-
function event_times(h::History, d::Int)
195-
h.N == 1 && d == 1 ? h.times : (@view h.times[h.dims .== d])
194+
function event_times(h::History, d::Union{Int, Nothing})
195+
h.N == 1 ? h.times : (@view h.times[h.dims .== d])
196196
end
197197

198198
"""
@@ -230,7 +230,7 @@ event_marks(h::History) = h.marks
230230
231231
Return the vector of event marks in dimension `d` of `h`, sorted according to their event times.
232232
"""
233-
function event_marks(h::History, d::Int)
233+
function event_marks(h::History, d::Union{Int, Nothing})
234234
h.N == 1 && d == 1 ? h.marks : (@view h.marks[h.dims .== d])
235235
end
236236

@@ -369,17 +369,37 @@ duration(h::History) = max_time(h) - min_time(h)
369369
370370
Add event `(t, m)` inside the interval `[h.tmin, h.tmax)` at the end of history `h`.
371371
372-
With `check_args=true` (the default), the event must satisfy
373-
`h.tmin <= t < h.tmax`, occur at or after the last existing event time, and
374-
(if `h` is multivariate) lie in dimension `d ∈ 1:h.N`. Violations throw an
375-
`AssertionError`. Pass `check_args=false` to skip these checks in trusted
376-
inner loops.
372+
With `check_args=true` (the default), the method checks if the event `t` satisfies
373+
`h.tmin <= t < h.tmax`, if it occurs after the last existing event time for that
374+
dimention, and (if `h` is multivariate) if the dimension lie in `d ∈ 1:h.N`.
375+
Pass `check_args=false` to skip these checks in trusted inner loops.
377376
"""
378377
function Base.push!(h::History, t::Real, m=nothing, d=nothing; check_args=true)
379378
if check_args
380-
@assert h.tmin <= t < h.tmax
381-
@assert (length(h) == 0) || (h.times[end] < t)
382-
@assert (d === nothing && h.N == 1) || 1 <= d <= h.N
379+
if !(h.tmin <= t < h.tmax)
380+
throw(
381+
DomainError(
382+
(t, h.tmin, h.tmax),
383+
"Event time must lie in the half-open interval [tmin, tmax).",
384+
),
385+
)
386+
end
387+
if !((d === nothing && h.N == 1) || (d isa Integer && 1 <= d <= h.N))
388+
throw(
389+
DomainError(
390+
d,
391+
"Event dimension must be between 1 and h.N for a multivariate history, or omitted for a univariate history.",
392+
),
393+
)
394+
end
395+
if !(isempty(h) || event_times(h, d)[end] < t)
396+
throw(
397+
DomainError(
398+
(t, event_times(h, d)[end]),
399+
"Event time must be strictly greater than the previous event time in the same dimension.",
400+
),
401+
)
402+
end
383403
end
384404
push!(h.times, t)
385405
push!(h.marks, m)

src/mark_distributions.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# Type definition
32
"Abstract type for defining mark distributions not in `Distributions.jl`"
43
abstract type AbstractMarkDistribution end
@@ -43,8 +42,6 @@ function DensityInterface.densityof(md::PointProcessMarkDistribution, t, h::Hist
4342
densityof(mark_distribution(md, t, h), m)
4443
end
4544

46-
StatsAPI.fit
47-
4845
# Support for `Distributions.jl`
4946
mark_distribution(d::Distribution, t, h::History) = d
5047

src/simulation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Simulate a temporal point process `pp` on interval `[tmin, tmax)` using Ogata's
2020
To infer the type of the marks, the implementation assumes that there is method of `mark_distribution` without the argument `h` such that it corresponds to the distribution of marks in case the history is empty.
2121
"""
2222
function simulate_ogata(
23-
rng::AbstractRNG, pp::AbstractPointProcess, tmin::T, tmax::T
23+
rng::AbstractRNG, pp::AbstractUnivariateProcess, tmin::T, tmax::T
2424
) where {T<:Real}
2525
M = eltype(pp.mark_dist)
2626
h = History(; times=T[], marks=M[], tmin=tmin, tmax=tmax)
Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
function simulate(rng::AbstractRNG, pp::PoissonProcess, tmin::T, tmax::T) where {T<:Real}
2-
times = simulate_poisson_times(rng, pp.λ, tmin, tmax)
3-
h_temp = History(times, tmin, tmax)
4-
marks = [sample_mark(pp.mark_dist, t, h_temp) for t in times]
5-
return History(; times=times, marks=marks, tmin=tmin, tmax=tmax)
2+
h = History(T[], tmin, tmax, eltype(pp.mark_dist)[])
3+
inter_dist = Exponential(inv(pp.λ))
4+
t = rand(rng, inter_dist)
5+
while t < tmax
6+
m = sample_mark(pp.mark_dist, t, h)
7+
push!(h, t, m; check_args=false)
8+
t += rand(rng, inter_dist)
9+
end
10+
return h
611
end
7-
8-
# function simulate(rng::AbstractRNG, pp::PoissonProcess, tmin::T, tmax::T) where {T<:Real}
9-
# h = History(T[], tmin, tmax, eltype(pp.mark_dist)[])
10-
# inter_dist = Exponential(inv(pp.λ))
11-
# t = rand(rng, inter_dist)
12-
# while t < tmax
13-
# m = sample_mark(pp.mark_dist, t, h)
14-
# push!(h, t, m; check_args=False)
15-
# t = rand(rng, inter_dist)
16-
# end
17-
# return h
18-
# end

test/history.jl

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
@testset "Univariate History" begin
2+
# Constructors
23
h_empty1 = History(0.0, 1.0)
34
h_empty2 = History(0.0, 1.0, 2)
45

5-
@test h_empty1 isa History{Float64}
6-
@test h_empty2 isa History{Float64}
6+
@test h_empty1 isa History{Float64,Any}
7+
@test h_empty2 isa History{Float64,Any}
78
@test ndims(h_empty1) == 1
89
@test ndims(h_empty2) == 2
910
@test isempty(h_empty1)
1011
@test isempty(h_empty2)
1112

1213
h = History([0.2, 0.8, 1.1], 0.0, 2.0, ["a", "b", "c"]);
1314

15+
@test h isa History{Float64,String}
16+
17+
# Access
1418
@test duration(h) == 2.0
1519
@test nb_events(h) == 3
1620
@test nb_events(h, 1.0, 2.0) == 1
@@ -21,20 +25,20 @@
2125
@test event_times(h) == [0.2, 0.8, 1.1]
2226
@test event_times(h, 0.2, 0.8) == [0.2]
2327
@test event_times(h, 0.8, 0.2) == []
28+
@test event_times(h, nothing) == h.times
2429
@test event_marks(h) == ["a", "b", "c"]
2530
@test event_marks(h, 0.2, 0.8) == ["a"]
2631
@test event_marks(h, 0.8, 0.2) == []
2732
@test ndims(h) == 1
2833
@test event_dims(h) == fill(nothing, 3)
2934

35+
# Interface
3036
push!(h, 1.7, "d")
3137

3238
@test has_events(h, 1.5, 2.0)
3339

3440
h2 = History(; times=[2.3], marks=["e"], tmin=2.0, tmax=2.5)
35-
h3 = History(; times=[[1], [2, 2.5]], tmin=0, tmax=3)
3641

37-
@test (event_marks(h3) == fill(nothing, 3)) && (event_dims(h3) == [1, 2, 2])
3842
@test string(h2) == "History{Float64,String} with 1 events on interval [2.0, 2.5)"
3943

4044
h_cat = cat(h, h2)
@@ -75,9 +79,20 @@ end
7579
@test event_marks(h_multi) == ["a", "c", "b", "d"]
7680
@test event_dims(h_multi) == [1, 2, 1, 2]
7781

82+
h_multi1 = History(h_multi, 1)
83+
h_multi2 = History(h_multi, 2)
84+
85+
@test event_times(h_multi1) == times1
86+
@test event_times(h_multi2) == times2
87+
@test event_marks(h_multi1) == marks1
88+
@test event_marks(h_multi2) == marks2
89+
7890
@test_throws DomainError History(rand(3), 0, 1, rand(3), [1, 2, 3], 2)
7991
@test event_dims(History([[0.5]], 0, 1)) == [nothing]
8092

93+
@test_throws DomainError History([1.0, 1.0, 2.0, 3.0, 4.0], 0.0, 5.0, fill(nothing, 5), [1, 1, 1, 2, 1], 2)
94+
@test_throws DomainError History([1.0, 1.0, 1.0, 2.0, 3.0], 0.0, 5.0, fill(nothing, 5), [1, 2, 1, 2, 1], 2)
95+
8196
# Test dimension-specific methods
8297
@test event_times(h_multi, 1) == [0.1, 0.5]
8398
@test event_times(h_multi, 2) == [0.2, 0.8]

test/hypothesis_tests.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
h1 = History([1, 2, 3, 4], 0, 5)
2-
h_empty = History(Float64[], 0, 2)
3-
PP = PoissonProcess{Float32,NoMarks}
1+
h1 = History([1.0, 2.0, 3.0, 4.0], 0.0, 5.0)
2+
h_empty = History(Float64[], 0.0, 2.0)
3+
PP = PoissonProcess{Float64,NoMarks}
44
pp = PoissonProcess()
55

66
@testset "Statistics" begin
@@ -10,7 +10,7 @@ pp = PoissonProcess()
1010
@test statistic(KSDistance{Exponential}, pp, h_empty) 1
1111
end
1212

13-
h2 = History(collect(0:999), 0, 1000)
13+
h2 = History(collect(0.0:999.0), 0.0, 1000.0)
1414

1515
@testset "BootstrapTest" begin
1616
@test_throws ArgumentError BootstrapTest(KSDistance{Uniform}, PP, h_empty)

test/mark_distributions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ end
4242
@test mark_distribution(md, 0.0, h) == Normal(1.0)
4343
@test eltype(md) == Float64
4444
@test densityof(md, 0.0, h, 0.0) == densityof(Normal(1.0), 0.0)
45-
end
45+
end

test/multivariate_poisson_process.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ end
4747

4848
@testset "Simulation" begin
4949
pp0 = PoissonProcess([0.0, 1.0, 0.0])
50-
bpp = BoundedPointProcess(pp1, 0, 1000)
50+
bpp = BoundedPointProcess(pp1, 0.0, 1000.0)
5151
h1 = simulate(rng, pp1, 0.0, 1000.0)
5252
h2 = simulate(rng, pp0, 0.0, 1000.0)
5353
h3 = simulate(rng, bpp)

0 commit comments

Comments
 (0)