Skip to content

Decoupled Homotopy #23

Description

@oameye

https://arxiv.org/pdf/[2208.08179v1](https://arxiv.org/pdf/2208.08179v1)

using HomotopyContinuation, LinearAlgebra
import Base.Iterators: product


struct OscillatorCache{T₁,T₂<:Tracker}
    s::Vector{ComplexF64}
    tracker_step_1::T₁
    tracker_step_2::T₂
end

## Define N = number of oscillators
N = 2
M = 2(N + 3)N
println("N = $N")
println("5^N = $(5^N)")

## Start Parameters p₀
p₀ = [randn(ComplexF64, 8) for _ in 1:N]

## Middle Parameters p₁
p₁ = [zeros(8 * N); randn(ComplexF64, M - N * 8)]

## Target Parameters p
p = randn(Float64, M)

## Start System
time_ss = @elapsed begin
    println("\n Computing Start System")
    ## Start System
    @var u₀, v₀
    @var a₀[1:4], b₀[1:4]
    n² = u₀^2 + v₀^2

    f = a₀[1] ** u₀ + a₀[2] * u₀ + a₀[3] * v₀ + a₀[4]
    g = b₀[1] ** v₀ + b₀[2] * u₀ + b₀[3] * v₀ + b₀[4]
    variables₀ = [u₀; v₀]
    parameters₀ = [a₀; b₀]

    Start_System = System([f; g],
        variables=variables₀,
        parameters=parameters₀)

    ## Start solutions
    p_single = randn(ComplexF64, 8)
    S₀ = solve(Start_System, target_parameters=p_single,
        show_progress=false)

    S = solve(Start_System,
        solutions(S₀),
        start_parameters=p_single,
        target_parameters=p₀,
        transform_result=(R, pᵢ) -> solutions(R),
        show_progress=false)

end
println("setting up start system = $time_ss seconds\n")

## Target system
@var u[1:N], v[1:N]
@var a[1:4, 1:N], b[1:4, 1:N]
@var c[1:N, 1:N], d[1:N, 1:N]
params = [vcat([[a[:, i]; b[:, i]] for i in 1:N]...);
    [c[i, j] for i in 1:N, j = 1:N if i != j];
    [d[i, j] for i in 1:N, j = 1:N if i != j]]

C = map(product(1:N, 1:N)) do (i, j)
    if i == j
        0
    else
        c[i, j]
    end
end
D = map(product(1:N, 1:N)) do (i, j)
    if i == j
        0
    else
        d[i, j]
    end
end

fs = [subs(f,
    variables₀ => [u[i], v[i]],
    parameters₀ => [a[:, i]; b[:, i]]) for i in 1:N]
gs = [subs(g,
    variables₀ => [u[i], v[i]],
    parameters₀ => [a[:, i]; b[:, i]]) for i in 1:N]

F = System([fs + C * v; gs + D * u],
    variables=[u; v],
    parameters=params)

## Tracking
@var t

F₁ = System(F([u; v], [vcat(p₀...); zeros(M - N * 8)] + (1 - t) .* p₁),
    variables=[u; v], parameters=[t])
F₂ = System(F([u; v], t .* p₁ + (1 - t) .* p),
    variables=[u; v], parameters=[t])
tracker₁ = Tracker(ParameterHomotopy(F₁, [1], [0]))
tracker₂ = Tracker(ParameterHomotopy(F₂, [1], [0]))

start_solution_iterator = Iterators.product(S...)

println("\n Solving Target System")
function oscillator_track(x::NTuple{N,Vector{ComplexF64}}, cache::OscillatorCache)
    s = cache.s
    for (j, xᵢ) in enumerate(x)
        s[j] = xᵢ[1]
        s[N+j] = xᵢ[2]
    end
    T = cache.tracker_step_1
    track!(T, s, 1, 0)
    s = T.state.x
    T = cache.tracker_step_2
    res = track!(T, s, 1, 0)
    if is_success(res)
        return copy(T.state.x)
    end
    nothing
end

cache = OscillatorCache(zeros(ComplexF64, 2 * N), tracker₁, tracker₂)

