Author Topic: Pythagorean Nightmare in the Digital Age  (Read 75 times)

0 Members and 0 Guests are viewing this topic.

_id_Crisis_

  • { }
  • { ∅, { ∅ } }
  • Posts: 3206
  • the programmer who never was
Pythagorean Nightmare in the Digital Age
« on: July 23, 2019, 08:33:12 pm »
Once again I find myself making two or more different versions of a program displaying calculations, and while it is necessary for the required approximation to be in decimal representation, to make hand-written calculations easier to "do" and "check with code," another version that displays some intermediate steps in Rational Form.

I am often haunted by the thought of Pythagoras' mistrust of "irrational" numbers ... I can't imagine his reaction to dealing with precision details and formatting output in C++ or Python.

Still, I am inspired by his innocent and foundational misgivings.

I mean, I suspect my preference for rational numbers is in dealing with integers, but when working with machines, this all can become tedious, what Schopenhauer would call drudgery.   To me, these technical challenges in representing abstract notions with machines which deal with actual real physical precision in space-time computer-memory reveal some inkling of the qualitas occulta of these concepts.

Is it easier for us to manipulate rational or decimal representations?

He [Arthur Schopenhauer] has been the most radical of all troublemakers. He was defiant. ~ (Marcuse?)

"Learning math is never a waste of time." ~ Ivan Savov

"Programming is understanding."  ~ Kristen Nygaard

{breathing piece of defecating meat destined to die}


_id_Crisis_

  • { }
  • { ∅, { ∅ } }
  • Posts: 3206
  • the programmer who never was
Re: Pythagorean Nightmare in the Digital Age
« Reply #1 on: July 24, 2019, 02:32:25 pm »
FILE ATTACHED: rsd.py

rsd.py is a python file (homegrown created specifically with my own intentions in mind, my own "agenda") I import while within the sage shell
-----------------------------------------------------------------------------------------
from rsd import *

There is a special version of this Repeated Synthetic Division function called rsd_Rational.  The code is to assist me with my hand-written pencil/paper work.  I spent three weeks building code to assist me with just one section of exercises (8.9) APPROXIMATING ZEROS from Modern Introductory Analysis, circa 1965.

The code was in C++, and it turned out very well with many learning experiences along the way.  However, since I do not require a full-fledged program, and want perform much of the beginning estimates in a more spontaneous, free-flowing, electro-digital-technology independent manner, apply a more rational [potentially] in-my-head, but certainly with pencil and paper, approach.   

I am studying methods which would be extremely useful in some situation when no computers or even calculators (YIKES!) were at hand.     In such scenarios, pencil and paper techniques become Mind Treasure … if you can track down pen and paper!   This method would literally work with a stone in the sand. 

Now, since I am comprising a step by step solution key to the future, I wish to check my arithmetic carefully.  It would be stress-inducing and make me horribly irritable.  So, I invested my mental energies in building code to assist me, to make the process of serving my Muse, Mary Dolciani, more fulfilling and perhaps leaving behind useful Mathematical Assistance along the way.

The thing is, while I will use the C++ code, for aiding me in arithmetic involved in the By Hand Techniques, this Python version for Sage is more direct and flexible on the fly run from a sage shell.

I have another version for SymPy but the Rational version has not been built yet.

I devote the Rational versions to Pythagoras, and I shall see at what point dealing with Rational Fractions becomes a hinderence.  I already know the drudgery of squaring decimal representations.    I know  we do not think of such things often since we usually have at least a calculator for arithmetic.   Schopenhauer was so on point with the comments about the drudgery of arithmetic.     I sense he would respect and honor my decision to expend efforts in building mathematical assistance in order to reduce the Tedium and Mechanical mental operations.

I prefer to explore patterns and other things.  The exercises in the book provide the opportunity for me to investigate different things, such as the structure of our different "number systems" and why rounding, precision and numerical computing gets so technical on the level of the hardware and the programming, making approximations of abstract concepts.  I will be on the look out to see if any of the exercises expose a flaw in my code.  The back and forth would make the code more robust.    The end goal is always to preserve the TECHNIQUE, not so much simply provide an answer or result.

Once again, I have used programming to write command line software which aims to preserve a hand-written technique, serving as an assistant, or just showing the process of how to do it just by running some example through it.

There is harmony in this irony.   

---------------------------------------------
Post Scriptum
________________________

While this method (by hand) can be used for polynomials of high degree, you can also get to the root (pun intended) of the Nightmares of Pythagoras by feeding the "technique" [mental machine discovered/invented/preserved] f(x) = x^2 - 2 = 0 to find the square root of 2 or 5 or 17 ... whatever. 

The Method preserved uses something called "repeated" synthetic division.  The repeated part is important, since the coefficients for the first row become the polynomial for the second row.   

I would like to upload an example or two to show how my little snippets of code (the core of the C++ program) written in Python can display how I will be working it out by hand.  This is the beauty of this.  I went through great trouble to be sure I would be fascinated by the arithmetic operations, rather than perturbed by them.  I will have created a mathematical assistant, so to speak.   

Now, rather than allow myself to be intimidated or even defeated by the exercises, as were the students who struggled through those challenging textbooks (instructors were advised to assign 1 or 2 out of 12 and the last two (13, 14), whereas I will  be solving each in detail with much scratch paper and hand-rolled (custom designed = homemade by the meat in my own head, no $$$) software.

I approach the exercises with confidence, but it was my humility which urged me to build such stress-reducing mind tools in preparation for the inevitible "drudgery of arithmetic.".   I do what I can to find some kind of Mojo.

_____________________________________________________
I felt obliged to show one quick example:

f(x) = x^2 - 5 = 0 would be input in sage shell (or Python with the imports) as:

from rsd import *
P = [-5, 0, 1]

explanation: coefficient of x^2 is 1, coefficient of x^1 is 0, and the constant term is -5.

x^2 = 5 ---->  x = sqrt(5)

So, all you do in a sage shell to run this code is create P and feed it to rsd along with other parameters: degree of polynomial (2), value of X (?), and LEVEL OF PRECISION (given as the number of significant digits required in results.)

OK, so, say you want to start off with 4 figures:

rsd(P, 2, ?, 4)

The ? will always be changing. 
I like this down and dirty Python way because it forces me to feed it an initial approximation.  I like my own in-the-head technique for that step, but I had to build it into the C++ program from the ground up [full-fledged].

These Sage versions, on the other hand focus very well on the important algorithm itself.    By the way, I used the instructions in the 1965 text for this method as inspiration for the main operations in the code.   It has been the fire of my heartbeat, and I am now relishing the documentation of my interaction with this material, rather than looking to drown drunk in the ocean.   

WARNING: the combination of symbolic mathematics and digital computing may increase your desire to sustain your animal body and thus submit to most of the  demands made by biological necessity.

Do not let that discourage you from your quest to find solace in arithmetic difficulties.  Death is the norm.  It will come when least expected, I suppose.

Eventually, like I said, I would return to this site to "copy and paste" some output which will simultaneously show the work.

The function is evaluated at x |------> the last element in the first row is f(x)

Then, without calculus (with brute force arithmetic you need paper for [and could program software to do] --- the most tedious part of the process I hope to make more interesting by exploring which steps might be "more elegant in rational form" where one long division at the end is preferable to all the nasty decimal multiplications, additions and subtractions along the way when using decimal representation from the start.

The machines have no choice, but I did find a way to make a version I will run along with the pure decimal version which will in fact display much of the work in rational form, which is the form I am most comfortable with when at liberty to take up a pencil for "reckoning."

you would call it with:

rsd(P, 2, 2, 4) where we chose 2.

Why 2 for sqrt(5)?

This is the part I like to do in my head because it's kind of fun to think it through.

4 is less than 5
sqrt(4) = 2 < sqrt(5) < sqrt(9) = 3 so the root is between 2 and 3.  That is,

2 < sqrt(5) < 3.

(I pause and post for a smoke?)
« Last Edit: July 26, 2019, 07:01:03 pm by gorticide »
He [Arthur Schopenhauer] has been the most radical of all troublemakers. He was defiant. ~ (Marcuse?)

"Learning math is never a waste of time." ~ Ivan Savov

"Programming is understanding."  ~ Kristen Nygaard

{breathing piece of defecating meat destined to die}

_id_Crisis_

  • { }
  • { ∅, { ∅ } }
  • Posts: 3206
  • the programmer who never was
Repeated Synthetic Division code example updated
« Reply #2 on: July 24, 2019, 04:34:22 pm »
Continuation of previous post, but with a recap on the example of how to use this method to approximate the square root of five.

f(x) = x^2 - 5 would be input in sage shell (or Python with the imports) as:

from rsd import *
P = [-5, 0, 1]

explanation: coefficient of x^2 is 1, coefficient of x^1 is 0, and the constant term is -5.

x^2 - 5 = 0
x^2 = 5 ---->  x = sqrt(5)


rsd(P, 2, 2, 4) where we chose 2.

Why 2 for sqrt(5)? 

4 is less than 5
sqrt(4) = 2 < sqrt(5) < sqrt(9) = 3 so the root is between 2 and 3.  That is,

2 < sqrt(5) < 3 (we'll start with x = 2)

So far, we know f(x) = x^2 - 5 = 0, f'(x) = 2x, f''(x) = 2, but you don't necessarily have to use the calculus.  My code displays the short form.  When I have time, I would like to show the longer form I use to do by hand. 
---------------------------------------------------------------------------------------- (updated)

mwh@coyote2:[~/work/sagework/analysis]:
$ ----> sage

│ SageMath version 8.4, Release Date: 2018-10-17                     │

sage: from rsd import *
sage: P = [-5, 0, 1]
sage: rsd(P, 2, 2, 4)


 x = 2.0 |           | f(2.0)
---------------------------------------------------
        |  1    2.0     -1.0
        |  1.0  4.0 =  f'(2.0)

 f(2.0) = -1.0
 and f'(2.0) = 4.0

        nextX = 2.0 - [f(2.0)/f'(2.0)]

        = 2.0 - [-1.0/4.0] = 2.0  + 0.25

         = 2.25 ~=~ 2.25


THE RATIONAL VERSION (created out of sheer curiosity and wonder):
rsd_Rational(P, 2, 2, 4)

sage: rsd_Rational(P, 2, 2, 4)

 x = 2 |             | f(2)
---------------------------------------------------
        |  1    2       -1
        |  1    4 =  f'(2.0)

 f(2.0) = -1.0
 and f'(2.0) = 4.0

        nextX = 2.0 - ( [f(2.0)] / [f'(2.0)] )

             = 2.0 - ( [-1.0] / [4.0] )
             = 2  - ( [-1] / [4] )

           = 2  + [1/4]
           = 2.0  + [0.25]

         = 2.25 ~=~ 2.25

Note that nextX = x - f(x)/f'(x), where f(x) is the function evaluated at x, and f'(x) is the derivative of the function evaluated at x.

You will soon discover that with this method, after each approximation the level of precision doubles.


Not much difference in work between the two for the first approximation.
I will show alternately.  Those interested might wish to pay attention:

------------------------------------------------------------------------------------------------------------

sage: rsd(P, 2, 2.25, 4)

 x = 2.25 |          | f(2.25)
---------------------------------------------------
        |  1    2.25    0.0625
        |  1.0  4.5 =  f'(2.25)

 f(2.25) = 0.0625
 and f'(2.25) = 4.5

        nextX = 2.25 - [f(2.25)/f'(2.25)]

        = 2.25 - [0.0625/4.5] = 2.25  - 0.0139

         = 2.236111111111111 ~=~ 2.2361

sage: rsd_Rational(P, 2, 2.25, 4)

 x = 9/4 |           | f(9/4)
---------------------------------------------------
        |  1    9/4     1/16
        |  1    9/2 =  f'(2.25)

 f(2.25) = 0.0625
 and f'(2.25) = 4.5

        nextX = 2.25 - ( [f(2.25)] / [f'(2.25)] )

             = 2.25 - ( [0.0625] / [4.5] )
             = 9/4  - ( [1/16] / [9/2] )

           = 9/4  - 1/72
           = 2.25  - 0.0139

         = 2.236111111111111 ~=~ 2.2361
------------------------------------------------------------------------------------------------------------
This is 5 figures (4 decimal places of precision).  We want four figures (3 decimal place precision), so x2 = 2.236

In order to verify to 4 significant figures, we have to have two successive results which agree up to that many decimal places (there's no avoiding them at this point, even in the rational version which I created just to help me explore some ideas about doing such intermediate calculations with the more elegant rational representations).

So, one last run for both:

sage: rsd(P, 2, 2.236, 4)

 x = 2.236 |         | f(2.236)
---------------------------------------------------
        |  1    2.236   -0.0003
        |  1.0  4.472 =  f'(2.236)

 f(2.236) = -0.0003
 and f'(2.236) = 4.472

        nextX = 2.236 - [f(2.236)/f'(2.236)]

        = 2.236 - [-0.0003/4.472] = 2.236  + 0.0001

         = 2.236067978533095 ~=~ 2.2361

sage: rsd_Rational(P, 2, 2.236, 4)

 x = 559/250 |               | f(559/250)
--------------------------------------------------
        |  1    559/250 -3/10000
        |  1    559/125 =  f'(2.236)

 f(2.236) = -0.0003
 and f'(2.236) = 4.472

        nextX = 2.236 - ( [f(2.236)] / [f'(2.236)] )

             = 2.236 - ( [-0.0003] / [4.472] )
             = 559/250  - ( [-3/10000] / [559/125] )

           = 559/250  + [670840787119857/10000000000000000000]
           = 2.236  + [0.0001]

         = 2.2360670840787122 ~=~ 2.2361

_______________________________________________________
So, to four significant figures, the square root of 5 is 2.236.

PERIOD.

 :P
« Last Edit: July 24, 2019, 11:51:23 pm by gorticide »
He [Arthur Schopenhauer] has been the most radical of all troublemakers. He was defiant. ~ (Marcuse?)

"Learning math is never a waste of time." ~ Ivan Savov

"Programming is understanding."  ~ Kristen Nygaard

{breathing piece of defecating meat destined to die}

_id_Crisis_

  • { }
  • { ∅, { ∅ } }
  • Posts: 3206
  • the programmer who never was
Re: Pythagorean Nightmare in the Digital Age
« Reply #3 on: July 24, 2019, 07:12:34 pm »
I am not satisfied with         nextX = 2.25 - ( [f(2.25)] / [f'(2.25)] )

             = 2.25 - ( [0.0625] / [4.5] )
             = 9/4  - ( [1/16] / [9/2] )

           = 9/4 - 139/10000
           = 2.25  - 0.0139

         = 2.236111111111111 ~=~ 2.2361

This step, here, - 139/10000, was produced by nsimplify(), a SymPy function.  It is only approximate.  I will replace it with code which performs the Fraction arithmetic, where numerator =  numerator1*denominator2 + numerator2 and denominator is denominator2.  Then the rational version will have EXACT Rational Expressions.   What's the point of having a rational number if it's just an approximation of 0.0139 = 139/10000?   I want to push the number closer in the direction of 0.013888888888888... between  0.01388 and 0.01389 somewhere.

it turns out to be (1 / 72).  I will make the correction and upload the corrected rsd.py file.

 UPDATE:  Since I can't extract the numerator and denominator from each numerator and denominator, the way I will go about it is this:

 nsimplify(0.0625)*nsimplify(1.0/4.5)
Out[8]: 1/72

This does (1/16)/(9/2) = (1/16)*(2/9) = 1/(8*9) = 1 / 72.

So, in rsd.py, I change line 119 -120:               

#tmp = round(1.0*R[1]/dy, F)

 tmp = nsimplify(R[1])*nsimplify(1.0/dy)
#num, den = farey(tmp, 500)

This eliminates my need for farey(x, 500), but I'll keep it in the file to show what lengths I was willing to go to display the Rational version as EXACTLY as possible.

That fix makes the output:

 rsd_Rational(P, 2, 2, 4)
 
 x = 2 |             | f(2)
---------------------------------------------------
        |  1    2       -1
        |  1    4 =  f'(2.0)

 f(2.0) = -1.0
 and f'(2.0) = 4.0

        nextX = 2.0 - ( [f(2.0)] / [f'(2.0)] )

             = 2.0 - ( [-1.0] / [4.0] )
             = 2  - ( [-1] / [4] )

           = 2  + [1/4]
           = 2.0  + [0.25]

         = 2.25 ~=~ 2.25
sage: rsd_Rational(P, 2, 2.25, 4)

 x = 9/4 |           | f(9/4)
---------------------------------------------------
        |  1    9/4     1/16
        |  1    9/2 =  f'(2.25)

 f(2.25) = 0.0625
 and f'(2.25) = 4.5

        nextX = 2.25 - ( [f(2.25)] / [f'(2.25)] )

             = 2.25 - ( [0.0625] / [4.5] )
             = 9/4  - ( [1/16] / [9/2] )

           = 9/4  - 1/72
           = 2.25  - 0.0139

         = 2.236111111111111 ~=~ 2.2361
sage:rsd_Rational(P, 2, 2.236, 6)

 x = 559/250 |               | f(559/250)
---------------------------------------------------
        |  1    559/250 -19/62500
        |  1    559/125 =  f'(2.236)

 f(2.236) = -0.000304
 and f'(2.236) = 4.472

        nextX = 2.236 - ( [f(2.236)] / [f'(2.236)] )

             = 2.236 - ( [-0.000304] / [4.472] )
             = 559/250  - ( [-19/62500] / [559/125] )

           = 559/250  + [4248658318425761/62500000000000000000]
           = 2.236  + [6.8e-05]

         = 2.236067978533095 ~=~ 2.236068

Look at that Fraction!   This is my point.  In the first couple of approximations rational form is reasonable (no pun intended on that one), but in this third phase of the process,  It is far easier to add or subtract decimal representation 0.000068 from 2.236 than to add or subtract [4248658318425761/62500000000000000000] to/from 559/250.    :-\ 

Trust me, all this will be worth the effort when I start doing these by hand, and need to organize my scratch work in order to master this method.  I can see working with whatever form is clearest until only decimal form is feasible for the poor ape-like sentient meat-head who must muster patience to perform the required arithmetic.   These methods aim to reduce the drudgery, not eliminate it altogether.  What;s cool though is that you may only really need to carry out the repeated division twice, in which case the rational form takes you fairly far into the calculations by hand before becoming quite ugly and not easy to operate with in that most exact form.

I'll have to edit the previous post, after which I will mark as UPDATED.
« Last Edit: July 24, 2019, 08:25:11 pm by gorticide »
He [Arthur Schopenhauer] has been the most radical of all troublemakers. He was defiant. ~ (Marcuse?)

"Learning math is never a waste of time." ~ Ivan Savov

"Programming is understanding."  ~ Kristen Nygaard

{breathing piece of defecating meat destined to die}