Python

Scientific Computing

Prof. Calvin

Why Python?

On Python

  • Python is free,
  • Python is very widely used,
  • Python is flexible,
  • Python is relatively easy to learn,
  • and Python is quite powerful.

Why not Python?

  • Python is a general purpose language used for Scientific Computing.
  • Not to build apps, build software, manage databases, or develop user interfaces.
  • Solve scientific and mathematical problems.

Python libraries

Scientists often use the following:

We’ll get to these.

Running Example

Diving In

  • Taking Python as a given, we’ll:
    • Use an example of something I helped a student with recently
    • Show step-by-step how to use Python
    • Introduce a number of Python features to solve the problem more easily.
  • This was from an introductory physics class I believe; I don’t know the context.

Motivating Example

  • Recently, I helped a student stuck on this:

\[ f(x) = \begin{cases} 9x^2 + 5 & x < 4 \\ 9 & 4 \leq x \leq 8 \\ 2 - x & x > 8 \end{cases} \]

  • Find \(f(x)\) for each of the following \(x\) values: \[ \{-1, 4, 5, 8, 11\} \]

Is this “real”?

  • Models income tax brackets, one of the most important drivers of human behavior in the largest economies in the world.
  • We use a simpler contrived example for now…
Marginal Tax Rate Single Taxable Income Married Filing Jointly or Qualified Widow(er) Taxable Income Married Filing Separately Taxable Income Head of Household Taxable Income
10% $0 – $9,275 $0 – $18,550 $0 – $9,275 $0 – $13,250
15% $9,276 – $37,650 $18,551 – $75,300 $9,276 – $37,650 $13,251 – $50,400
25% $37,651 – $91,150 $75,301 – $151,900 $37,651 – $75,950 $50,401 – $130,150
28% $91,151 – $190,150 $151,901 – $231,450 $75,951 – $115,725 $130,151 – $210,800
33% $190,151 – $413,350 $231,451 – $413,350 $115,726 – $206,675 $210,801 – $413,350
35% $413,351 – $415,050 $413,351 – $466,950 $206,676 – $233,475 $413,351 – $441,000
39.6% $415,051+ $466,951+ $233,476+ $441,001+

How to solve?

  • Think about how you would solve such a problem.
  • What steps would you take?
  • What would making solving it hard?
    • Keep track of details?
    • Performing the arithmetic?
    • Anything else?
  • Python, in my view, is a way to solve these problems.

Python in action

  • My preferred way to do calculation as an experienced Python user is writing code:
  • Mathematical expression \[ \begin{cases} 9x^2 + 5 & x < 4 \\ 9 & 4 \leq x \leq 8 \\ 2 - x & x > 8 \end{cases} \]
  • Python expression (code)
9 * -1 * -1 + 5
14
  • I write x * x for \(x^2\) because it’s non-obvious how to write “squared” yet.

Arithmetic Operations

  • In Python, we can write many of the same arithmetic operations we use in our math and science classes.
6 + 3
9
6 - 3
3
6 * 3
18
6 / 3
2.0

Wait?

  • Use Python? How?
  • To use Python to make this calculation, first we must install Python.
    • It is a program, like Firefox, MS Word or Fortnite

Installing Python

Warning!

  • There is a very important box to check while installing!
    • Be careful working ahead!
    • We’ll teach how to fix not checking this box but not for a while

Installation

  • We go to the offial webpage to get an installer for our computer:
  • Be careful about starting it!
    • You can open it and check the next slide.

Add Python to PATH

Why?

  • The benefit of adding Python to path is that we can use it at
  • <dramatic music>
  • The Command Line
    • A text-based interface to computing resources, including its ability to do e.g. arithmetic and save notes.

Terminal

  • On MS Windows
    • I press Windows key, type “terminal” then press enter.
  • On MacOS
    • I open Launchpad, type “terminal” then press enter.

MacOS

Windows

Expression evaluation

  • Returning to the terminal, we can type at the “prompt”.
  • On MacOS, perhaps a line that begins with $ and a flashing cursor
  • On Window, perhaps PS C:\Users\calvin>
    • PS stands for “powershell” - more latter.
    • C:\Users\calvin is the name of a folder - more latter
    • > is the prompt, with a flashing cursor.

“Run” Python

In the following examples, I remove line numbers to denote they are not Python code snippets.

  • On Windows, type python
Windows
PS C:\Users\calvin> python
  • On MacOS, type python3
MacOS
$ python3
  • On both, press the ↵ᴇɴᴛᴇʀ key.

See Python

  • You’ll see something like this:
  • Take note of the prompt!
  • >>>
  • Those three are how you know it is Python, and not the Terminal, that you are working in.

Example

  • If I type python at the command line
  • Then 9 * -1 * -1 + 5 within Python
  • It will look like this:
  • This is how Python shows that 9 * -1 * -1 + 5 is 14

Evaluating Expressions

Recall

\[ \begin{cases} 9x^2 + 5 & x < 4 \\ 9 & 4 \leq x \leq 8 \\ 2 - x & x > 8 \end{cases} \] \[ \{-1, 4, 5, 8, 11\} \]

>>> 9 * -1 * -1 + 5
14
>>> 9
9
>>> 9
9
>>> 9
9
>>> 2 - 11
-9
  • This is still quite tedious and annoying!

(In)equality testing

  • Like + or - which we use to calculate numbers…
  • We can use < or > to calculate inequalities.
  • Specifically, we see whether an inequality is True or False
-1 < 4
True
4 < 4
False

Accomodating Keyboards

  • Some things aren’t super easy to type.
  • I don’t have a “\(\leq\)” key on my keyboard.
  • Combine with = as <= for “less than or equal” or “\(\leq\)
4 <= 4
True
  • We can “chain” inequalities as well - one after another.
4 <= 4 <= 8
True

A note

  • We always put the equal sign = second.
4 <= 5
True
5 >= 4
True
  • A (somewhat confusing) error if we try =>

= and ==

New Topics

  • We have now touch on two new topics:
    • True and False
      • Expressions which don’t evaluate to a number
      • Called “booleans”
    • “Assignment”
      • Associated with the = sign
      • Different from inequality testing!
  • We’ll explore both!

Booleans

  • Sometimes, a Python expression is a numerical value.
2 + 2
4
7
7
  • But it doesn’t have to be!
2 < 2
False

If

  • Booleans are mostly useful for writing if statements.
    • These are multiline expressions in Python.
  • To see the result of multi-line expression, we have to print the result…
if (1 <= 1):
    print(2 + 2)
4
if (1 < 1):
    print(2 + 2)

Piecewise

  • We can see the immediate use of this in a piecewise function!

\[ \begin{cases} 9x^2 + 5 & x < 4 \\ 9 & 4 \leq x \leq 8 \\ 2 - x & x > 8 \end{cases} \] \[ \{-1, 4, 5, 8, 11\} \]

if (-1 < 4):
    print(9 * -1 * -1 + 5)
14
  • Or least part of one…
if (4 < 4):
    print(9 * 4 * 4 + 5)
  • Uh oh!

Else

  • Oftentimes, we use if with else
if (1 < 1):
    print("1 is less than 1")
else:
    print("1 is not less than 1")
1 is not less than 1

Elif

  • If we have more than two options, we can place a special elif in the middle.
if (1 < 1):
    print("1 is less than 1")
elif (1 > 1):
    print("1 is greater than 1")
else:
    print("1 is equal to 1")
1 is equal to 1
if (2 < 1):
    print("2 is less than 1")
elif (2 > 1):
    print("2 is greater than 1")
else:
    print("2 is equal to 1")
2 is greater than 1
  • By the way, it is extremely obnoxious to manually type 2 in 5 different places

Assignment

  • We can also assign variables!
    • I call this single-equals assignment
    • Use a single equals sign = and some variable name, like x
