Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Perl and maths

by ReinhardE (Sexton)
on Feb 15, 2005 at 09:40 UTC ( [id://431081]=perlquestion: print w/replies, xml ) Need Help??

ReinhardE has asked for the wisdom of the Perl Monks concerning the following question:

Helping my daughter with her maths I got an idea, maybe some other one already had:
wouldn't be interesting job of writing a program which "can maths" ?
I would like to input
(5/3 + 7/13)/(5/2-3/7)
and let them perl produce line bye line
(39 + 3/13)/(35-9/21)
and so on.

But ...... format this also nicely using Perl/Tk . Some ideas ?
It's more a game than a serious job, but it could get very exciting .....
cheers
reinhard

Replies are listed 'Best First'.
Re: Perl and maths
by rg0now (Chaplain) on Feb 15, 2005 at 11:15 UTC
    So you want symbolic math? Then you might want to look into Math::Symbolic. Seems pretty promising, although I myself have never tried it. For me, Mathematica from Wolfram Research proved to be unbeatable, although it is a commercial software...

    rg0now

Re: Perl and maths
by Courage (Parson) on Feb 15, 2005 at 12:31 UTC
    I suggest using Maxima, which has strong connection to Tcl and also has Tcl/Tk GUI frontend.

    See information about Maxima and its usage from Tcl at http://mini.net/tcl/4758

    you could feed maxima.exe with your data and read results
    This involves 2-way pipes

    Another approach could be to start Tcl/Tk GUI for maxima and manipulate this GUI from Perl to get your results.

    addition 1,2:

    I get my 2nd way to work, but this required some Tcl touches and looking Tcl/Tk wiki for some Maxima connection details.
    But finally I got Perl+Tcl/Tk gui with a button that do symbolic algebra computations

    use strict; use Tcl; use Tcl::Tk; my $int = new Tcl::Tk; # this one for Maxima GUI my $int2 = new Tcl::Tk; my $mwm = $int->mainwindow; my $mw = $int2->mainwindow; # get maxima $int->Eval('source xmaxima0'); $int->Eval('source m0.tcl'); # do our GUI my $text_res; my $str = 'integrate(1/(1+x^3),x)'; # text example for maxima expr $mw->Entry(-font=>'Courier 12',-textvariable=>\$str)->pack(-fill=>'x') +; $mw->Button(-text=>'Do it!',-command=>sub { $text_res->insert('end',''.$int->domax($str)); $text_res->seeEnd; })->pack; $text_res = $mw->Scrolled('Text',-font=>'Courier 12')->pack; $mwm->withdraw; $int2->MainLoop; $mwm->destroy;
    Happy screenshot at http://www.vkonovalov.ru/xmaxima-scr.jpg
Re: Perl and maths
by blazar (Canon) on Feb 15, 2005 at 10:05 UTC
    Well this may soon become of a formidable complexity. For one thing you should do the parsing of the expressions in the first place. I'm not even trying to do anything like that because admittedly I have no experience at all in this field. However as a general direction you may either roll-your-own solution or design a very simplified grammar with e.g. Parse::RecDescent.

    IIRC something roughely along these lines had been discussed on clpmisc short before I stopped regularly following it.

    As far as the (Tk) UI is concerned, it's simply up to you and to your skills and tastes, however this seems to me like a task well suited for a cmd-line console based UI, so if you really want to go graphical, then probably something as simple as a window with an input field, a text field for output and an update button would suffice.

    UPDATE: Now that I re-read this, I realize that you were most probably referring to the formatting of mathematical expressions. Then in practice you're asking about implementing a typesetting engine, even if you may be content with an elementary one. In any case it won't be an easy task. I recommend you give a peek into the (La)TeX world instead. In particular you may be interested in mimeTeX and preview-latex.

Re: Perl and maths
by Hena (Friar) on Feb 15, 2005 at 09:50 UTC
    I think this would easily get complicated. Only thing that I can come up with is that you need functions to take that input apart. Eg. array with one element that has one calculation each. Remember that order needs to be two fold, order in line and order to do the calculation. Also function that parses your array back into printable line.

    Then you just do one calculation for each element and print out whats between. Since I'm at office, I'm not going to start coding, but thats a how i would start doing something like this. Note that since I haven't done any Perl/Tk stuff, i can't comment on how that should be done. Good luck :).
Re: Perl and maths
by halley (Prior) on Feb 15, 2005 at 14:47 UTC
    I wanted to code something like this twenty years ago. It would have been cumbersome in C but I think a lot more do-able in a reasonable effort in Perl.

    The task is really just a bunch of simple text (or tree) transforms, and a set of rules on how to apply them. It has very little to do with math itself.

    There are several symbolic math engines out there, but they usually skip the step-by-step proof production. They simplify the expression as far as possible, and stop. If you have source code to these engines, it should be trivial to break it up into an iterative process, returning a set of proof production steps.

    Each rule would have a pattern it looks for, and a replacement pattern. Rules should be simple and ordered. Rules should be scanned in the order they are asserted. (Hey, this is sounding more like Prolog now.) Each time you apply a rule successfully, you should start at the top again to see if it can be simplified further.

    For maximum benefit, each production in the proof should also explain the mathematical rule it applied. For instance:

    (a*(b+c)) (a*b + a*c) -- distribute a to terms b and c

    (Sheepishly, I tried to look up an official name for that simple transform on Wolfram's site, but came up empty. Apparently, if it's not some tensor product of primoral eigenvalues, it's too simple for Wolfram to discuss.)

    --
    [ e d @ h a l l e y . c c ]

      This is the distributive property of multiplication

      -j

      Yep, I once wrote something like this in Prolog as an assignment. I don't remember the details and the code is long lost though. Anyway if I were to do it again (and had to implement it myself) I'd definitely use Prolog again. It does take some time to get used to it since you really have to think differently than when using imperative languages, but once you get the twist it's great for this kind of tasks.

      Jenda
      We'd like to help you learn to help yourself
      Look around you, all you see are sympathetic eyes
      Stroll around the grounds until you feel at home
         -- P. Simon in Mrs. Robinson

      this almost looks like you are getting into sentential and predicate logic, although not quite, but it could be considered a basic proof to go from (5/3 + 7/13)/(5/2 - 3/7) to 1204/1131 (is that the right answer?). just a thought...
Re: Perl and maths
by artist (Parson) on Feb 15, 2005 at 14:48 UTC
    I think that, I know what you are after. It would be fun to see math equations solved step by step automatically. Your input is an equation and as output you want to get step by step answers. You need to define the steps and precedence. In the case you have presented, for example, you might want to do cross multiplication of the numbers within the parantheis and then remove the paranthesis and make it more simple before getting the final answer. It would be fun to define all these rules for different equations. Once you do that, you will have better control of working of math euqation and will serve a useful aid in your teaching.

    For coding these, you may define each element as a seperate entitiy in your euqation. Parse::RecDescent would be very useful for this. Once you have elements and their positions within equation, you may apply your rules to create the next step and so on.

Re: Perl and maths
by Animator (Hermit) on Feb 15, 2005 at 10:42 UTC

    If that is the way you're explaining it to her, then I would say: stop.

    perl -wle 'print ((5/3 + 7/13) / (5/2 - 3/7));' ==> prints 1.06454465075155
    perl -wle 'print ((39 + 3 /13) / (35 - 9/21));' ==> prints 1.1347743165925

    Are you sure you know math? Or is it Perl that doesn't know math? :)

    Now back on topic, are you looking for a fully-featured calculator? or just a basic one (one that can only handle +, -, *, /)?

      no, I don't try it to explain her maths using Perl, ....
      I'm trying to have fun for myself
      I'm not searching a calculator either. I don't also want to deal with 0.3333 if I mean 1/3.
      You remember when you went to school ?
      I wish to transform ( for beginning ) simple expressions.
      cheers,
      reinhard
Re: Perl and maths
by hardburn (Abbot) on Feb 15, 2005 at 16:49 UTC

    And they shall call it "LISP" :)

    Really, run through the first chapter of SICP, which shows how each step of a LISP computation (well, Scheme technically) is performed until you get the basic answer. One could build an interpreter that takes a basic LISP expression (you don't need a full LISP, just the basic arithmatic operations are enough), and then show the reduction of each step until you get the final answer.

    You'll have to live with prefix-notation instead of the common infix notation, but I think we need more of that, anyway.

    "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

Re: Perl and maths
by tall_man (Parson) on Feb 15, 2005 at 16:28 UTC
    Here's something you could get working very quickly, without a lot of coding. Use bigrat to work with fractions, and let perl itself parse the math. You will have to break up the parts into stages, though, so it doesn't do all the simplifications at once. Here is an example:
    use strict; use bigrat; my ($x, $y); $x = 5/3 + 7/13; print $x,"\n"; $y = 5/2 - 3/7; print $y,"\n"; print $x/$y,"\n";

    This prints:

    86/39 29/14 1204/1131

    With a loop to read expressions from input and an eval statement, you could get a perl fractional calculator going in no time.

Re: Perl and maths
by Grundle (Scribe) on Feb 15, 2005 at 20:07 UTC
    Why not just break up the mathematical expression into in a tree? Then you can "percolate up" the tree generating the new expression line by line. The first line printed by perl would be all the leaf nodes with their conecting operator signs (+-*/).

    The second line would be the leaf node operations completed and so on until you only have a root

    You would basically need 2 routines.
    1. Build-Tree -> responsible for taking an expression and making a tree out of it

    2. iterate-tree -> responsible for performing the mathematical operations described at leaf level and replacing the parent node with the new answer. i.e.

             <some-root>  <some-root>
                 /             /
                +      =>     9
              /   \
             5     4
     

    Printing intermediate results is a breeze since it is in tree form. Just make sure that you adhere to the same principle you used when generating the tree (in-order, pre-order, or post-order).
Re: Perl and maths
by Anonymous Monk on Feb 15, 2005 at 11:03 UTC
    What do you mean, "produce Perl line by line"? (5/3 + 7/13)/(5/2-3/7) and (39 + 3/13)/(35-9/21) are valid Perl expressions.
      I admit, I was not clear
      You remember at school ?
      The teacher gave you an expression
      and you transformed it step by step into
      a simpler one
      , at the end remained a "nice" result
      or at least it should ....
      That's what I'm trying to simulate ..
      cheers
      reinhard

        I believe you mean you would like to have perl 'simplify' the expression. Although, typically these expressions have variables. On the other hand, is this to teach 'order of operations'?

        Neil Watson
        watson-wilson.ca

Re: Perl and maths
by pingo (Hermit) on Feb 15, 2005 at 16:29 UTC
    If you use KDE and can live with a really (really) basic interface, you could try using kdialog (I assume there is something similar for Gnome).
    $val = `kdialog --title "Question" --inputbox "What is $a x $b?"`; if ($val == $correct) { system("kdialog --msgbox 'Correct!'"); } else { system("kdialog --msgbox 'Wrong!'"); }

    I've used it for a math quiz thingy which was fairly successful. :-)
Re: Perl and maths
by sleepingsquirrel (Chaplain) on Feb 15, 2005 at 18:00 UTC
    Here are the beginnings of a brief skeleton of an evaluator for simple (and fully parenthesized) arithmetic expressions to get you started. It prints out all of the intermediate steps before it gets to the final answer. You'd need to swizzle the results around to get exactly what you wanted, but I think you get the idea...
    ((1+2)+((3+4)+(5*6)))
    1 + 2 = 3
    3 + 4 = 7
    5 * 6 = 30
    7 + 30 = 37
    3 + 37 = 40
    Final Answer: 40


    -- All code is 100% tested and functional unless otherwise noted.
      Here's a modification to my code above which handles adding fractions and printing out the partial results. Finishing it off is left as an exercise to the reader...
      (1/2+2/3)
      7/6

      (1/2+(2/3+4/5))
      (1/2+22/15)
      59/30

      ((5/3+7/13)+(5/2+3/7))
      (86/39+(5/2+3/7))
      (86/39+41/14)
      2803/546


      -- All code is 100% tested and functional unless otherwise noted.
Re: Perl and maths
by Jaap (Curate) on Feb 15, 2005 at 16:28 UTC
    It would help to get your example right. What is this?
    (5/3 + 7/13)/(5/2-3/7)
    and let them perl produce line bye line
    (39 + 3/13)/(35-9/21)
    Did you mean this?
    (65/39 + 21/39)/(35/14 - 6/14)

    Edit: fixed typo: thanks Paulster2

      But didn't you mean:

      (65/39 + 21/39) / (35/14 - 6/14) ??

      I agree that the original looks a little screwy though.

      Paulster2


      You're so sly, but so am I. - Quote from the movie Manhunter.
Re: Perl and maths
by tphyahoo (Vicar) on Feb 15, 2005 at 16:18 UTC
    If you're practical, excel.

    If you're aesthetical, and you can afford the price, Mathematica.

    If you're full of hubris.... hell, why not... perl!

Re: Perl and maths
by mrborisguy (Hermit) on Feb 15, 2005 at 17:28 UTC
    i think i would start with creating a module for fractions, with, and probably with a function that does all of the operations of fractions (add, subtract...). maybe you'll have to make it output the common denominator step inside the module though. so then you have something like ($frac1 + $frac2) / ($frac3 + $frac4) where $frac\d is of the type of your new fraction module. and then you might end up with another fraction... where $new_fraction's numerator is ($frac1 + $frac2) and it's denominator is ($frac3 + $frac4).

    so (obvioulsy implementation is up to you) i would think of something a data structure for fraction as a hash with numerator and denominator, and your $new_fraction would be something like:
    $new_frac => { numerator => "5/3 + 7/13", denominator => "5/2 - 3/7" }
    and then eventually something like
    $new_frac => { numerator => { numerator => 86, denominator => 39 }, denominator => { numerator => 29, denominator => 14 } }
    come to think of it, you may need to have a data structure or module to represent an "expression" too.

    also, to parse the expression, you may want to look at postfix (although you can certainly still output the expressions in infix)

    these are just my thoughts on how i'd approach it.
Re: Perl and maths
by samizdat (Vicar) on Feb 15, 2005 at 19:05 UTC
    As rg0now and hardburn have alluded to, such coding has been done. For a historical referent, look up MACSYMA, which does what you want and much more, including much of Calculus and DiffEq. The original LISP code was floating around an MIT server at one time... it's really elegant.

    Math::Symbolic can be whacked to print your intermediate results.
Re: Perl and maths
by chas (Priest) on Feb 16, 2005 at 04:32 UTC
    One problem that occurs to me is that there are many ways of "simplfying" such mathematical expressions, and it would be very difficult to formulate rules to choose an efficient sequence of simplifications. For example one could proceed by simplifying the "innermost" expressions and proceed outward, but that might be very inefficient in some cases. I.e., if we had an expresion of the form:
    (a+b)(c+d)+(a+b)(e+f)+(a+b)(gh+ij+kl) then one should clearly factor out (a+b) first instead of computing a+b 3 times. Of course, one could just formulate some simplification scheme, but it might not be at all like what one would do in practice in many cases.
    Maybe I didn't understand what you wanted to do completely, though.
    chas
      Yes. You're rigth.
      There are many ways of solving such an equation.
      So it would also be great to have an interactive tool to follow up the semplification.
      Furthermore sometimes we just see the most elegant way to perform semplification.
      I do not expect me from a programming language to "Just See" the correct way.
      Getting philosophical now ????

      However putting together a little bit of what I understood:
      -- first we have to parse the formula
      -- then we have to project the formula onto an internal representation ( a tree with single objects representing the numbers, maybe one object holding the fraction ? )
      -- present this graphically shouldn't be so difficult.
      -- Ask the user how to proceed further
      -- present the result of the semplification choosed by the user
      -- ask again the user for the next step
      present .......
      -- and so on

      cheers reinhard

Re: Perl and maths
by saintmike (Vicar) on Feb 16, 2005 at 07:40 UTC
    Math::Algebra::Symbols helps with these kinds of algebra tasks. It can also solve equations (even quadratic ones!). Here's an article (sorry, German only!) showing a couple of examples.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://431081]
Approved by Corion
Front-paged by Courage
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-03-29 13:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found