Python代写:CS6001 Module

使用numpy, matplotlib, sympy, pickle这些python库,按照要求代写程序。

Background

Core commands, functions, methods and keywords that may be of use during this coursework:

for, xrange, append, return, float, pow

Modules, module functions and module methods that may be of use during ths coursework:

numpy: zeros, log, linspace
matplotlib.pyplot: imshow, show, plot, cla
sympy: symbols, diff, solve, subs, re, im
pickle: open, close, dump, load

(Note that if you’re using an IPython notebook, numpy and all its functions may be pre-imported and need no prefix, and matplotlib.pyplot may already be imported as plt. This will depend on your version.)

Your submission should be a brief report. You should submit this report electronically, either as a Word document or (preferably) as an IPython notebook.

IMPORTANT

Write your report so that it would make sense to someone reading it who knows maths, and Python, but who hasn’t got the questions in front of them. You needn’t write a huge essay, but you should briefly explain, for each question section, what you’re doing and what your output means. A report consisting just of Python code and output will not get full marks.

Problem 1

The complex recurrence relation zn+1 = zn^2 + c, where z0 = 0 and c is a complex constant, exhibits different behaviours depending on the value of c. The iteration must then diverge to infinity; but for some values of c this never happens.

(a) Write and test a Python function called complex_map_iterates that takes as its arguments a complex number c and a number of iterations n, and a returns a Python list (or a NumPy array) consisting of the iterates z0, z1, z2, …, zn.

(b) Using your function, find values of c for which the iterated map appears:

  • i. to tend to a limit;
  • ii. to tend to infinity, taking between ten and twenty iterations to attain an absolute value greater than 2;
  • iii. to remain bounded, for at least twenty iterations without seeming to show convergent or cyclical behaviour.

(c) Write and test a function called escape_time that takes as its arguments a complex number c and a maximum number of iterations nmax. It should then iterate the above recurrence relation until either an iterate attains an absolute value greater than 2 or the number of iterations hits nmax. Finally, it should return a positive integer representing the number of iterations that have been executed.

