Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

W2Julia expects an Expr, not a WExpr. #85

Open
L2Fish opened this issue Mar 9, 2024 · 6 comments
Open

W2Julia expects an Expr, not a WExpr. #85

L2Fish opened this issue Mar 9, 2024 · 6 comments

Comments

@L2Fish
Copy link

L2Fish commented Mar 9, 2024

W2Julia expects an Expr to be returned, not WExpr.

Expr(:call , funcDict[ wexpr.head.name],[W2Julia(arg) for arg in wexpr.args])

or use W2JuliaExpr instead

W2JuliaExpr(wexpr::WExpr)=Expr(
    :call, 
    haskey(funcDict, wexpr.head.name) ? funcDict[wexpr.head.name] : wexpr.head.name, 
    [W2JuliaExpr(arg) for arg in wexpr.args]...
    )
W2JuliaExpr(wexpr::WSymbol) = Symbol(wexpr.name)
W2JuliaExpr(wexpr::Number) = wexpr

add Expr2Fcn to convert WExpr into a usable function.

getSymbols(sym::Symbol) = sym in values(funcDict) ? Vector{Symbol}() : [sym]
getSymbols(sym::Number) = Vector{Symbol}()
function getSymbols(expr::Expr)
    r = [getSymbols(exp) for exp in expr.args]
    rnew = []
    for rr in r::Vector
        append!(rnew, rr)
    end
    unique(rnew)
end

Expr2Fcn(expr::Expr,vars::Expr) = eval(Expr(:(->), vars, expr))
Expr2Fcn(expr::Expr) = Expr2Fcn(expr, Expr(:tuple, getSymbols(expr)...))
Expr2Fcn(wexpr::WExpr)= Expr2Fcn(W2JuliaExpr(wexpr))
Expr2Fcn(weval(W`mathematica expression`))
@fremling
Copy link
Collaborator

fremling commented Mar 9, 2024

Hi @L2Fish:
I think there is some misunderstanding as to the usage to W2Julia here (probably because of the name)

W2Julia is designed primarily to convert wolfram structures to Julia structures. This includes conversions of Mathematica lists to Julia vectors and Mathematica associations to Julia dictionaries.

Some examples or tests that will evaluate to true:

using Test
@test W2Julia(W`{1,2,3}`) == [1,2,3]
@test W2Julia([1,2,3]) == [1,2,3]
@test W2Julia(W`{1,2,3}`) == [1,2,3]
@test W2Julia(W`{1,a,{1,2}}`) == [1,W"a",[1,2]]
@test W2Julia([.1,W`{1,a,3}`]) == [.1,[1,W"a",3]]

@test W2Julia(Dict( 1 => "A" , "B" => 2)) ==Dict( 1 => "A" , "B" => 2)

@test W2Julia(W`Association["A" -> "B", "C" -> "D"]`) == Dict( "A" => "B" , "C" => "D")

@test W2Julia(W`Association["A" -> {1,a,3}, "B" -> "C"]`) == Dict( "A" => [1,W"a",3] , "B" => "C")

W2Julia does not convert expressions to Julia functions, as not all functions will be able to evaluate when WSymbols are present.

Can you give an example test case of how you would like W2Julia to work for you?

@L2Fish
Copy link
Author

L2Fish commented Mar 9, 2024

as described here
How to copy Mathematica expression into a Julia function
They used PyCall to solve the problem.
However, I am looking forward to MathLink supporting this feature or even replacing SymEngine.
They haven’t implemented many functions yet, such as Eigenvalues, where mathmatica is very powerful.

@fremling
Copy link
Collaborator

@L2Fish I see what you want. I have now taken the first step and renamed W2Julia => W2JuliaStruct and introduced W2JuliaExpr as a new function. This is released as MathLink 0.6.0.

Below are some of the tests documenting its usage

        @test W2JuliaExpr(W`a+b`) == :(a+b)
        @test W2JuliaExpr(W`a*b`) == :(a*b)
        @test W2JuliaExpr(W`Sin[a]`) == :(sin(a))
        @test W2JuliaExpr(W`Sin[a+b]`) == :(sin(a+b))
        @test W2JuliaExpr(W`Cos[a^b]`) == :(cos(a^b))
        @test W2JuliaExpr(W`a/b`) == :(a*(b^-1))
        @test W2JuliaExpr(W`a^b`) == :(a^b)
        @test W2JuliaExpr(W`Exp[a]`) == :(exp(a))

I seems good to also do the second step and introduce the functions. Stay tuned.

@L2Fish
Copy link
Author

L2Fish commented Mar 10, 2024

@L2Fish I see what you want. I have now taken the first step and renamed W2Julia => W2JuliaStruct and introduced W2JuliaExpr as a new function. This is released as MathLink 0.6.0.

Below are some of the tests documenting its usage

        @test W2JuliaExpr(W`a+b`) == :(a+b)
        @test W2JuliaExpr(W`a*b`) == :(a*b)
        @test W2JuliaExpr(W`Sin[a]`) == :(sin(a))
        @test W2JuliaExpr(W`Sin[a+b]`) == :(sin(a+b))
        @test W2JuliaExpr(W`Cos[a^b]`) == :(cos(a^b))
        @test W2JuliaExpr(W`a/b`) == :(a*(b^-1))
        @test W2JuliaExpr(W`a^b`) == :(a^b)
        @test W2JuliaExpr(W`Exp[a]`) == :(exp(a))

I seems good to also do the second step and introduce the functions. Stay tuned.

believe that MathLink.jl will perform better.

@fremling
Copy link
Collaborator

fremling commented Mar 10, 2024

I looked into it and i'm not sure how much automation one really wants to build in here. One can in principle build a function that automatically detects all the argument as creates a function for it. However, it seems to me that the user would need to know what the argument are in ny case in order to be able to sue it properly, and the code do construct such a functin is also a short oneliner :

ex = W2JuliaExpr(W`Sin[a]`)
fun = @eval (a) -> $ex
@test fun(0)  == sin(0)
@test fun(1)  == sin(1)

I'm thinking wrapping the fun = @eval (a) -> $ex in a function might just complicate things.

@L2Fish
Copy link
Author

L2Fish commented Mar 11, 2024

I'm thinking wrapping the fun = @eval (a) -> $ex in a function might just complicate things.

you're right.
I have two suggestions, one is to trigger a warning when automatically obtaining symbol variables, and the other is to add it as a reference suggestion in the readme file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants