From 2015afa8db991c11b0d05ca756e8636c9dfb0d6f Mon Sep 17 00:00:00 2001 From: Joseph Campolongo Date: Tue, 15 Nov 2022 14:15:19 -0500 Subject: [PATCH 01/13] Avi's code adding default implementations Adding unit tests --- src/operators/op_defs.jl | 4 +- src/sfuncs/conddist/invertible.jl | 2 +- src/sfuncs/op_impls/basic_ops.jl | 23 +++++- test/runtests.jl | 1 + test/test_core.jl | 2 +- test/test_ops.jl | 122 ++++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 7 deletions(-) create mode 100644 test/test_ops.jl diff --git a/src/operators/op_defs.jl b/src/operators/op_defs.jl index 858c6e16..e2e95f1e 100644 --- a/src/operators/op_defs.jl +++ b/src/operators/op_defs.jl @@ -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} diff --git a/src/sfuncs/conddist/invertible.jl b/src/sfuncs/conddist/invertible.jl index fddb8139..f10b17ef 100644 --- a/src/sfuncs/conddist/invertible.jl +++ b/src/sfuncs/conddist/invertible.jl @@ -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. diff --git a/src/sfuncs/op_impls/basic_ops.jl b/src/sfuncs/op_impls/basic_ops.jl index 3a3ac64d..ada1c2fa 100644 --- a/src/sfuncs/op_impls/basic_ops.jl +++ b/src/sfuncs/op_impls/basic_ops.jl @@ -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 diff --git a/test/runtests.jl b/test/runtests.jl index 44895a4d..7b2865ed 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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") diff --git a/test/test_core.jl b/test/test_core.jl index 23505052..1c2d05cc 100644 --- a/test/test_core.jl +++ b/test/test_core.jl @@ -11,7 +11,7 @@ using Scruff.SFuncs import Scruff: make_initial, make_transition import Scruff.Models: get_dt -import Scruff.Operators: Sample, sample, Logcpdf, logcpdf, Marginalize, marginalize +import Scruff.Operators: Sample, sample, Logcpdf, logcpdf, Marginalize, marginalize, expectation struct MyModel <: Model{Tuple{}, Tuple{Int}, Tuple{Int, Int}} end diff --git a/test/test_ops.jl b/test/test_ops.jl new file mode 100644 index 00000000..381a567c --- /dev/null +++ b/test/test_ops.jl @@ -0,0 +1,122 @@ +using Test + +import Logging + +using Scruff +using Scruff.Operators +using Scruff.MultiInterface: @impl + +import Scruff.Operators: sample, forward, cpdf, logcpdf +import Scruff.SFuncs: Constant + +# Test default implementation of operators + +logger = Logging.SimpleLogger(stderr, Logging.Error+1) + +struct SF1 <: SFunc{Tuple{Int},Int} end + +@impl begin + struct SF1Forward end + function forward(sf::SF1, i::Tuple{Int})::Dist{Int} + Constant(1) + end +end + +@impl begin + struct SF1Sample end + function sample(sf::SF1, i::Tuple{Int})::Int + 0 + end +end + +struct SF2 <: SFunc{Tuple{Int},Int} end + +@impl begin + struct SF2Forward end + function forward(sf::SF2, i::Tuple{Int})::Dist{Int} + Constant(1) + end +end + +struct SF3 <: SFunc{Tuple{Int}, Int} end + +struct SF4 <: SFunc{Tuple{Int}, Int} end + +@impl begin + struct SF4Cpdf end + function cpdf(sf::SF4, i::Tuple{Int}, o::Int) + 0.0 + end +end + +@impl begin + struct SF4Logcpdf end + function logcpdf(sf::SF4, i::Tuple{Int}, o::Int) + 0.0 # so cpdf is 1.0 + end +end + +struct SF5 <: SFunc{Tuple{Int}, Int} end + +@impl begin + struct SF5Cpdf end + function cpdf(sf::SF5, i::Tuple{Int}, o::Int) + 0.0 + end +end + +struct SF6 <: SFunc{Tuple{Int}, Int} end + +@impl begin + struct SF6Logcpdf end + function logcpdf(sf::SF6, i::Tuple{Int}, o::Int) + 0.0 + end +end + +struct SF7 <: SFunc{Tuple{Int}, Int} end + +Logging.with_logger(logger) do + +@testset "Implementation of sample using forward" begin + @testset "When explicit sample defined that is different" begin + # To test the calls, we implement forward and sample in contradictory ways + # The explicit sample should be used + @test sample(SF1(), (2,)) == 0 + end + + @testset "When forward is implemented explicitly but not sample" begin + # sample should use forward + @test sample(SF2(), (2,)) == 1 + end + + @testset "When neither sample nor forward are implemented explicitly" begin + # Should throw a MethodError because forward is not found when using the default implemenation of sample`` + @test_throws MethodError sample(SF3(), (2,)) + end +end + +@testset "Default implementations of cpdf and logcpdf in terms of each other" begin + @testset "When both cpdf and logcpdf are implemented explicitly" begin + # To test the calls, we implement cpdf and logcpdf in contradictory ways + @test cpdf(SF4(), (2,), 1) == 0.0 + @test logcpdf(SF4(), (2,), 1) == 0.0 + end + + @testset "When only cpdf is implemented explicitly" begin + @test cpdf(SF5(), (2,), 1) == 0.0 + @test logcpdf(SF5(), (2,), 1) == -Inf64 + end + + @testset "When only cpdf is implemented explicitly" begin + @test cpdf(SF6(), (2,), 1) == 1.0 + @test logcpdf(SF6(), (2,), 1) == 0.0 + end + + # @testset "When neither cpdf nor logcpdf are implemented explicitly" begin + # # should detect infinite loop and throw error + # @test_throws ErrorException cpdf(SF7(), (2,), 1) + # @test_throws ErrorException logcpdf(SF7(), (2,), 1) + # end +end +end \ No newline at end of file From 3f43ce039d23f2130142e4c659a502075814ab4b Mon Sep 17 00:00:00 2001 From: Joseph Campolongo Date: Fri, 10 Feb 2023 11:26:58 -0500 Subject: [PATCH 02/13] Increment version to 0.8.2 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index d5ed0c7f..22caa470 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Scruff" uuid = "6c98c146-7a27-4df0-99b1-e6e7c9a81876" -version = "0.8.1" +version = "0.8.2" [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" From 738f5cb4bfa8c9509f243a190fc172072313459d Mon Sep 17 00:00:00 2001 From: Joseph Campolongo Date: Fri, 10 Feb 2023 12:47:18 -0500 Subject: [PATCH 03/13] Updating compats to have upper bounds --- Project.toml | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Project.toml b/Project.toml index 22caa470..fdeac771 100644 --- a/Project.toml +++ b/Project.toml @@ -28,23 +28,22 @@ TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" [compat] -AbstractTrees = ">= 0.3.4" -Cassette = ">= 0.3.10" -Clustering = ">= 0.14.2" -DataStructures = ">= 0.18.11" -Distributions = ">= 0.25.52" -Folds = ">= 0.2.7" -MLDatasets = ">= 0.5.15" -MacroTools = ">= 0.5.9" -MetaGraphs = ">= 0.7.1" -Parameters = ">= 0.12.3" -Plots = ">= 1.27.2" -PrettyPrint = ">= 0.2" -PyPlot = ">= 2.10" -SimpleTraits = ">= 0.9.4" -StatsBase = ">= 0.33.16" -StatsFuns = ">= 0.9.16" -TensorOperations = ">= 3.2.3" +AbstractTrees = "0.3.4 - 0.4" +Cassette = "0.3.10" +Clustering = "0.14.2" +DataStructures = "0.18.11" +Distributions = "0.25.52" +Folds = "0.2.7" +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" +TensorOperations = "3.2.3" julia = "^1.6" [extras] From f5dff8a6351e01dea9107d7edbc93393fd5af008 Mon Sep 17 00:00:00 2001 From: Joseph Campolongo Date: Fri, 10 Feb 2023 13:11:54 -0500 Subject: [PATCH 04/13] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index fdeac771..d49ea7e8 100644 --- a/Project.toml +++ b/Project.toml @@ -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" From 457add0d5c040b48a60d62c1241ccd0c54e23a78 Mon Sep 17 00:00:00 2001 From: Joseph Campolongo Date: Fri, 10 Feb 2023 13:32:19 -0500 Subject: [PATCH 05/13] Change for auto-registry --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index d49ea7e8..fdeac771 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Scruff" uuid = "6c98c146-7a27-4df0-99b1-e6e7c9a81876" -version = "0.8.3" +version = "0.8.2" [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" From 5d562092f9a079bae3be913d07fa8df673f20a71 Mon Sep 17 00:00:00 2001 From: apfeffer Date: Wed, 29 Mar 2023 15:52:31 -0400 Subject: [PATCH 06/13] Uniform --- src/sfuncs.jl | 1 + src/sfuncs/dist/uniform.jl | 123 +++++++++++++++++++++++++++++++++++++ test/test_bp.jl | 14 ++--- test/test_bp_logger.jl | 12 ++-- test/test_core.jl | 10 +-- test/test_filter.jl | 14 ++--- test/test_importance.jl | 12 ++-- test/test_logger.jl | 12 ++-- test/test_lsfi.jl | 14 ++--- test/test_net.jl | 6 +- test/test_score.jl | 8 +-- test/test_sfuncs.jl | 38 ++++++++++-- test/test_utils.jl | 6 +- test/test_ve.jl | 14 ++--- 14 files changed, 218 insertions(+), 66 deletions(-) create mode 100644 src/sfuncs/dist/uniform.jl mode change 100644 => 100755 test/test_sfuncs.jl diff --git a/src/sfuncs.jl b/src/sfuncs.jl index ea46d34b..72bdfc7c 100644 --- a/src/sfuncs.jl +++ b/src/sfuncs.jl @@ -14,6 +14,7 @@ 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") diff --git a/src/sfuncs/dist/uniform.jl b/src/sfuncs/dist/uniform.jl new file mode 100644 index 00000000..a3cc3f73 --- /dev/null +++ b/src/sfuncs/dist/uniform.jl @@ -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 + + + + + diff --git a/test/test_bp.jl b/test/test_bp.jl index b0e8fc35..cebbfd31 100644 --- a/test/test_bp.jl +++ b/test/test_bp.jl @@ -5,13 +5,13 @@ import Scruff.Operators.bounded_probs import Scruff.Operators.range using Test -using Scruff -using Scruff.Utils -using Scruff.RTUtils -using Scruff.SFuncs -using Scruff.Models -using Scruff.Operators -import Scruff.Algorithms: three_pass_BP, loopy_BP, ThreePassBP, LoopyBP, infer, probability +using ..Scruff +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.SFuncs +using ..Scruff.Models +using ..Scruff.Operators +import ..Scruff.Algorithms: three_pass_BP, loopy_BP, ThreePassBP, LoopyBP, infer, probability @testset "BP" begin diff --git a/test/test_bp_logger.jl b/test/test_bp_logger.jl index d7988d79..5d8db55f 100644 --- a/test/test_bp_logger.jl +++ b/test/test_bp_logger.jl @@ -1,11 +1,11 @@ include("..//src//utils//logplots.jl") -using Scruff -using Scruff.SFuncs -using Scruff.Utils -using Scruff.RTUtils -using Scruff.Models -import Scruff.Algorithms +using ..Scruff +using ..Scruff.SFuncs +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.Models +import ..Scruff.Algorithms pyplot() diff --git a/test/test_core.jl b/test/test_core.jl index 9ad7d0c0..4c0a3f51 100644 --- a/test/test_core.jl +++ b/test/test_core.jl @@ -5,11 +5,11 @@ using Plots import Distributions -using Scruff -using Scruff.Operators -using Scruff.MultiInterface -using Scruff.Models -using Scruff.SFuncs +using ..Scruff +using ..Scruff.Operators +using ..Scruff.MultiInterface +using ..Scruff.Models +using ..Scruff.SFuncs import Scruff: make_initial, make_transition import Scruff.Models: get_dt diff --git a/test/test_filter.jl b/test/test_filter.jl index 9a4fb7ce..c3986c60 100644 --- a/test/test_filter.jl +++ b/test/test_filter.jl @@ -1,12 +1,12 @@ using Test -using Scruff -using Scruff.Utils -using Scruff.RTUtils -using Scruff.Models -using Scruff.SFuncs -using Scruff.Algorithms -import Scruff: make_initial, make_transition +using ..Scruff +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.Models +using ..Scruff.SFuncs +using ..Scruff.Algorithms +import ..Scruff: make_initial, make_transition @testset "Filtering" begin diff --git a/test/test_importance.jl b/test/test_importance.jl index c6333fde..fbdefb0c 100644 --- a/test/test_importance.jl +++ b/test/test_importance.jl @@ -3,12 +3,12 @@ import Base.isapprox import PrettyPrint using Test -using Scruff -using Scruff.Utils -using Scruff.RTUtils -using Scruff.SFuncs -using Scruff.Algorithms -import Scruff.Operators: cpdf +using ..Scruff +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.SFuncs +using ..Scruff.Algorithms +import ..Scruff.Operators: cpdf @testset "Importance" begin diff --git a/test/test_logger.jl b/test/test_logger.jl index 781d1c80..c1c12bf5 100644 --- a/test/test_logger.jl +++ b/test/test_logger.jl @@ -1,12 +1,12 @@ using Test using Logging -using Scruff -using Scruff.Models -using Scruff.Utils -using Scruff.RTUtils -using Scruff.SFuncs -using Scruff.Operators +using ..Scruff +using ..Scruff.Models +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.SFuncs +using ..Scruff.Operators @testset "test loggers" begin x1 = Cat([1,2], [0.1, 0.9])()(:x1) diff --git a/test/test_lsfi.jl b/test/test_lsfi.jl index 1476aa70..e69d26bc 100644 --- a/test/test_lsfi.jl +++ b/test/test_lsfi.jl @@ -3,13 +3,13 @@ import Base.isapprox import PrettyPrint using Test -using Scruff -using Scruff.Utils -using Scruff.RTUtils -using Scruff.Models -using Scruff.SFuncs -using Scruff.Operators -import Scruff.Algorithms: LSFI, probability_bounds, prepare, refine, ve +using ..Scruff +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.Models +using ..Scruff.SFuncs +using ..Scruff.Operators +import ..Scruff.Algorithms: LSFI, probability_bounds, prepare, refine, ve using Scruff.MultiInterface diff --git a/test/test_net.jl b/test/test_net.jl index 4e96ff7c..1711c610 100644 --- a/test/test_net.jl +++ b/test/test_net.jl @@ -1,7 +1,7 @@ using Test -using Scruff -using Scruff.SFuncs -using Scruff.Operators +using ..Scruff +using ..Scruff.SFuncs +using ..Scruff.Operators @testset "net" begin @testset "Build NetworkSFunc" begin diff --git a/test/test_score.jl b/test/test_score.jl index b1c1c059..c7201516 100644 --- a/test/test_score.jl +++ b/test/test_score.jl @@ -1,8 +1,8 @@ using Test -using Scruff -using Scruff.Operators -using Scruff.SFuncs -using Scruff.Utils +using ..Scruff +using ..Scruff.Operators +using ..Scruff.SFuncs +using ..Scruff.Utils @testset "Score" begin diff --git a/test/test_sfuncs.jl b/test/test_sfuncs.jl old mode 100644 new mode 100755 index 5ce563c4..4256c578 --- a/test/test_sfuncs.jl +++ b/test/test_sfuncs.jl @@ -1,9 +1,9 @@ using Test -using Scruff -using Scruff.Operators -using Scruff.MultiInterface -using Scruff.SFuncs -using Scruff.Utils +using ..Scruff +using ..Scruff.Operators +using ..Scruff.MultiInterface +using ..Scruff.SFuncs +using ..Scruff.Utils import Distributions function test_support(sf::SFunc{I,O}, parranges, target, quality; @@ -145,6 +145,34 @@ end @test isapprox(compute_pi(f, [false, true], (), ()).params, [0.3, 0.7]) end + @testset "Uniform" begin + u = SFuncs.Uniform(-1.0, 3.0) + + test_support(u, (), [-1.0, 0.0, 1.0, 2.0, 3.0], :IncrementalSupport; size = 5) + test_support(u, (), [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0], :IncrementalSupport; + size = 9, curr = [-0.5, 0.5, 1.5, 2.5]) + test_support(u, (), [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0], :IncrementalSupport; + size = 10, curr = [-0.5, 0.5, 1.0, 1.5, 2.5]) + + cs = [0.0, 0.0, 0.0, 0.0] + tot = 1000 + for i in 1:tot + x = sample(u, ()) + cs[Int(floor(x)) + 2] += 1 + end + for j in 1:4 + @test isapprox(cs[j] / tot, 0.25; atol = 0.05) + end + @test isapprox(logcpdf(u, (), 0.0), log(0.25)) + @test isapprox(logcpdf(u, (), 5.0), -Inf64) + + @test isapprox(bounded_probs(u, [-1.0, 0.0, 1.0, 2.0, 3.0], ())[1], + [0.125, 0.25, 0.25, 0.25, 0.125]) + @test isapprox(bounded_probs(u, [-1.0, 0.0, 1.0, 2.0, 3.0], ())[2], + [0.125, 0.25, 0.25, 0.25, 0.125]) + @test isapprox(bounded_probs(u, [-1.0, -9.0, -8.0], ())[1], [0.0, 0.0, 1.0]) + end + @testset "Normal" begin n = SFuncs.Normal(-1.0,1.0) dist = Distributions.Normal(-1.0, 1.0) diff --git a/test/test_utils.jl b/test/test_utils.jl index 0ed1533f..d8996a88 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -1,7 +1,7 @@ using Test -using Scruff -using Scruff.Utils -using Scruff.RTUtils +using ..Scruff +using ..Scruff.Utils +using ..Scruff.RTUtils using AbstractTrees using DataStructures diff --git a/test/test_ve.jl b/test/test_ve.jl index 27bf7241..9f2fec19 100644 --- a/test/test_ve.jl +++ b/test/test_ve.jl @@ -1,11 +1,11 @@ using Test -using Scruff -using Scruff.Utils -using Scruff.RTUtils -using Scruff.Models -using Scruff.SFuncs -using Scruff.Operators -import Scruff.Algorithms: VE, ve, infer, probability, greedy_order, unconnected_neighbors, cost, copy_graph, eliminate +using ..Scruff +using ..Scruff.Utils +using ..Scruff.RTUtils +using ..Scruff.Models +using ..Scruff.SFuncs +using ..Scruff.Operators +import ..Scruff.Algorithms: VE, ve, infer, probability, greedy_order, unconnected_neighbors, cost, copy_graph, eliminate @testset "VE" begin From b99c0fc8f61658dc04f751be297cd537d1a7244d Mon Sep 17 00:00:00 2001 From: apfeffer Date: Fri, 31 Mar 2023 14:12:37 -0400 Subject: [PATCH 07/13] MultipleScore --- src/sfuncs.jl | 1 + src/sfuncs/score/multiplescore.jl | 15 +++++++++++++++ test/test_score.jl | 9 +++++++++ 3 files changed, 25 insertions(+) create mode 100644 src/sfuncs/score/multiplescore.jl diff --git a/src/sfuncs.jl b/src/sfuncs.jl index 72bdfc7c..ab47241e 100644 --- a/src/sfuncs.jl +++ b/src/sfuncs.jl @@ -19,6 +19,7 @@ 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") diff --git a/src/sfuncs/score/multiplescore.jl b/src/sfuncs/score/multiplescore.jl new file mode 100644 index 00000000..06c3a6ef --- /dev/null +++ b/src/sfuncs/score/multiplescore.jl @@ -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 + diff --git a/test/test_score.jl b/test/test_score.jl index c7201516..10c47dda 100644 --- a/test/test_score.jl +++ b/test/test_score.jl @@ -34,6 +34,15 @@ using ..Scruff.Utils @test get_log_score(s, :b) == -2.0 end + @testset "Multiple score" begin + s1 = SoftScore([:a, :b], [0.1, 0.2]) + s2 = LogScore([:b, :c], [-1.0, -2.0]) + s = MultipleScore([s1, s2]) + @test isapprox(get_log_score(s, :a), -Inf64) + @test isapprox(get_log_score(s, :b), log(0.2) - 1.0) + @test isapprox(get_log_score(s, :c), -Inf64) + end + @testset "Functional score" begin f(x) = 1.0 / x s = FunctionalScore{Float64}(f) From 728bc6fff5389833c5b6368c0158dcf15e799275 Mon Sep 17 00:00:00 2001 From: Michael Harradon Date: Fri, 22 Mar 2024 13:41:58 -0400 Subject: [PATCH 08/13] Add soccer example to docs --- docs/src/tutorial/examples.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/tutorial/examples.md b/docs/src/tutorial/examples.md index 8b43393e..48b6b216 100644 --- a/docs/src/tutorial/examples.md +++ b/docs/src/tutorial/examples.md @@ -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) From 6d10977e8b339e05141b88a29e596d1ade0c2f3f Mon Sep 17 00:00:00 2001 From: Michael Harradon Date: Fri, 22 Mar 2024 13:53:21 -0400 Subject: [PATCH 09/13] Update --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cbdb956..184384bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,9 +19,9 @@ jobs: strategy: matrix: version: - - '1.6' - - '1.7' - '1.8' + - '1.9' + - '1.10' - 'nightly' os: - ubuntu-latest From d0ac4747500c350d7ad0dcecada2100e2fd5b501 Mon Sep 17 00:00:00 2001 From: Michael Harradon Date: Fri, 22 Mar 2024 13:58:38 -0400 Subject: [PATCH 10/13] Get rid of relative paths in tests --- test/test_bp.jl | 14 +++++++------- test/test_bp_logger.jl | 12 ++++++------ test/test_core.jl | 10 +++++----- test/test_filter.jl | 14 +++++++------- test/test_importance.jl | 12 ++++++------ test/test_logger.jl | 12 ++++++------ test/test_lsfi.jl | 14 +++++++------- test/test_net.jl | 6 +++--- test/test_score.jl | 8 ++++---- test/test_sfuncs.jl | 10 +++++----- test/test_utils.jl | 6 +++--- test/test_ve.jl | 14 +++++++------- 12 files changed, 66 insertions(+), 66 deletions(-) diff --git a/test/test_bp.jl b/test/test_bp.jl index cebbfd31..b0e8fc35 100644 --- a/test/test_bp.jl +++ b/test/test_bp.jl @@ -5,13 +5,13 @@ import Scruff.Operators.bounded_probs import Scruff.Operators.range using Test -using ..Scruff -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.SFuncs -using ..Scruff.Models -using ..Scruff.Operators -import ..Scruff.Algorithms: three_pass_BP, loopy_BP, ThreePassBP, LoopyBP, infer, probability +using Scruff +using Scruff.Utils +using Scruff.RTUtils +using Scruff.SFuncs +using Scruff.Models +using Scruff.Operators +import Scruff.Algorithms: three_pass_BP, loopy_BP, ThreePassBP, LoopyBP, infer, probability @testset "BP" begin diff --git a/test/test_bp_logger.jl b/test/test_bp_logger.jl index 5d8db55f..d7988d79 100644 --- a/test/test_bp_logger.jl +++ b/test/test_bp_logger.jl @@ -1,11 +1,11 @@ include("..//src//utils//logplots.jl") -using ..Scruff -using ..Scruff.SFuncs -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.Models -import ..Scruff.Algorithms +using Scruff +using Scruff.SFuncs +using Scruff.Utils +using Scruff.RTUtils +using Scruff.Models +import Scruff.Algorithms pyplot() diff --git a/test/test_core.jl b/test/test_core.jl index a0243fdf..b1819d7d 100644 --- a/test/test_core.jl +++ b/test/test_core.jl @@ -5,11 +5,11 @@ using Plots import Distributions -using ..Scruff -using ..Scruff.Operators -using ..Scruff.MultiInterface -using ..Scruff.Models -using ..Scruff.SFuncs +using Scruff +using Scruff.Operators +using Scruff.MultiInterface +using Scruff.Models +using Scruff.SFuncs import Scruff: make_initial, make_transition import Scruff.Models: get_dt diff --git a/test/test_filter.jl b/test/test_filter.jl index c3986c60..9a4fb7ce 100644 --- a/test/test_filter.jl +++ b/test/test_filter.jl @@ -1,12 +1,12 @@ using Test -using ..Scruff -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.Models -using ..Scruff.SFuncs -using ..Scruff.Algorithms -import ..Scruff: make_initial, make_transition +using Scruff +using Scruff.Utils +using Scruff.RTUtils +using Scruff.Models +using Scruff.SFuncs +using Scruff.Algorithms +import Scruff: make_initial, make_transition @testset "Filtering" begin diff --git a/test/test_importance.jl b/test/test_importance.jl index fbdefb0c..c6333fde 100644 --- a/test/test_importance.jl +++ b/test/test_importance.jl @@ -3,12 +3,12 @@ import Base.isapprox import PrettyPrint using Test -using ..Scruff -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.SFuncs -using ..Scruff.Algorithms -import ..Scruff.Operators: cpdf +using Scruff +using Scruff.Utils +using Scruff.RTUtils +using Scruff.SFuncs +using Scruff.Algorithms +import Scruff.Operators: cpdf @testset "Importance" begin diff --git a/test/test_logger.jl b/test/test_logger.jl index c1c12bf5..781d1c80 100644 --- a/test/test_logger.jl +++ b/test/test_logger.jl @@ -1,12 +1,12 @@ using Test using Logging -using ..Scruff -using ..Scruff.Models -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.SFuncs -using ..Scruff.Operators +using Scruff +using Scruff.Models +using Scruff.Utils +using Scruff.RTUtils +using Scruff.SFuncs +using Scruff.Operators @testset "test loggers" begin x1 = Cat([1,2], [0.1, 0.9])()(:x1) diff --git a/test/test_lsfi.jl b/test/test_lsfi.jl index e69d26bc..1476aa70 100644 --- a/test/test_lsfi.jl +++ b/test/test_lsfi.jl @@ -3,13 +3,13 @@ import Base.isapprox import PrettyPrint using Test -using ..Scruff -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.Models -using ..Scruff.SFuncs -using ..Scruff.Operators -import ..Scruff.Algorithms: LSFI, probability_bounds, prepare, refine, ve +using Scruff +using Scruff.Utils +using Scruff.RTUtils +using Scruff.Models +using Scruff.SFuncs +using Scruff.Operators +import Scruff.Algorithms: LSFI, probability_bounds, prepare, refine, ve using Scruff.MultiInterface diff --git a/test/test_net.jl b/test/test_net.jl index 1711c610..4e96ff7c 100644 --- a/test/test_net.jl +++ b/test/test_net.jl @@ -1,7 +1,7 @@ using Test -using ..Scruff -using ..Scruff.SFuncs -using ..Scruff.Operators +using Scruff +using Scruff.SFuncs +using Scruff.Operators @testset "net" begin @testset "Build NetworkSFunc" begin diff --git a/test/test_score.jl b/test/test_score.jl index 10c47dda..53a91a54 100644 --- a/test/test_score.jl +++ b/test/test_score.jl @@ -1,8 +1,8 @@ using Test -using ..Scruff -using ..Scruff.Operators -using ..Scruff.SFuncs -using ..Scruff.Utils +using Scruff +using Scruff.Operators +using Scruff.SFuncs +using Scruff.Utils @testset "Score" begin diff --git a/test/test_sfuncs.jl b/test/test_sfuncs.jl index 4256c578..18be3e82 100755 --- a/test/test_sfuncs.jl +++ b/test/test_sfuncs.jl @@ -1,9 +1,9 @@ using Test -using ..Scruff -using ..Scruff.Operators -using ..Scruff.MultiInterface -using ..Scruff.SFuncs -using ..Scruff.Utils +using Scruff +using Scruff.Operators +using Scruff.MultiInterface +using Scruff.SFuncs +using Scruff.Utils import Distributions function test_support(sf::SFunc{I,O}, parranges, target, quality; diff --git a/test/test_utils.jl b/test/test_utils.jl index d8996a88..0ed1533f 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -1,7 +1,7 @@ using Test -using ..Scruff -using ..Scruff.Utils -using ..Scruff.RTUtils +using Scruff +using Scruff.Utils +using Scruff.RTUtils using AbstractTrees using DataStructures diff --git a/test/test_ve.jl b/test/test_ve.jl index 9f2fec19..27bf7241 100644 --- a/test/test_ve.jl +++ b/test/test_ve.jl @@ -1,11 +1,11 @@ using Test -using ..Scruff -using ..Scruff.Utils -using ..Scruff.RTUtils -using ..Scruff.Models -using ..Scruff.SFuncs -using ..Scruff.Operators -import ..Scruff.Algorithms: VE, ve, infer, probability, greedy_order, unconnected_neighbors, cost, copy_graph, eliminate +using Scruff +using Scruff.Utils +using Scruff.RTUtils +using Scruff.Models +using Scruff.SFuncs +using Scruff.Operators +import Scruff.Algorithms: VE, ve, infer, probability, greedy_order, unconnected_neighbors, cost, copy_graph, eliminate @testset "VE" begin From dc6fc7c4183dbea28a6f26a9cb6bfd37f851864a Mon Sep 17 00:00:00 2001 From: Michael Harradon Date: Fri, 22 Mar 2024 14:02:16 -0400 Subject: [PATCH 11/13] Remove some unused deps --- Project.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Project.toml b/Project.toml index fdeac771..a660bf0a 100644 --- a/Project.toml +++ b/Project.toml @@ -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" @@ -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" From 2a35f43b0cc299b32a4ad0a239d92b6d9dc28213 Mon Sep 17 00:00:00 2001 From: Michael Harradon Date: Fri, 22 Mar 2024 14:21:38 -0400 Subject: [PATCH 12/13] Bump version number --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index a660bf0a..12d66c59 100644 --- a/Project.toml +++ b/Project.toml @@ -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" From 2901596f667afe764618d12aeae1491ca3aa6f89 Mon Sep 17 00:00:00 2001 From: Michael Harradon Date: Fri, 22 Mar 2024 15:32:12 -0400 Subject: [PATCH 13/13] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7253fc65..a771c48d 100644 --- a/README.md +++ b/README.md @@ -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.