Declare arbitrary number of variables to create the ring of polynomials julia - julia

I would like to have an algorithm for a n=a (where a is any number that I choose), such that
Julia understands that I declare the monomial variables x_{1}...x_{a} with #polyvar
Which package do you recommend me to do this?TypedPolynomials?
Thank you for your help

Normally you almost always use Vectors for things like this:
julia> a=3
3
julia> x = [n for n in 1:a]
3-element Vector{Int64}:
1
2
3
julia> x[2]
2
It is very hard to think about a scenario when it is not the best idea.
However, if you really need you can do a macro. The rule of thumb with Julia macros is "if you do not know how to write it perhaps you do not need it". Anyway here it is:
julia> macro var(n, initval)
exs = [ :( $(Symbol("x_",i)) = $initval ) for i in 1:n ]
esc(Expr(:block, exs...))
end
#var (macro with 1 method)
julia> #var(5, 77)
77
julia> x_4
77

Related

StepRange description in Julia

while working in julia programming, for creating an array instead of using a=[1:1:20...] i used a=[1:1:20] and it created an array saying "1-element Array{StepRange{Int64,Int64},1}".
What does this "1-element Array{StepRange{Int64,Int64},1}" mean? what StepRange means?
From the documentation of StepRange (type ?StepRange in the Julia REPL to see this):
StepRange{T, S} <: OrdinalRange{T, S}
Ranges with elements of type T with spacing of type S. The step
between each element is constant, and the range is defined in terms
of a start and stop of type T and a step of type S. Neither T nor S
should be floating point types. The syntax a:b:c with b > 1 and a,
b, and c all integers creates a StepRange.
So, for example
julia> typeof(1:1:20)
StepRange{Int64,Int64}
and
julia> [1:1:20]
1-element Array{StepRange{Int64,Int64},1}:
1:1:20
thus constructs a Vector (1D Array) containing one StepRange. If you want to materialize the lazy StepRange I would recommend collect(1:1:20) instead of using splatting ([1:1:20...]).
You can access start / step / stop fields of a StepRange using:
julia> r = 1:1:20
julia> r.start
1
julia> r.stop
20
julia> r.step
1

How to represent a performant heterogenous stack in Julia

I would like to implement a simple concatenative language (aka Joy or Factor) as a DSL in Julia and I am troubled how to optimally represent the stack.
The stack, which represents both data and program code, should be able to hold a sequence of items of different types. In the simplest case Ints, Symbols and, recursively again, stacks (to represent quoted code). The program will then heavily use push! and pop! to shuffle values between different such stacks.
One obvious implementation in Julia, which works but runs rather slow, is to use cell arrays. For example, the following Joy stack [ 1 [ 1 2 +] i + ] (which evaluates to [4]) can be implemented in Julia as
stack = Any[:+,:i,Any[:+,2,1],1]. My typical code then looks like this:
x = pop!(callstack)
if isa(x,Int)
push!(x,datastack)
elseif isa(x,Symbol)
do_stuff(x,datastack)
end
This, however, runs really slow and uses huge memory allocations, probably because such code is not typestable (which is a big performance bottleneck in Julia).
Using C, I would represent the stack compactly as an array (or alternatively as a linked list) of a union:
typedef union Stackelem{
int val;
char *sym;
union Stackelem *quote;
} Stackelem;
Stackelem stack[n];
But how can I achieve such a compact representation of the heterogeneous stack in Julia, and how I avoid the type instability?
This is one way, another way would be to represent args with type Vector{Any}:
julia> immutable Exp
head::Symbol
args::Tuple
end
julia> q = Exp(:+, (1, Exp(:-, (3, 4))))
Exp(:+,(1,Exp(:-,(3,4))))
edit: Another way to represent it might be:
immutable QuoteExp{T} ; vec::Vector{T} ; end
typealias ExpTyp Union{QuoteExp, Int, Symbol}
typealias Exp QuoteExp{ExpTyp}
and then you can do the following:
julia> x = Exp(ExpTyp[:+, 1, 2])
QuoteExp{Union{Int64,QuoteExp{T},Symbol}}(Union{Int64,QuoteExp{T},Symbol}[:+,1,2])
julia> x.vec[1]
:+
julia> x.vec[2]
1
julia> x.vec[3]
2
julia> push!(x.vec,:Scott)
4-element Array{Union{Int64,QuoteExp{T},Symbol},1}:
:+
1
2
:Scott
julia> x.vec[4]
:Scott

