Julia: Assign and Get Functions - assign

I would like to be able to assign values to variables in Julia through a simple string loop.
For instance:
x1, x2, x3, x4 = 14, 12, 34, 19
letters = "abcd"
for i in 1:4
val = get("x$i")
var = letters[i]
assign(var, val)
end
a
14
Note, I choose the function "assign" and "get" because I am used to them in R.
The reason I want to do this is because I have a function which takes multiple arguments which are all evaluated identically and I figured there was no point duplicating code. Something like:
function f(a,b,c,d)
if a<0 a==-9999 end
if b<0 b==-9999 end
if c<0 c==-9999 end
if d<0 d==-9999 end
end
Of course the functions that I am applying to each is really much longer than a simple recode command.
I guess I could do something like this:
function f(a=1,b=2,c=3,d=4, p=[a,b,c,d])
for (i in 1:4)
if p[i]<0
p[i]=-9999
end
end
sum(p)
end
However, this creates other problems with "set index" which is something I will need to read up more on. Thanks for your consideration!
Francis

After your second suggestion for what to do, I figure you might actually want something like this.
function f(args...)
acc = zero(args[1])
for a in args
if a < 0
acc -= 9999
else
acc += a
end
end
acc
end
Usage is just like

This does the trick:
x1, x2, x3, x4 = 14, 12, 34, 19
letters = "abcd"
for i in 1:4
assignment = parse("$(letters[i]) = x$(i)")
eval(assignment)
end
You can read about the parse function, which turns strings into expressions, here:
http://julia.readthedocs.org/en/latest/stdlib/base/#Base.parse

To do this kind of weird dynamic variable trixing in Julia, you have to use macros and metaprogramming. The gist of it is a very powerful interface to code generation. I think it would be possible to write a macro that does the same as the above code on the form
x1, x2, x3, x4 = 14, 12, 34, 19
#assign("abcd", 1:4)
and translates that "compile time" to
x1, x2, x3, x4 = 14, 12, 34, 19
begin
a = x1
b = x2
c = x3
d = x4
end
It will take me some time to write and debug such a macro. Can you describe your use case, so I can see if there are some constraints that are actually not important, or more functionality you'd like? The 1:4 for example seems redundant as I can just use for (i, letter) in enumerate("abcd") to get the same loop.

Related

Generate initial guess for any function?

