Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing the bug in issue #563 #564

Merged
merged 6 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/src/systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ fix_parameters(F::AbstractSystem, p)
```@docs
RandomizedSystem
```

## Real Systems
```@docs
is_real
```
66 changes: 55 additions & 11 deletions src/certification.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
is_complex(certificate::AbstractSolutionCertificate)

Returns `true` if `certificate` certifies that the certified solution interval
contains a true complex zero of the system.
contains a non-real complex zero of the system.
"""
is_complex(C::AbstractSolutionCertificate) = C.complex

Expand Down Expand Up @@ -320,7 +320,6 @@
cert::AbstractSolutionCertificate,
)
d = squared_distance_interval(cert, distinct_sols.reference_point)

for match in IntervalTrees.intersect(distinct_sols.distinct_tree, d)
certᵢ = IntervalTrees.value(match)
if Bool(Arblib.overlaps(cert.I, certᵢ.I))
Expand Down Expand Up @@ -752,6 +751,8 @@
throw(ArgumentError("The given system expects parameters but none are given."))
end

is_real_system = ModelKit.is_real(F)

Check warning on line 754 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L754

Added line #L754 was not covered by tests

distinct_sols =
DistinctSolutionCertificates(n; extended_certificate = extended_certificate)
ncertified = Threads.Atomic{Int}(0)
Expand Down Expand Up @@ -793,7 +794,8 @@
s,
Tp[tid],
Tcache[tid],
i;
i,
is_real_system;
extended_certificate = extended_certificate,
certify_solution_kwargs...,
)
Expand Down Expand Up @@ -853,7 +855,8 @@
s,
p,
cache,
i;
i,
is_real_system;
extended_certificate = extended_certificate,
certify_solution_kwargs...,
)
Expand Down Expand Up @@ -930,7 +933,6 @@
)
end


function certify_solution(
F::AbstractSystem,
solution_candidate::AbstractVector,
Expand All @@ -940,6 +942,30 @@
max_precision::Int = 256,
refine_solution::Bool = true,
extended_certificate::Bool = false,
)
certify_solution(

Check warning on line 946 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L946

Added line #L946 was not covered by tests
F,
solution_candidate,
cert_params,
cert_cache,
index,
ModelKit.is_real(F);
max_precision = max_precision,
refine_solution = refine_solution,
extended_certificate = extended_certificate,
)
end

function certify_solution(

Check warning on line 959 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L959

Added line #L959 was not covered by tests
F::AbstractSystem,
solution_candidate::AbstractVector,
cert_params::Union{Nothing,CertificationParameters},
cert_cache::CertificationCache,
index::Int,
is_real_system::Bool;
max_precision::Int = 256,
refine_solution::Bool = true,
extended_certificate::Bool = false,
)
@unpack C, arb_C, arb_x̃₀ = cert_cache

Expand All @@ -966,13 +992,21 @@

certified, x₁, x₀, is_real = ε_inflation_krawczyk(x̃₀, cert_params, C, cert_cache)

if !is_real_system
is_real = false

Check warning on line 996 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L995-L996

Added lines #L995 - L996 were not covered by tests
end

if certified
is_complex = any(xi -> !(0.0 in imag(xi)), x₁)
if is_complex
is_real = false

Check warning on line 1002 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L1000-L1002

Added lines #L1000 - L1002 were not covered by tests
end
if extended_certificate
return ExtendedSolutionCertificate(
solution_candidate = solution_candidate,
certified = true,
real = is_real,
complex = any(xi -> !(0.0 in imag(xi)), x₁),
complex = is_complex,
index = index,
prec = 53,
I = AcbMatrix(x₀; prec = 53),
Expand All @@ -986,7 +1020,7 @@
solution_candidate = solution_candidate,
certified = true,
real = is_real,
complex = any(xi -> !(0.0 in imag(xi)), x₁),
complex = is_complex,
index = index,
prec = 53,
I = AcbMatrix(x₁; prec = 53),
Expand All @@ -1001,7 +1035,8 @@
x̃₀,
cert_params,
cert_cache,
index;
index,
is_real_system;
max_precision = max_precision,
extended_certificate = extended_certificate,
)
Expand All @@ -1013,7 +1048,8 @@
x̃₀::AbstractVector,
cert_params::Union{Nothing,CertificationParameters},
cert_cache::CertificationCache,
index::Int;
index::Int,
is_real_system::Bool;
max_precision::Int = 256,
extended_certificate::Bool = false,
)
Expand All @@ -1036,9 +1072,17 @@
certified, arb_x₁, arb_x₀, is_real =
arb_ε_inflation_krawczyk(arb_x̃₀, cert_params, arb_C, cert_cache; prec = prec)

if !is_real_system
is_real = false

Check warning on line 1076 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L1075-L1076

Added lines #L1075 - L1076 were not covered by tests
end

if certified
I = AcbMatrix(n, 1; prec = prec)
Arblib.set!(I, arb_x₀)
is_complex = any(xi -> !Arblib.contains_zero(Arblib.imagref(xi)), arb_x₁)
if is_complex
is_real = false

Check warning on line 1084 in src/certification.jl

View check run for this annotation

Codecov / codecov/patch

src/certification.jl#L1082-L1084

Added lines #L1082 - L1084 were not covered by tests
end

if extended_certificate
I′ = AcbMatrix(n, 1; prec = prec)
Expand All @@ -1051,7 +1095,7 @@
solution_candidate = solution_candidate,
certified = true,
real = is_real,
complex = any(xi -> !Arblib.contains_zero(Arblib.imagref(xi)), arb_x₁),
complex = is_complex,
index = index,
prec = prec,
I = I,
Expand All @@ -1066,7 +1110,7 @@
solution_candidate = solution_candidate,
certified = true,
real = is_real,
complex = any(xi -> !Arblib.contains_zero(Arblib.imagref(xi)), arb_x₁),
complex = is_complex,
index = index,
prec = prec,
I = I,
Expand Down
16 changes: 15 additions & 1 deletion src/model_kit/abstract_system_homotopy.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export AbstractSystem, AbstractHomotopy, jacobian
export AbstractSystem, AbstractHomotopy, jacobian, is_real

"""
AbstractSystem
Expand Down Expand Up @@ -75,6 +75,20 @@
ModelKit.to_smallest_eltype(U)
end

