Printing variable subscripts in Julia - julia

Hey so I know that due to the Unicode support in Julia one, may write for instance the letter a with the subscript 1 by typing a\_1<TAB>. Now, what if I wanted to do something like the following:
for i in [1 2 3]
println("a\_i")
end
and have the output be written as
a₁
a₂
a₃
How would I go about this without writing out all the possible subscripts myself?

You could do this (at least in version 0.6):
ltx = Base.REPLCompletions.latex_symbols
for i in 1:3
println("a$(ltx["\\_$i"])")
end

Bogumił Kamiński's answer seems the neatest, but I needed to reverse the order to get the correct string for two-digit numbers:
subscript(i::Integer) = i<0 ? error("$i is negative") : join('₀'+d for d in reverse(digits(i)))
for i=7:13 println("a"*subscript(i)) end

Building off the other answers here, I wrote a set of functions to allow for negative numbers and to work with the more complex superscript case.
function subscriptnumber(i::Int)
if i < 0
c = [Char(0x208B)]
else
c = []
end
for d in reverse(digits(abs(i)))
push!(c, Char(0x2080+d))
end
return join(c)
end
function superscriptnumber(i::Int)
if i < 0
c = [Char(0x207B)]
else
c = []
end
for d in reverse(digits(abs(i)))
if d == 0 push!(c, Char(0x2070)) end
if d == 1 push!(c, Char(0x00B9)) end
if d == 2 push!(c, Char(0x00B2)) end
if d == 3 push!(c, Char(0x00B3)) end
if d > 3 push!(c, Char(0x2070+d)) end
end
return join(c)
end
julia> for i in [1 -2 39]
println("a"*superscriptnumber(i))
println("a"*subscriptnumber(i))
end
a¹
a₁
a⁻²
a₋₂
a³⁹
a₃₉

Related

How to modify superscripts in Julia (labels of Gadfly plots)?

Could somebody suggest me how to initiate and end the superscript in a Gadfly plot using Julia correctly? Or if there are any other better solutions instead of using <sup></sup>, please also share them with me.
Thanks so much.
using Gadfly
ticks = [400, 1000, 1500, 2000, 2500, 3000, 3500, 4000]
Gadfly.plot(PET, x = :Wavenumber, y = :Transmittance, Geom.line,
Coord.cartesian(xflip=true, xmin=400, xmax=4000, ymax=100, ymin=0),
Scale.x_continuous(maxticks=2000),
Guide.xticks(ticks=ticks),
Guide.xlabel("Wavenumber (cm<sup>-1</sup>)"),
Guide.ylabel("Transmittance (%)"))
In a supported text editor, you can type the superscript characters directly with tab completion. \^-1<Tab> should transform into ⁻¹ once you press <Tab>.
Copy the characters from this answer to your string: ⁻¹.
Use my function below to convert integers to their corresponding Unicode superscripts. Use the * function to join the output string with the rest of your xlabel.
"Finds and prints the appropraite unicode value for any numerical superscript."
function superscriptnumber(i::Int)
if i < 0
c = [Char(0x207B)]
else
c = []
end
for d in reverse(digits(abs(i)))
if d == 0 push!(c, Char(0x2070)) end
if d == 1 push!(c, Char(0x00B9)) end
if d == 2 push!(c, Char(0x00B2)) end
if d == 3 push!(c, Char(0x00B3)) end
if d > 3 push!(c, Char(0x2070+d)) end
end
return join(c)
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

Julia NLopt force stops before the first iteration