Here is the Newton's method code from Wikipedia page:
x0 = 1 # The initial guess
f(x) = x^2 - 2 # The function whose root we are trying to find
fprime(x) = 2x # The derivative of the function
tolerance = 1e-7 # 7 digit accuracy is desired
epsilon = 1e-14 # Do not divide by a number smaller than this
maxIterations = 20 # Do not allow the iterations to continue indefinitely
solutionFound = false # Have not converged to a solution yet
for i = 1:maxIterations
y = f(x0)
yprime = fprime(x0)
if abs(yprime) < epsilon # Stop if the denominator is too small
break
end
global x1 = x0 - y/yprime # Do Newton's computation
if abs(x1 - x0) <= tolerance # Stop when the result is within the desired tolerance
global solutionFound = true
break
end
global x0 = x1 # Update x0 to start the process again
end
if solutionFound
println("Solution: ", x1) # x1 is a solution within tolerance and maximum number of iterations
else
println("Did not converge") # Newton's method did not converge
end
When I implement this I see that there are cases I need to apply new initial guess:
When functions (i.e: f, fPrime) give Infinity or NaN result (e.g in C#, this happens when result = 1/x when x=0, result = √x when x=-1,...)
When abs(yprime) < epsilon
When x0 is too large for y/yprime (e.g x0 = 1e99 but y/yprime = 1e25, this will make x1 = x0 while it's mathematically wrong, this will make the algorithm leads to nowhere).
My app allows user to input the math function and the initial guess, (e.g: Initial guess for x can be 1e308, function can be 9=√(-81+x), 45=InverseSin(x), 3=√(x-1e99),... ).
So when the initial guess is bad, my app will automatically apply the new initial guess with hope that it can give the result.
My current solution: the initial guess is the array of values:
double[] arrInitialGuess =
{
[User's initial guess], 0, 1, -1, 2, -2,... (you know, Factorial n!)..., 7.257416E+306, -7.257416E+306,
}
I have the following questions:
Is the big number (e.g 7.257416E+306) even needed? because I see that in x1 = x0 - y/yprime, if the initial guess x0 is too big compare to y/yprime, it programmatically leads to nowhere. If the big number is pointless, what is the cap for initial guess (e.g 1e17?)
2. What is better for the array of initial guess: the factorial n! {+-1, +-2, +-6,...}, or 2^x {+-2^0, +-2^1, +-2^2,...}, or 10^x {+-1e0, +-1e1, +-1e2,...},...
If my predefined-array-initial-guess method is not good, is there any better way to get new initial guess for Newton's method? (e.g an algorithm to get next initial-guess?)
Update:
Change of thought, the pre-defined array of initial guess doesn't work.
For example, I have the formula: 8=3/x => y=8-3/x which gives this graph
In this case, I can find the solution when initial guess is in the range [ 0.1 ; 0.7 ], so if I have the pre-defined initial guess arrray = {0, 1, 2,..., Inf}, it won't do me any good but wasting my precious resource.
So my new thought now is: steering the next initial guess base on the graph. The idea is: applying the last guess and compare with current guess to see that the value of y is heading toward 0 or not, so that I can determine to increase or decrease the next initial guess to steer the y toward 0. But I still consider the pre-defined initial guess idea in case the guesses all give Infinity value.
Update 2:
New thought: pick the new initial guess in the range [ x0; x1 ] where
there is no error between x0 and x1 (e.g there is no error divide by zero when apply a value in the range [ x0; x1 ]). So I can form the line AB: A(x0, y0) and B(x1, y1).
y0 and y1 have different sign: (y0 > 0 && y1 < 0) || (y0 < 0 && y1 > 0). So that the line AB can cut the x axis (which cause a big possibility there is an y = 0 somewhere between y0 and y1, if the graph isn't too weird).
Try to narrow the range [ x0; x1 ] as small as possible, then run a few initial guesses between the range.

Julia JuMP array variable constraint

I am trying to model a non-linear problem involving vector rotation using JuMP in Julia. I need a constraint, which looks something like v[1:3] == rotate(v) If I write it like this, it does not work, since "Nonlinear expressions may contain only scalar expressions". How can I work around this?
I could say something like v[1] == rotate(v)[1] and same for v[2] and v[3], but then I would have to compute rotate(v) three times as often. I could also try to split the rotate function into three functions which compute one element each, but the actual constraint is a bit more complicated than a simple rotation, so this could prove to be tricky.
Are there any other ways to do this? Maybe to have something like an auxiliary variable which can be computed as a vector and then in the constraint only compare the elements of the two vectors (essentialy the first approach, but without computing the function three times)?
See here for a suggested work-around:
https://discourse.julialang.org/t/how-to-set-up-nlconstraints-from-multi-output-user-defined-function/42309/5?u=odow
using JuMP
using Ipopt
function myfun(x)
return sum(xi for xi in x), sum(xi^2 for xi in x)
end
function memoized()
cache = Dict{UInt, Any}()
fi = (i, x) -> begin
h = hash((x, typeof(x)))
if !haskey(cache, h)
cache[h] = myfun(x)
end
return cache[h][i]::Real
end
return (x...) -> fi(1, x), (x...) -> fi(2, x)
end
model = Model(Ipopt.Optimizer)
f1, f2 = memoized()
register(model, :f1, 3, f1; autodiff = true)
register(model, :f2, 3, f2; autodiff = true)
#variable(model, x[1:3] >= 0, start = 0.1)
#NLconstraint(model, f1(x...) <= 2)
#NLconstraint(model, f2(x...) <= 1)
#objective(model, Max, sum(x))
optimize!(model)

Modelica: assign array return value to scalars

The following model tries to assign a vector return value of a function call to a vector of scalars. It checks and works if it is inside an equation section, but it fails inside an algorithm section. Is that a bug in the Modelica tool I am using, or am I doing something wrong? And, how can I write it without introducing the intermediate variable x[2]?
model returnVector
Real x1;
Real x2;
Real x[2];
Real A[2,2] = [1,2;3,4];
Real b[2] = {8,7};
algorithm
x = Modelica.Math.Matrices.solve(A,b);
{x1, x2} = Modelica.Math.Matrices.solve(A,b);
end returnVector;
You are doing something wrong :-)
In equations the left-hand-side is any expression; so you could even write Modelica.Math.Matrices.solve(A,b)={x1,x2};.
In algorithms the left-hand-side must be a component-reference (section 11.2 in Modelica 3.4; https://modelica.org/documents/ModelicaSpec34.pdf ) and the right-hand-side is evaluated and then assigned to the left-hand-side variable.
Under the 'algorithm', one must use ' := ' to represent the Assignment in Modelica instead of ' = ' as like in C/C++.
So the code could be rewritten as follows:
model returnVector
Real x1;
Real x2;
Real x[2];
Real A[2,2] = [1, 2; 3, 4];
Real b[2] = {8, 7};
algorithm
x := Modelica.Math.Matrices.solve(A, b);
x1 := x[1];
x2 := x[2];
//{x1, x2} = Modelica.Math.Matrices.solve(A, b);
end returnVector;
Simply write the left-hand-side within round parentheses:
({x1, x2}) := Modelica.Math.Matrices.solve(A, b);

Error Programming Cholesky decomposition in FORTRAN 90

Im struggling with my thesis on wave energy devices. Since I am a newbie to FORTRAN 90, I would like to improve my programming skills. Therefore, I just picked up an example from
http://rosettacode.org/wiki/Cholesky_decomposition
and tried to implement what is explained in the homepage. Basically it is about to program the Cholesky factorization of a 3x3 matrix A. I know there are already packages that do the decomposition for Fortran, but I would like to experience myself the effort in learning how to program.
There is no error in compilation, but the results do not match. I basically find out all the elements despite of the element L(3,3). Attached, you can find the code I've created from scratch in Fortran 90:
Program Cholesky_decomp
implicit none
!size of the matrix
INTEGER, PARAMETER :: m=3 !rows
INTEGER, PARAMETER :: n=3 !cols
REAL, DIMENSION(m,n) :: A, L
REAL :: sum1, sum2
INTEGER i,j,k
! Assign values to the matrix
A(1,:)=(/ 25, 15, -5 /)
A(2,:)=(/ 15, 18, 0 /)
A(3,:)=(/ -5, 0, 11 /)
! Initialize values
L(1,1)=sqrt(A(1,1))
L(2,1)=A(2,1)/L(1,1)
L(2,2)=sqrt(A(2,2)-L(2,1)*L(2,1))
L(3,1)=A(3,1)/L(1,1)
sum1=0
sum2=0
do i=1,n
do k=1,i
do j=1,k-1
if (i==k) then
sum1=sum1+(L(k,j)*L(k,j))
L(k,k)=sqrt(A(k,k)-sum1)
elseif (i > k) then
sum2=sum2+(L(i,j)*L(k,j))
L(i,k)=(1/L(k,k))*(A(i,k)-sum2)
else
L(i,k)=0
end if
end do
end do
end do
!write output
do i=1,m
print "(3(1X,F6.1))",L(i,:)
end do
End program Cholesky_decomp
Can you tell me what is the mistake in the code? I get L(3,3)=0 when it should be L(3,3)=3. I'm totally lost, and just for the record: on the Rosetta code homepage there is no solution for fortran, so any any hint is appreciated.
Thank you very much in advance.
You want to set sum1 and sum2 to zero for each iteration of the i and k loops.
I've finally found out how to solve the problem for greater order, 4x4 matrices, etc. as presented in the link I attached above. Here is the final code:
Program Cholesky_decomp
!*************************************************!
!LBH # ULPGC 06/03/2014
!Compute the Cholesky decomposition for a matrix A
!after the attached
!http://rosettacode.org/wiki/Cholesky_decomposition
!note that the matrix A is complex since there might
!be values, where the sqrt has complex solutions.
!Here, only the real values are taken into account
!*************************************************!
implicit none
INTEGER, PARAMETER :: m=3 !rows
INTEGER, PARAMETER :: n=3 !cols
COMPLEX, DIMENSION(m,n) :: A
REAL, DIMENSION(m,n) :: L
REAL :: sum1, sum2
INTEGER i,j,k
! Assign values to the matrix
A(1,:)=(/ 25, 15, -5 /)
A(2,:)=(/ 15, 18, 0 /)
A(3,:)=(/ -5, 0, 11 /)
!!!!!!!!!!!!another example!!!!!!!
!A(1,:) = (/ 18, 22, 54, 42 /)
!A(2,:) = (/ 22, 70, 86, 62 /)
!A(3,:) = (/ 54, 86, 174, 134 /)
!A(4,:) = (/ 42, 62, 134, 106 /)
! Initialize values
L(1,1)=real(sqrt(A(1,1)))
L(2,1)=A(2,1)/L(1,1)
L(2,2)=real(sqrt(A(2,2)-L(2,1)*L(2,1)))
L(3,1)=A(3,1)/L(1,1)
!for greater order than m,n=3 add initial row value
!for instance if m,n=4 then add the following line
!L(4,1)=A(4,1)/L(1,1)
do i=1,n
do k=1,i
sum1=0
sum2=0
do j=1,k-1
if (i==k) then
sum1=sum1+(L(k,j)*L(k,j))
L(k,k)=real(sqrt(A(k,k)-sum1))
elseif (i > k) then
sum2=sum2+(L(i,j)*L(k,j))
L(i,k)=(1/L(k,k))*(A(i,k)-sum2)
else
L(i,k)=0
end if
end do
end do
end do
!write output
do i=1,m
print "(3(1X,F6.1))",L(i,:)
end do
End program Cholesky_decomp
Look forward to hear about comments, better ways to program it, corrections and any kind of feedback. Thanks 2 francescalus for answering so quickly!
Regards, lbh

How to apply HoldForm to a list of variables without the variables in the list being evaluated first?

I am writing a debug function, which prints a variable name, and its value. I call this debug function with a list of variables from anywhere in the program. So the idea is for it to work like this:
debug[var_List] := Module[{values = ReleaseHold[var], i},
For[i = 1, i <= Length[values], i++,
Print[var[[i]], " = ", values[[i]]]
]
];
Now I use the above, like this
x = 3; y = 5;
debug[{HoldForm[x], HoldForm[y]}]
and I see in the console the following
x = 3
y = 5
But I have a large program and long list of variables at different places I want to debug. And I do not want to type HoldForm to each variable to make up the list to call the debug[] function. Much easier to Map it if possible. Less typing each time. But this does not work:
debug[ Map[HoldForm,{x,y}]]
The reason is that {x,y} was evaluated before HoldForm got hold of it. So I end up with a list that has the values in it, like this:
3 = 3
5 = 5
I could not find a way to Map HoldForm without the list being evaluated.
The best I could find is this:
debug[HoldForm[Defer[{x, y}]]]
which gives the following output from the above debug[] function:
{x,y} = {3,5}
Since Defer[{x, y}] has length 1, and it is just one thing, I could not break it up to make a 2 column list like in the above example.
It will be better if I can get an output of the form
x = 3
y = 5
easier to match the variable with its value since I have many variables.
question is: Any one knows of a programming trick to convert HoldForm[{x,y}] to {HoldForm[x],HoldForm[y]}
thanks
Just use Thread:
Thread[HoldForm[{x, y}]]
alternatively,
Map[HoldForm, Unevaluated[{x, y}]]
Here is a longer alternative demonstrating use of Hold, found in Roman Maeder's Programming In Mathematica (3rd ed.), page 137:
e1 = Hold[{x, y}];
e2 = MapAt[Hold, e1, {1, 0}];
e3 = Map[HoldForm, e2, {2}];
e4 = MapAt[ReleaseHold, First[e3], {0}];
debug[e4]
x=3
y=5
I did a PrintIt function using attributes that does what you want. I posted it here https://stackoverflow.com/a/8270643/884752, I repeat the code:
SetAttributes[System`ShowIt, HoldAll];
System`ShowIt[code__] := System`ShowIt[{code}];
System`ShowIt[code_] :=
With[{y = code},
Print[Defer[code = y]];
y
];
SetAttributes[System`PrintIt, {HoldAll,Listable}];
System`PrintIt[expr__]:=System`PrintIt[{expr}];
System`PrintIt[expr_] := System`ShowIt[expr];

Resources