Inverse matrix error

I would like to do the inverse of matrix or number by multiplyig a vector with its trasposed but it gives me an error.
v=[1,2,3]
inv(v'*v)
`inv` has no method matching inv(::Array{Int64,1})
while loading In[45], in expression starting on line 2
I would like to obtain a number or a square matrix at the end.
I do not want to use pinv function because i need to do further manipulations and i need exactly a number or a square matrix.
How to fix this? Thanks in advance
v is a 3-element vector and v'*v is a 1-element vector:
julia> v = [1,2,3]
3-element Array{Int64,1}:
1
2
3
julia> v'*v
1-element Array{Int64,1}:
14
You cannot invert a vector. If you want to compute the scalar dot product of v with itself, you can use the dot function and then invert it using inv:
julia> dot(v,v)
14
julia> inv(dot(v,v))
0.07142857142857142
This comes long after the question was asked, but maybe it is useful for someone. To elaborate a little:
[1, 2, 3] is a vector or one-dimensional (of type Array{Int64,1} or Vector{Int64})
[1 2 3] is a 1x3 matrix (of type Array{Int64,2})
[1 2 3]' is (is essence) a 3x1 matrix (of type Array{Int64,2}). This is not quite right, it is really a lazy (non-evaluated) version of it, but it will behave as it should
So what you want to achieve can be done as follows:
v = [1 2 3]
display(v' * v)
inv(v' * v)
This fails now for the right reason :-), i.e., the 3x3 matrix is not invertible.
BTW, you can convert a vector v (of type Vector{T} and length n) into an n×1-array of type Array{T,2} with hcat(v).

What is the best way to form inner products?

I was delighted to learn that Julia allows a beautifully succinct way to form inner products:
julia> x = [1;0]; y = [0;1];
julia> x'y
1-element Array{Int64,1}:
0
This alternative to dot(x,y) is nice, but it can lead to surprises:
julia> #printf "Inner product = %f\n" x'y
Inner product = ERROR: type: non-boolean (Array{Bool,1}) used in boolean context
julia> #printf "Inner product = %f\n" dot(x,y)
Inner product = 0.000000
So while i'd like to write x'y, it seems best to avoid it, since otherwise I need to be conscious of pitfalls related to scalars versus 1-by-1 matrices.
But I'm new to Julia, and probably I'm not thinking in the right way. Do others use this succinct alternative to dot, and if so, when is it safe to do so?
There is a conceptual problem here. When you do
julia> x = [1;0]; y = [0;1];
julia> x'y
0
That is actually turned into a matrix * vector product with dimensions of 2x1 and 1 respectively, resulting in a 1x1 matrix. Other languages, such as MATLAB, don't distinguish between a 1x1 matrix and a scalar quantity, but Julia does for a variety of reasons. It is thus never safe to use it as alternative to the "true" inner product function dot, which is defined to return a scalar output.
Now, if you aren't a fan of the dots, you can consider sum(x.*y) of sum(x'y). Also keep in mind that column and row vectors are different: in fact, there is no such thing as a row vector in Julia, more that there is a 1xN matrix. So you get things like
julia> x = [ 1 2 3 ]
1x3 Array{Int64,2}:
1 2 3
julia> y = [ 3 2 1]
1x3 Array{Int64,2}:
3 2 1
julia> dot(x,y)
ERROR: `dot` has no method matching dot(::Array{Int64,2}, ::Array{Int64,2})
You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
The error message suggestion is dot(vec(x),vec(y), but sum(x.*y) also works in this case and is shorter.
julia> sum(x.*y)
10
julia> dot(vec(x),vec(y))
10
Now, you can write x⋅y instead of dot(x,y).
To write the ⋅ symbol, type \cdot followed by the TAB key.
If the first argument is complex, it is conjugated.
Now, dot() and ⋅ also work for matrices.
Since version 1.0, you need
using LinearAlgebra
before you use the dot product function or operator.

Julia #evalpoly macro with varargs

I'm trying to grok using Julia's #evalpoly macro. It works when I supply the coefficients manually, but I've been unable to puzzle out how to provide these via an array
julia> VERSION
v"0.3.5"
julia> #evalpoly 0.5 1 2 3 4
3.25
julia> c = [1, 2, 3, 4]
4-element Array{Int64,1}:
1
2
3
4
julia> #evalpoly 0.5 c
ERROR: BoundsError()
julia> #evalpoly 0.5 c...
ERROR: BoundsError()
julia> #evalpoly(0.5, c...)
ERROR: BoundsError()
Can someone point me in the right direction on this?
Added after seeing the great answers to this question
There is one subtlety to that I hadn't seen until I played with some of these answers. The z argument to #evalpoly can be a variable, but the coefficients are expected to be literals
julia> z = 0.5
0.5
julia> #evalpoly z 1 2 3 4
3.25
julia> #evalpoly z c[1] c[2] c[3] c[4]
ERROR: c not defined
Looking at the output of the expansion of this last command, one can see that it is indeed the case that z is assigned to a variable in the expansion but that the coefficients are inserted literally into the code.
julia> macroexpand(:#evalpoly z c[1] c[2] c[3] c[4])
:(if Base.Math.isa(z,Base.Math.Complex)
#291#t = z
#292#x = Base.Math.real(#291#t)
#293#y = Base.Math.imag(#291#t)
#294#r = Base.Math.+(#292#x,#292#x)
#295#s = Base.Math.+(Base.Math.*(#292#x,#292#x),Base.Math.*(#293#y,#293#y))
#296#a2 = c[4]
#297#a1 = Base.Math.+(c[3],Base.Math.*(#294#r,#296#a2))
#298#a0 = Base.Math.+(Base.Math.-(c[2],Base.Math.*(#295#s,#296#a2)),Base.Math.*(#294#r,#297#a1))
Base.Math.+(Base.Math.*(#298#a0,#291#t),Base.Math.-(c[1],Base.Math.*(#295#s,#297#a1)))
else
#299#t = z
Base.Math.+(Base.Math.c[1],Base.Math.*(#299#t,Base.Math.+(Base.Math.c[2],Base.Math.*(#299#t,Base.Math.+(Base.Math.c[3],Base.Math.*(#299#t,Base.Math.c[4]))))))
end)
I don't believe what you are trying to do is possible, because #evalpoly is a macro - that means it generates code at compile-time. What it is generating is a very efficient implementation of Horner's method (in the real number case), but to do so it needs to know the degree of the polynomial. The length of c isn't known at compile time, so it doesn't (and cannot) work, whereas when you provide the coefficients directly it has everything it needs.
The error message isn't very good though, so if you can, you could file an issue on the Julia Github page?
UPDATE: In response to the update to the question, yes, the first argument can be a variable. You can think of it like this:
function dostuff()
z = 0.0
# Do some stuff to z
# Time to evaluate a polynomial!
y = #evalpoly z 1 2 3 4
return y
end
is becoming
function dostuff()
z = 0.0
# Do some stuff to z
# Time to evaluate a polynomial!
y = z + 2z^2 + 3z^3 + 4z^4
return y
end
except, not that, because its using Horners rule, but whatever. The problem is, it can't generate that expression at compile time without knowing the number of coefficients. But it doesn't need to know what z is at all.
Macros in Julia are applied to their arguments. To make this work, you need to ensure that c is expanded before #evalpoly is evaluated. This works:
function f()
c=[1,2,3,4]
#eval #evalpoly 0.5 $(c...)
end
Here, #eval evaluates its argument, and expands $(c...). Later, #evalpoly sees five arguments.
As written, this is probably not efficient since #eval is called every time the function f is called. You need to move the call to #eval outside the function definition:
c=[1,2,3,4]
#eval begin
function f()
#evalpoly 0.5 $(c...)
end
end
This calls #eval when f is defined. Obviously, c must be known at this time. Whenever f is actually called, c is not used any more; it is only used while f is being defined.
Erik and Iain have done a great job of explaining why #evalpoly doesn't work and how to coerce it into working. If you just want to evaluate the polynomial, however, the easiest solution is probably just to use Polynomials.jl:
julia> using Polynomials
c = [1,2,3,4]
polyval(Poly(c), 0.5)
3.25

Resources