Julia: where is the missing end? - julia

I am trying to convert a program written in Python to Julia. I have been using Julia for the last 2 hours.
My code is the following:
function spin_add(buff,clust,spins,padd)
if size(buff) == 0
return(clust)
else
i = buff[1][1] #row
j = buff[1][2]] #column
L = size(spins[1:1,:])
u = i-1
d = i+1
r = j+1
l = j-1
if i == L
d = 1
end
if i == 1
u = L
end
if j == L
r = 0
end
if j == 1
l = L
end
nei = [(u,j),(d,j),(i,r),(i,l)]
popfirst!(buff)
for site in nei
if site not in clust
if spins[site] == spins[i,j]
if rand() < padd
push(clust,site)
push(buff,site)
end
end
end
end
return(spin_add(buff, clust, spins, padd))
end
end
However, I am getting an error that says that an end is not added. The exact error is
syntax: "if" at In[10]:2 expected "end", got "]"
Stacktrace:
[1] top-level scope
# In[10]:6
[2] eval
# .\boot.jl:360 [inlined]
[3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
# Base .\loading.jl:1116
I do not understand where I must add the end.

j = buff[1][2]-->]<-- #column
Taking out that extra "]" should solve it.

Related

Why does Base.rsplit not invert the order (compared to Base.split) of the data in Julia?

