107 lines
3.3 KiB
Markdown
107 lines
3.3 KiB
Markdown
|
Julia is another high-performance fast programming language that could be great for future quantum programmers as an option to code in. There are several resources available online for learning quantum through julia as well.
|
||
|
|
||
|
- Error correction also exists for the Julia program - [HOQST ](https://uscqserver.github.io/OpenQuantumTools.jl/dev/)which is mainly an annealing tool but with the recent Nature paper proves that it may be better than qiskit pulse
|
||
|
One great source is this article that explains how to [build a quantum circuit simulator in one day](https://blog.rogerluo.dev/2020/03/31/yany/)!
|
||
|
|
||
|
```
|
||
|
using LinearAlgebra
|
||
|
function naive_broutine!(r::AbstractVector, U::AbstractMatrix, loc::Int)
|
||
|
n = Int(log2(length(r))) # get the number of qubits
|
||
|
return kron(I(1<<(n-loc+1)), U), I(1<<loc)
|
||
|
end
|
||
|
|
||
|
log2i(x::Int64) = !signbit(x) ? (63 - leading_zeros(x)) : throw(ErrorException("nonnegative expected ($x)"))
|
||
|
log2i(x::UInt64) = 63 - leading_zeros(x)
|
||
|
|
||
|
for N in [8, 16, 32, 64, 128]
|
||
|
T = Symbol(:Int, N)
|
||
|
UT = Symbol(:UInt, N)
|
||
|
@eval begin
|
||
|
log2i(x::$T) =
|
||
|
!signbit(x) ? ($(N - 1) - leading_zeros(x)) :
|
||
|
throw(ErrorException("nonnegative expected ($x)"))
|
||
|
log2i(x::$UT) = $(N - 1) - leading_zeros(x)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function broutine!(r::AbstractVector, U::AbstractMatrix, locs::NTuple{N, Int}) where N
|
||
|
end
|
||
|
|
||
|
|
||
|
function bmask(itr)
|
||
|
isempty(itr) && return 0
|
||
|
ret = 0
|
||
|
for b in itr
|
||
|
ret += 1 << (b - 1)
|
||
|
end
|
||
|
return ret
|
||
|
end
|
||
|
|
||
|
|
||
|
function bmask(range::UnitRange{Int})
|
||
|
((1 << (range.stop - range.start + 1)) - 1) << (range.start - 1)
|
||
|
end
|
||
|
|
||
|
function bmask(::Type{T}, itr) where {T<:Integer}
|
||
|
isempty(itr) && return 0
|
||
|
ret = zero(T)
|
||
|
for b in itr
|
||
|
ret += one(T) << (b - 1)
|
||
|
end
|
||
|
return ret
|
||
|
end
|
||
|
|
||
|
function bmask(::Type{T}, range::UnitRange{Int})::T where {T<:Integer}
|
||
|
((one(T) << (range.stop - range.start + 1)) - one(T)) << (range.start - 1)
|
||
|
end
|
||
|
|
||
|
bmask(args...) = bmask(Int, args...)
|
||
|
# this is for removing the infinity call of the later function
|
||
|
bmask(::Type{T}) where {T<:Integer} = zero(T)
|
||
|
bmask(::Type{T}, positions::Int...) where {T<:Integer} = bmask(T, positions)
|
||
|
|
||
|
bmask(args...) = bmask(Int, args...)
|
||
|
bmask(::Type{T}) where {T<:Integer} = zero(T)
|
||
|
bmask(::Type{T}, positions::Int...) where {T<:Integer} = bmask(T, positions)
|
||
|
|
||
|
function bmask(::Type{T}, itr) where {T<:Integer}
|
||
|
isempty(itr) && return 0
|
||
|
ret = zero(T)
|
||
|
for b in itr
|
||
|
ret += one(T) << (b - 1)
|
||
|
end
|
||
|
return ret
|
||
|
end
|
||
|
|
||
|
function bmask(::Type{T}, range::UnitRange{Int})::T where {T<:Integer}
|
||
|
((one(T) << (range.stop - range.start + 1)) - one(T)) << (range.start - 1)
|
||
|
end
|
||
|
|
||
|
(xxx & ~0b001) << 1 + (xxx & 0b001) # = xx00x
|
||
|
|
||
|
@inline lmove(b::Int, mask::Int, k::Int)::Int = (b & ~mask) << k + (b & mask)
|
||
|
|
||
|
|
||
|
|
||
|
function group_shift(locations)
|
||
|
masks = Int[]
|
||
|
region_lens = Int[]
|
||
|
k_prv = -1
|
||
|
for k in locations
|
||
|
# if current position in the contiguous region
|
||
|
# since these bits will be moved together with
|
||
|
# the first one, we don't need to generate a
|
||
|
# new mask
|
||
|
if k == k_prv + 1
|
||
|
region_lens[end] += 1
|
||
|
else
|
||
|
# we generate a bit mask where the 1st to k-th bits are 1
|
||
|
push!(masks, bmask(0:k-1))
|
||
|
push!(region_lens, 1)
|
||
|
end
|
||
|
k_prv = k
|
||
|
end
|
||
|
return masks, region_lens
|
||
|
end
|
||
|
```
|