From 950879e28a53cef533027c566de803cee3a3dd8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 00:52:50 +0200 Subject: [PATCH 01/13] Update CI.yml --- .github/workflows/CI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 099f7ca..2e12187 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -32,7 +32,7 @@ jobs: with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 + - uses: actions/cache@v4 env: cache-name: cache-artifacts with: From c4c77bf68ff499632c3413a24739e1941e3aaa40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 00:53:28 +0200 Subject: [PATCH 02/13] Update Project.toml --- Project.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index d5a9e06..f14f23c 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "AffineArithmetic" uuid = "2e89c364-fad6-56cb-99bd-ebadcd2cf8d2" authors = ["dpsanders"] -version = "0.2.1" +version = "0.3.0" [deps] IntervalArithmetic = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253" @@ -9,10 +9,10 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" [compat] -IntervalArithmetic = "0.16, 0.17, 0.18, 0.19, 0.20" +IntervalArithmetic = "0.22" Polynomials = "0.6, 1, 2, 3" StaticArrays = "0.12, 1" -julia = "1" +julia = "1.9" [extras] Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" From 28f00ab542dc47ce8ed3b4be8afe2e91bf27524e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 00:54:45 +0200 Subject: [PATCH 03/13] Delete .codecov.yml --- .codecov.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .codecov.yml diff --git a/.codecov.yml b/.codecov.yml deleted file mode 100644 index 69cb760..0000000 --- a/.codecov.yml +++ /dev/null @@ -1 +0,0 @@ -comment: false From bcc18964324f61f476f5a6a69bf53cfc8f807d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 00:56:24 +0200 Subject: [PATCH 04/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6447db1..80c1f6f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# `AffineArithmetic.jl` +# AffineArithmetic [![Build Status](https://github.com/juliaintervals/AffineArithmetic.jl/workflows/CI/badge.svg)](https://github.com/juliaintervals/AffineArithmetic.jl/actions) From c0451e306e48af6fa7a610a8eba48acbd45933f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:01:32 +0200 Subject: [PATCH 05/13] Update aff.jl --- src/aff.jl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/aff.jl b/src/aff.jl index 8f8db90..fbd23da 100644 --- a/src/aff.jl +++ b/src/aff.jl @@ -33,7 +33,7 @@ function Aff(X::Interval{T}, n, i) where {T} γ = SVector(ntuple(j->i==j ? r : zero(r), n)) - return Aff(c, γ, Interval{T}(0)) + return Aff(c, γ, zero(Interval{T})) end +(x::Aff{N,T}, y::Aff{N,T}) where {N,T} = Aff(x.c + y.c, x.γ .+ y.γ, x.Δ + y.Δ) @@ -41,7 +41,7 @@ end -(x::Aff{N,T}, y::Aff{N,T}) where {N,T} = Aff(x.c - y.c, x.γ .- y.γ, x.Δ - y.Δ) -interval(C::Aff) = C.c + sum(abs.(C.γ))*(-1..1) + C.Δ +interval(C::Aff) = C.c + sum(abs.(C.γ))*interval(-1, 1) + C.Δ function *(x::Aff{N,T}, y::Aff{N,T}) where {N,T} @@ -49,14 +49,14 @@ function *(x::Aff{N,T}, y::Aff{N,T}) where {N,T} γ = x.c .* y.γ + y.c .* x.γ - Δ = (x.γ ⋅ y.γ) * (0..1) # ϵ_i^2 + Δ = (x.γ ⋅ y.γ) * interval(0, 1) # ϵ_i^2 if N > 1 - Δ += sum(x.γ[i] * y.γ[j] for i in 1:N, j in 1:N if i ≠ j) * (-1..1) # ϵ_i * ϵ_j + Δ += sum(x.γ[i] * y.γ[j] for i in 1:N, j in 1:N if i ≠ j) * interval(-1, 1) # ϵ_i * ϵ_j end - Δ += (x.c + sum(abs.(x.γ))*(-1..1)) * y.Δ - Δ += (y.c + sum(abs.(y.γ))*(-1..1)) * x.Δ + Δ += (x.c + sum(abs.(x.γ))*interval(-1, 1)) * y.Δ + Δ += (y.c + sum(abs.(y.γ))*interval(-1, 1)) * x.Δ Δ += x.Δ * y.Δ @@ -97,12 +97,12 @@ end Base.literal_pow(::typeof(^), x::Aff, ::Val{p}) where {p} = x^p -x = Aff{2,Float64}(0.0, SVector(1.0, 0.0), 0..0) -y = Aff{2,Float64}(0.0, SVector(0.0, 1.0), 0..0) +# x = Aff{2,Float64}(0.0, SVector(1.0, 0.0), 0..0) +# y = Aff{2,Float64}(0.0, SVector(0.0, 1.0), 0..0) -x = Aff(3..5, 2, 1) -y = Aff(2..4, 2, 2) +# x = Aff(3..5, 2, 1) +# y = Aff(2..4, 2, 2) # # 3-x # interval(3-x) @@ -173,21 +173,21 @@ end function Base.sqrt(x::Aff, X=interval(x)) - a, b = X.lo, X.hi + a, b = bounds(X) # @show a, b # min-range: de Figuereido book, pg. 64 α = 1 / (2*√b) ζ = (√b) / 2 - δ = ( (√(b) - √(a))^2 / (2*√b) ) * (-1..1) + δ = ( (√(b) - √(a))^2 / (2*√b) ) * interval(-1, 1) return affine_approx(x, α, ζ, δ) end function Base.inv(x::Aff, X=interval(x)) - a, b = X.lo, X.hi + a, b = bounds(X) # @show a, b @@ -195,7 +195,7 @@ function Base.inv(x::Aff, X=interval(x)) α = -1 / (b^2) d = interval(1/b - α*b, 1/a - α*a) ζ = mid(d) - δ = radius(d) * (-1..1) + δ = radius(d) * interval(-1, 1) if a < 0 ζ = -ζ From ece8db97ba4067272b01443cbf6e03eb21a66213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:04:59 +0200 Subject: [PATCH 06/13] Update affine.jl --- src/affine.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/affine.jl b/src/affine.jl index 9ff7fce..040bff1 100644 --- a/src/affine.jl +++ b/src/affine.jl @@ -20,11 +20,11 @@ interval(x::Affine) = x.range range(x::Affine) = x.range eltype(::Affine{N, T}) where {N, T} = T -zero(::Affine{N, T}) where {N, T} = Affine(Interval(zero(T))) -zero(::Type{Affine{T}}) where {T} = Affine(Interval(zero(T))) +zero(::Affine{N, T}) where {N, T} = Affine(zero(Interval{T})) +zero(::Type{Affine{T}}) where {T} = Affine(zero(Interval{T})) -one(::Affine{T}) where T = Affine(Interval(one(T))) -one(::Type{Affine{T}}) where T = Affine(Interval(one(T))) +one(::Affine{T}) where T = Affine(one(Interval{T})) +one(::Type{Affine{T}}) where T = Affine(one(Interval{T})) function Base.show(io::IO, C::Affine{N,T}) where {N,T} print(io, "affine=", C.affine, "; range=", C.range) @@ -40,7 +40,7 @@ function Affine(X::Interval{T}, n, i) where {T} end Affine(X::Interval) = Affine(X, 1, 1) -Affine(X::Number) = Affine(Interval(X), 1, 1) +Affine(X::Number) = Affine(interval(X), 1, 1) affine(Xs::Interval...) = Affine.(Xs, length(Xs), 1:length(Xs)) @@ -50,7 +50,7 @@ for op in (:+, :*, :-) range = $op(x.range, y.range) - range = range ∩ interval(affine) + range = intersect_interval(range, interval(affine)) return Affine(affine, range) end @@ -62,7 +62,7 @@ for op in (:sqrt, :inv) range = $op(x.range) - range = range ∩ interval(affine) + range = intersect_interval(range, interval(affine)) return Affine(affine, range) end From 1cd343ccf2ee7bdd9b50c237ff8c3e61e5629d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:08:48 +0200 Subject: [PATCH 07/13] Update full_affine.jl --- src/full_affine.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/full_affine.jl b/src/full_affine.jl index 58eebe6..caae2dd 100644 --- a/src/full_affine.jl +++ b/src/full_affine.jl @@ -1,4 +1,3 @@ - const affine_index = [1] # which affine vector index to use reset_affine_index() = affine_index[1] = 1 @@ -40,7 +39,7 @@ end # conversion of numerical constant to affine: FullAffine(c::Real) = FullAffine(c, Float64[]) -range(C::FullAffine) = C.c + sum(abs.(C.γ))*(-1..1) +range(C::FullAffine) = C.c + sum(abs.(C.γ))*interval(-1, 1) range(X::Interval) = X # morally: From ec6d5c8b9adfbe0ce396e183368cc86cf3351fcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:10:06 +0200 Subject: [PATCH 08/13] Update affine.jl --- src/affine.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/affine.jl b/src/affine.jl index 040bff1..cc2f96b 100644 --- a/src/affine.jl +++ b/src/affine.jl @@ -20,11 +20,12 @@ interval(x::Affine) = x.range range(x::Affine) = x.range eltype(::Affine{N, T}) where {N, T} = T + zero(::Affine{N, T}) where {N, T} = Affine(zero(Interval{T})) -zero(::Type{Affine{T}}) where {T} = Affine(zero(Interval{T})) +zero(::Type{Affine{N, T}}) where {N, T} = Affine(zero(Interval{T})) -one(::Affine{T}) where T = Affine(one(Interval{T})) -one(::Type{Affine{T}}) where T = Affine(one(Interval{T})) +one(::Affine{N, T}) where {N, T} = Affine(one(Interval{T})) +one(::Type{Affine{N, T}}) where {N, T} = Affine(one(Interval{T})) function Base.show(io::IO, C::Affine{N,T}) where {N,T} print(io, "affine=", C.affine, "; range=", C.range) From c17d2cc13951195c76a1a955d381ae75995b235f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:17:15 +0200 Subject: [PATCH 09/13] Update runtests.jl --- test/runtests.jl | 52 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index b5f4ba9..1535474 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,38 +4,38 @@ using Test using AffineArithmetic: Aff @testset "Construction from intervals" begin - X = 1..3 + X = interval(1, 3) X_a = Affine(X) X_a isa Affine - Y = 2..4 + Y = interval(2, 4) Y_a = Affine(Y) - @test Y_a.range == 2..4 - @test Y_a.affine == Aff(3.0, SVector{1, Float64}(1.0), 0..0) + @test isequal_interval(Y_a.range, interval(2, 4)) + @test Y_a.affine == Aff(3.0, SVector{1, Float64}(1.0), interval(0)) sum_a = X_a + Y_a - @test sum_a.range == 3..7 - @test sum_a.affine == Aff(5.0, SVector{1, Float64}(2.0), 0..0) + @test isequal_interval(sum_a.range, interval(3, 7)) + @test sum_a.affine == Aff(5.0, SVector{1, Float64}(2.0), interval(0)) prod_a = X_a * Y_a - @test prod_a.range == 2..12 - @test prod_a.affine == Aff(6.0, SVector{1, Float64}(5.0), 0..1) + @test isequal_interval(prod_a.range, interval(2, 12)) + @test prod_a.affine == Aff(6.0, SVector{1, Float64}(5.0), interval(0, 1)) end @testset "Small powers and range" begin - X = 1..3 + X = interval(1, 3) Y = Affine(X) f(x) = x^2 - x + 1 - @test range(f(X)) == -1..9 - @test range(f(Y)) == 0..7 # affine is a little better + @test isequal_interval(range(f(X)), interval(-1, 9)) + @test isequal_interval(range(f(Y)), interval(0, 7)) # affine is a little better g(x) = (x - 1)^3 - @test range(g(X)) == 0..8 - @test range(g(Y)) == 0..8 # affine gives the same + @test isequal_interval(range(g(X)), interval(0, 8)) + @test isequal_interval(range(g(Y)), interval(0, 8)) # affine gives the same end reset_affine_index() @@ -43,15 +43,15 @@ reset_affine_index() @testset "Matrix multiplication" begin A = 0.5 * [1 2; -1 1] - X = Affine(-1..1) - Y = Affine(-1..1) + X = Affine(interval(-1, 1)) + Y = Affine(interval(-1, 1)) XX = [X, Y] - @test XX == [Affine(Aff(0.0, SVector{1, Float64}(1.0), 0..0), -1..1), - Affine(Aff(0.0, SVector{1, Float64}(1.0), 0..0), -1..1)] + @test all(isequal_interval.(XX, [Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1)), + Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1))])) - @test A * XX == [Affine(Aff(0.0, SVector{1, Float64}(1.5), 0..0), -1.5 .. 1.5), - Affine(Aff(0.0, SVector{1, Float64}(0.0), 0..0), 0..0)] + @test all(isequal_interval.(A * XX, [Affine(Aff(0.0, SVector{1, Float64}(1.5), interval(0)), interval(-1.5, 1.5)), + Affine(Aff(0.0, SVector{1, Float64}(0.0), interval(0)), interval(0))])) end reset_affine_index() @@ -61,18 +61,18 @@ reset_affine_index() p = Polynomial([-3, 1]) # x - 3 p2 = p^8 - x = 4 ± 1e-4 + x = interval(4, 1e-4; format = :midpoint) y = Affine(x) - @test (-70..70) ⊆ range(p2(x)) - @test range(p2(y)) ⊆ 0.998..1.002 # affine is extremely much better! + @test issubset_interval(interval(-70, 70), range(p2(x))) + @test issubset_interval(range(p2(y)), interval(0.998, 1.002)) # affine is extremely much better! end @testset "Constructors with intervals" begin - X = Affine(1..2) + X = Affine(interval(1, 2)) @test X isa Affine - @test X - X == Affine(0..0) + @test X - X == Affine(interval(0)) - x, y = affine(1..2, 3..4) - @test interval(x + y - x - y) == 0..0 + x, y = affine(interval(1, 2), interval(3, 4)) + @test isequal_interval(interval(x + y - x - y), interval(0)) end From aa5f9a2836e9c52e13f14005f200c3cae933a11a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:22:57 +0200 Subject: [PATCH 10/13] Update aff.jl --- src/aff.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aff.jl b/src/aff.jl index fbd23da..b291bbc 100644 --- a/src/aff.jl +++ b/src/aff.jl @@ -22,7 +22,7 @@ function Base.show(io::IO, C::Aff{N,T}) where {N,T} print(io, "⟨", C.c, "; ", C.γ, "; ", C.Δ, "⟩") end -==(C::Aff, D::Aff) = C.c == D.c && C.γ == D.γ && C.Δ == D.Δ +==(C::Aff, D::Aff) = C.c == D.c && C.γ == D.γ && isequal_interval(C.Δ, D.Δ) """ Make an `Aff` based on an interval, which is number `i` of `n` total variables. From fbc2ae0ab49dc0972dedaf7ebe7423686a87147f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:23:32 +0200 Subject: [PATCH 11/13] Update affine.jl --- src/affine.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/affine.jl b/src/affine.jl index cc2f96b..d9c17b7 100644 --- a/src/affine.jl +++ b/src/affine.jl @@ -31,7 +31,7 @@ function Base.show(io::IO, C::Affine{N,T}) where {N,T} print(io, "affine=", C.affine, "; range=", C.range) end -==(C::Affine, D::Affine) = C.affine == D.affine && C.range == D.range +==(C::Affine, D::Affine) = C.affine == D.affine && isequal_interval(C.range, D.range) """ Make an `Affine` based on an interval, which is number `i` of `n` total variables. From ef8f273cbee71d14537fdf3533c140952800791e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:27:59 +0200 Subject: [PATCH 12/13] Update runtests.jl --- test/runtests.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 1535474..4f82c7d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -47,11 +47,11 @@ reset_affine_index() Y = Affine(interval(-1, 1)) XX = [X, Y] - @test all(isequal_interval.(XX, [Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1)), - Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1))])) + @test XX == [Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1)), + Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1))] - @test all(isequal_interval.(A * XX, [Affine(Aff(0.0, SVector{1, Float64}(1.5), interval(0)), interval(-1.5, 1.5)), - Affine(Aff(0.0, SVector{1, Float64}(0.0), interval(0)), interval(0))])) + @test A * XX == [Affine(Aff(0.0, SVector{1, Float64}(1.5), interval(0)), interval(-1.5, 1.5)), + Affine(Aff(0.0, SVector{1, Float64}(0.0), interval(0)), interval(0))])) end reset_affine_index() From 9af3d2890a1390fc624d83cbcd3373b46da11599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20H=C3=A9not?= <38465572+OlivierHnt@users.noreply.github.com> Date: Sat, 26 Apr 2025 01:30:56 +0200 Subject: [PATCH 13/13] Update runtests.jl --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 4f82c7d..0b7d3d2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -51,7 +51,7 @@ reset_affine_index() Affine(Aff(0.0, SVector{1, Float64}(1.0), interval(0)), interval(-1, 1))] @test A * XX == [Affine(Aff(0.0, SVector{1, Float64}(1.5), interval(0)), interval(-1.5, 1.5)), - Affine(Aff(0.0, SVector{1, Float64}(0.0), interval(0)), interval(0))])) + Affine(Aff(0.0, SVector{1, Float64}(0.0), interval(0)), interval(0))] end reset_affine_index()