Skip to content

Commit

Permalink
Merge pull request #41 from charles-river-analytics/develop
Browse files Browse the repository at this point in the history
New Release. Build succeeds other than nightly.
  • Loading branch information
mharradon authored Mar 22, 2024
2 parents b3c5ef4 + 2901596 commit 37e4282
Show file tree
Hide file tree
Showing 15 changed files with 329 additions and 15 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
strategy:
matrix:
version:
- '1.6'
- '1.7'
- '1.8'
- '1.9'
- '1.10'
- 'nightly'
os:
- ubuntu-latest
Expand Down
6 changes: 1 addition & 5 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Scruff"
uuid = "6c98c146-7a27-4df0-99b1-e6e7c9a81876"
version = "0.8.2"
version = "0.8.3"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand All @@ -17,8 +17,6 @@ Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
PrettyPrint = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Serialization = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
SimpleTraits = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
Expand All @@ -38,8 +36,6 @@ MacroTools = "0.5.9"
Parameters = "0.12.3"
Plots = "1.27.2"
PrettyPrint = "0.2"
PyCall = "1.95.1"
PyPlot = "2.10"
SimpleTraits = "0.9.4"
StatsBase = "0.33.16"
StatsFuns = "1"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Scruff is an AI framework to build agents that sense, reason, and learn in the world using a variety of models. It aims to integrate many different kinds of models in a coherent framework, provide flexibility in spatiotemporal modeling, and provide tools to compose, share, and reuse models and model components.

Scruff is provided as a [Julia](https://julialang.org/) package and is licensed under the BSD-3-Clause License. It should be run using Julia v1.6 or v1.7.
Scruff is provided as a [Julia](https://julialang.org/) package and is licensed under the BSD-3-Clause License.

> *Warning*: Scruff is rapidly evolving beta research software. Although the software already has a lot of functionality, we intend to expand on this in the future and cannot promise stability of the code or the APIs at the moment.
Expand Down
1 change: 1 addition & 0 deletions docs/src/tutorial/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
* [novelty_example.jl](https://github.com/p2t2/Scruff.jl/tree/main/docs/examples/novelty_example.jl)
* [novelty_lazy.jl](https://github.com/p2t2/Scruff.jl/tree/main/docs/examples/novelty_lazy.jl)
* [novelty_filtering.jl](https://github.com/p2t2/Scruff.jl/tree/main/docs/examples/novelty_filtering.jl)
* [soccer_example.jl](https://github.com/charles-river-analytics/Scruff.jl/tree/main/docs/examples/soccer_example.jl)
4 changes: 3 additions & 1 deletion src/operators/op_defs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ __Opt{T} = Union{Nothing, T}
# to support
MultiInterface.get_imp(::Nothing, args...) = nothing

@interface forward(sf::SFunc{I,O}, i::I)::Dist{O} where {I,O}
@interface inverse(sf::SFunc{I,O}, o::O)::Score{I} where {I,O}
@interface is_deterministic(sf::SFunc)::Bool
@interface sample(sf::SFunc{I,O}, i::I)::O where {I,O}
@interface sample_logcpdf(sf::SFunc{I,O}, i::I)::Tuple{O, AbstractFloat} where {I,O}
@interface invert(sf::SFunc{I,O}, o::O)::I where {I,O}
# @interface invert(sf::SFunc{I,O}, o::O)::I where {I,O}
@interface lambda_msg(sf::SFunc{I,O}, i::SFunc{<:__Opt{Tuple{}}, O})::SFunc{<:__Opt{Tuple{}}, I} where {I,O}
@interface marginalize(sf::SFunc{I,O}, i::SFunc{<:__Opt{Tuple{}}, I})::SFunc{<:__Opt{Tuple{}}, O} where {I,O}
@interface logcpdf(sf::SFunc{I,O}, i::I, o::O)::AbstractFloat where {I,O}
Expand Down
2 changes: 2 additions & 0 deletions src/sfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ include("sfuncs/dist/cat.jl")
include("sfuncs/dist/constant.jl")
include("sfuncs/dist/flip.jl")
include("sfuncs/dist/normal.jl")
include("sfuncs/dist/uniform.jl")

include("sfuncs/score/score.jl")
include("sfuncs/score/hardscore.jl")
include("sfuncs/score/softscore.jl")
include("sfuncs/score/multiplescore.jl")
include("sfuncs/score/logscore.jl")
include("sfuncs/score/functionalscore.jl")
include("sfuncs/score/normalscore.jl")
Expand Down
2 changes: 1 addition & 1 deletion src/sfuncs/conddist/invertible.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export
Invertible

"""
struct Invertible{I,O} <: SFunc{Tuple{I},O,Nothing}
struct Invertible{I,O} <: SFunc{Tuple{I},O}
An invertible sfunc, with both a `forward` and a `inverse` function provided.
Expand Down
123 changes: 123 additions & 0 deletions src/sfuncs/dist/uniform.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Continuous uniform sfunc

export Uniform

import Distributions

mutable struct Uniform <: Dist{Float64}
params :: Tuple{Float64, Float64}
Uniform(l, u) = new((l,u))
end

lb(u::Uniform) = u.params[1]
ub(u::Uniform) = u.params[2]

mean(u::Uniform) = (lb(u) + ub(u)) / 2.0

sd(u::Uniform) = (ub(u) - lb(u)) / sqrt(12.0)

dist(u::Uniform) = Distributions.Uniform(lb(u), ub(u))

@impl begin
struct UniformSupport end
function support(
sf::Uniform,
::NTuple,
size::Integer,
curr::Vector{Float64}
)
newsize = size - length(curr)
result = curr
if newsize > 0
x = lb(sf)
push!(result, x)
numsteps = newsize - 1
step = (ub(sf) - lb(sf)) / numsteps
for i in 1:numsteps
x += step
push!(result, x)
end
end
unique(result)
end
end


@impl begin
struct UniformSupportQuality end
function support_quality(::Uniform, parranges)
:IncrementalSupport
end
end


@impl begin
struct UniformSample end
function sample(sf::Uniform, x::Tuple{})::Float64
rand(dist(sf))
end
end

@impl begin
struct UniformLogcpdf end
function logcpdf(sf::Uniform, i::Tuple{}, o::Float64)::AbstractFloat
Distributions.logpdf(dist(sf), o)
end
end

@impl begin
struct UniformBoundedProbs end

# assumes range is sorted
function bounded_probs(
sf::Uniform,
range::Vector{Float64},
::NTuple
)
l = lb(sf)
u = ub(sf)
d = u - l
n = length(range)

# Each element in the range is associated with the interval between the midpoint
# of it and the point below and the midpoint between it and the point above,
# except for the end intervals which go to negative or positive infinity.
points = [-Inf64]
for i in 2:n
push!(points, (range[i-1] + range[i]) / 2)
end
push!(points, Inf64)

# Each interval might be completely, partially, or not contained in the bounds
# of the uniform distribution. The following code determines the length of each
# interval that is in the bounds.
lengthsinbound = Float64[]
for i in 1:n
a = max(points[i], l)
b = min(points[i+1], u)
push!(lengthsinbound, max(b-a, 0.0))
end

ps = [lengthsinbound[i] / d for i in 1:n]
return (ps, ps)
end

end

@impl begin
struct UniformComputePi end

function compute_pi(sf::Uniform,
range::Vector{Float64},
::NTuple,
::Tuple)::Cat{Float64}

ps = bounded_probs(sf, range, ())[1]
Cat(range, ps)
end
end





23 changes: 19 additions & 4 deletions src/sfuncs/op_impls/basic_ops.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
# Default implementations of basic operators
#=
# Default implementations of operators. These are defined using other operators.
# They will always be called if a more specific implementation is not provided.
# If the operators they rely on are not implemented, they will produce a runtime error.
# Writers of default implementations should avoid infinite loops.
=#

# cpdf and logcpdf have default operators in terms of the other. Sfuncs should implement one or the other.
# if forward is defined, we get a default implementation of sample
@impl begin
struct DefaultSample end
# This should not produce an infinite loop, because a dist should not implement forward,
# since forwards maps a parent to a dist, but here the parent is empty.
function sample(sf::SFunc{I,O}, i::I)::O where {I,O}
d = forward(sf, i)
return sample(d, tuple())
end
end

@impl begin
struct SFuncCpdf end
function cpdf(sf::SFunc{I,O}, i::I, o::O)::AbstractFloat where {I,O}
exp(logcpdf(sf, i, o))
end
end

@impl begin
struct SFuncLogcpdf end
function logcpdf(sf::SFunc{I,O}, i::I, o::O)::AbstractFloat where {I,O}
log(cpdf(sf, i, o))
end
end

# TODO: Create default implementations of compute_pi and send_lambda
# TODO: Create weighted_sample operator with default implementation using inverse
15 changes: 15 additions & 0 deletions src/sfuncs/score/multiplescore.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# MultipleScore lets you assert multiple evidence on the same variable
export MultipleScore

struct MultipleScore{I} <: Score{I}
components :: Vector{<:Score{I}}
end

function get_log_score(ms::MultipleScore{I}, i::I) where I
tot = 0.0
for m in ms.components
tot += get_log_score(m, i)
end
tot
end

1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using Test
include("test_sfuncs.jl")
include("test_score.jl")
include("test_utils.jl")
include("test_ops.jl")
include("test_ve.jl")
include("test_lsfi.jl")
include("test_bp.jl")
Expand Down
2 changes: 1 addition & 1 deletion test/test_core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,4 @@ wienerprocess = WienerProcess(0.1)
end
end

end
end
Loading

2 comments on commit 37e4282

@mharradon
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/103435

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.8.3 -m "<description of version>" 37e4282a8c2ee11ff0964e61a1eff254ce8c2e45
git push origin v0.8.3

Please sign in to comment.