Boolean algebra, conditional statements, loops.

by Eugeniy E. Mikhailov and Greg Bentsen

Boolean algebra

Boolean algebra

Variable of boolean type can have only two values

There are three logical operators which are used in boolean algebra

  • ¬\lnot - logic not, Python not ¬true = false¬false = true\begin{aligned} \lnot \text{true = false}\\ \lnot \text{false = true} \end{aligned}
  • \land - logic and, Python and AB={true,if A=true and B=true,false,otherwise\begin{aligned} A \land B = \begin{cases} \text{true}, \ \text{if A=true~and~B=true}, \\ \text{false}, \ \text{otherwise} \end{cases} \end{aligned}
  • \lor - logic or, Python or AB={false,if A=false and B=false,true,otherwise\begin{aligned} A \vee B = \begin{cases} \text{false}, \ \text{if A=false~and~B=false}, \\ \text{true}, \ \text{otherwise} \end{cases} \end{aligned}

Boolean operators precedence in Python

Assume

A=False
B=True
C=True

what is the resulting value of

A or not B and C

not has highest precedence, then and, and then or

A or ( (not B) and C )

Thus

>>> A or not B and C
False

“Cat is an animal and cat is not an animal”

is a false statement

>>> C and not C
False

Fun with boolean logic

“To be or not to be”
The answer is always True

>>> B=True
>>> B or not B
True
>>>
>>> B=False
>>> B or not B
True

There is an island, which is populated by two kind of people: liars and truthlovers.

Suppose you land on this island and meet a person. What will be the answer to your question “Who are you?”

Now you see a person who answers to your question. “I am a liar.”

Is it possible?

Python boolean edge cases

>>> True and 13
13
>>> True or 13
True
>>> 123.3 and 12
123.3
>>> 123.3 or 14
123.3
>>> True + True
2
>>> False + True
1

Do not make you program depending on strange mix of logic and numbers math.

It is very hard to wrap your mind around such use.

Comparison operators

Comparison operators

Math or human notation Python
== == double equal sign!
\ne !=
<< <
\le <=
>> >
\ge >=
>>> 2 > 3
False
>>> 2 == 2
True
>>> 23 != 3
True
>>> x=[1,2,3,4,5]
>>> x>3
Traceback (most recent call last):
  File "<python-input-148>", line 1, in <module>
    x>3
TypeError: '>' not supported between instances of 'list' and 'int'

But note that the comparison would fail with lists

We need to use the array data structure, e.g. numpy module’s array

>>> import numpy as np
>>> x=np.array([1,2,3,4,5])
>>> x
array([1, 2, 3, 4, 5])
>>> x > 3
array([False, False, False,  True,  True])
>>> x[x > 3]  # chose from x element larger than 3
array([4, 5])

Comparison with arrays (specifically numpy arrays)

It is done element-wise, i.e. we apply comparison to every element independently

>>> A = np.array( [[1, 2], [3, 4]] )
>>> A
array([[1, 2],
       [3, 4]])
>>> B = np.array( [[11, 22], [63, 64]] )
>>> B
array([[11, 22],
       [63, 64]])
>>> A >= 2
array([[False,  True],
       [ True,  True]])

We get back a 2D array

Useful idiom: chose from … where … is true

>>> A[A >= 2]
array([2, 3, 4])

We get back a 1D array

>>> B[A >= 2]
array([22, 63, 64])

We get back a 1D array

Conditional statements

if-else statement

if *expression* :
    # this part is executed only
    # if *expression* is true
else:
    #this part is executed only
    #if *expression* is false

# this part is not part of if
if *hungry*:
    buy some food
else:
    keep working for 10 min
Check the clock
if (x>=0):
    y=np.sqrt(x)
else:
    ValueError("x must be larger than 0")

Unconventional but technically correct

>>> if 5:
...     print(56)  # the only branch that will be taken
... else:
...     print(11)
...
56
>>> # we will alway see 56 above

Common mistake in the ‘if’ statement

>>> x=3
>>> y=4
>>> if (x=y):
...     D=4
... else:
...     D=2

The value of ‘D’ is always 4, except the case when y=0

assignment operator (=) is not equality operator (==)

Modern python will warn you about this potential error.

python says

  File "<python-input-177>", line 1
    if (x=y):
        ^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

ipython says

  Cell In[1], line 3
    if (x=y):
        ^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Short form of ‘if’ without ‘else’ statement

We can skip else when we do not need it

if *expression* :
    # this part is executed only
    # if *expression* is true
if *won a million*:
    go party
keep doing as before
if (delta<0.1):
    return x1
delta = x1 - x1

Loops

The ‘while’ loop

while *expression*:
    this part is executed while *expression* is true
while *hungry*:
    keep eating
>>> x=1
>>> while (x<4):
...     print(x)
...     x = x + 1
...
1
2
3

while loop is extremely useful but they are not guaranteed to finish.

For a bit more complicated conditional statement and the loop body, it is hard to predict if the loop will finish.

Yet another common mistake is

>>> c=1
>>> i=1
>>> while (i<5):
...     print(c)
...     c=c+5

We will never finish, since `i` is not changing within the loop.

The ‘for’ loop

for variable in list_like:
    do something

In this case variable is assigned consequently with values taken from list_like and then statements inside of the loop are executed

>>> sum=0
... x=[1, 2, 7, 5]
... for v in x:
...     sum = sum + v
... print(sum)
15

for loops are guaranteed to complete after predictable number of iterations (the amount of columns in expression).

Series

Example: sum a series of numbers

S=i=0100i=0+1+2+3+4++99+100S=\sum_{i=0}^{100} i = 0 + 1 + 2 + 3 + 4 + \cdots + 99 + 100

>>> S=0
>>> i=0;
>>> while(i<=100):
...     S=S+i
...     i=i+1
... print(f"{S=}")  # handy way to print
... print(f"{i=}")  # variable and its value
...
S=5050
i=101
>>> S=0
... i=21321  # note: it will be reassigned
... for i in range(101):  # note 101 and not 100
...     S=S+i
... print(f"{S=}")
... print(f"{i=}")
...
S=5050
i=100

Example

Calculate sum S=k=5100akS=\sum_{k=5}^100 a_k As long as ak105a_k \ge 10^{-5}, where ak=kka_{k}=k^{-k}.

Using while loop

>>> S=0
... k=5
... while (k<=100):
...     a_k  = k**(-k)
...     k = k+1  # update loop controlling variable ASAP
...     if a_k < 10**(-5):
...         break  # new operator! break out of the loop
...     S = S + a_k
... print(S)
...
0.0003414334705075446

Using for loop

>>> S=0
... for k in range(5,101):  # note +1 to the upper end
...     a_k  = k**(-k)
...     if a_k < 10**(-5):
...         break  # new operator! break out of the loop
...     S = S + a_k
... print(S)
...
0.0003414334705075446

Arguably, for loop is less work

Same example with array operations

Calculate sum S=k=5100akS=\sum_{k=5}^100 a_k As long as ak105a_k \ge 10^{-5}, where ak=kka_{k}=k^{-k}.

When dealing with numerical operations, often it is more elegant to use Python array operators. It is also much faster if the body of the loop is executed many times (> 1000).

>>> import numpy as np
... k = np.arange(5,101)  # again notice +1 to the upper end
... k = 1.0*k  # this looks useless, but it converts integer to float needed for `np.pow`
... a_k = np.pow(k, -k)
... S  = np.sum( a_k[a_k >= 10**(-5)] )
... print(S)
...
0.0003414334705075446

Note