x = 1
if (x < 1):
    print("x is less than 1")
elif (x > 1):
    print("x is greater than 1")
else:
    print("x is equal to 1")
x is equal to 1
x = 2
if (x < 1):
    print("x is less than 1")
elif (x > 1):
    print("x is greater than 1")
else:
    print("x is equal to 1")
x is greater than 1

Double equals equality

  • I call it single-equals assignment because sometimes we check if a variable is precisely equal to some value.
  • That is somewhat confusingly done with == double equals equality test.
x = 1
if (x == 1):
    print("x is equal to 1")
else:
    print("x is not equal to 1")
x is equal to 1
x = 2
if (x == 1):
    print("x is equal to 1")
else:
    print("x is not equal to 1")
x is not equal to 1

Double ** Exponentation

  • Doubling is used in a few other cases.
  • Double asterisk ** is exponentiation.
5 ** 2
25
  • We note that ^ - sometimes used for exponentiation - is something different (and confusing!) in Python.
5 ^ 2
7
  • Always use **

Piecewise

  • We can finally write the piecewise expression!

\[ \begin{cases} 9x^2 + 5 & x < 4 \\ 9 & 4 \leq x \leq 8 \\ 2 - x & x > 8 \end{cases} \] \[ \{-1, 4, 5, 8, 11\} \]

x = 11
if (x < 4):
    print(9 * x ** 2 + 5)
elif (4 <= x <= 8):
    print(9)
elif (x > 8):
    print(2 - x)
-9

Code Reuse

Recycle

  • It is still extremely tedious to either:
    • Copy-paste, or
    • Type more than once.
  • Also very annoying/difficult to write them many lines without error!
  • We introduce the def keyword to define functions
  • A way to reuse code we have already written.

def

  • We recall we use print in a multi-line.
def double(x):
    print(x + x)
  • def + some function name + ( + some variable name + ):
double(7)
14
  • “Call” functions the same way we call print - with parens.

Metaphor

  • def is like asking a friend for something.
  • “Hey can you add x and x together?”
  • print is how your friend tells you the result.
  • “Can you print out the result of x + x for me?”

return

  • It is more common to use return than print in a function.
  • When we call a function, we can think of it as expression with some value.
  • That value is defined by the value that is return.
def six_gt_five_print():
    print(True)

if (six_gt_five_print()):
    print(123)
True
def six_gt_five_print():
    return True

if (six_gt_five_print()):
    print(123)
123

Example

  • Suppose an interest rate doubles our savings every ~7 years.
  • How much savings in 14 years?
savings = 10
double(savings)
20

Use return

def double(x):
    return x + x
  • Now, double(savings) becomes equal to x + x
savings = 10
savings = double(savings)
savings
20
double(savings)
40
  • Or even
double(double(10))
40

Piecewise

  • We can finally write the piecewise function (was: expression)!
    • Function: use many times in many expressions
    • Expression: evaluate once and get one answer

\[ \begin{cases} 9x^2 + 5 & x < 4 \\ 9 & 4 \leq x \leq 8 \\ 2 - x & x > 8 \end{cases} \] \[ \{-1, 4, 5, 8, 11\} \]

def piecewise(x):
    if (x < 4):
        return 9 * x ** 2 + 5
    elif (4 <= x <= 8):
        return 9
    elif (x > 8):
        return 2 - x
piecewise(4)
9

Iteration

Tedium

  • This is still quite tedious.
piecewise(-1)
14
piecewise(4)
9
piecewise(5)
9
piecewise(8)
9
piecewise(11)
-9

Sets

  • This is a set:

\[ \{-1, 4, 5, 8, 11\} \]

  • A set is an unordered collection of elements.
    • In this case, elements are integers - whole numbers.
  • Python can also recognize sets!
{-1, 4, 5, 8, 11}
{-1, 4, 5, 8, 11}

Type

  • To be sure that is, in fact, a set, we use the helpful built-in type() to ask Python.
