Modify sparse identity matrix in julia sparse - julia

I'm creating an identity sparse matrix because I would like to modify some entries of this matrix:
Is = copy(sparse(I, N^2, N^2))
However, I got the error (e.g. for Is[1,3] = -1)
ERROR: LoadError: InexactError: Bool(-1.0)
Is there a way I can modify Is? I don't want to run two loops of size N because this parameter is very big.

Example:
julia> using SparseArrays, LinearAlgebra
julia> Is = copy(sparse(I, N^2, N^2));
julia> Is[3, 5] = -1.0;
ERROR: InexactError: Bool(-1.0)
Stacktrace:
[1] Bool
# ./float.jl:158 [inlined]
[2] convert
# ./number.jl:7 [inlined]
[3] _setindex_scalar!(A::SparseMatrixCSC{Bool, Int64}, _v::Float64, _i::Int64, _j::Int64)
# SparseArrays ~/Desktop/Julia/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/SparseArrays/src/sparsematrix.jl:2670
[4] setindex!(A::SparseMatrixCSC{Bool, Int64}, _v::Float64, _i::Int64, _j::Int64)
# SparseArrays ~/Desktop/Julia/Julia-1.8.app/Contents/Resources/julia/share/julia/stdlib/v1.8/SparseArrays/src/sparsematrix.jl:2667
[5] top-level scope
# REPL[11]:1
Looks like Is is expected to contain booleans, so Julia attempts to convert -1.0 to a Boolean and fails. Indeed, Is contains booleans:
julia> typeof(Is)
SparseMatrixCSC{Bool, Int64}
Why is that? Apparently, I is UniformScaling{Bool}, so I is an identity matrix of booleans. You can multiply it by 1.0 to get floats:
julia> 1.0*I
UniformScaling{Float64}
1.0*I
Then create the new matrix:
julia> Is = copy(sparse(1.0*I, N^2, N^2));
julia> eltype(Is)
Float64
julia> Is[3,5] = -1.0;

Related

How to count minimum on multiple variables in Julia

I want to plot correct y-axis limits. So, require to count the maximum y and minimum y.
y1=[2 3 4]
y2=[7 5 6]
...
m = minimum(y1)
m = minimum(m, minimum(y2))
error message
ERROR: MethodError: objects of type Int64 are not callable
Maybe you forgot to use an operator such as *, ^, %, / etc. ?
Stacktrace:
[1] mapreduce_first(f::Int64, op::Function, x::Int64)
# Base ./reduce.jl:419
[2] mapreduce(f::Int64, op::Function, a::Int64)
# Base ./reduce.jl:446
[3] minimum(f::Int64, a::Int64; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
# Base ./reduce.jl:725
[4] minimum(f::Int64, a::Int64)
# Base ./reduce.jl:725
[5] top-level scope
# REPL[107]:1
Previous code is just a simplified code, in my case, it require parse and get from a loop the pseudo code like:
x_data, y_data, names, y_min, y_max = [], [], [], 100, 0
for filename in *.csv
df = parse_csv(filename) # df is a dataframe
push!(names, filename)
d = df.value
y_min = minimum(y_min, d)
....
end
# plot all file by the y_min, y_max
i=1
for d in y_data;
lineplot(x_data, d, ylims=(y_min,y_max), name=names[i])
i += 1
end
Here are two solutions:
First. This is simple, just take the minimums of the minimums, etc.
julia> min(minimum(y1), minimum(y2))
2
julia> max(maximum(y1), maximum(y2))
7
Second solution. This iterates over each pair of values from y1 and y2, takes the minimum/maximum of each pair, and then finds the minimum of those again.
julia> minimum(minimum, zip(y1, y2))
2
julia> maximum(maximum, zip(y1, y2))
7
Here's a third one:
julia> min(y1..., y2...)
2
julia> max(y1..., y2...)
7
Elegant, but splatting of vectors is often inefficient in terms of performance.
The problem is that you don't know the difference between the min function and the minimum function (or you're unaware of the min function):
minimum(itr; [init])
Returns the smallest element in a collection.
So it gets a collection (E.g., Array) and returns the minimum of it.
min(x, y, ...)
Return the minimum of the arguments.
This one gets indefinite arguments and returns the minimum of them! It can't apply min on the x if the x is a container by itself!
julia> min(2, 3)
2
julia> min([2, 3])
ERROR: MethodError: no method matching min(::Vector{Int64})
On the other hand, for the minimum function:
julia> minimum(2, 3)
ERROR: MethodError: objects of type Int64 are not callable
julia> minimum([2, 3])
2
So I wanted to explain these to you to understand your code's meaning better.
We have this minimum(m, minimum(y2)) expression in your code block. This is literally the same as minimum(2, 5). So you're not passing containers to the function, leading to an error! For this, you should choose min instead:
julia> m = min(m, minimum(y2))
2
Or we can wrap m and minimum(y2) in a container and use the minimum function to achieve the overall min:
julia> m = minimum([m, minimum(y2)])
2
If you follow the explanation, you can absolutely understand the following:
julia> min(m, minimum(y2)) == minimum([m, minimum(y2)]) == min(m, min(y2...))
true

