davidedc / Algebrite

Computer Algebra System in Javascript (Typescript)
http://algebrite.org
MIT License
955 stars 59 forks source link

Where is the scope in Algebrite? #28

Open pabloahb opened 7 years ago

pabloahb commented 7 years ago

Hi I am creating an application using Algebrite and I want to save the scope containing the declared variables and functions. The problem is that I can’t find that object. When someone runs something like ‘x=10’ in Algebrite, in which object is stored? Thank you, Algebrite is great.

davidedc commented 7 years ago

quick answer: it's in the symbol table. You can look at the function execution code to see how parameters are passed and how they live in their own scope in the function context. Also the "for" and "sum" functions protect index variables in their own scope, that can also help. Can provide more precise links and description when off my phone, but ideally you should find enough comments in those areas, let me know if that's not the case.

pabloahb commented 7 years ago

Thank you @davidedc In this moment I am trying two different approaches to save and load symbols from Algebrite. The first one is to get the symbols with the following function:

# get all the modified symbols as a symbols - binds object
get_symbols = ->
    i = 0
    count=0
    symb=[]
    bind=[]
    for i in [0...NSYM]
        if binding[i] != symtab[i]
            symb[count]=symtab[i]
            bind[count]=binding[i]
            count=count+1
    symlist =
        symbols: symb
        binding: bind
    return symlist

Then serialize them and save them. The problem with this method is that the compatibility of the saved symbols depends on keeping unchanged the U class.

The second approach is to convert the symbols in something that you can run in Algebrite by using the "toString()" function of the symbol:

# convert a binding to string 
binding_to_string = (s,b) ->
    symstring=""
    sString=s.toString()
    bString=b.toString()
    switch b.k
        when CONS
            if bString.indexOf("function ")==0
                func_array=bString.split(" -> ")
                func_array[0]=func_array[0].replace("function ",s.toString()).replace(" ",",")
                symstring=func_array[0]+"="+func_array[1]
            else
                symstring=sString+"="+bString
        when NUM
            symstring=sString+"="+bString
        when DOUBLE
            symstring=sString+"="+bString
        when STR
            symstring=sString+"="+bString
        when TENSOR
            symstring=sString+"="+bString
        when SYM
            symstring=sString+"="+bString
        else
            symstring=sString+"="+bString
    return symstring
# get all the modified symbols as a vector of strings
get_symbols_as_strings = ->
    i = 0
    count=0
    symb=[]
    for i in [0...NSYM]
        if binding[i] != symtab[i]
            symb[count]=binding_to_string(symtab[i],binding[i])
            count=count+1
    return symb

This function returns something like this:

Array[15]
0:"printLeaveEAlone=1"
1:"printLeaveXAlone=0"
2:"autoexpand=1"
3:"last=0"
4:"trace=0"
5:"tty=0"
6:"i=(-1)^(1/2)"
7:"e=exp(1)"
8:"trange=(-pi,pi)"
9:"xrange=(-10,10)"
10:"yrange=(-10,10)"
11:"cross(u,v)=(u[2] v[3] - u[3] v[2],u[3] v[1] - u[1] v[3],u[1] v[2] - u[2] v[1])"
12:"curl(v)=(d(v[3],y) - d(v[2],z),d(v[1],z) - d(v[3],x),d(v[2],x) - d(v[1],y))"
13:"div(v)=d(v[1],x) + d(v[2],y) + d(v[3],z)"
14:"ln(x)=log(x)"

This method works unless the "toString()" function returns something that can't be interpreted by algebrite.

Do you have a better idea to allow persistence in Algebrite based applications?

Thank you for your help.

davidedc commented 7 years ago

I think that should work. I'm thinking about a couple of potential complications...

P.S. there is a persist/unpersist mechanism implemented as part of a caching mechanism in the "zeno" branch which is very similar. (Search for "cache"). I'm making a note about checking the behaviour against point 2 above because I'm not too sure how it behaves actually...