SageMath: matrix_plot not returning any output within a subroutine - sage

A=identity_matrix(2)
def f(n):
matrix_plot(n*A)
f(5)
I'm puzzled as the command matrix_plot(5*A) works fine on itself, but it produces no output when it goes inside a subroutine as in the above SageMath code.
I'd appreciate any help with understanding why this is so/resolving this.
PS I have tested this both on Sagecell.sagemath.org and a local installation.

As written, the function computes the matrix plot
but does not return it and does not display it.
To have the function display it:
def f(n, A):
matrix_plot(n*A).show()
To have the function return the plot (probably better):
def f(n, A):
return matrix_plot(n*A)
Then
sage: n = 5
sage: A = identity_matrix(2)
sage: f(n, A)

Related

Defining a procedure that plots a function with its derivative but yields no output

I'm trying to define a procedure that plots a function on an interval (a,b) along with its first derivative
def graph(f,a,b):
g(x)=f
h(x)=g.diff(x,1)
g1=plot(g,a,b)
g2=plot(h,a,b)
(g1+g2).show
but when i try it, for example with
graph(x^2,1,2)
there is no output.
I'd appreciate any hints/help
so meanwhile I've figured it out
def graph(f,a,b):
g(x)=f
h(x)=g.diff(x,1)
g1=plot(g,a,b)
g2=plot(h,a,b)
p=(g1+g2)
return p
does the trick

How to calculate complex functions in Fortran which are not easy to separate into real and imaginary components?

I need to calculate a complex function for different x values, something like
(i+1) exp(i * x) / x
I see that my option is to expand it in terms of sin and cos, and then separate out real and imaginary parts manually by hand, to be able to calculate them individually in code, and then define my complex function. This is a relatively simple function, but I have some bigger ones, not so easy to segregate manually into two components.
Am I missing something or this is the only way?
EDIT : I am pasting the sample code which works after helpful comments from everyone below, hope it's useful :
program complex_func
IMPLICIT NONE
Real(8) x
complex CF
x = 0.7
call complex_example(x, CF)
write(*,*) CF
end program complex_func
Subroutine complex_example(y, my_CF)
Implicit None
Real(8) y
Complex my_CF
complex, parameter :: i = (0, 1) ! sqrt(-1)
my_CF = (i+1) * exp(i*y) / y
!my_CF = cmplx(1, 1) * exp(cmplx(0.0, y)) / y !!THIS WORKS, TOO
write(*,*) my_CF
return
end Subroutine complex_example

1D integration with multivariable function input

To demonstrate, let's start with a simple multi-variable function f(x,y) = xy^2.
I am trying to find a command that would allow me to numerically integrate f(2, y) = 2y^2 from y = 0 to y = 2. (i.e. the original function is multi-variable, but only one variable remains when actually doing the integration)
I needed to define the function that way as I need to obtain the results using different values of x. (probably going to involve for-loop, but that is another story)
I have tried to walk through Cubature's user guide but apparently did not find anything useful. Maybe I have missed it
Can anyone help?
In such case it is simplest to use an anonymous function wrapper:
using QuadGK
f(x,y) = x*y^2
intf(x) = quadgk(y -> f(x, y), 0, 2)
if the anonymous function would be longer you could write:
intf(x) = quadgk(0, 2) do y
f(x, y)
end
This is an exact equivalent of the latter but do syntax allows you to write longer bodies of an anonymous function.
Now you can write e.g.:
julia> intf(1)
(2.6666666666666665, 4.440892098500626e-16)
julia> intf(2)
(5.333333333333333, 8.881784197001252e-16)
julia> intf(3)
(8.0, 0.0)

Julia: adding anonymous functions together

