How do I perform a nested iteration? - julia

I defined a function m(r,T,a,w) and I have vectors for the variables r,T,w.
What I want to do is to take the first element of each of those vectors and iterate my function for a in 1:T, then take the sum and repeat this iteration for the second element of those vectors and so on.
In the end I want to have a vector consisting of all the sums.
I would appreciate your help.
What I tried so far:
(W,R,LE are the vectors for the variables for w,r,T, respectively)
M = []
for w in W, r in R, T in LE
for a in 1:T
MM=sum(m(r,T,a,w))
push!(M,MM)
end
end
clearly Julia would not recognise what Im trying to do

The syntax:
for w in W, r in R, T in LE
...
does not iterate over the vectors at the same time. Rather, it is equivalent to the product:
for w in W
for r in R
for T in LE
...
It sounds like you want to iterate over those three vectors at the same time. In that case, you can use zip:
for (w,r,T) in zip(W,R,LE)
...

Matt's answer is correct, but you might want to improve a few other things, such as the types, and putting this in a function so that it isn't using a global variable. Do you know what the type of the sum is? Would a Float64 work, or a Int64?
For example:
function myfun(W, R, LE)
M = Vector{Float64}()
for (w, r, T) in zip(W, R, LE), a in T
push!(M, sum(m(r, T, a, w)))
end
M
end

Thanks for the very helpful comments. I managed to code what I wanted
MM = Vector{Float64}()
M = Vector{Float64}()
for (w, r, T) in zip(W, R, LE)
for a in 1:T
push!(MM, m(r,T,a,w))
end
push!(M,sum(MM))
end

Related

Inclusivity of Julia ranges

I hate that ranges include the end. Here is an example where I've deliberately removed the end of the range.
N = 100
for x in 0.0 : 2*pi/N : 2*pi*(N-1)/N
println(x)
end
Is there any way to avoid the ugliness of this for loop?
Yes, there is
N = 100
for x in range(0; step=2π/N, length=N)
println(x)
end
Maybe not the most elegant way... take the first n-1 elements
r = 0.0 : 2*pi/N : 2*pi
r = Iterators.take(r,length(r)-1)
Unfortunately, inclusive ranges (and 1-based indexing) is baked into the idioms of Julia at a fundamental level.
However, for this specific case, do note that stepping with floating point values can be problematic, as adding N values might be less than, equal to, or greater than the final value, giving different results for the for loop. Although julia tries really hard, there's no way to quite do the right thing in all circumstances. As a bonus, working in integer values only for the ranges simplifies things. You might want to consider:
for ix in 0:N-1
x = ix * 2 * pi / N
println(x)
end
Alternatively, the range() function has a form with a len parameter:
for x in range(0, 2*pi*(N-1)/N, length=n)
println(x)
end
Or indeed, combining this with the other answer of only taking (N-1) could work.
You could actually define your own operator such as:
▷(a,b) = a:b-1
Now you can write:
julia> 3▷6
3:5
Julia also natively supports custom indices for arrays. There is a package CustomUnitRanges that is maybe an overkill here.

Cumulative Integration Options With Julia

I have two 1-D arrays in which I would like to calculate the approximate cumulative integral of 1 array with respect to the scalar spacing specified by the 2nd array. MATLAB has a function called cumtrapz that handles this scenario. Is there something similar that I can try within Julia to accomplish the same thing?
The expected result is another 1-D array with the integral calculated for each element.
There is a numerical integration package for Julia (see the link) that defines cumul_integrate(X, Y) and uses the trapezoidal rule by default.
If this package didn't exist, though, you could easily write the function yourself and have a very efficient implementation out of the box because the loop does not come with a performance penalty.
Edit: Added an #assert to check matching vector dimensions and fixed a typo.
function cumtrapz(X::T, Y::T) where {T <: AbstractVector}
# Check matching vector length
#assert length(X) == length(Y)
# Initialize Output
out = similar(X)
out[1] = 0
# Iterate over arrays
for i in 2:length(X)
out[i] = out[i-1] + 0.5*(X[i] - X[i-1])*(Y[i] + Y[i-1])
end
# Return output
out
end

get rectangular Fortran array from subroutine output into R?