X = Vector{Union{Vector{ComplexF64},Nothing}}()
time_b = @elapsed for x in start_solution_iterator
    push!(X, oscillator_track(x, cache))
end
println("solving target system = $time_b seconds\n")
success_rate = 1 - count(X .== nothing) / 5^N
println("success rate = $success_rate\n")


#
using HomotopyContinuation, LinearAlgebra
import Base.Iterators: product

struct OscillatorCache{T<:Tracker}
    s::Vector{ComplexF64}
    tracker::T
end


## Define N = number of oscillators
N = 2
M = 2(N + 3)N
println("N = $N")
println("5^N = $(5^N)")

## Target Parameters p
p = randn(Float64, M)

## Start Parameters p₀
p₀ = [p[8*(i-1)+1:8*i] for i in 1:N]

## Start System
time_s = @elapsed begin
    println("\n Computing Start System")
    ## Start System
    @var u₀, v₀
    @var a₀[1:4], b₀[1:4]
    n² = u₀^2 + v₀^2

    f = a₀[1] ** u₀ + a₀[2] * u₀ + a₀[3] * v₀ + a₀[4]
    g = b₀[1] ** v₀ + b₀[2] * u₀ + b₀[3] * v₀ + b₀[4]
    variables₀ = [u₀; v₀]
    parameters₀ = [a₀; b₀]

    Start_System = System([f; g],
        variables=variables₀,
        parameters=parameters₀)

    ## Start solutions
    p_single = randn(ComplexF64, 8)
    S₀ = solve(Start_System, target_parameters=p_single,
        show_progress=false)

    S = solve(Start_System,
        solutions(S₀),
        start_parameters=p_single,
        target_parameters=p₀,
        transform_result=(R, pᵢ) -> solutions(R),
        show_progress=false)

end
println("setting up start system = $time_s seconds\n")

## Target system
@var u[1:N], v[1:N]
@var a[1:4, 1:N], b[1:4, 1:N]
@var c[1:N, 1:N], d[1:N, 1:N]
params = [vcat([[a[:, i]; b[:, i]] for i in 1:N]...);
    [c[i, j] for i in 1:N, j = 1:N if i != j];
    [d[i, j] for i in 1:N, j = 1:N if i != j]]

C = map(product(1:N, 1:N)) do (i, j)
    if i == j
        0
    else
        c[i, j]
    end
end
D = map(product(1:N, 1:N)) do (i, j)
    if i == j
        0
    else
        d[i, j]
    end
end

fs = [subs(f,
    variables₀ => [u[i], v[i]],
    parameters₀ => [a[:, i]; b[:, i]]) for i in 1:N]
gs = [subs(g,
    variables₀ => [u[i], v[i]],
    parameters₀ => [a[:, i]; b[:, i]]) for i in 1:N]

F = System([fs + C * v; gs + D * u],
    variables=[u; v],
    parameters=params)


## Tracking
@var t
q = p[8*N+1:M]
F = System(F([u; v], [vcat(p₀...); (1 - t) .* q]),
    variables=[u; v], parameters=[t])
tracker = Tracker(ParameterHomotopy(F, [1], [0]))

start_solution_iterator = Iterators.product(S...)

println("\n Solving Target System")

function oscillator_track(x::NTuple{N,Vector{ComplexF64}}, cache::OscillatorCache)
    s = cache.s
    for (j, xᵢ) in enumerate(x)
        s[j] = xᵢ[1]
        s[N+j] = xᵢ[2]
    end
    T = cache.tracker
    track!(T, s, 1, 0)
    res = track!(T, s, 1, 0)
    if is_success(res)
        return copy(T.state.x)
    end
    nothing
end

cache = OscillatorCache(zeros(ComplexF64, 2 * N), tracker)

X = Vector{Union{Vector{ComplexF64},Nothing}}()
time_b = @elapsed for x in start_solution_iterator
    push!(X, oscillator_track(x, cache))
end
println("solving target system = $time_b seconds\n")
success_rate = 1 - count(X .== nothing) / 5^N
println("success rate = $success_rate\n")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Fields

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions