$$ \newcommand{\tp}{\thinspace .} $$

Exercises

Exercise 1: Make a dictionary from a table

The file src/files/constants.txt contains a table of the values and the dimensions of some fundamental constants from physics. We want to load this table into a dictionary constants, where the keys are the names of the constants. For example, constants['gravitational constant'] holds the value of the gravitational constant (\( 6.67259\cdot 10^{-11} \)) in Newton's law of gravitation. Make a function that reads and interprets the text in the file, and finally returns the dictionary. Filename: fundamental_constants.py.

Exercise 2: Explore syntax differences: lists vs. dicts

Consider this code:

t1 = {}
t1[0] = -5
t1[1] = 10.5
Explain why the lines above work fine while the ones below do not:

t2 = []
t2[0] = -5
t2[1] = 10.5
What must be done in the last code snippet to make it work properly? Filename: list_vs_dict.py.

Exercise 3: Use string operations to improve a program

Consider the program density.py from the section Example: File data in dictionaries. One problem with this program is that the name of the substance can contain only one or two words, while more comprehensive tables may have substances with names consisting of several words. The purpose of this exercise is to use string operations to shorten the code and make it more general and elegant.

a) Make a Python function that lets the name substance consist of all the words that line is split into, but not the last (which is the value of the corresponding density). Use the join method in string objects to combine the words that make up the name of the substance.

b) Observe that all the density values in the file densities.dat start in the same column. Write an alternative function that makes use of substring indexing to divide line into two parts (substance and density).

Hint. Remember to strip the first part such that, e.g., the density of ice is obtained as densities['ice'] and not densities['ice '].

c) Make a test function that calls the two other functions and tests that they produce the same result.

Filename: density_improved.py.

Exercise 4: Interpret output from a program

The program src/funcif/lnsum.py produces, among other things, this output:

epsilon: 1e-04, exact error: 8.18e-04, n=55
epsilon: 1e-06, exact error: 9.02e-06, n=97
epsilon: 1e-08, exact error: 8.70e-08, n=142
epsilon: 1e-10, exact error: 9.20e-10, n=187
epsilon: 1e-12, exact error: 9.31e-12, n=233
Redirect the output to a file (by python lnsum.py > file). Write a Python program that reads the file and extracts the numbers corresponding to epsilon, exact error, and n. Store the numbers in three arrays and plot epsilon and the exact error versus n. Use a logarithmic scale on the \( y \) axis.

Hint. The function semilogy is an alternative to plot and gives logarithmic scale on \( y \) axis.

Filename: read_error.py.

Exercise 5: Make a nested dictionary from a file

The file src/files/human_evolution.txt holds information about various human species and their height, weight, and brain volume. Make a program that reads this file and stores the tabular data in a nested dictionary humans. The keys in humans correspond to the specie name (e.g., homo erectus), and the values are dictionaries with keys for height, weight, brain volume, and when (the latter for when the specie lived). For example, humans['homo neanderthalensis']['mass'] should equal '55-70'. Let the program write out the humans dictionary in a nice tabular form similar to that in the file. Filename: humans.py.

Exercise 6: Make a nested dictionary from a file

The viscosity \( \mu \) of gases depends on the temperature. For some gases the following formula is relevant: $$ \mu (T) = \mu_0\frac{T_0-C}{T+C}\left(\frac{T}{T_0}\right)^{1.5},$$ where the values of the constants \( C \), \( T_0 \), and \( \mu_0 \) are found in the file src/files/viscosity_of_gases.dat. The temperature is measured in Kelvin.

a) Load the file into a nested dictionary mu_data such that we can look up \( C \), \( T_0 \), and \( \mu_0 \) for a gas with name name by mu_data[name][X], where X is 'C' for \( C \), 'T_0' for \( T_0 \), and 'mu_0' for \( \mu_0 \).

b) Make a function mu(T, gas, mu_data) for computing \( \mu(T) \) for a gas with name gas (according to the file) and information about constants \( C \), \( T_0 \), and \( \mu_0 \) in mu_data.

c) Plot \( \mu(T) \) for air, carbon dioxide, and hydrogen with \( T\in [223, 373] \).

Filename: viscosity_of_gases.py.

Exercise 7: Compare data structures for polynomials

Write a code snippet that uses both a list and a dictionary to represent the polynomial \( -\frac{1}{2} + 2x^{100} \). Print the list and the dictionary, and use them to evaluate the polynomial for \( x=1.05 \).

Hint. You can apply the poly1 and poly2 functions from the section Example: Polynomials as dictionaries).

Filename: poly_repr.py.