s = {-1, 4, 5, 8, 11}
type(s)
set
  • We have also worked with integers.
type(1)
int
  • And booleans - True and False values.
type(1 == 1)
bool

Loops

  • With a set, do something to each element
  • In Python, use a for loop:
    • The for keyword
    • The name to refer to an element, like e or x
    • The in keyword
    • The set/collection (or its variable name)
    • The : colon special character
    • An indented new line of code

Example

  • for element in collection
    • do thing
for e in {-1, 4, 5, 8, 11}:
    print(piecewise(e))
9
9
9
-9
14
  • What do you see?

Example

  • What if we just try to print the elements?
    • Easier to think about!
for e in {-1, 4, 5, 8, 11}:
    print(e)
4
5
8
11
-1
  • What do you see?

Ordering

  • Recall: “A set is an unordered collection of elements”.
  • We need to put things in order!
  • The most common way to do this in Python is with a list.
  • Almost the same as sets, just use “boxy brackets” []
type([1,2,3])
list

Example

  • for element in collection
    • do thing
for e in [-1, 4, 5, 8, 11]:
    print(piecewise(e))
14
9
9
9
-9
  • What do you see?

Seeing lists

  • We can also use lists to print multiple values!
    • Very helpful for keeping track of things!
for e in [-1, 4, 5, 8, 11]:
    print([e, piecewise(e)])
[-1, 14]
[4, 9]
[5, 9]
[8, 9]
[11, -9]

Updating lists

  • Each element is a lot like a variable.
    • They just have a name and number, use []
    • The initial element is number 0 (not 1)
xs = [-1, 4, 5, 8, 11]
xs[0]
-1
  • And like variables, we can assign a value with =
xs[0] = -2
xs
[-2, 4, 5, 8, 11]

Metaphor

  • Think of a list like a block in a neighborhood.
    • Perhaps to “400” block or “8000”
  • The house on the corner has the block number.
    • 400 1st St, 8000 9th Ave
  • Latter houses have higher numbers.
    • 404 1st St, 8019 9th Ave

Adding lists

  • Lists also helpfully support addition with +
[-1] + [4, 5, 8, 11]
[-1, 4, 5, 8, 11]
  • We often use this to make new lists.
result = []
for e in [-1, 4, 5, 8, 11]:
    result = result + [piecewise(e)]
result
[14, 9, 9, 9, -9]
  • This pattern also works with numbers!
x = 0 
x = x + 1
x
1

Careful!

  • We cannot add numbers directly to lists
    • [1] + 2 doesn’t work!
  • I think of this as adding a house to block without having an address for it.
    • Where would the house go?
  • To add a house to block, we need to have a new “lot” for the house to be on.

Exercise

Income tax

  • Recall the example of a piecewise function:
Marginal Tax Rate Single Taxable Income Married Filing Jointly or Qualified Widow(er) Taxable Income Married Filing Separately Taxable Income Head of Household Taxable Income
10% $0 – $9,275 $0 – $18,550 $0 – $9,275 $0 – $13,250
15% $9,276 – $37,650 $18,551 – $75,300 $9,276 – $37,650 $13,251 – $50,400
25% $37,651 – $91,150 $75,301 – $151,900 $37,651 – $75,950 $50,401 – $130,150
28% $91,151 – $190,150 $151,901 – $231,450 $75,951 – $115,725 $130,151 – $210,800
33% $190,151 – $413,350 $231,451 – $413,350 $115,726 – $206,675 $210,801 – $413,350
35% $413,351 – $415,050 $413,351 – $466,950 $206,676 – $233,475 $413,351 – $441,000
39.6% $415,051+ $466,951+ $233,476+ $441,001+

Singles only…

Rate From
10% 0
15% 9275
25% 37650
28% 91150
33% 190150
35% 413350
39.6% 415050

