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

 

 

 

This chapter is taken from the book A Primer on Scientific Programming with Python by H. P. Langtangen, 5th edition, Springer, 2016.

Exercises

Exercise 1: Make a dictionary from a table

The file src/dictstring/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.

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.

Exercise 3: Use string operations to improve a program

Consider the program density.py from the section Example: Storing 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.

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.

Exercise 5: Make a dictionary

Based on the stars data in the exercise named "Write a sort function for a list of 4-tuples" in the document Functions and branching [1], make a dictionary where the keys contain the names of the stars and the values correspond to the luminosity. Filename: stars_data_dict1.

Exercise 6: Make a nested dictionary

Store the data about stars from the exercise named "Write a sort function for a list of 4-tuples" in the document Functions and branching [1] in a nested dictionary such that we can look up the distance, the apparent brightness, and the luminosity of a star with name N by

stars[N]['distance']
stars[N]['apparent brightness']
stars[N]['luminosity']

Hint.

Initialize the data by just copying the stars.txt text into the program.

Filename: stars_data_dict2.

Exercise 7: Make a nested dictionary from a file

The file src/dictstring/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.

Exercise 8: 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/dictstring/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.

Exercise 9: Compute the area of a triangle

The purpose of this exercise is to write an area function as in the exercise named "Compute the area of an arbitrary triangle" in the document Functions and branching [1], but now we assume that the vertices of the triangle is stored in a dictionary and not a list. The keys in the dictionary correspond to the vertex number (1, 2, or 3) while the values are 2-tuples with the \( x \) and \( y \) coordinates of the vertex. For example, in a triangle with vertices \( (0,0) \), \( (1,0) \), and \( (0,2) \) the vertices argument becomes

{1: (0,0), 2: (1,0), 3: (0,2)}

Filename: area_triangle_dict.

Exercise 10: 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 eval_poly_dict and eval_poly_list functions from the section Example: Polynomials as dictionaries).

Filename: poly_repr.

Exercise 11: 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.

Exercise 12: 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 [2] and about a variable number of keyword arguments in the document Variable number of function arguments in Python [3].

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.

Exercise 13: 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)

Write a test function for verifying the implementation (fill sys.argv with appropriate content prior to each individual test).

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.

Exercise 14: 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.

Exercise 15: Generate an HTML report with figures

The goal of this exercise is to let a program write a report in HTML format containing the solution to the exercise named "Animate a wave packet" in the document Arrays and plotting [4]. First, include the program from that exercise, with additional explaining text if necessary. Program code can be placed inside <pre> and </pre> tags. Second, insert three plots of the \( f(x,t) \) function for three different \( t \) values (find suitable \( t \) values that illustrate the displacement of the wave packet). Third, add an animated GIF file with the movie of \( f(x,t) \). Insert headlines (<h1> tags) wherever appropriate. Filename: wavepacket_report.

References

  1. H. P. Langtangen. Functions and branching, \emphhttp://hplgit.github.io/primer.html/doc/pub/funcif, http://hplgit.github.io/primer.html/doc/pub/funcif.
  2. H. P. Langtangen. User input and error handling, \emphhttp://hplgit.github.io/primer.html/doc/pub/input, http://hplgit.github.io/primer.html/doc/pub/input.
  3. H. P. Langtangen. Variable number of function arguments in Python, \emphhttp://hplgit.github.io/primer.html/doc/pub/varargs, http://hplgit.github.io/primer.html/doc/pub/varargs.
  4. H. P. Langtangen. Array computing and curve plotting, \emphhttp://hplgit.github.io/primer.html/doc/pub/plot, http://hplgit.github.io/primer.html/doc/pub/plot.