(d) Test the following script (note: this uses your escape_time function, and won’t work unless your function does!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import numpy as np
import matplotlib.pyplot as plt
# set parameters
xmin = -1.5
xmax = 0.5
ymin = -1.0
ymax = 1.0
npoints = 21

# calculate step sizes
xstep = (xmax - xmin)/float(npoints - 1)
ystep = (ymax - ymin)/float(npoints - 1)

# initialize array
et_array = np.zeros([npoints, npoints])

# nested loop
for x_index in xrange(npoints):
# real part of c
x = xmin + x_index * xstep

for y_index in xrange(npoints):
# imaginary part of c
y = ymin + y_index * ystep
# calculate c
c = x+y*1j

# calculate log of escape time and drop into array
log_et = np.log(escape_time(c, 200))
et_array[npoints-y_index-1, x_index] = log_et

# plot array as a bitmap
plt.imshow(et_array, extent = [xmin, xmax, ymin, ymax])
plt.show()

This should plot a crude picture of a fascinating shape called the Mandelbrot set.

(e) Write and test a function called mandelbrot_array which takes as its arguments an xmin, an xmax, a ymin, a ymax and an npoints, and returns a square NumPy array consisting of the logarithms of the escape times for c = x + i y, calculated as above.

(f) Write a function called mandelbrot_plot which takes as its arguments an xmin, an xmax, a ymin, a ymax and an npoints, and returns no values but generates an imshow plot of mandelbrot_array(xmin, xmax, ymin, ymax, npoints).
Test it by typing

mandelbrot_plot(-1.5, 0.5, -1.0, 1.0, 21)

Generate a more high-resolution image by typing

mandelbrot_plot(-1.5, 0.5, -1.0, 1.0, 201)

(g) The above plots show a square of side 2 in the complex plane. By changing the values of xmin, xmax, ymin and ymax, examine instead a square of side 0.2 (make it an interesting one!) Show also an interesting square of side 0.02. (You can push this further if you like, but you don’t need to show the results of doing so; including lots of high-resolution images will make your file quite big.)

Problem 2

(a) Write and test a function called plot_with_SPs which takes as its arguments:

  • a symbolic expression, expr;
  • a symbolic variable name, var;
  • a minimum x-value for plotting, xmin;
  • a maximum x-value for plotting, xmax.

It should then do the following:

  • Symbolically differentiate expr with respect to var.
  • Use SymPy’s solve function to find the values of var for which this derivative is zero, as floats.
  • Find the corresponding values of expr, again as floats (so you now have the coordinates of the stationary points).
  • Set up a Python list, or a NumPy array, consisting of around 201 equallyspaced values between xmin and xmax inclusive.
  • Set up a Python list, or a NumPy array, consisting of the corresponding values of expr, as floats (so you now have the coordinates of around 201 points along the curve).
  • Plot the curve in blue, and superimpose, in red, the stationary points.

Test your function on the following example:

1
2
3
from sympy import symbols
x = symbols('x')
plot_with_SPs(x**3 - 3*x, x, -3, 3)

(b) Unless you’ve already been very clever, your function won’t handle examples where some of the roots of the derivative are non-real; for example, this won’t work:

plot_with_SPs(12*x**5+45*x**4+40*x**3-60*x**2-240*x, x, -3.0, 2.0)

Fix this.

Problem 3

(For this question, you need only show your input code, and any comments; no output is required).

(a) Write and test a script that does the following:

  • Assign to the variables initial_xmin and initial_xmax the values 1.5 and 0.5 respectively.
  • Assign to the variables initial_ymin and initial_ymax the values 1.0 and 1.0 respectively.
  • Assign to the variables centre_x and centre_y the values 0.133 and 0.595 respectively.
  • Loop over the iteration variable frame_index, from 0 to 99:
    • Set xmin = centre_x + (initial_xmin - centre_x) 0.9 ** frame_index, xmax = centre_x + (initial_xmax - centre_x) 0.9 ** frame_index and similarly for ymin and ymax.
    • Calculate the corresponding mandelbrot_array, using npoints = 21.
    • Pickle this array. Use a filename that incorporates the current value of frame_index; for example, on the first turn of the loop.

(b) Write and test a script that loops over the iteration variable frame_index, from 0 to 99, doing the following:

  • Load the pickled array corresponding to this value of frame_index, assigning it to a suitable variable name.
  • Use imshow to generate a plot of the array you’ve just loaded.
  • Use pyplot’s show function to create an image of this plot on screen.
  • Use pyplot’s pause function to pause for 0.01 seconds.
  • Unless this is the last frame, use pyplot’s cla function to clear the axes.

Write a short description and explanation of what you see.

If this is all working well, you might want to try increasing the value of npoints, though this will create quite large files, and will mean that your first script may take quite a long time to execute.

Problem 4

The following code sets up a Python class called RSACipher with two attributes, n and e:

1
2
3
4
5
6
class RSACipher(object):
'A public-key RSA Cipher'

def __init__(self, n, e):
self.n = n
self.e = e

(a) Add a method to this class called encrypt, which takes as its arguments self and an integer called plaintext, and returns the integer that represents plaintext to the power e, reduced modulo n.

(b) Test your class. If everything’s working properly, when you type my_cipher = RSACipher(7735534351, 79) my_cipher.encrypt(12345) you should get the value 3305244447L.
Test it on at least one other example.

(c) Write a class called PrivateRSACipher which inherits the n and e attributes, and the encrypt method, from RSACipher, but which differs in the following ways:

  • The __init__ function should take as its arguments not n and e but primes and e, where primes is a tuple, list or array containing two primes. It should assign values to self.primes and self.e.
  • primes should be a property (you can achieve this using the appropriate decorator).
  • The setter for the primes property should take as its arguments self and primes, and do the following:
    • Assign to the self.__primes attribute the value (min(primes), max(primes)) so that the primes are always stored as a tuple, smaller one first.
    • Assign to the self.n attribute the value primes[0] * primes[1]

Test your class using the primes 93629 and 82619, whose product is 7735534351 (which you’ve already used above).

(d) Add to your class a method called decrypt, which uses Euclid’s algorithm to calculate, from the values of self.e and self.primes, the value of the decryption exponent d, and hence decrypts any given ciphertext. Test your method.

(e) Adapt your decrypt method so that it prints a warning if e is not coprime to (primes[0] - 1) * (primes[1] - 1)