This is a follow up of my previous question. The difference is that instead of a one dimensional array i want to get a 2 dimensional array.
I have the following Fortran subroutine:
subroutine test(d, i, nMCd, DF, X)
integer, intent(in) :: d, i, nMCd
double precision, intent(in), dimension(i,nMCd) :: DF
double precision, intent(out), dimension(i,nMCd) :: X
X = DF + DF
end subroutine test
In R the code is simple:
input <- data.frame(A=c(11,12), B=c(21, 22))
input + input
and I get a 2 by 2 data frame
I am able to compile it for R load it and run it.
system("R CMD SHLIB ./Fortran/mytest.f90")
dyn.load("./Fortran/mytest.so")
X <- .Fortran("test", d = as.integer(1), i = nrow(input), nMCd = ncol(input), DF = unlist(input), X = numeric(nrow(input)*ncol(input)))$X
But I get a vector of length 4 instead of a 2x2 matrix or data frame. I tried X = numeric(nrow(input), ncol(input)) but it does not work
The only solution I can think is running after I run the fortran function
matrix(X,nrow = nrow(input),ncol = ncol(input))
Thanks!
I've reviewed the documentation for .Fortran, .Call and "Writing R extensions" and have not found any instances where a Fortran subroutine returns a matrix. Furthermore, there is no matrix type in the ?.Fortran help page, so I think my comment(s) might be the best solution:
in R you can also coerce a vector to matrix by adding a dimension: dim(X) <- c(2,2).
Or even with more generality: dim(X) <- dim(input)
Obviously I cannot claim this to be from high authority, since I've not done any Fortran programming before. If you were interested in writing code that interacts with R objects in place, you might want to consider studying the data.table package's code. Most such efforts use C or C++. You might also consider the Rcpp or inline package interfaces. The Fortran interface is mostly used to take advantage of the many numerical functions that have been bullet proofed.

Julia: confusion with error on datatype / DataFrame

