Hi I am unable to add two time components. Any idea why?
using Dates
t1 = Time(00,30,18)
t2 = Time(00,40,42)
t1 + t2
# Out >
ERROR: MethodError: no method matching +(::Time, ::Time)
Closest candidates are:
+(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
+(::StridedArray{var"#s832", N} where {var"#s832"<:Union{Dates.CompoundPeriod, Period}, N}, ::TimeType) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/Dates/src/deprecated.jl:10
+(::Period, ::TimeType) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/Dates/src/arithmetic.jl:85
...
Stacktrace:
[1] top-level scope
# REPL[5]:1
The appropriate Julia type for your use case is Period/CompoundPeriod. To replicate your use case:
julia> p1 = Minute(30) + Second(18)
30 minutes, 18 seconds
julia> p2 = Minute(40) + Second(42)
40 minutes, 42 seconds
julia> typeof.((p1, p2))
(Dates.CompoundPeriod, Dates.CompoundPeriod)
julia> p1 + p2
70 minutes, 60 seconds
julia> typeof(ans)
Dates.CompoundPeriod
As stated in the comments below here is hack that I used to solve the above answer.
using Dates
t1 = Time(00,30,18)
t2 = Time(00,40,42)
t1.instant + t2.instant |> Time #t1.instant returns time in nanoseconds
# Out >
01:11:00
Related
Im working with some roughly 100000x100000 hermitian complex sparse-matrices, with roughly 5% of entries populated, and want to calculate the eigenvalues/eigenvectors.
Sofar ive been using Arpack.jl eigs(A).
But this is not working well as soon as i crank the size to higher then 5000.
For the benchmarks ive been using the following code to generate some TestMatrices:
using Arpack
using SparseArrays
using ProgressMeter
pop = 0.05
n = 3000 # for example
A = spzeros(Complex{Float64}, n, n)
#showprogress for _ in 1:round(Int,pop * (n^2))
A[rand(1:n), rand(1:n)] = rand(Complex{Float64})
end
# make A hermite
A = A + conj(A)
t = #elapsed eigs(A,maxiter=1500) # ends up being ~ 13 seconds
For n ~ 3000 the eigs() call already takes 13 seconds on my machine, and for bigger n it doesn't finish in any 'reasonable' time or outright quits.
Is there a specialized package/method for this ?
Any help is appreciated
https://github.com/JuliaLinearAlgebra/ArnoldiMethod.jl seems to be what you want:
julia> let pop=0.05, n=3000
A = sprand(Complex{Float64},n,n, 0.05)
A = A + conj(A)
#time eigs(A; maxiter=1500)
#time decomp, history = partialschur(A, nev=10, tol=1e-6, which=LM());
end;
10.521786 seconds (50.73 k allocations: 3.458 MiB, 0.04% gc time)
2.244129 seconds (19 allocations: 1.892 MiB)
sanity check:
julia> a,(b,c) = let pop=0.05, n=300
A = sprand(Complex{Float64},n,n, 0.05)
A = A + conj(A)
eigs(A; maxiter=2500), partialschur(A, nev=6, tol=1e-6, which=LM());
end;
julia> a[1]
6-element Vector{ComplexF64}:
14.5707071003175 + 8.218901803015509e-16im
4.493079744504954 - 0.8390429567118733im
4.493079744504933 + 0.8390429567118641im
-0.3415176925293196 + 4.254184281244591im
-0.3415176925293088 - 4.25418428124452im
0.49406553681541177 - 4.229680489599233im
julia> b
PartialSchur decomposition (ComplexF64) of dimension 6
eigenvalues:
6-element Vector{ComplexF64}:
14.570707100307926 + 7.10698633463049e-12im
4.493079906269516 + 0.8390429076809746im
4.493079701528448 - 0.8390430155670777im
-0.3415174262177961 + 4.254183175902487im
-0.34151626930774975 - 4.25418321627979im
0.49406543866702 + 4.229680079205066im
How can I define an outer constructor that has same number of arguments as the field values? What I want to do is something like this:
struct data
x
y
end
function data(x, y)
return data(x-y, x*y)
end
But it obviously causes stackoverflow.
Based on the various helpful comments, thanks to all, I changed my answer. Here is an example in Julia 1.0.0 of what you may be after. I am learning Julia myself, so maybe further comments can improve this example code.
# File test_code2.jl
struct Data
x
y
Data(x, y) = new(x - y, x * y)
end
test_data = Data(105, 5)
println("Constructor example: test_data = Data(105, 5)")
println("test_data now is...: ", test_data)
#= Output
julia> include("test_code2.jl")
Constructor example: test_data = Data(105, 5)
test_data now is...: Data(100, 525)
=#
This works for me
julia> struct datatype
x
y
end
julia> function datatype_create(a,b)
datatype(a - b, a * b)
end
datatype_create (generic function with 1 method)
julia> methods(datatype_create)
# 1 method for generic function "datatype_create":
[1] datatype_create(a, b) in Main at none:2
julia> methods(datatype)
# 1 method for generic function "(::Type)":
[1] datatype(x, y) in Main at none:2
julia> a = datatype_create(105,5)
datatype(100, 525)
julia> b = datatype_create(1+2im,3-4im)
datatype(-2 + 6im, 11 + 2im)
julia> c = datatype_create([1 2;3 4],[4 5;6 7])
datatype([-3 -3; -3 -3], [16 19; 36 43])
julia> d = datatype_create(1.5,0.2)
datatype(1.3, 0.30000000000000004)
If you are absolutely Ideologically Hell Bent on using an outer constructor, then you can do something like this
julia> datatype(a,b,dummy) = datatype(a - b,a * b)
datatype
julia> e = datatype(105,5,"dummy")
datatype(100, 525)
Antman's solution using the power of MACRO
julia> macro datatype(a,b)
return :( datatype($a - $b , $a * $b) )
end
#datatype (macro with 1 method)
julia> f = #datatype( 105 , 5 )
datatype(100, 525)
I want to sort a list (or in julia speak an one dimensional array) of complex numbers, by real part then by imaginary part of the complex number. I tried using anonymous function for the lt but it does not work.
julia> b=[3 + 1im,1 + 2im,1 + 1im,5 + 6im]
4-element Array{Complex{Int64},1}:
3 + 1im
1 + 2im
1 + 1im
5 + 6im
julia> sort(b,lt = x,y -> if(real(x)==real(y)) imag(x)<imag(y) else real(x)<real(y) end)
ERROR: UndefVarError: x not defined
Stacktrace:
[1] top-level scope at none:0
I want the following results
1 + 1im
1 + 2im
3 + 1im
5 + 6im
So close!
julia> sort(b, lt = (x,y) -> real(x)==real(y) ? imag(x)<imag(y) : real(x)<real(y))
4-element Array{Complex{Int64},1}:
1+1im
1+2im
3+1im
5+6im
Tuples are sorted in lexicographic order (the 1st element; then the second one, and so on).
You could just do:
b = [3 + 1im, 1 + 2im, 1 + 1im, 5 + 6im]
sort(b, lt = (x, y) -> (real(x), imag(x)) < (real(y), imag(y)))
edit: The comment above, using by= , is much cleaner.
I'm trying to find functionality in Julia similar to MATLAB's meshgrid or ndgrid. I know Julia has defined ndgrid in the examples but when I try to use it I get the following error.
UndefVarError: ndgrid not defined
Anyone know either how to get the builtin ndgrid function to work or possibly another function I haven't found or library that provides these methods (the builtin function would be preferred)? I'd rather not write my own in this case.
Thanks!
We prefer to avoid these functions, since they allocate arrays that usually aren't necessary. The values in these arrays have such a regular structure that they don't need to be stored; they can just be computed during iteration. For example, one alternative approach is to write an array comprehension:
julia> [ 10i + j for i=1:5, j=1:5 ]
5×5 Array{Int64,2}:
11 12 13 14 15
21 22 23 24 25
31 32 33 34 35
41 42 43 44 45
51 52 53 54 55
Or, you can write for loops, or iterate over a product iterator:
julia> collect(Iterators.product(1:2, 3:4))
2×2 Array{Tuple{Int64,Int64},2}:
(1, 3) (1, 4)
(2, 3) (2, 4)
I do find sometimes it's convenient to use some function like meshgrid in numpy. It's easy to do it with list comprehension:
function meshgrid(x, y)
X = [i for i in x, j in 1:length(y)]
Y = [j for i in 1:length(x), j in y]
return X, Y
end
e.g.
x = 1:4
y = 1:3
X, Y = meshgrid(x, y)
now
julia> X
4×3 Array{Int64,2}:
1 1 1
2 2 2
3 3 3
4 4 4
julia> Y
4×3 Array{Int64,2}:
1 2 3
1 2 3
1 2 3
1 2 3
However, I did not find this makes the code run faster than using iteration. Here's what I mean:
After defining
x = 1:1000
y = x
X, Y = meshgrid(x, y)
I did benchmark on the following two functions
using Statistics
function fun1()
return mean(sqrt.(X.*X + Y.*Y))
end
function fun2()
sum = 0.0
for i in 1:1000
for j in 1:1000
sum += sqrt(i*i + j*j)
end
end
return sum / (1000*1000)
end
Here are the benchmark results:
julia> #btime fun1()
8.310 ms (19 allocations: 30.52 MiB)
julia> #btime run2()
1.671 ms (0 allocations: 0 bytes)
The meshgrid method is both significantly slower and taking more memory. Any Julia expert knows why? I understand Julia is a compiling language unlike Python so iterations won't be slower than vectorization, but I don't understand why vector(array) calculation is many times slower than iteration. (For bigger N this difference is even larger.)
Edit: After reading this post, I have the following updated version of the 'meshgrid' method. The idea is to not create a meshgrid beforehand, but to do it in the calculation via Julia's powerful elementwise array operation:
x = collect(1:1000)
y = x'
function fun1v2()
mean(sqrt.(x .* x .+ y .* y))
end
The trick here is the .+ between a size-M column array and a size-N row array which returns a M-by-N array. It does the 'meshgrid' for you. This function is nearly 3 times faster then fun1, albeit not as fast as fun2.
julia> #btime fun1v2()
3.189 ms (24 allocations: 7.63 MiB)
765.8435104896155
Above, #ChrisRackauckas suggests that the "proper way" to do this is with a lazy operator but he hadn't gotten around to it.
There is now a registered packaged with lazy ndgrid in it:
https://github.com/JuliaArrays/LazyGrids.jl
It is more general than the version in
VectorizedRoutines.jl
because it can handle vectors with different types, e.g.,
ndgrid(1:3, Float16[0:2], ["x", "y", "z"]).
There are Literate.jl examples in the docs that show the lazy performance is pretty good.
Of course lazy meshgrid is just one step away:
meshgrid(y,x) = (ndgrid_lazy(x,y)[[2,1]]...,)
Is there a way to concatenate ArrayViews in Julia, that doesn't copy the underlying data? (I'd also be glad to use a SubArray, if that solves the problem.)
In the code below, for example, I want a single ArrayView that references the data in both y1 and y2.
julia> x = [1:50];
julia> using ArrayViews;
julia> y1 = view(x, 2:5);
julia> y2 = view(x, 44:48);
julia> concat(y1, y2) # I wish there were a function like this
ERROR: concat not defined
julia> [y1, y2] # This copies the data in y1 and y2, unfortunately
9-element Array{Int64,1}:
2
3
4
5
44
45
46
47
48
Not directly. But you could roll your own type with something like:
julia> type CView{A<:AbstractArray} <: AbstractArray
a::A
b::A
end
julia> import Base: size, getindex, setindex!
julia> size(c::CView) = tuple([sa+sb for (sa, sb) in zip(size(c.a), size(c.b))]...)
size (generic function with 57 methods)
julia> getindex(c::CView, i::Int) = i <= length(c.a) ? getindex(c.a, i) : getindex(c.b, i)
getindex (generic function with 180 methods)
julia> c = CView(y1, y2);
julia> size(c)
(9,)
julia> c[1]
2
julia> c[4]
5
julia> c[5]
48
These methods may not be optimal but they can certainly get you started. To be useful, more methods would probably be needed. Note that the key is simply in deciding which member array to index into. For multidimensional indexing sub2ind can be used.