Python Exam

This Python exam covers the following topics:

  • Problem 1: Variable types and formats
  • Problem 2: Debugging
  • Problem 3: Functions, Conditionals, and Loops
  • Problem 4: Solve Linear Equations
  • Problem 5: Solve Nonlinear Equations
  • Problem 6: Integration
  • Problem 7: Differentiate
  • Problem 8: Interpolation
  • Problem 9: Polynomial Regression
  • Problem 10: General Nonlinear Regression
  • Problem 11: Solve Differential Equation
  • Problem 12: Optimization

A template for each problem is provided with instructions on what is needed. In some cases, the problem is to debug a section of code to produce a specific result. In other cases, the problem is to import a module and produce a result. This exam allows open access to any online resources, prior homework solutions, or other files.

In [1]:
!conda info
Current conda install:

               platform : win-64
          conda version : 4.3.30
       conda is private : False
      conda-env version : 4.3.30
    conda-build version : 3.0.27
         python version : 3.6.3.final.0
       requests version : 2.18.4
       root environment : C:\Anaconda3  (writable)
    default environment : C:\Anaconda3
       envs directories : C:\Anaconda3\envs
                          C:\Users\John Hedengren\AppData\Local\conda\conda\envs
                          C:\Users\John Hedengren\.conda\envs
          package cache : C:\Anaconda3\pkgs
                          C:\Users\John Hedengren\AppData\Local\conda\conda\pkgs
           channel URLs : https://repo.continuum.io/pkgs/main/win-64
                          https://repo.continuum.io/pkgs/main/noarch
                          https://repo.continuum.io/pkgs/free/win-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/r/win-64
                          https://repo.continuum.io/pkgs/r/noarch
                          https://repo.continuum.io/pkgs/pro/win-64
                          https://repo.continuum.io/pkgs/pro/noarch
                          https://repo.continuum.io/pkgs/msys2/win-64
                          https://repo.continuum.io/pkgs/msys2/noarch
            config file : C:\Users\John Hedengren\.condarc
             netrc file : None
           offline mode : False
             user-agent : conda/4.3.30 requests/2.18.4 CPython/3.6.3 Windows/10 Windows/10.0.17134    
          administrator : False
In [2]:
# install new packages with "!pip install module-name"
!pip install gekko
Requirement already satisfied: gekko in c:\anaconda3\lib\site-packages (0.0.4rc3)
Requirement already satisfied: numpy>=1.8 in c:\anaconda3\lib\site-packages (from gekko) (1.13.3)
Requirement already satisfied: flask in c:\anaconda3\lib\site-packages (from gekko) (0.12.2)
Requirement already satisfied: Werkzeug>=0.7 in c:\anaconda3\lib\site-packages (from flask->gekko) (0.12.2)
Requirement already satisfied: Jinja2>=2.4 in c:\anaconda3\lib\site-packages (from flask->gekko) (2.9.6)
Requirement already satisfied: itsdangerous>=0.21 in c:\anaconda3\lib\site-packages (from flask->gekko) (0.24)
Requirement already satisfied: click>=2.0 in c:\anaconda3\lib\site-packages (from flask->gekko) (6.7)
Requirement already satisfied: MarkupSafe>=0.23 in c:\anaconda3\lib\site-packages (from Jinja2>=2.4->flask->gekko) (1.0)
In [3]:
print('Hello, World!')

myName = 'BYU Student'  # input('Name: ')
print('Hello, ' + myName + '!')
Hello, World!
Hello, BYU Student!

Problem 1: Variable types and formats

Part A

Add x=5 and y='4' together to produce a string (54) in addition to the example code of below of adding them as integers (9). In addition to printing the results, show the type of variable with type() to confirm that the result is a string.

Hint: An integer is converted to a string with str() and a string is converted to an integer with int().

In [4]:
x = 2
y = '3'

# adding two integers together (5)
z = x + int(y)
# show the result of adding 2+3
print(z)
# show that z is an integer
print(type(z))

# add strings
z = str(x)+y
print(z)
print(type(z))
5
<class 'int'>
23
<class 'str'>

Part B

Show the result of $y = exp(0.0)$ and $z = 1.0$ to 20 decimal places. Is there a difference in the results?

In [5]:
import numpy as np
print('NumPy version:')
print(np.__version__)

y = np.exp(0.0)
z = 1.0
NumPy version:
1.13.3
In [6]:
#### Solution
print('y = {:.20f}'.format(y))
print('z = {:.20f}'.format(z))

print('Another way to format numbers')
print('z = %.20f' %z)

# difference
print('Difference')
print('{:.20e}'.format(y-z))
y = 1.00000000000000000000
z = 1.00000000000000000000
Another way to format numbers
z = 1.00000000000000000000
Difference
0.00000000000000000000e+00

Plots

In [7]:
%matplotlib inline
import matplotlib.pyplot as plt

x = np.linspace(0,10)
y = np.sin(x)
z = np.cos(x)

plt.figure(1)
plt.plot(x,y,'r--',label='sine')
plt.plot(x,z,'b-.',label='cosine')
plt.legend(loc='best')

plt.figure(2)
plt.subplot(2,1,1)
plt.plot(x,y,'r--',linewidth=5)
plt.legend(['sin(x)'],loc='best')
plt.ylabel('sin(x)')
plt.subplot(2,1,2)
plt.plot(x,z,'bo',markersize=5)
plt.legend(['cosine(x)'],loc='best')
plt.xlabel('x')
plt.ylabel('cos(x)')
plt.savefig('myPlot.png')
plt.savefig('myPlot.eps')

Problem 2: Read / Write Files

In [8]:
# write messages or data to file
fid = open('msg.txt','w')
fid.write('Writing to a text file \n')
fid.write('Second line')
fid.write('Third line?')
fid.close()

# read one line at a time
fid = open('msg.txt','r')
text = fid.readline()
print(text)
text = fid.readline()
print(text)
fid.close()

x = np.linspace(0,2*np.pi,20)
y = np.cos(x)

#--- stack rows together from (x,y) to produce data 
#--- then transpose data to convert rows into columns
data = np.vstack((x,y))
data = data.T

#--- save data to data.txt
np.savetxt('data.txt',data)
#--- load text file
z = np.loadtxt('data.txt')
#print(z)

#--- create plot of y = sin(x)
plt.plot(x,y,linewidth=3)
plt.plot(z[:,0],z[:,1],'ro')
plt.xlabel('x')
plt.ylabel('cos(x)')
Writing to a text file 

Second lineThird line?
Out[8]:
Text(0,0.5,'cos(x)')

Problem 3: Functions, Conditionals, and Loops

In [9]:
def f(x):
    y = x**2
    if y>=20:
        y = np.nan # nan = not a number
    return y

x = np.linspace(0,5,100)
y = np.empty_like(x)

# calculate with loop
i = 0
for xi in x:
    y[i] = f(xi)
    i = i + 1

# plot result
plt.plot(x,y)
# optional to make plot look better
plt.xlim([0,5])
plt.ylim([0,30])
plt.title('Clipped Function')
plt.ylabel('x')
plt.xlabel('y')
Out[9]:
Text(0.5,0,'y')

Problem 4: Matrices, Solve Linear Equations

In [10]:
A = np.array([[3,2],[1,2]])
print('A matrix')
print(A)

# b in matrix form
b = np.array([1,0])
print('b vector')
print(b)

#### Solution 1
x = np.dot(np.linalg.inv(A),b)
print(x)

#### Solution 2
x = np.linalg.solve(A,b)
print(x)

#### Solution 3
import sympy as sym
from IPython.display import display
x, y = sym.symbols('x y')
ans = sym.linsolve([3*x + 2*y - 1, x + 2*y], (x, y))
# 3 ways to display answer (ans)
print(ans)
sym.pprint(ans)
display(ans)
A matrix
[[3 2]
 [1 2]]
b vector
[1 0]
[ 0.5  -0.25]
[ 0.5  -0.25]
{(1/2, -1/4)}
{(1/2, -1/4)}
{(1/2, -1/4)}

Problem 5: Solve Nonlinear Equations