Exercise 8: Compute the derivative of a polynomial

A polynomial can be represented by a dictionary as explained in the section Example: Polynomials as dictionaries. Write a function diff for differentiating such a polynomial. The diff function takes the polynomial as a dictionary argument and returns the dictionary representation of the derivative. Here is an example of the use of the function diff:

>>> p = {0: -3, 3: 2, 5: -1}    # -3 + 2*x**3 - x**5
>>> diff(p)                     # should be 6*x**2 - 5*x**4
{2: 6, 4: -5}

Hint. Recall the formula for differentiation of polynomials: $$ \begin{equation} {d\over dx}\sum_{j=0}^n c_jx^j = \sum_{j=1}^{n} jc_jx^{j-1}\tp \tag{1} \end{equation} $$ This means that the coefficient of the \( x^{j-1} \) term in the derivative equals \( j \) times the coefficient of \( x^j \) term of the original polynomial. With p as the polynomial dictionary and dp as the dictionary representing the derivative, we then have dp[j-1] = j*p[j] for j running over all keys in p, except when j equals 0.

Filename: poly_diff.py.

Exercise 9: Specify functions on the command line

Explain what the following two code snippets do and give an example of how they can be used.

Hint. Read about the StringFunction tool in the document User input and error handling [1] and about a variable number of keyword arguments in the document Variable number of function arguments in Python [2].

a)

import sys
from scitools.StringFunction import StringFunction
parameters = {}
for prm in sys.argv[4:]:
    key, value = prm.split('=')
    parameters[key] = eval(value)
f = StringFunction(sys.argv[1], independent_variables=sys.argv[2],
                   **parameters)
var = float(sys.argv[3])
print f(var)

b)

import sys
from scitools.StringFunction import StringFunction
f = eval('StringFunction(sys.argv[1], ' + \ 
         'independent_variables=sys.argv[2], %s)' % \ 
         (', '.join(sys.argv[4:])))
var = float(sys.argv[3])
print f(var)

Filename: cml_functions.py.

Exercise 10: Interpret function specifications

To specify arbitrary functions \( f(x_1,x_2,\ldots; p_1, p_2, \ldots) \) with independent variables \( x_1, x_2, \ldots \) and a set of parameters \( p_1, p_2, \ldots \), we allow the following syntax on the command line or in a file:

<expression> is function of <list1> with parameter <list2>
where <expression> denotes the function formula, <list1> is a comma-separated list of the independent variables, and <list2> is a comma-separated list of name=value parameters. The part with parameters <list2> is omitted if there are no parameters. The names of the independent variables and the parameters can be chosen freely as long as the names can be used as Python variables. Here are four different examples of what we can specify on the command line using this syntax:

sin(x) is a function of x
sin(a*y) is a function of y with parameter a=2
sin(a*x-phi) is a function of x with parameter a=3, phi=-pi
exp(-a*x)*cos(w*t) is a function of t with parameter a=1,w=pi,x=2
Create a Python function that takes such function specifications as input and returns an appropriate StringFunction object. This object must be created from the function expression and the list of independent variables and parameters. For example, the last function specification above leads to the following StringFunction creation:

f = StringFunction('exp(-a*x)*cos(w*t)',
                   independent_variables=['t'],
                   a=1, w=pi, x=2)

Hint. Use string operations to extract the various parts of the string. For example, the expression can be split out by calling split('is a function of'). Typically, you need to extract <expression>, <list1>, and <list2>, and create a string like

StringFunction(<expression>, independent_variables=[<list1>],
               <list2>)
and sending it to eval to create the object.

Filename: text2func.py.

Exercise 11: Compare average temperatures in cities

The tarfile src/misc/city_temp.tar.gz contains a set of files with temperature data for a large number of cities around the world. The files are in text format with four columns, containing the month number, the date, the year, and the temperature, respectively. Missing temperature observations are represented by the value \( -99 \). The mapping between the names of the text files and the names of the cities are defined in an HTML file citylistWorld.htm.

a) Write a function that can read the citylistWorld.htm file and create a dictionary with mapping between city and filenames.

b) Write a function that takes this dictionary and a city name as input, opens the corresponding text file, and loads the data into an appropriate data structure (dictionary of arrays and city name is a suggestion).

c) Write a function that can take a number of data structures and the corresponding city names to create a plot of the temperatures over a certain time period.

Filename: temperature_data.py.

References

  1. H. P. Langtangen. User input and error handling, http://hplgit.github.io/primer.html/doc/pub/input.
  2. H. P. Langtangen. Variable number of function arguments in Python, http://hplgit.github.io/primer.html/doc/pub/varargs.