I am trying out Base.rsplit() for the first time and I was surprised to see that the order of the data does not change when I use split vs rsplit. See this example:
julia> my_string = "Hello.World.This.Is.A.Test"
"Hello.World.This.Is.A.Test"
julia> a = split(my_string, ".")
6-element Vector{SubString{String}}:
"Hello"
"World"
"This"
"Is"
"A"
"Test"
julia> b = rsplit(my_string, ".")
6-element Vector{SubString{String}}:
"Hello"
"World"
"This"
"Is"
"A"
"Test"
julia> a == b
true
This is a bit counterintuitive given that rsplit says:
Similar to split, but starting from the end of the string.
rsplit just goes from the right side and the only practical difference is the limit parameter.
Try typing in Julia:
#less rsplit("txt",".")
You will find the following function:
function _rsplit(str::AbstractString, splitter, limit::Integer, keepempty::Bool, strs::Array)
n = lastindex(str)::Int
r = something(findlast(splitter, str)::Union{Nothing,Int,UnitRange{Int}}, 0)
j, k = first(r), last(r)
while j > 0 && k > 0 && length(strs) != limit-1
(keepempty || k < n) && pushfirst!(strs, #inbounds SubString(str,nextind(str,k)::Int,n))
n = prevind(str, j)::Int
r = something(findprev(splitter,str,n)::Union{Nothing,Int,UnitRange{Int}}, 0)
j, k = first(r), last(r)
end
(keepempty || n > 0) && pushfirst!(strs, SubString(str,1,n))
return strs
end

Multiple outputs used repeatedly in for loop Julia

I am using Julia and I've designed a for loop that takes the outputs of a function in one loop and uses them as the input of that function in the next loop (and over and over). When I run this code, Julia flags an "undefined" error, however, if I run the code in debug mode, it executes perfectly. For example, the code looks like this:
function do_command(a,b,c,d)
a = a + 1
b = split(b, keepempty=false)[1]
c = split(b, keepempty=false)[1]
if a == 1000
d = true
else
d = false
end
return a, b, c, d
end
for ii in 1:length(x)
if ii == 1
a = 0
b = "string something"
c = ""
d = false
end
a,b,c,d = do_command(a,b,c,d)
if d == true
print(string(b))
break
end
end
What am I doing wrong here?
An issue with your code is that for introduces a new scope for each iteration of the loop. That is to say: variable a created within the loop body at iteration 1 is not the same as variable a created within the loop body at iteration 2.
In order to fix your problem, you should declare variables outside the loop, so that at each iteration, references to them from within the loop body would actually refer to the same variables from the enclosing scope.
I'd go with something like this:
function do_command(a,b,c,d)
a = a + 1
b = split(b, keepempty=false)[1]
c = split(b, keepempty=false)[1]
if a == 1000
d = true
else
d = false
end
return a, b, c, d
end
# Let's create a local scope: it's good practice to avoid global variables
let
# All these variables are declared in the scope introduced by `let`
a = 0
b = "string something"
c = ""
d = false
for ii in 1:10 #length(x)
# now these names refer to the variables declared in the enclosing scope
a,b,c,d = do_command(a,b,c,d)
if d == true
print(string(b))
break
end
end
end

Parallel operations over arrays in Julia

What is the parallel (over multiple CPUs) version of this code in Julia?
V = zeros(3)
for i = 1:100000
cc = rand(1:3)
V[cc] += 1
end
This is a direct rewrite of your loop that is thread, tread-safe and avoiding false sharing:
using Random
using Base.Threads
V = let
mt = Tuple([MersenneTwister() for _ in 1:nthreads()])
Vv = Tuple([zeros(3) for _ in 1:nthreads()])
#threads for i = 1:100000
#inbounds cc = rand(mt[threadid()], 1:3)
#inbounds Vv[threadid()][cc] += 1
end
reduce(+, Vv)
end
However, in general for such a small job probably using threading will not give you much benefit. Also if you really need performance probably the code should be restructured a bit e.g. like this:
function worker(iters, rng)
v = zeros(3)
for i = 1:iters
cc = rand(rng, 1:3)
v[cc] += 1
end
v
end
V = let
mt = Tuple([MersenneTwister() for _ in 1:nthreads()])
Vv = [zeros(3) for _ in 1:nthreads()]
jobs_per_thread = fill(div(100000, nthreads()),nthreads())
for i in 1:100000-sum(jobs_per_thread)
jobs_per_thread[i] += 1
end
#assert sum(jobs_per_thread) == 100000
#threads for i = 1:nthreads()
Vv[threadid()] = worker(jobs_per_thread[threadid()], mt[threadid()])
end
reduce(+, Vv)
end
Also under Julia 1.3 you will not have to do manual MersenneTwister management, as Julia will create separate PRNG per thread.

Why am I getting no method matching Complex(::Sym)?

I am having one function to be executed, it has been compiled but for the execution it shows me a MethodError, here is the function
For this function I'm using SymPy
function op_mat(op)
op = op.as_poly(domain="C")
op_a = op.x.gens
nab = op.length()
op_ab = ones(SymPy.Sym, nab)
coef = zeros(Complex, nab)
mat = zeros(Int64, length(op_a), nab)
for (i, (ps, c)) in enumerate(op.as_dict())
for (j, p) in enumerate(ps)
mat[j, i] = p
op_ab[i] = op_a[j]^p * op_ab[i]
end
coef[i] = c
end
return op_a, op_ab, mat, coef
end
The error message that I'm having is this one:
Complex(::T<:Number) where T<:Number at boot.jl:718
Complex(::Real) at complex.jl:16
Complex(::T<:Real, ::T<:Real) where T<:Real at complex.jl:12
...
Stacktrace:
[1] convert(::Type{Complex}, ::Sym) at ./number.jl:7
[2] setindex!(::Array{Complex,1}, ::Sym, ::Int64) at ./array.jl:766
[3] op_mat(::Sym) at ./REPL[3]:13
[4] top-level scope at REPL[7]:1
since the type of c is Sym i should have only change the type to complex coef[i]=complex(c) or coef[i]=N(c)

Print an extra space if the value is positive

I'm trying to get a visually clear output of my program:
a = -1234
b = 1234
#printf "a = %s%1.2e" "" a
#printf "b = %s%1.2e" " " b
which gives:
a = 1.23e+03
b = -1.23e+03
(The point is to add an extra space for positive number)
Now I want to automate it. I tried to write a funtion:
function negspace(x::Number)
if x < 0
return "", x
else
return " ", x
end
end
and print with
a = -1234
b = 1234
#printf "a = %s%1.2e" negspace( a )
#printf "b = %s%1.2e" negspace( b )
Even simpler is to use the printf format flag to do this directly by putting a space after the %:
julia> #sprintf("a = % 1.2e", -1234)
"a = -1.23e+03"
julia> #sprintf("b = % 1.2e", 1234)
"b = 1.23e+03"
Found a way:
#!/usr/bin/env julia
function signspace(x::Number)
if x > 0
return #sprintf(" %1.2e", x)
else
return #sprintf( "%1.2e", x)
end
end
a = -1234
b = 1234
println("a = ", signspace(a))
println("b = ", signspace(b))
but I'm not sure it is optimal.

Resources