New to Julia. Following this blog to do Neural Network:
http://blog.yhathq.com/posts/julia-neural-networks.html
I am confused about data types and error messages in Julia. This is my code (again, following the blog post on Neural Network):
# read in df to train
train_df = readtable("data/winequality-red.csv", separator=';')
# create train and test data splits
y = train_df[:quality]
x = train_df[:, 1:11] # matrix of all except quality
# vector() and matrix() from blog post
n = length(y)
is_train = shuffle([1:n] .> floor(n * .25))
x_train,x_test = x[is_train,:],x[!is_train,:]
y_train,y_test = y[is_train],y[!is_train]
type StandardScalar
mean::Vector{Float64}
std::Vector{Float64}
end
# initialize empty scalar
function StandardScalar()
StandardScalar(Array(Float64, 0), Array(Float64, 0))
end
# compute mean and std of each col
function fit_std_scalar!(std_scalar::StandardScalar, x::Matrix{Float64})
n_rows, n_cols = size(x_test)
std_scalar.std = zeros(n_cols)
std_scalar.mean = zeros(n_cols)
for i = 1:n_cols
std_scalar.mean[i] = mean(x[:,i])
std_scalar.std[i] = std(x[:,i])
end
end
# further vectorize the transformation
function transform(std_scalar::StandardScalar, x::Matrix{Float64})
# element wise subtraction of mean and division of std
(x .- std_scalar.mean') ./ std_scalar.std'
end
# fit and transform
function fit_transform!(std_scalar::StandardScalar, x::Matrix{Float64})
fit_std_scalar!(std_scalar, x)
transform(std_scalar, x)
end
# fit scalar on training data and then transform the test
std_scalar = StandardScalar()
n_rows, n_cols = size(x_test)
# cols before scaling
println("Col means before scaling: ")
for i = 1:n_cols
# C printf function
#printf("%0.3f ", (mean(x_test[:, i])))
end
I am getting the error:
'.-' has no method matching .-(::DataFrame, ::Array{Float64,2}) in fit_transform! ...
For this code:
x_train = fit_transform!(std_scalar, x_train)
x_test = transform(std_scalar, x_test)
# after transforming
println("\n Col means after scaling:")
for i = 1:n_cols
#printf("%0.3f ", (mean(x_test[:,i])))
end
I am new to Julia and am just not understanding what the issue is. Vector() and Matrix() do not work from the blog post. I assume that was from an older version of DataFrame.
What I think my issue is: these functions are taking in ::Matrix{Float64} and I am passing in the DataFrame. I assume that deprecated (?) Matrix() would have fixed this? Not sure. How do I analyze this error and pass these functions the correct types (if that is the problem here)?
Thank you!
The error message says that you're attempting an element-wise subtraction, .-, between a DataFrame and an Array but that operation has no definition for those types. A silly example of this sort of situation:
julia> "a" .- [1, 2, 3]
ERROR: `.-` has no method matching .-(::ASCIIString, ::Array{Int64,1})
My guess is that if you add
println(typeof(x_train))
in front of
x_train = fit_transform!(std_scalar, x_train)
that you'll be told that it's a DataFrame rather than an array that you're trying to work with. I'm not experienced with the DataFrame library but may be able to dig up the conversion tomorrow sometime. This is all I have time for just now.
Added comments after obtaining data file
I retrieved winequality-red.csv and worked with its DataFrame
julia> VERSION
v"0.3.5"
julia> using DataFrames
julia> train_df = readtable("data/winequality-red.csv", separator=';')
julia> y = train_df[:quality]
1599-element DataArray{Int64,1}:
julia> x = train_df[:, 1:11]
1599x11 DataFrame
julia> typeof(x)
DataFrame (constructor with 22 methods)
x and y are at this point array-like objects. The blog post apparently uses vector and matrix to convert these to true arrays, but these functions are unfamiliar to me. As IainDunning points out in his answer (I'd like to cite this properly but haven't puzzled that out yet), this conversion is now done via array. Perhaps this is what you need to do:
julia> y = array(train_df[:quality])
1599-element Array{Int64,1}:
julia> x = array(train_df[:, 1:11])
1599x11 Array{Float64,2}:
I've not followed through with an analysis of all of the other code, so this is a hint at the answer rather than a fully fleshed out and tested solution to your problem. Please let me know how this it works out if you give it a try.
I'm accustomed to seeing and using Array{Float64,1} and Array{Float64,2} rather than Vector{Float64} and Matrix{Float64}. Possibly the vector and matrix synonyms for specific types of arrays is deprecated.
I believe vector(...) and matrix(...) were both replaced with just array(...), but I can't find an issue number to correspond with that change.

Passing constant arguments to a multidimensional rootfinder in Sage

I have a five-dimensional rootfinding problem I'd like to solve from within a Sage notebook, but the functions I wish to solve depend on other parameters that shouldn't be varied during the rootfinding. Figuring out how to set up a call to, say, scipy.optimize.newton_krylov has got me stumped. So let's say I have (with a,b,c,d,e the parameters I want to vary, F1,F2,F3,F4,F5 the five expressions I which to solve to be equal to F1Val,F2Val,F3Val,F4Val,F5Val, values I already know, and posVal another known parameter)
def func(a, b, c, d, e, F1Val, F2Val, F3Val, F4Val, F5Val, posVal):
F1.subs(x1=a,x2=b,x3=c,x4=d,x5=e,position=posVal)
F2.subs(x1=a,x2=b,x3=c,x4=d,x5=e,position=posVal)
F3.subs(x1=a,x2=b,x3=c,x4=d,x5=e,position=posVal)
F4.subs(x1=a,x2=b,x3=c,x4=d,x5=e,position=posVal)
F5.subs(x1=a,x2=b,x3=c,x4=d,x5=e,position=posVal)
return (F1-F1Val, F2-F2Val, F3-F3Val, F4-F4Val, F5-F5Val)
and now I want to pass this to a rootfinding function to yield func = (0,0,0,0,0). I want to pass an initial guess (a0, b0, c0, d0, e0) vector and a set of arguments (F1Val, F2Val, F3Val, F4Val, F5Val, posVal) for the evaluation, but I can't figure out how to do this. Is there a standard technique for this sort of thing? The multidimensional rootfinders in scipy seem to be lacking the args=() variable that the 1D rootfinders offer.
Best,
-user2275987
Well, I'm still not sure how to actually employ the Newton-Raphson method here, but using fsolve works, for functions that accept a vector of variables and a vector of constant arguments. I'm reproducing my proof of concept here
def tstfunc(xIn, constIn):
x = xIn[0]
y = xIn[1]
a = constIn[0]
b = constIn[1]
out = [x+2*y+a]
out.append(a*x*y+b)
return out
from scipy.optimize import fsolve
ans = fsolve(tstfunc, x0=[1,1], args=[0.3, 2.1])
print ans

Resources