I'm using NLopt for a constrained maximization problem. Regardless of the algorithm or start values, the optimization program is force stopped even before the first iteration (or so I assume because it gives me the initial value). I've attached my code here. I'm trying to find probabilities attached to a grid such that a function is maximized under some constraints. Any help is appreciated.
uk = x -> x^0.5
function objective(u,p,grd)
-p'*u.(grd)
end
function c3(grd,p)
c =[]
d =[]
for i=1:length(grd)
push!(c,quadgk(x -> (i-x)*(x <= i ? 1 : 0),0,1)[1])
push!(d,sum(p[1:i]'*(grd[1:i] .- grd[i])))
end
return append!(d-c,-p)
end
function c4(grd,p)
return (grd .* p)-quadgk(x,0,1)
end
grd = n -> collect(0:1/n:1)
opt = Opt(:LD_SLSQP,11)
inequality_constraint!(opt, p -> c3(grd(10),p))
inequality_constraint!(opt, p -> -p)
equality_constraint!(opt, p -> sum(p)-1)
equality_constraint!(opt, p -> c4(grd(10),p))
opt.min_objective = p -> objective(-uk, p, grd(10))
k = push!(ones(11)*(1/11))
(minf,minx,ret) = optimize(opt, k)
I'm not a julia developer, but I only know this, if you need exit before complete the loop for is not your best choice, you need do a while with a sentinel variable.
here you have an article that explain you how while with sentinels works
and here you have a julia example changing your for to a while with a sentinel that exit after the third loop
i = 1
third = 0
while i < length(grd) && third != 1
# of course you need change this, it is only an example that will exit in the 3 loop
if i == 3
third = 1
end
push!(c,quadgk(x -> (i-x)*(x <= i ? 1 : 0),0,1)[1])
push!(d,sum(p[1:i]'*(grd[1:i] .- grd[i])))
i += 1
end

Populating an array using a FOR loop and a function

I was expecting that the following code would populate E with random 1's and 0's, but that does not happen. I cannot figure out why.
Pkg.add("StatsBase")
using StatsBase
function randomSample(items,weights)
sample(items, Weights(weights))
end
n = 10
periods = 100
p = [ones(n,periods)*0.5]
E = fill(NaN, (n,periods))
for i in 1:periods
for ii in 1:n
E(ii,i) = randomSample([1 0],[(p(ii,i)), 1 - p(ii,i)])
end
end
E
The statement:
E(ii,i) = randomSample([1 0],[(p(ii,i)), 1 - p(ii,i)])
defines a local function E and is not an assignment operation to a matrix E. Use
E[ii,i] = randomSample([1, 0],[p[ii,i], 1 - p[ii,i]])
(I have fixed additional errors in your code so please check out the differences)
and for it to run you should also write:
p = ones(n,periods)*0.5

Find indices of non-zero elements from [1,2,0,0,4,0] in julia and create an Arrray with them

I know there is a function that does this, for example:
A = [1,2,0,0,4,0]
find(A)
3-element Array{Int64,1}:
1
2
5
I am trying to do it on my own way, however, I am stuck here
for i=1:endof(A)
if A[i] != 0
[]
end
end
Thanks in advance.
Here's one alternative:
function myfind(c)
a = similar(c, Int)
count = 1
#inbounds for i in eachindex(c)
a[count] = i
count += (c[i] != zero(eltype(c)))
end
return resize!(a, count-1)
end
It actually outperformed find for all the cases I tested, though for the very small example vector you posted, the difference was negligible. There is perhaps some performance advantage to avoiding the branch and dynamically growing the index array.
I have notice that the question is really confusion (because is poorly formulated, sorry about that). Therefore, there are two possible answers: one is [1,2,4]which is an array with the non-zero elements; the other is [1,2,5] which is an array of the indices of the non-zero elements.
Let´s begin with the first option
A = [1,2,0,0,4,0]
B = []
for i=1:endof(A)
if A[i] != 0
push!(B,i)
end
end
println(B)
The output is Any[1,2,5]
However, the type is not the one I wanted. Using typeof(B) it shows Array{Any,1} so I added this code:
B = Array{Int64}(B)
println(B)
typeof(B)
And the result is the desired
[1,2,5]
Array{Int64,1}
To improve its efficiency, following with the recommendations in the comments, I have specified the type of B with the eltype() function before the loop as follows:
A1 = [1,2,0,0,4,0] #The default type is Array{Int64,1}
B1 = eltype(A1)[] #Define the type of the 0 element array B with the type of A
#B1 = eltype(typeof(A))[] this is also valid
for i=1:endof(A1)
if A1[i] != 0
push!(B1::Array{Int64,1},i::Int64)
end
end
println(B1)
typeof(B1)
Then, the output is again the desired
[1,2,5]
Array{Int64,1}
The simplest way of doing this is using the function find(). However, since I´m a beginner, I wanted to do it in another way. However, there is another alternative provided by #DNF that outperform find() for the cases he has tested it (see below answers).
The second option, which creates an output matrix with the non-zero elements has been provided by other users (#Harrison Grodin and #P i) in this discussion.
Thanks all of you for the help!
You have a few options here.
Using the strategy you started with, you can use push! inside the for loop.
julia> B = Int[]
0-element Array{Int64,1}
julia> for element = A
if element != 0
push!(B, element)
end
end
julia> B
3-element Array{Int64,1}:
1
2
4
You can also opt to use short-circuit evaluation.
julia> for element = A
element != 0 && push!(B, element)
end
julia> for element = A
element == 0 || push!(B, element)
end
Both filter and list comprehensions are valid, as well!
julia> B = [element for element = A if element != 0]
3-element Array{Int64,1}:
1
2
4
julia> filter(n -> n != 0, A)
3-element Array{Int64,1}:
1
2
4
Edit: Thanks to the OP's comment, I have realized that the desired result is the indices of the nonzero elements, not the elements themselves. This can be achieved simply with the following. :)
julia> find(A)
3-element Array{Int64,1}:
1
2
5
Just because I don't see a simple solution posted here, this is approach I took to the same problem. I think it is the simplest and most elegant solution. Hope this closes the thread!
julia> A = [1,2,0,0,4,0];
julia> findall(!iszero,A)
3-element Vector{Int64}:
1
2
5

Resources