In [11]:
from scipy.optimize import fsolve
import sympy as sym
sym.init_printing()

#### Solution with fsolve
def f(z):
    x = z[0]
    y = z[1]
    return [x + 2*y, x**2+y**2-1]

zguess = [0,1]
z = fsolve(f,zguess)
print(z)

#### Solution with Sympy
ans = sym.nonlinsolve([x + 2*y, x**2+y**2-1], [x,y])
display(ans)
[-0.89442719  0.4472136 ]
$$\left\{\left ( - \frac{2 \sqrt{5}}{5}, \quad \frac{\sqrt{5}}{5}\right ), \left ( \frac{2 \sqrt{5}}{5}, \quad - \frac{\sqrt{5}}{5}\right )\right\}$$

Problem 6: Integration

In [12]:
from scipy.integrate import quad
import sympy as sym

#### Solution (scipy)
print('SciPy Solution')
def f(x):
    return x**2
print(quad(f,0,2)[0])
print(8/3)

#### Solution (sympy)
print('SymPy Solution')
x = sym.Symbol('x')
f = sym.integrate(x**2,x)
print(f)
sym.pprint(f)
display(f)
SciPy Solution
2.666666666666667
2.6666666666666665
SymPy Solution
x**3/3
 3
x 
──
3 
$$\frac{x^{3}}{3}$$

Problem 7: Differentiate

In [13]:
from scipy.misc import derivative
import sympy as sym

# numeric method 1
def f(x):
    return x**3 + 2.0*x**2 + 3.0*x + 1.0
print(derivative(f,1))
print(derivative(f,1,dx=1e-10))
der = (f(1.0+1e-10) - f(1.0-1e-10))/2.e-10
print(der)
#help(derivative)

# analytic solution with sympy
x = sym.Symbol('x')
f=sym.diff(x**3 + 2.0*x**2 + 3.0*x + 1.0,x)
print(f.subs(x,1))
sym.pprint(f)
display(f)
11.0
10.0000008274
10.00000082740371
10.0000000000000
   2              
3⋅x  + 4.0⋅x + 3.0
$$3 x^{2} + 4.0 x + 3.0$$

Problem 8: Interpolation

In [14]:
from scipy.interpolate import interp1d
x = np.array([0,1,2,3,4,5])
y = np.array([0.1,0.2,0.3,0.5,1.0,0.9])
plt.plot(x,y,'bo')

xp = np.linspace(0,5,100)
y1 = interp1d(x,y,kind='linear')
print(y1(3))
plt.plot(xp,y1(xp),'g-')

y2 = interp1d(x,y,kind='quadratic')
print(y2(3))
plt.plot(xp,y2(xp),'r--')
0.5
0.5
Out[14]:
[<matplotlib.lines.Line2D at 0x207c1cfb160>]

Problem 9: Linear and Polynomial Regression

In [15]:
x = np.array([0,1,2,3,4,5])
y = np.array([0.1,0.2,0.3,0.5,0.8,2.0])

#### Solution
# linear
p1 = np.polyfit(x,y,1)
# quadratic
p2 = np.polyfit(x,y,2)
# cubic
p3 = np.polyfit(x,y,3)
print(p3)

# plot fit
plt.plot(x,y,'ko',markersize=10)
xp = np.linspace(0,5,100)
plt.plot(xp,np.polyval(p1,xp),'b--',linewidth=2)
plt.plot(xp,np.polyval(p2,xp),'r--',linewidth=3)
plt.plot(xp,np.polyval(p3,xp),'g:',linewidth=2)
plt.legend(['Data','Linear','Quadratic','Cubic'],loc='best')
plt.xlabel('x')
plt.ylabel('y')
[ 0.04166667 -0.2         0.33690476  0.07857143]
Out[15]:
Text(0,0.5,'y')

Problem 10: Nonlinear Regression

In [16]:
from scipy.optimize import curve_fit

x = np.array([0,1,2,3,4,5])
y = np.array([0.1,0.2,0.3,0.5,0.8,2.0])

## Solution
def f(x,a):
    return 0.1 * np.exp(a*x)

