From: Richard F. <fa...@gm...> - 2023-07-17 23:16:03
|
The usual symbolic expressions ("s-exprs") used in Maxima are internally Lisp atoms or (recursively) lists. As you know, they are displayed like (a b c ...) where a,b,c are either parenthesized lists or atoms [including numbers, strings, symbols]. There is a minor additional issue for "dotted pairs". This is not only pretty clear, once you get it out of your mind that parentheses are somehow "complicated" it has the major advantage that you can often re-create the expression from the printed form by typing it in to lisp. (or copy-pasting). There is a straightforward way of understanding simple programs, and also much more complicated ones, by tracing. For example, if you want to understand the canonical rational function operations, try doing this in Maxima: :lisp (trace newvar pplus ptimes pexpt) v: rat((x+y+5)^2); You can look at the source code and trace more functions if you want to understand more of the detailed processing, or if you want to look at more elaborate functionality. The Taylor series representation is an elaboration on the CRE idea, but mostly it is a separate near-duplication of the code base, adding truncation levels to the variables, so I recommend you understand rat() before taylor(). As far as picking out parts of the expressions, there are a variety of methods. Perhaps the simplest and fastest would be if you can pick out the required parts using ratcoef. You can also use operations like division or subtraction. Converting the expression out of CRE form into a "normal" lisp algebraic expression tree is also possible, as suggested previously, using load(ratpow). It is possible to see the lisp expression underlying the named variable v by typing ?print(v)$ which prints as below.. [your version may have different generated symbols other than x442, x443 ...] ((MRAT SIMP ($X $Y) (#:X443 #:X442)) (#:X442 2 1 1 (#:X443 1 2 0 10) 0 (#:X443 2 1 1 10 0 25)) . 1) You can of course, create a new expression with that header and a modified body, using lisp's car/cdr/cons but this is not something I would recommend. If you are actually going to study computer algebra programming, learning about canonical forms is an important step. Fussing around with algebraic trees makes it quite difficult to write efficient/general algorithms. RJF On Fri, Aug 5, 2022 at 9:01 PM Eduardo Ochs <edu...@gm...> wrote: > On Fri, 5 Aug 2022 at 12:45, Robert Dodier <rob...@gm...> > wrote: > >> On Thu, Aug 4, 2022 at 8:56 PM Eduardo Ochs <edu...@gm...> >> wrote: >> >> > Problem solved - with: >> > luatreedir : pathname_directory(load_pathname); >> > Sorry for the noise! >> > The program is here: >> > http://angg.twu.net/eev-maxima.html#luatree >> > https://github.com/edrx/luatree/#introduction >> >> Eduardo, thanks for the message, that looks interesting. I like the >> style of the tree diagram that's printed. I see part of the program is >> Maxima, part Lisp, part Lua. Can you say a little bit about how the >> different parts fit together here? >> >> One approach to getting diagrams generated by Maxima is to output >> stuff in a format understood by Graphviz, and then use one of the >> GraphViz programs (I know there's dot, I forget the others) to render >> it. Dunno if it's possible to get ASCII art in the same form you >> showed. I've worked with Maxima + GraphViz to visualize function call >> graphs, it's not hard. I can sketch out that approach if you're >> interested. >> >> best, >> >> Robert >> > > Hi Robert! > > I think that I found a way to answer your question that makes the main > idea look portable to other language. Let me try. > > I usually program using REPLs from Emacs, with this: > > http://angg.twu.net/eepitch.html > > My favorite programming language is Lua and my init file for Lua has > lots of functions and classes that I use often in throwaway programs. > If I just start a Lua REPL and type this in it, > > foo = {[0]="+", {[0]="*", "2", "3"}, {[0]="/", "4", "5"}, 6} > print(SynTree.from(foo)) > > the first line sets foo to an associative table that I interpret as a > tree as: > > 2*3 + 4/5 + 6 > > and the second line converts it to an object of the class SynTree in a > certain way and prints it using the __tostring method of the SynTree > class. What we see in the REPL buffer is this: > > Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio > > foo = {[0]="+", {[0]="*", "2", "3"}, {[0]="/", "4", "5"}, 6} > > print(SynTree.from(foo)) > +_____._____. > | | | > *__. /__. 6 > | | | | > 2 3 4 5 > > > > The first version of my luatree.lua just read stdin, interpreted it as > a Lua expression, and ran something like this: > > print(SynTree.from(expressionreadfromstdin)) > > Then at some point I rewrote luatree.lua to make it self-contained, > i.e., independent of my init file, and it became this: > > http://angg.twu.net/luatree/luatree.lua.html > > Note that at the end of luatree.lua there is a multi-line comment > containing this test, > > echo '{[0]="[", {[0]="/", "x", "y"}, "33"}' \ > | ./luatree.lua > > that outputs this when I run it: > > [_____. > | | > /__. 33 > | | > x y > > The function luatree1d in > > http://angg.twu.net/luatree/luatree.mac.html > > receives a Maxima object and returns a string that is a > one-dimensional representation of a tree in Lua syntax - like the > > '{[0]="[", {[0]="/", "x", "y"}, "33"}' > > in the "echo" above - and the function luatree, that is defined in > luatree.mac as: > > luatree : lambda([o], print(luatree_lua(luatree1d(o))), ""); > > calls luatree_lua to convert the 1D representation of a tree into a 2D > representation... and luatree_lua is defined in > > http://angg.twu.net/luatree/luatree.lisp.html > > as: > > (require :asdf) > > (defun luatree-lua (bigstr) > (with-input-from-string > (s bigstr) > (reduce (lambda (a b) (format nil "~a~%~a" a b)) > (uiop:run-program > (concatenate 'string #$luatreedir$ "luatree.lua") > :input s :output :lines)))) > > (defmfun $luatree_lua (str) (luatree-lua str)) > > This is my first Common Lisp program ever, and I had to ask for help > on IRC channels a lot to find this way to use uiop:run-program to pipe > a string through luatree.lua. > > The class SynTree in luatree.lua builds the 2D representation of a > "syntax tree" by manipulation ascii rectangles that are objects of the > class Rect. Here is a demo that creates two Rect objects in a very > low-level way and then "concatenates" them: > > Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio > > r1 = Rect({"a", "bb", "ccc"}) > > r2 = Rect({"dd", "e"}) > > print(r1..r2) > a dd > bb e > ccc > > > > Lua sees both r1 and r2 as tables, and the usual concatenation > operator - the ".." - doesn't know how to handle concatenation of > tables, so it calls the function __concat in the metatable of r1. I > don't know how to do something like that in Common Lisp, but I plan to > learn how to do that when I grow up. Help welcome! =P > > About GraphViz: I'm interested! Please explain! =) > Cheers, > Eduardo > > _______________________________________________ > Maxima-discuss mailing list > Max...@li... > https://lists.sourceforge.net/lists/listinfo/maxima-discuss > |