-
Notifications
You must be signed in to change notification settings - Fork 25
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
System of Linear Equations #67
Conversation
Codecov Report
@@ Coverage Diff @@
## master #67 +/- ##
==========================================
+ Coverage 56.14% 62.52% +6.37%
==========================================
Files 10 10
Lines 431 467 +36
==========================================
+ Hits 242 292 +50
+ Misses 189 175 -14
Continue to review full report at Codecov.
|
Thanks! I don't see the benchmarks though. |
I manually benchmarked, and shared the results on #intervals in slack |
Please include at least the benchmarking script (using BenchmarkTools) in a new directory |
I have included the script and results for n = 1:25 |
That's the kind of thing I had in mind, thanks. You could instead collect the data using |
Okay, I'll try it out! |
Try à version using IntervalBox and setindex. |
IntervalBox is immutable like an SVector. So modifying it actually requires making a new copy and changing the relevant entry using setindex (without !) |
src/linear_eq.jl
Outdated
function gauss_seidel_interval_static1{T, N}(A::SMatrix{N, N, Interval{T}}, b::SVector{N, Interval{T}}; precondition=true, maxiter=100) | ||
|
||
n = size(A, 1) | ||
x = @MVector fill(-1e16..1e16, n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SVector
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized only x
has to be modified, so I tried a version where A
and b
are SVector
s, and that showed improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please try a version where x
is an SVector
and you use setindex
to "modify" it (i.e. replace x
with a new SVector
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I think this version gives the best benchmarks.
This needs tests. |
@dpsanders Travis and AppVeyor both use the latest tagged version and don't have |
I tried to tag a new version but it was causing failures in ValidatedNumerics. I did some upgrades, but I think we should plan carefully how to make patches-versions, so they don't break everything. See this comment. |
Actually the matrix version could be pretty efficient when using SMatrix and SVector everywhere. Have you tried that? |
db737c7
to
e3f58c1
Compare
Done. |
src/linear_eq.jl
Outdated
""" | ||
function gauss_seidel_interval_static2!{T, N}(x::SVector{N, Interval{T}}, A::SMatrix{N, N, Interval{T}}, b::SVector{N, Interval{T}}; precondition=true, maxiter=100) | ||
|
||
precondition && ((M, r) = preconditioner_static2(A, b)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens is precondition
is false? Where are M
and r
defined then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
So it seems just using normal arrays is fine? |
More or less, yes. Should I remove the other implementations and update the PR? |
perf/linear_eq.jl
Outdated
t2 = @belapsed gauss_seidel_interval_static($mA, $mb) | ||
t3 = @belapsed gauss_seidel_interval_static1($sA, $sb) | ||
t4 = @belapsed gauss_seidel_interval_static2($sA, $sb) | ||
t5 = @belapsed gauss_seidel_contractor($A, $b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try this one with the static vectors too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gauss_seidel_contractor
with static vectors? Okay
perf/linear_eq.jl
Outdated
t3 = @belapsed gauss_seidel_interval_static1($sA, $sb) | ||
t4 = @belapsed gauss_seidel_interval_static2($sA, $sb) | ||
t5 = @belapsed gauss_seidel_contractor($A, $b) | ||
df[Symbol("n = $n")] = [t1, t2, t3, t4, t5] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need Symbol
here? Can't you just use a string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
julia> df["test"] = [1, 2, 3, 4]
ERROR: MethodError: no method matching setindex!(::DataFrames.DataFrame, ::Array{Int64,1}, ::String)
The DataFrames
package takes a symbol as the index.
perf/linear_eq.jl
Outdated
t3 = @belapsed gauss_seidel_interval_static1($sA, $sb) | ||
t4 = @belapsed gauss_seidel_interval_static2($sA, $sb) | ||
t5 = @belapsed gauss_seidel_contractor($A, $b) | ||
df[Symbol("n = $n")] = [t1, t2, t3, t4, t5] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't you in fact just make n
another column?
│ 17 │ n = 17 │ 0.00122326 │ 0.00125759 │ 0.0398127 │ 0.00134961 │ 0.00125675 │ | ||
│ 18 │ n = 18 │ 0.00167176 │ 0.00159463 │ 0.043795 │ 0.00181409 │ 0.00162584 │ | ||
│ 19 │ n = 19 │ 0.0018632 │ 0.00185617 │ 0.0549107 │ 0.00208529 │ 0.00196587 │ | ||
│ 20 │ n = 20 │ 0.0020604 │ 0.00210595 │ 0.0635598 │ 0.00232704 │ 0.00212374 │ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually n
seems to be redundant since it's just the same as the row.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The row numbers need not be sequential due to the stack operations, That's why I kept the column with the value of n
src/linear_eq.jl
Outdated
|
||
n = size(A, 1) | ||
|
||
for iter in 1:maxiter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add @inbounds
to the outer for
loop in each of these functions.
You should squash down the implementations as I suggested; I think you should leave all of them for now. Could you please add the example from the Jaulin book in the Actually you should keep a separate repo, e.g. in your GitHub account or in JuliaIntervals, with a Jupyter notebook with usage examples and explanation. |
src/linear_eq.jl
Outdated
Keyword `precondition` to turn preconditioning off. | ||
Eldon Hansen and G. William Walster : Global Optimization Using Interval Analysis - Chapter 5 - Page 115 | ||
""" | ||
function gauss_seidel_interval_static1!{T, N}(x::MVector{N, Interval{T}}, A::SMatrix{N, N, Interval{T}}, b::SVector{N, Interval{T}}; precondition=true, maxiter=100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several versions of the function whose code is identical.
Just make a single version and do much looser type annotations as AbstractArray
etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Or no type annotations at all)
@dpsanders Is this accurate? |
Tests fail as it uses |
Ah great, thanks |
I have redefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Could you please add Tests for \ and comparisons to Base.\
Since |
Right, but the tests are also for future-proofing, eg if we change the implementation of \ again. So you can just add a couple of tests to make sure the output of \ and gaussian elim are the same. |
@eeshan9815 Did you actually check that the definition of |
On the example in the testset "Linear Equations", the new definition seems to be worse than using Base's |
I have imported |
Hmm, I see, sorry. I don't know why it didn't work for me, then. What's the advantage of preconditioning, then? I thought it was supposed to narrow, not widen, the result. |
After checking out your PR, I get
which shows that the |
Ignore me, I seem not to have managed to checkout the latest version, apologies. |
No, don't ignore me -- you defined |
test/linear_eq.jl
Outdated
end | ||
end | ||
|
||
\(A::StaticMatrix{Interval{T}}, b::StaticArray{Interval{T}}; kwargs...) where T = gauss_elimination_interval(A, b, kwargs...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be moved to the source code.
I think you can define a single method if you use AbstractMatrix
and AbstractVector
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be moved to the source code.
I'm terribly sorry, I didn't realize.
I think you can define a single method if you use AbstractMatrix and AbstractVector
I tried AbstractArray
s earlier, but it doesn't work since it matches its type with the \
for StaticArray
s or Array
s instead.
What's the advantage of preconditioning, then? I thought it was supposed to narrow, not widen, the result
Preconditioning doesn't always give a better result. Specifically, for M-matrices, the non-preconditioned version computes the exact hull whereas preconditioning causes some widening.
No problem, thanks! |
Running julia> IntervalRootFinding.gauss_elimination_interval(A, b)
2-element Array{IntervalArithmetic.Interval{Float64},1}:
[-130.228, 167.728]
[-60.0001, 267.273]
julia> IntervalRootFinding.gauss_elimination_interval(A, b, precondition=false)
2-element Array{IntervalArithmetic.Interval{Float64},1}:
[-120, 90]
[-60, 240]
julia> IntervalRootFinding.gauss_seidel_interval(A, b, precondition=false)
2-element Array{IntervalArithmetic.Interval{Float64},1}:
[-5e+15, 5.00001e+15]
[-1e+16, 1e+16]
julia> A
2×2 Array{IntervalArithmetic.Interval{Float64},2}:
[2, 3] [0, 1]
[1, 2] [1, 3]
julia> b
2-element Array{IntervalArithmetic.Interval{Float64},1}:
[0, 120]
[-60, 240]
julia> A \ b
2-element Array{IntervalArithmetic.Interval{Float64},1}:
[-1e+16, 1e+16]
[-1e+16, 1e+16] |
I think this needs more tests. E.g. the |
Z = extended_div(Y, A[i, i]) | ||
x[i] = hull((x[i] ∩ Z[1]), x[i] ∩ Z[2]) | ||
end | ||
if all(x .== x¹) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably use a tolerance instead.
Can you write this as all(==, x, x1)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doing that gives this error -
julia> A = [2..3 0..1;1..2 2..3]
2×2 Array{IntervalArithmetic.Interval{Float64},2}:
[2, 3] [0, 1]
[1, 2] [2, 3]
julia> all(==, A, A)
ERROR: ArgumentError: reduced dimension(s) must be integers
Stacktrace:
[1] reduced_indices(::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}, ::Array{IntervalArithmetic.Interval{Float64},2}) at ./reducedim.jl:35
[2] reducedim_initarray(::Array{IntervalArithmetic.Interval{Float64},2}, ::Array{IntervalArithmetic.Interval{Float64},2}, ::Bool, ::Type{Bool}) at ./reducedim.jl:73
[3] mapreducedim at ./reducedim.jl:242 [inlined]
[4] all(::Function, ::Array{IntervalArithmetic.Interval{Float64},2}, ::Array{IntervalArithmetic.Interval{Float64},2}) at ./reducedim.jl:583
[5] macro expansion at /home/eeshan/.julia/v0.6/Atom/src/repl.jl:118 [inlined]
[6] anonymous at ./<missing>:?
@eeshan9815 There seems to be a real test failure here. |
The test failure appears to be in a test for 2D roots, giving error messages similar to the ones faced when the |
The incorrect modification issue has also been resolved.
|
@eeshan9815 Tests are now passing. Is this ready? |
Yes, I think so. I added 88 tests (mostly randomly generated) to make sure the methods are working. |
Thanks very much! |
No description provided.