Motivating example

  • How much would a single making 400k pay?
  • 10% on 9275
  • 15% on 37650 - 9275
  • 25% on 91150 - 37650
  • 28% on 190150 - 91150
  • 33% on 400000 - 190150
Rate From
10% 0
15% 9275
25% 37650
28% 91150
33% 190150
35% 413350
39.6% 415050

Sum it up!

  • Watch out for order-of-operations!
  • 10% on 9275
  • 15% on 37650 - 9275
  • 25% on 91150 - 37650
  • 28% on 190150 - 91150
  • 33% on 400000 - 190150
x = .10 * 9275
y = .15 * (37650 - 9275)
z = .25 * (91150 - 37650)
r = .28 * (190150 - 91150)
s = .33 * (400000 - 190150)
x + y + z + r + s
115529.25

Add as you go

  • We may set a variable to an expression over that variable
    • I think of this as an “old” version of the variable on the right side of the equal sign.
x = .10 * 9275
x = x + .15 * (37650 - 9275)
x = x + .25 * (91150 - 37650)
x = x + .28 * (190150 - 91150)
x + .33 * (400000 - 190150)
115529.25
x = .10 * 9275
y = .15 * (37650 - 9275)
z = .25 * (91150 - 37650)
r = .28 * (190150 - 91150)
s = .33 * (400000 - 190150)
x + y + z + r + s
115529.25

Assign-update

  • We may use an “assignment operator” +=
    • Reassign a variable based on the result of an arithmetic operation.
x = .10 * 9275
x = x + .15 * (37650 - 9275)
x = x + .25 * (91150 - 37650)
x = x + .28 * (190150 - 91150)
x + .33 * (400000 - 190150)
115529.25
x = .10 * 9275
x += .15 * (37650 - 9275)
x += .25 * (91150 - 37650)
x += .28 * (190150 - 91150)
x + .33 * (400000 - 190150)
115529.25

Exercise

  • Write function
  • def single_tax(pay):
  • Return tax cost.
    • Return not print!
  • Bonus: Also write single_tax_rate which returns the percent tax rate at some income level.
Rate From
10% 0
15% 9275
25% 37650
28% 91150
33% 190150
35% 413350
39.6% 415050

Solution

  • Spoiler alert!
Code
def single_tax(pay):
    tax = 0
    if pay > 415050:
        tax += (pay - 415050) * .396
        pay = 415050
    if pay > 413350:
        tax += (pay - 413350) * .35
        pay = 413350
    if pay > 190150:
        tax += (pay - 190150) * .33
        pay = 190150
    if pay > 91150:
        tax += (pay - 91150) * .28
        pay = 91150
    if pay > 37650:
        tax += (pay - 37650) * .25
        pay = 37650
    if pay > 9275:
        tax += (pay - 9275) * .15
        pay = 9275
    return tax + pay * .1
  • The solution gives the following results!
[
    single_tax(100000),
    single_tax(100000),
    single_tax(200000),
    single_tax(300000),
    single_tax(400000),
]
[21036.75, 21036.75, 49529.25, 82529.25, 115529.25]
  • 115529.25 matches our calculations.

Challenge Problem

  • Calculate at what income does the tax rate reach the second highest marginal tax rate of 35%?
    • That is, at what pay does tax == pay * .35
Code
m = .396
b = 0
b += (415050 - 413350) * .35
b += (413350 - 190150) * .33
b += (190150 - 91150) * .28
b += (91150 - 37650) * .25
b += (37650 - 9275) * .15
b += 9275 * .1
(m * -415050 + b)/(.35 - m)
952827.173913043

Bonus Solution

  • single_tax with loops
Code
def single_tax(pay):
    tax_policy = [
        [415050, .396], 
        [413350, .35],
        [190150, .33],
        [91150, .28],
        [37650, .25],
        [9275, .15]
    ]
    tax = 0
    for bracket in tax_policy:
        if pay > bracket[0]:
            tax += (pay - bracket[0]) * bracket[1]
            pay = bracket[0]
    return tax + pay * .1