"""
is_real(F::AbstractSystem)

Checks, if `F(ℝⁿ) ⊂ ℝᵐ`, where `(m,n) = size(F)`.
This is an algorithm that works with probability one:
It randomly samples `x ∈ ℝⁿ` and checks if `F(x) ∈ ℝᵐ`.
"""
function is_real(F::T) where {T<:AbstractSystem}
x = randn(Float64, size(F, 2))
u = F(x)
all(ui -> imag(ui) == 0, u)

Check warning on line 88 in src/model_kit/abstract_system_homotopy.jl

View check run for this annotation

Codecov / codecov/patch

src/model_kit/abstract_system_homotopy.jl#L85-L88

Added lines #L85 - L88 were not covered by tests
end


##############
## Homotopy ##
##############
Expand Down
16 changes: 15 additions & 1 deletion test/certification_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@
@test ndistinct_real_certified(cert) == 4
end

@testset "Reality Check" begin

@var x
x0 = [1.0]

F = System([x - 1 + 1e-16 * im])
certF = certify(F, [x0])
@test is_real(certificates(certF)[1]) == false

G = System([x - 1])
certG = certify(G, [x0])
@test is_real(certificates(certG)[1]) == true
end

@testset "Parameters: Input = Vector{Expression}" begin
@var x y
f = (x^4 + y^4 - 1) * (x^2 + y^2 - 2) + x^5 * y
Expand Down Expand Up @@ -337,7 +351,7 @@
f = fixed(F)
c = HomotopyContinuation.CertificationCache(f)
q = HomotopyContinuation.certification_parameters(p)
cert = HomotopyContinuation.certify_solution(f, sol, q, c, 1)
cert = HomotopyContinuation.certify_solution(f, sol, q, c, 1, false)
@test is_certified(cert)
end
end
8 changes: 8 additions & 0 deletions test/systems_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,12 @@ end
G = SlicedSystem(g, L)
test_system(G, System(G))
end

@testset "is_real" begin
@var x
f = System([x - 1])
g = System([x - 1 + 1e-16 * im])
@test ModelKit.is_real(fixed(f)) == true
@test ModelKit.is_real(fixed(g)) == false
end
end
Loading