If I define some anonymous functions a(x) and b(x) as
a = x -> x^2
b = x -> 2x
it would be helpful for recursive problems to add them together, say over the duration of some loop:
for i=1:5
a = x -> a(x) + b(x)
end
where the goal would be to have this represented internally each loop iteration as
a = x -> x^2 + 2x
a = x -> x^2 + 2x + x^2 + 2x
a = x -> x^2 + 2x + x^2 + 2x + x^2 + 2x
...
But, this fails and returns some error. I'm assuming it's because calling the new a(x) is interpreted as: a(2) = 2 -> x^2 + x^2 + ... + x^2 + 2x
julia> a(2)
ERROR: StackOverflowError:
in (::##35#36)(::Int64) at ./REPL[115]:0
in (::##35#36)(::Int64) at ./REPL[115]:1 (repeats 26666 times)
Is there any way around this?
You can do exactly what you're looking for using the let keyword:
a = x -> x^2
b = x -> 2x
for i=1:5
a = let a = a; x -> a(x) + b(x); end
end
a(2) # returns 24
Explanation
The let keyword allows you to create a block with local scope, and return the last statement in the block back to its caller scope. (contrast that with the begin keyword for instance, which does not introduce new scope).
If you pass a sequence of "assignments" to the let keyword, these become variables local to the block (allowing you, therefore, to re-use variable names that already exist in your workspace). The declaration let a = a is perfectly valid and means "create a local variable a which is initialised from the a variable of the outer scope" --- though if we wanted to be really clear, we could have written it like this instead:
for i=1:5
a = let a_old = a
x -> a_old(x) + b(x);
end
end
then again, if you were willing to use an a_old variable, you could have just done this instead:
for i=1:5; a_old = a; a = x-> a_old(x) + b(x); end
let is a very useful keyword: it's extremely handy for creating on-the-spot closures; in fact, this is exactly what we did here: we have returned a closure, where the "local variable a" essentially became a closed variable.
PS. Since matlab was mentioned, what you're doing when you evaluate a = # (x) a(x) + b(x) in matlab is essentially creating a closure. In matlab you can inspect all the closed variables (i.e. the 'workspace' of the closure) using the functions command
PPS. The Dr Livingstone, I presume?
Using Polynomials package could be a way. This would go:
julia> using Polynomials # install with Pkg.add("Polynomials")
julia> x = Poly([0,1])
Poly(x)
julia> a = x^2
Poly(x^2)
julia> b = 2x
Poly(2*x)
julia> a = a+b
Poly(2*x + x^2)
julia> a(2.0)
8.0
The reason this works is because essentially the behavior you want is symbolic manipulation of functions. Julia does not work this way (it's a compiler - or ahead-of-time (AOT) compiler), but it is flexible. If fancier functions than polynomials are required, maybe a symbolic math package would help (there is SymPy, but I haven't used it).
This:
a = x -> a(x) + b(x)
is a recursive call with no stopping condition. It has nothing to do with Julia. As soon as you define this the previous definition (x^2) was overridden, and will have nothing to to with the stack or your result. It doesn't exist anymore. What you're trying to do is:
a(2) = a(2)+2*2 = (a(2)+2*2)+2*2 = ((a(2)+2*2)+2*2)+2*2 = ...
etc. The 2*2 will not even be substituted, I just wrote it to be clear. You probably want to define
c = x -> a(x) + b(x)
EDIT
I see now coming from MATLAB you're expecting the syntax to mean something else. What you wrote in nearly all languages is a recursive call, which you do not want. What you do want is something like:
concatFuncs => f1,f2 -> (x->f1(x)+f2(x))
This piece of code will take any to functions accepting an x and generate a + between the resulting calls. This will work with anything that '+' works with. So:
summed = concatFuncs(a,b)
is the function you need.

Julia how to eval the sym

Help! I got a result in the form of sym. But it seems eval doesn't work. How can I get a numerical answer? Thanks.
#show BBias
#show eval(BBias)
#show typeof(eval(BBias))
BBias = -213.53387843501*cos(6) + 73.4119295548356*sin(6) - 50*sin(6)*cos(6) + 316.255048160247
eval(BBias) = -213.53387843501*cos(6) + 73.4119295548356*sin(6) - 50*sin(6)*cos(6) + 316.255048160247
typeof(eval(BBias)) = SymPy.Sym
What you have here is a symbolic SymPy expression, not a Julia expression. eval in Julia will only evaluate a Julia expression. The N function from SymPy will evaluate and expression down to it's floating point value.
You can do a typeof(BBias) to see what kind of an object this is. Since I don't know how you have generated that object, I cannot replicate it fully. But here is some simple example showing how to using SymPy from Julia
julia> using SymPy
julia> x=Sym("pi")
pi
julia> typeof(x)
SymPy.Sym
julia> y=sin(x)
0
julia> typeof(y)
SymPy.Sym
julia> typeof(eval(y))
SymPy.Sym
julia> z=N(y)
0
julia> typeof(z)
Int64
A detailed tutorial on using SymPy from Julia is available here: http://nbviewer.jupyter.org/github/jverzani/SymPy.jl/blob/master/examples/tutorial.ipynb

Resources