How to run parallel function in julia?

I would like to run the function f() on all my 4 processors (intel i7) and fetch the rands sum, as follows:
using Distributed;
#everywhere function f()
return sum(rand(10000))
end
#sync for w in workers()
#async begin
res = #spawnat w f()
values[w-1] = fetch(res)
end
end
But, getting the following error:
ERROR: TaskFailedException
nested task error: MethodError: no method matching setindex!(::typeof(values), ::Float64, ::Int64)
Stacktrace:
[1] macro expansion
# ./REPL[58]:4 [inlined]
[2] (::var"#68#70"{Channel{Any}, Int64})()
# Main ./task.jl:411
Stacktrace:
[1] sync_end(c::Channel{Any})
# Base ./task.jl:369
[2] top-level scope
# task.jl:388
Please guide me in resolving the issue!
For your code the easiest way would be (assuming Julia has been run with -p 4 command line parameter or you have run addprocs(4):
julia> values = #distributed (append!) for i in 1:4
[f()]
end
4-element Vector{Float64}:
5001.232864826896
4999.244031827526
4966.883114472259
5014.022690758762
If you want to do #spawns yourself this code works:
julia> values = Vector{Float64}(undef, 4);
julia> #sync for w in workers()
#async values[w-1] = fetch(#spawnat w f())
end
julia> values
4-element Vector{Float64}:
5029.967318172736
4993.1064528029
5016.491407076979
5062.0706219606345
However your code mostly didn't work because the type of your values was not Vector{Float64}. Here is how to replicate your error:
julia> vv()=0
vv (generic function with 1 method)
julia> vv[1]=11
ERROR: MethodError: no method matching setindex!(::typeof(vv), ::Int64, ::Int64)

In Julia, creating a Weights vector in statsbase

I am playing a bit with Julia.
Consider this function:
function drawValues(fromDistribution, byCount)
#=
inputs:
fromDistribution :
A 2D array
Each element is an array with two elements
The first one is a value, and the second one is the probability of that value
We will draw a value out of this distribution from a random number generator
byCount :
An integer
We draw that many values from the source distribution
=#
values = []
wts = []
for i = 1:length(fromDistribution)
push!(values, fromDistribution[i][1])
push!(wts , fromDistribution[i][2])
end
w = Weights(wts)
res = []
for i = 1:byCount
r = sample(values, w)
push!(res, r)
end
plot(values, wts)
print(res)
end
This throws the error :
ERROR: MethodError: no method matching Weights(::Array{Any,1},
::Float64) Closest candidates are: Weights(::var"#18#V",
::var"#16#S") where {var"#16#S"<:Real, var"#17#T"<:Real,
var"#18#V"<:AbstractArray{var"#17#T",1}} at
/home/hedgehog/.julia/packages/StatsBase/EA8Mh/src/weights.jl:13
Weights(::Any) at
/home/hedgehog/.julia/packages/StatsBase/EA8Mh/src/weights.jl:16
Stacktrace: [1] Weights(::Array{Any,1}) at
/home/hedgehog/.julia/packages/StatsBase/EA8Mh/src/weights.jl:16 [2]
drawValues(::Array{Array{Float64,1},1}, ::Int64) at
/home/hedgehog/LASER.jl:51 [3] top-level scope at REPL[13]:1 [4]
run_repl(::REPL.AbstractREPL, ::Any) at
/build/julia/src/julia-1.5.3/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
It seems, that the second definition ( Weights(::Array{Any,1})) whould fit. But somehow Julia sees two input arguments?
Please help.
Version details :
Julia Version 1.5.3
Commit 788b2c77c1* (2020-11-09 13:37 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: AMD Ryzen 7 3700X 8-Core Processor
WORD_SIZE: 64
LIBM: libopenlibm
LLVM:
libLLVM-10.0.1 (ORCJIT, znver2)
Your Vectors have elements of type any.
It should be:
wts = Float64[]
When you write wts=[] it is an equivalent of wts=Any[].
Have a look at the weight methods:
julia> methods(weights)
# 3 methods for generic function "weights":
[1] weights(vs::AbstractArray{T,1} where T<:Real) in StatsBase at c:\JuliaPkg\Julia1.5.3\packages\StatsBase\EA8Mh\src\weights.jl:76
[2] weights(vs::AbstractArray{T,N} where N where T<:Real) in StatsBase at c:\JuliaPkg\Julia1.5.3\packages\StatsBase\EA8Mh\src\weights.jl:77
[3] weights(model::StatisticalModel) in StatsBase at c:\JuliaPkg\Julia1.5.3\packages\StatsBase\EA8Mh\src\statmodels.jl:143
A container having elements of subtype of Real is required.
Similarly for the other containers providing the types is recommended as well:
value = Float64[]
res = Float64[] # or maybe Int[] depending on what your code does

error generator in Julia JuMP optimization error

I am converting a code in julia 0.6 to 1.2.
Here is the old version:
#variable(model, use[i=eachindex(n), j=1:m], Bin)
Used = [indmax(getvalue(use[i,j])
for j=1:m) for i=eachindex(n)]
I converted to the following,
#variable(model, use[i=eachindex(n), j=1:m], Bin)
JuMP.optimize!(model)
Used = [argmax(JuMP.value(use[i,j])
for j=1:m) for i=eachindex(n)]
but with error:
MethodError: no method matching keys(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##261#266")){Int64,JuMP.Containers.SparseAxisArray{VariableRef,2,Tuple{Any,Any}}}})
Closest candidates are:
keys(!Matched::Core.SimpleVector) at essentials.jl:606
keys(!Matched::Cmd) at process.jl:963
keys(!Matched::BenchmarkTools.BenchmarkGroup) at /Users/shuaiwang/.julia/packages/BenchmarkTools/7aqwe/src/groups.jl:31
...
pairs(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##261#266")){Int64,JuMP.Containers.SparseAxisArray{VariableRef,2,Tuple{Any,Any}}}}) at abstractdict.jl:132
_findmax(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##261#266")){Int64,JuMP.Containers.SparseAxisArray{VariableRef,2,Tuple{Any,Any}}}}, ::Colon) at array.jl:2068
findmax(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##261#266")){Int64,JuMP.Containers.SparseAxisArray{VariableRef,2,Tuple{Any,Any}}}}) at array.jl:2065
argmax(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##261#266")){Int64,JuMP.Containers.SparseAxisArray{VariableRef,2,Tuple{Any,Any}}}}) at array.jl:2153
(::getfield(Main, Symbol("##260#265")){ScenarioGraph,JuMP.Containers.SparseAxisArray{VariableRef,2,Tuple{Any,Any}}})(::Int64) at none:0
iterate at generator.jl:47 [inlined]
collect at array.jl:606 [inlined]
The problem seems to be unrelated to JuMP. The fix to your code is:
Used = [argmax([JuMP.value(use[i,j]) for j=1:m]) for i=eachindex(n)]
(I have not tested the whole code as it was not complete)
And the core of the issue is that you are not allowed to use argmax on generators, you have to pass a collection that supports pairs to it, e.g.:
julia> argmax(i for i in 1:3)
ERROR: MethodError: no method matching keys(::Base.Generator{UnitRange{Int64},getfield(Main, Symbol("##15#16"))})
fails, but
julia> argmax([i for i in 1:3])
3
julia> argmax((1,2,3))
3
julia> argmax((a=1,b=2,c=3))
:c
julia> argmax(Dict(:a=>1,:b=>2,:c=>3))
:c
work

Why does Julia Int64, Float64 and boolean support getindex

In Julia, you can declare an Int64, Bool or a Float64 and index it with 1.
julia> aa = 10
10
julia> typeof(10)
Int64
julia> aa[1]
10
julia> aa[0]
ERROR: BoundsError
Stacktrace:
[1] getindex(::Int64, ::Int64) at .\number.jl:78
[2] top-level scope at none:0
julia> aa[2]
ERROR: BoundsError
Stacktrace:
[1] getindex(::Int64, ::Int64) at .\number.jl:78
[2] top-level scope at none:0
Are there practical or theoretical reasons for this functionality to exist? I have never seen it in any other language I've used (Python, Ruby, Matlab, C++).
The reason is twofold:
Numbers are treated by Julia as 0-dimensional containers.
If you add 1 as a dimension index number in getindex then it is not an error, even if 1 is beyond the dimensionality of the container.
These two rules in combination lead to the behavior you describe. Here are some more examples of the same:
julia> a = 1
1
julia> b = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> a[]
1
julia> a[1,1,1,1]
1
julia> b[2,1,1,1,1]
2
and note that standard functions defined for containers are defined for numbers and behave as for 0-dimensional objects, e.g.:
julia> size(a)
()
julia> axes(a)
()
There is an open PR that gives more details how omitted and extra indices work.

Resources