I want to change a SymPy expression, for example x+y ( x=symbols("x") and the same thing for y), into a polynomial, and then get the generators of this polynomial and the length of this polynomial.
I've tried
op=x+y
op = op[:as_poly](domain="C")
op_a = op.x[:gens]
nab = op[:length]()
but it seems that it doesn't work .
The error that i'm getting is this:
ERROR: MethodError: no method matching getindex(::Sym, ::Symbol)
Closest candidates are:
getindex(::Sym, ::Sym...) at /Users/midow/.julia/packages/SymPy/1Cwgd/src/utils.jl:18
getindex(::Number) at number.jl:75
getindex(::Number, ::Integer) at number.jl:77
...
Stacktrace:
[1] top-level scope at REPL[11]:1
As #phipsgabler mentioned, the interface changed from getindex to getproperty so
using SymPy
x=symbols("x")
y=symbols("y")
op = op.as_poly(domain="C")
op_a = op.x.gens
nab = op.length()
should give you what you want.
Related
I need to be able to compare instances of a struct named Hijri, so I have defined a new method for the isless() function as follows:
function isless(a::Hijri, b::Hijri)
tuple_a = datetuple(a)
tuple_b = datetuple(b)
return tuple_a < tuple_b
end
datetuple() returns values of the Hijri struct as a tuple.
This works fine:
#show isless(a, b)
However, this one
#show a < b
throws an error:
ERROR: LoadError: MethodError: no method matching isless(::Main.HijriConverter.Hijri, ::Main.HijriConverter.Hijri)
Closest candidates are:
isless(::Any, ::Missing) at ~/Downloads/julia-1.7.0/share/julia/base/missing.jl:88
isless(::Missing, ::Any) at ~/Downloads/julia-1.7.0/share/julia/base/missing.jl:87
Stacktrace:
[1] <(x::Main.HijriConverter.Hijri, y::Main.HijriConverter.Hijri)
# Base ./operators.jl:352
[2] top-level scope
# show.jl:1047
in expression starting at /home/jafar_isbarov/Documents/projects/hijri/HijriConverter.jl/src/HijriConverter.jl:1
What could be the reason?
I had to import isless from Base:
import Base: isless
or use Base.isless (instead of isless) in my function definition.
function Base.isless(...)
end
This question was originally answered on Julia Discourse.
I am playing a bit with Julia.
Consider this function:
function drawValues(fromDistribution, byCount)
#=
inputs:
fromDistribution :
A 2D array
Each element is an array with two elements
The first one is a value, and the second one is the probability of that value
We will draw a value out of this distribution from a random number generator
byCount :
An integer
We draw that many values from the source distribution
=#
values = []
wts = []
for i = 1:length(fromDistribution)
push!(values, fromDistribution[i][1])
push!(wts , fromDistribution[i][2])
end
w = Weights(wts)
res = []
for i = 1:byCount
r = sample(values, w)
push!(res, r)
end
plot(values, wts)
print(res)
end
This throws the error :
ERROR: MethodError: no method matching Weights(::Array{Any,1},
::Float64) Closest candidates are: Weights(::var"#18#V",
::var"#16#S") where {var"#16#S"<:Real, var"#17#T"<:Real,
var"#18#V"<:AbstractArray{var"#17#T",1}} at
/home/hedgehog/.julia/packages/StatsBase/EA8Mh/src/weights.jl:13
Weights(::Any) at
/home/hedgehog/.julia/packages/StatsBase/EA8Mh/src/weights.jl:16
Stacktrace: [1] Weights(::Array{Any,1}) at
/home/hedgehog/.julia/packages/StatsBase/EA8Mh/src/weights.jl:16 [2]
drawValues(::Array{Array{Float64,1},1}, ::Int64) at
/home/hedgehog/LASER.jl:51 [3] top-level scope at REPL[13]:1 [4]
run_repl(::REPL.AbstractREPL, ::Any) at
/build/julia/src/julia-1.5.3/usr/share/julia/stdlib/v1.5/REPL/src/REPL.jl:288
It seems, that the second definition ( Weights(::Array{Any,1})) whould fit. But somehow Julia sees two input arguments?
Please help.
Version details :
Julia Version 1.5.3
Commit 788b2c77c1* (2020-11-09 13:37 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: AMD Ryzen 7 3700X 8-Core Processor
WORD_SIZE: 64
LIBM: libopenlibm
LLVM:
libLLVM-10.0.1 (ORCJIT, znver2)
Your Vectors have elements of type any.
It should be:
wts = Float64[]
When you write wts=[] it is an equivalent of wts=Any[].
Have a look at the weight methods:
julia> methods(weights)
# 3 methods for generic function "weights":
[1] weights(vs::AbstractArray{T,1} where T<:Real) in StatsBase at c:\JuliaPkg\Julia1.5.3\packages\StatsBase\EA8Mh\src\weights.jl:76
[2] weights(vs::AbstractArray{T,N} where N where T<:Real) in StatsBase at c:\JuliaPkg\Julia1.5.3\packages\StatsBase\EA8Mh\src\weights.jl:77
[3] weights(model::StatisticalModel) in StatsBase at c:\JuliaPkg\Julia1.5.3\packages\StatsBase\EA8Mh\src\statmodels.jl:143
A container having elements of subtype of Real is required.
Similarly for the other containers providing the types is recommended as well:
value = Float64[]
res = Float64[] # or maybe Int[] depending on what your code does
I am still learning the language Julia and i have this error. I am writing an mosquito population model and i am trying to run my main function a 100 times. This main function uses many other functions to calculate the subpopulation levels.
# Importing KNMI data
xf = XLSX.readxlsx("C:/Scriptie_mosquitoes/knmi_csv.xlsx")
sh = xf["knmi_csv"]
temperature = sh["B3:B368"]
precip = sh["F3:F368"]
subpopulation_amount = 100
imat_list1 = zeros(100,length(temperature))
imat_list = Array{Float64}(imat_list1)
adul_list1 = zeros(100,length(temperature))
adul_list = Array{Float64}(adul_list1)
egg_list1 = zeros(100,length(temperature))
egg_list = Array{Float64}(egg_list1)
diaegg_list1 = zeros(100,length(temperature))
diaegg_list = Array{Float64}(diaegg_list1)
imat_list[1] = 100.0
adul_list[1] = 1000.0
egg_list[1] = 100.0
diaegg_list[1] = 100.0
for counter = 1:1:subpopulation_amount
u = Distributions.Normal()
temp_change = rand(u)
tempa = temperature .+ temp_change
println(tempa)
e = Distributions.Normal()
precip_change = rand(e)
println("hallo", precip_change)
println(counter,tempa,precip,precip_change)
main(counter,tempa::Array{Float64,2},precip::Array{Any,2},precip_change::Float64,imat_list::Array{Float64,2},adul_list::Array{Float64,2},egg_list::Array{Float64,2},diaegg_list::Array{Float64,2})
end
However i get this error which i tried to fix with all the Float64 stuf. I doesn't work unfortunatly. I hope some of you guys see the problem or can help me with understanding the error message.
ERROR: InexactError: Int64(87.39533010546728)
Stacktrace:
[1] Int64 at .\float.jl:710 [inlined]
[2] convert at .\number.jl:7 [inlined]
[3] setindex! at .\array.jl:825 [inlined]
[4] main(::Int64, ::Array{Float64,2}, ::Array{Any,2}, ::Float64, ::Array{Float64,2}, ::Array{Float64,2}, ::Array{Float64,2}, ::Array{Float64,2}) at .\REPL[905]:19
[5] top-level scope at .\REPL[938]:10
You can check the documentation for InexactError by typing ?InexactError:
help?> InexactError
search: InexactError
InexactError(name::Symbol, T, val)
Cannot exactly convert val to type T in a method of function name.
I think that explains it nicely. There is no Int64 that represents the value 87.39533010546728.
You have a variety of options available. Check their help to learn more about them:
julia> trunc(Int, 87.39533010546728)
87
julia> Int(round(87.39533010546728))
87
julia> Int(floor(87.39533010546728))
87
We do not see the code of main. However it seems that you are using values of one of the Arrays that you have as its argument to use for indexing some vector in your code. And since vector indices need to be integers it fails. Most likely some variable is in wrong place in your main - look around [] operators.
When debugging you could also try to change your Arrays to Int elements and see which change causes the problem to stop. E.g. round.(Int, tempa) etc.
The problem is just what it says: you cannot exactly represent a decimal number (87.39) as an integer.
You need to decide what you want to do here - one option is to just round() your decimal number before converting it to an integer.
It's hard to say from the code you posted where exactly the error occurs, but one potentially less obvious way for this to happen is if you try to index into an array (e.g. my_array[i]), and your calculations lead to i having a non-integer value.
Julia manual states:
Every Julia program starts life as a string:
julia> prog = "1 + 1"
"1 + 1"
I can easily get the AST of the simple expression, or even a function with the help of quote / code_*, or using Meta.parse / Meta.show_sexpr if I have the expression in a string.
The question: Is there any way to get the whole AST of the codepiece, possibly including several atomic expressions? Like, read the source file and convert it to AST?
If you want to do this from Julia instead of FemtoLisp, you can do
function parse_file(path::AbstractString)
code = read(path, String)
Meta.parse("begin $code end")
end
This takes in a file path, reads it and parses it to a big expression that can be evaluated.
This comes from #NHDaly's answer, here:
https://stackoverflow.com/a/54317201/751061
If you already have your file as a string and don’t want to have to read it again, you can instead do
parse_all(code::AbstractString) = Meta.parse("begin $code end")
It was pointed out on Slack by Nathan Daly and Taine Zhao that this code won't work for modules:
julia> eval(parse_all("module M x = 1 end"))
ERROR: syntax: "module" expression not at top level
Stacktrace:
[1] top-level scope at REPL[50]:1
[2] eval at ./boot.jl:331 [inlined]
[3] eval(::Expr) at ./client.jl:449
[4] |>(::Expr, ::typeof(eval)) at ./operators.jl:823
[5] top-level scope at REPL[50]:1
This can be fixed as follows:
julia> eval_all(ex::Expr) = ex.head == :block ? for e in ex eval_all(e) end : eval(e);
julia> eval_all(ex::Expr) = ex.head == :block ? eval.(ex.args) : eval(e);
julia> eval_all(parse_all("module M x = 1 end"));
julia> M.x
1
Since the question asker is not convinced that the above code produces a tree, here is a graph representation of the output of parse_all, clearly showing a tree structure.
In case you're curious, those leaves labelled #= none:1 =# are line number nodes, indicating the line on which each following expression takes place.
As suggested in the comments, one can also apply Meta.show_sexpr to an Expr object to get a more "lispy" representation of the AST without all the pretty printing julia does by default:
julia> (Meta.show_sexpr ∘ Meta.parse)("begin x = 1\n y = 2\n z = √(x^2 + y^2)\n end")
(:block,
:(#= none:1 =#),
(:(=), :x, 1),
:(#= none:2 =#),
(:(=), :y, 2),
:(#= none:3 =#),
(:(=), :z, (:call, :√, (:call, :+, (:call, :^, :x, 2), (:call, :^, :y, 2))))
)
There's jl-parse-file in the FemtoLisp implementation of the Julia parser. You can call it from the Lisp REPL (julia --lisp), and it returns an S-expression for the whole file. Since Julia's Expr is not much different from Lisp S-expressions, that might be enough for you purposes.
I still wonder how one would access the result of this from within Julia. If I understand correctly, the Lisp functions are not exported from libjulia, so there's no direct way to just use a ccall. But maybe a variant of jl_parse_eval_all can be implemented.
I am trying to do something like this:
function outer(x::Array{Float64}, y::Array{Float64}=nothing)
if (y == nothing)
function inner(y::Array{Float64})
return x .* y
end
return inner
else
return x .+ y
end
end
outer([2.], [3.]) # to return 5, works
outer([2.])([3.]) # to return 6, fails.
outer([2.], [3.]) works just fine.
The problem is that outer([2.])([3.]) raises a MethodError stating:
MethodError: no method matching outer(::Array{Float64,1}, ::Void)
Closest candidates are:
outer(::Array{Float64,N} where N) at In[1]:2
outer(::Array{Float64,N} where N, ::Array{Float64,N} where N) at In[1]:2
Stacktrace:
[1] outer(::Array{Float64,1}) at ./In[1]:2
[2] include_string(::String, ::String) at ./loading.jl:522
The weird bit is that under Closest candidates, the single-argument outer(::Array{Float64,N} where N) is the first candidate. So why does it not work with the single argument?
Note: outer([2.], )([3.]), outer([2.], nothing)([3.]), outer([2.], [nothing])([3.]) all produce the same (similar) error.
This can be reproduced using a single argument function too:
function outer(y::Array{Float64}=nothing)
if (y == nothing)
function inner(y::Array{Float64})
return y .* y
end
return inner
else
return y .+ y
end
end
outer([2.])
1-element Array{Float64,1}:
4.0
outer()([3.])
MethodError: no method matching outer(::Void)
Closest candidates are:
outer() at In[6]:2
outer(::Array{Float64,N} where N) at In[6]:2
outer(::Array{Float64,N} where N, ::Array{Float64,N} where N) at In[1]:2
Stacktrace:
[1] outer() at ./In[6]:2
[2] include_string(::String, ::String) at ./loading.jl:522
And again, there is a zero-argument function outer() listed first in the Closest candidates list!
Basically, the above example is a MWE representing a log-sum/likelihood evaluation, where x is the data and y is the parameter of a model. I am trying to return a function in the parameter of the model to optimise using MLE, or return the log-sum if the parameter is passed.
In this analogy, outer computes log-sum, given data and parameter, or returns inner as a function of the parameter, which can be optimised.
You can reproduce this with simply:
f(x::Float64=nothing) = x
f()
When you add = nothing that sets nothing as a default argument. And also adds f() as a method. But when you call f() then julia will try to run f(nothing) as nothing is your default argument. That will then error as nothing is of type Void and you asserted that the argument must be Float64.
For example you could (but shouldn't) use f(x::Union{Float64,Void}=nothing) = x to get around this. But it'd be much better to use a Nullable which is exactly for interacting with a value that may or may not exist.
Read more about Nullables here or type ?Nullable in the REPL.
Edit by OP
MWE:
function outer(x::Array{Float64}, y=Nullable{Array{Float64}}())
if isnull(y)
function inner(y::Array{Float64})
return x .* y
end
return inner
else
return x .+ y
end
end
outer([2.])([3.]) # Produces 6,
outer([2.], [3.]) # Produces 5.
Works as expected.
Readability counts so maybe you have to reconsider define 2 methods explicitly (and simple as it is in Julian way):
outer(x::Array{Float64}, y::Array{Float64}) = x .+ y
outer(x::Array{Float64}) = y -> x .* y