aopt, pcov = curve_fit(f,x,y)
print('a = '+str(aopt))

plt.plot(x,y,'bo')
xp = np.linspace(0,5)
plt.plot(xp,f(xp,aopt),'r-')
a = [ 0.58628748]
Out[16]:
[<matplotlib.lines.Line2D at 0x207c1cbd9b0>]

Problem 11: Solve Differential Equation

Solve the following differential equation with initial condition $y(0) = 5$:

$ k \, \frac{dy}{dt} = -t \, y$

where $k=10$. The solution of $y(t)$ should be reported from an initial time $0$ to final time $20$. Create of plot of the result for $y(t)$ versus $t$.

In [17]:
from scipy.integrate import odeint

def dydt(y,t,k):
    return -t*y/k

k = 10.0
t = np.linspace(0,20)
y0 = 5.0
y = odeint(dydt,y0,t,args=(k,))
plt.plot(t,y)
plt.xlabel('time')
plt.ylabel('y')
Out[17]:
Text(0,0.5,'y')

Problem 12: Nonlinear Optimization

Solve the following nonlinear optimization problem:

$\min x_1 x_4 \left(x_1 + x_2 + x_3\right) + x_3$

$\mathrm{s.t.} \quad x_1 x_2 x_3 x_4 \ge 25$

$x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40$

$1\le x_1, x_2, x_3, x_4 \le 5$

with initial conditions:

$x_0 = (1,5,5,1)$

In [18]:
import numpy as np
from scipy.optimize import minimize

def objective(x):
    return x[0]*x[3]*(x[0]+x[1]+x[2])+x[2]

def constraint1(x):
    return x[0]*x[1]*x[2]*x[3]-25.0

def constraint2(x):
    sum_eq = 40.0
    for i in range(4):
        sum_eq = sum_eq - x[i]**2
    return sum_eq

# initial guesses
n = 4
x0 = np.zeros(n)
x0[0] = 1.0
x0[1] = 5.0
x0[2] = 5.0
x0[3] = 1.0

# show initial objective
print('Initial Objective: ' + str(objective(x0)))

# optimize
b = (1.0,5.0)
bnds = (b, b, b, b)
con1 = {'type': 'ineq', 'fun': constraint1} 
con2 = {'type': 'eq', 'fun': constraint2}
cons = ([con1,con2])
solution = minimize(objective,x0,method='SLSQP',\
                    bounds=bnds,constraints=cons)
x = solution.x

# show final objective
print('Final Objective: ' + str(objective(x)))

# print solution
print('Solution')
print('x1 = ' + str(x[0]))
print('x2 = ' + str(x[1]))
print('x3 = ' + str(x[2]))
print('x4 = ' + str(x[3]))
Initial Objective: 16.0
Final Objective: 17.0140172456
Solution
x1 = 1.0
x2 = 4.74299609688
x3 = 3.82115462341
x4 = 1.37940764508

Use Python GEKKO

See GEKKO documentation and example problems. GEKKO is a Python package developed in the BYU PRISM Lab by Logan Beal. Logan is supported by the National Science Foundation, Grant #1547110, EAGER: Cyber-Manufacturing with Multi-echelon Control and Scheduling.

In [19]:
from gekko import GEKKO

# Initialize Model
m = GEKKO()

# initialize variables
x1,x2,x3,x4 = [m.Var(lb=1, ub=5) for i in range(4)]

# initial values
x1.value = 1
x2.value = 5
x3.value = 5
x4.value = 1

# Equations
m.Equation(x1*x2*x3*x4>=25)
m.Equation(x1**2+x2**2+x3**2+x4**2==40)

# Objective
m.Obj(x1*x4*(x1+x2+x3)+x3)

# Solve
m.solve(disp=False)

# show final objective
print('Final Objective: ' + str(m.options.objfcnval))

# print solution
print('Solution')
print('x1: ' + str(x1.value))
print('x2: ' + str(x2.value))
print('x3: ' + str(x3.value))
print('x4: ' + str(x4.value))
Final Objective: 17.0140171
Solution
x1: [1.0]
x2: [4.743]
x3: [3.82115]
x4: [1.379408]