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

Problem with Broadcasting #42

Open
ssfrr opened this issue Oct 1, 2019 · 7 comments
Open

Problem with Broadcasting #42

ssfrr opened this issue Oct 1, 2019 · 7 comments

Comments

@ssfrr
Copy link
Contributor

ssfrr commented Oct 1, 2019

I'm having some trouble minimizing a function that includes complex numbers and broadcasting. I'm not sure which is causing the problem. On slack @dpsanders mentioned being a little concerned by complex numbers, but looking at the stack trace I'm actually wondering if its a broadcasting problem (it seems to be trying to assign an interval into the result array from a broadcasting operation, and for some reason the result array has float elements.

I'm coming from a DSP background, and the application is delay estimation between two signals where the delay is not an integer number of samples. The main insight here is that a delay in the time domain is the same as multiplying by a complex exponential in the frequency domain. The frequency of the exponential determines the delay, so we can estimate the delay by finding the frequency that minimizes the distance between the two spectra. Here's a MWE:

using Plots
using IntervalOptimisation
using IntervalArithmetic
using FFTW

# first we generate some test data
D = 0.68 # just picking a random target delay (in samples)
x1 = randn(1000)
N = length(x1) ÷ 2 + 1
ω = range(0, π, length=N)
# create a target signal by delaying our original signal and adding some noise
x2 = irfft(rfft(x1) .* exp.(-im .* ω .* D), length(x1)) .+ randn.() .* 0.1
plot([x1[1:40] x2[1:40]])

Which gives
image

We're trying to estimate D. Here's our error function (which we see has a minimum at 0.68):

X1 = rfft(x1)
X2 = rfft(x2)
err(D) = sum(@.(abs2(X2 - X1 * exp(-im*ω*D))))
x = range(-5,5,length=100)
plot(x, err.(x))

image

Trying to minimise it gives:

globmin, minxs = IntervalOptimisation.minimise(err, -2..2)
MethodError: no method matching Float64(::Interval{Float64})
Closest candidates are:
  Float64(::Real, !Matched::RoundingMode) where T<:AbstractFloat at rounding.jl:194
  Float64(::T<:Number) where T<:Number at boot.jl:741
  Float64(!Matched::Int8) at float.jl:60
  ...

Stacktrace:
 [1] convert(::Type{Float64}, ::Interval{Float64}) at ./number.jl:7
 [2] setindex!(::Array{Float64,1}, ::Interval{Float64}, ::Int64) at ./array.jl:767
 [3] macro expansion at ./broadcast.jl:843 [inlined]
 [4] macro expansion at ./simdloop.jl:73 [inlined]
 [5] copyto! at ./broadcast.jl:842 [inlined]
 [6] copyto! at ./broadcast.jl:797 [inlined]
 [7] copy at ./broadcast.jl:773 [inlined]
 [8] materialize(::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(abs2),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(-),Tuple{Array{Complex{Float64},1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(*),Tuple{Array{Complex{Float64},1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(exp),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(*),Tuple{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{0},Nothing,typeof(-),Tuple{Complex{Bool}}},StepRangeLen{Float64,Base.TwicePrecision{Float64},Base.TwicePrecision{Float64}},Interval{Float64}}}}}}}}}}}) at ./broadcast.jl:753
 [9] err(::Interval{Float64}) at ./In[54]:3
 [10] #minimise#1(::Type, ::Float64, ::Function, ::typeof(err), ::Interval{Float64}) at /home/sfr/.julia/packages/IntervalOptimisation/A3NrJ/src/optimise.jl:34
 [11] minimise(::Function, ::Interval{Float64}) at /home/sfr/.julia/packages/IntervalOptimisation/A3NrJ/src/optimise.jl:19
 [12] top-level scope at In[55]:1
@ssfrr
Copy link
Contributor Author

ssfrr commented Oct 1, 2019

update - rewriting the broadcast in terms of map seems to work:

function err(D)
    errs = map(X1, X2, ω) do x1, x2, om
        abs2(x2 - x1 * exp(-im*om*D))
    end
    sum(errs)
end

So it seems the problem is with the broadcasting

@ssfrr ssfrr changed the title Problem with Complex numbers (or maybe broadcasting?) Problem with Broadcasting Oct 1, 2019
@dpsanders dpsanders reopened this Oct 1, 2019
@dpsanders
Copy link
Member

dpsanders commented Oct 1, 2019

(Oops, wrong button sorry.)

It works for me:

julia> err(D) = sum(@.(abs2(X2 - X1 * exp(-im*ω*D))))
err (generic function with 1 method)

julia> @time minimise(err, -5..5)
  0.034151 seconds (3.65 k allocations: 1.380 MiB)
([5366.36, 5405.64], Interval{Float64}[[0.679316, 0.679927], [0.679926, 0.680537], [0.678715, 0.679317], [0.680536, 0.681157], [0.678105, 0.678716], [0.677504, 0.678106], [0.681156, 0.681748], [0.681747, 0.682349], [0.676904, 0.677505], [0.682348, 0.682949], [0.676313, 0.676905], [0.682948, 0.683559], [0.675702, 0.676314], [0.683558, 0.68416], [0.675102, 0.675703]])

What version of IntervalArithmetic.jl et al are you using?

@ssfrr
Copy link
Contributor Author

ssfrr commented Oct 4, 2019

I just re-tried this with IntervalOptimisation#master and IntervalArithmetic#master and got the same error. I tried on both Julia 1.1 and Julia 1.2.

@ssfrr
Copy link
Contributor Author

ssfrr commented Oct 4, 2019

Also, there's a much more minimal MWE:

using IntervalArithmetic

randn(10) .+ (-2..2)

So this is actually an IntervalArithmetic problem, not IntervalOptimization. I can move the issue over there.

@ssfrr
Copy link
Contributor Author

ssfrr commented Oct 4, 2019

Oh, actually this is a dup of JuliaIntervals/IntervalArithmetic.jl#255

@dpsanders
Copy link
Member

Closing since needs to be fixed in IntervalArithmetic.jl.

@dpsanders dpsanders reopened this Jul 7, 2020
@dpsanders
Copy link
Member

Reopening since it's not fixed yet...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants