Difference between revisions of "CompSciSpring2016"

From Predictive Chemistry
Jump to: navigation, search
m (Homework)
(Group Work Pages)
Line 183: Line 183:
 
Group 3 [https://docs.google.com/document/d/1LT_J-vObN9tPa1JoQ1B_h04ENsL5Ko2xeFeRMp-99f8/edit?usp=sharing]
 
Group 3 [https://docs.google.com/document/d/1LT_J-vObN9tPa1JoQ1B_h04ENsL5Ko2xeFeRMp-99f8/edit?usp=sharing]
 
Group 4 [https://docs.google.com/document/d/1hGlNlg1w7_3qCo6LE-y9rSZx1Chwc0FBUoxK6cyzWW8/edit?usp=sharing]
 
Group 4 [https://docs.google.com/document/d/1hGlNlg1w7_3qCo6LE-y9rSZx1Chwc0FBUoxK6cyzWW8/edit?usp=sharing]
  +
  +
<source lang="python">
  +
import numpy as np
  +
import matplotlib.path as mpath
  +
import matplotlib.patches as mpatches
  +
import matplotlib.pyplot as plt
  +
  +
Path = mpath.Path
  +
  +
fig, ax = plt.subplots()
  +
  +
#arrows = np.array([[[0.0, 0.0], [0.0, 2.0]]])
  +
arrows = np.array([[0.0, 2.0], [-1,-1], [3,-0.5]])
  +
  +
codes = [Path.MOVETO, Path.LINETO, Path.LINETO,
  +
Path.LINETO, Path.LINETO, Path.LINETO]
  +
  +
def path_from_vec(x,y,dx,dy):
  +
r = (dx*dx+dy*dy)**0.5
  +
a = 0.5
  +
c = 0.2*dx/r
  +
s = 0.2*dy/r
  +
x1 = x + (r-0.2)*dx/r
  +
y1 = y + (r-0.2)*dy/r
  +
pathdata = [(x,y),
  +
(x1,y1),
  +
(x1+s-a*c, y1-c-a*s),
  +
(x1+c, y1+s),
  +
(x1-s-a*c, y1+c-a*s),
  +
(x1,y1)]
  +
return pathdata
  +
  +
def to_path(v, color='green'):
  +
verts = path_from_vec(0., 0., *v)
  +
path = mpath.Path(verts, codes)
  +
patch = mpatches.PathPatch(path, facecolor=color, edgecolor='k', alpha=0.5)
  +
ax.add_patch(patch)
  +
return patch
  +
  +
class PathInteractor(object):
  +
"""
  +
An path editor.
  +
  +
Key-bindings
  +
  +
't' toggle vertex markers on and off. When vertex markers are on,
  +
you can move them, delete them
  +
  +
  +
"""
  +
  +
showverts = True
  +
epsilon = 5 # max pixel distance to count as a vertex hit
  +
  +
def __init__(self, vecs):
  +
self.paths = []
  +
for v in vecs:
  +
path = to_path(v)
  +
self.paths.append(path)
  +
path.set_animated(True)
  +
  +
self.ax = self.paths[0].axes
  +
canvas = self.ax.figure.canvas
  +
self.vecs = vecs
  +
  +
print vecs
  +
self.line, = ax.plot(vecs[:,0], vecs[:,1], 'o',
  +
markerfacecolor='r', animated=True)
  +
  +
self._ind = None # the active vert
  +
  +
canvas.mpl_connect('draw_event', self.draw_callback)
  +
canvas.mpl_connect('button_press_event', self.button_press_callback)
  +
canvas.mpl_connect('key_press_event', self.key_press_callback)
  +
canvas.mpl_connect('button_release_event', self.button_release_callback)
  +
canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)
  +
self.canvas = canvas
  +
  +
def draw_callback(self, event):
  +
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
  +
for path in self.paths:
  +
self.ax.draw_artist(path)
  +
self.ax.draw_artist(self.line)
  +
self.canvas.blit(self.ax.bbox)
  +
  +
#def pathpatch_changed(self, pathpatch):
  +
# 'this method is called whenever the pathpatchgon object is called'
  +
# # only copy the artist props to the line (except visibility)
  +
# vis = self.line.get_visible()
  +
# #plt.Artist.update_from(self.line, pathpatch)
  +
# #self.pathpatch.get_path().vertices[:] = self.vecs ?
  +
# self.vecs[self._ind] = x, y
  +
# self.line.set_data(zip(*self.vecs))
  +
#
  +
# plt.Artist.update_from(self.line, self.vecs)
  +
# self.line.set_visible(vis) # don't use the pathpatch visibility state
  +
  +
def get_ind_under_point(self, event):
  +
'get the index of the vertex under point if within epsilon tolerance'
  +
  +
# display coords
  +
xy = self.vecs
  +
xyt = self.paths[0].get_transform().transform(xy)
  +
xt, yt = xyt[:, 0], xyt[:, 1]
  +
d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
  +
ind = d.argmin()
  +
  +
if d[ind] >= self.epsilon:
  +
ind = None
  +
  +
return ind
  +
  +
def button_press_callback(self, event):
  +
'whenever a mouse button is pressed'
  +
if not self.showverts:
  +
return
  +
if event.inaxes is None:
  +
return
  +
if event.button != 1:
  +
return
  +
self._ind = self.get_ind_under_point(event)
  +
  +
def button_release_callback(self, event):
  +
'whenever a mouse button is released'
  +
if not self.showverts:
  +
return
  +
if event.button != 1:
  +
return
  +
self._ind = None
  +
  +
def key_press_callback(self, event):
  +
'whenever a key is pressed'
  +
if not event.inaxes:
  +
return
  +
if event.key == 't':
  +
self.showverts = not self.showverts
  +
self.line.set_visible(self.showverts)
  +
if not self.showverts:
  +
self._ind = None
  +
  +
self.canvas.draw()
  +
  +
def motion_notify_callback(self, event):
  +
'on mouse movement'
  +
if not self.showverts:
  +
return
  +
if self._ind is None:
  +
return
  +
if event.inaxes is None:
  +
return
  +
if event.button != 1:
  +
return
  +
x, y = event.xdata, event.ydata
  +
  +
self.vecs[self._ind] = x, y
  +
self.line.set_data(zip(*self.vecs))
  +
self.paths[self._ind].get_path().vertices[:] = \
  +
path_from_vec(0., 0., *self.vecs[self._ind])
  +
# update vec 0 based on callback
  +
if self._ind != 0:
  +
self.vecs[0] = update_vec(self.vecs)
  +
self.paths[0].get_path().vertices[:] = \
  +
path_from_vec(0., 0., *self.vecs[0])
  +
  +
self.canvas.restore_region(self.background)
  +
for path in self.paths:
  +
self.ax.draw_artist(path)
  +
self.ax.draw_artist(self.line)
  +
self.canvas.blit(self.ax.bbox)
  +
  +
def update_vec(x):
  +
return x[1]+1.0
  +
  +
interactor = PathInteractor(arrows)
  +
ax.set_title('drag vertices to update path')
  +
ax.set_xlim(-3, 4)
  +
ax.set_ylim(-3, 4)
  +
  +
plt.show()
  +
</source>

Revision as of 12:22, 30 March 2016

Introduction to Scientific Computing

Course Info

  • Course Numbers CHM 4932-004/6938-010, CRN: 22347/22348
  • Credit Hours: 3
  • Meeting Dates: January 22 - April 27, 2016
    • No Class Jan. 18 or Mar. 14-19
  • Meeting Times: Mon. and Wed., 12:30-13:45 in SCA 222
    • Lab Session & Office Hours: Fri. 12:30-13:45 in SCA 222 (or SCA 433)

Overview

Mathematical models in the natural sciences take many shapes and forms. The moment they become more complicated than tracking a few variables over time, we have to put away our Excel spreadsheets and make use of a solid foundation in computational science. The course establishes this foundation by introducing data structures and algorithms used in everyday scientific computing using examples in the python scripting language. By the end of the Semester, students will be able to navigate the Linux command-line to go from a mathematical model to a numerical solution. Best practices for working with computer code and visualizing data will also be covered.

Topics

  1. Languages
    • bash (shell)
    • python (scripting)
    • stack & register-based machine languages: overview of C and Fortran syntax & compiling with gcc, ‘thread safety’
    • Shared libraries & language inter-operability (FFI)
  2. Algorithms
    • Horner’s algorithm for polynomials
    • Newton’s root finding algo.
    • Overview of general optimization algo-s (example: linear & nonlin. least-squares)
    • Numerical integration (scripted, plus gnu ODE)
    • Communication (how HTTP get/put works)
  3. Data Structures
    • Linked Lists
    • Trees (file system hierarchies)
    • Graphs
    • Arrays (dense & sparse) example: vectors & rotations / transpositions, densities and difference operators
  4. Presentation & visualization
    • Flat CSV files (and excel)
    • Working with binary data
    • Python matplotlib (2D images)
    • Binning histograms & weighted averages
  5. Best Practices
    • High-level code design (modularity, interface specifications, unit testing, etc.)
    • Code audit: open-source libraries, ex. Gnu Scientific Library, qsort in libc, Boost
    • Source code versioning (example: git or mercurial)
    • gdb & execution profiling
    • documentation
    • Makefiles

Grading

Grading Scale (out of 400 points possible)

Grade Undergraduate Graduate
A 230 300
B 180 230
C 150 180
D 120 150
  • Points Possible:
    • 10 homework assignments (20 points per homework)
    • 2 projects / competitions (100 points per project)
  • Homework Rules
    • For work done in groups, credit is divided equally among participants - so the max homework grade for a group of 2 is 10 points each.
    • For each homework, 1 re-do at full credit can be sent at any time after the due date, but must present a unique solution to previous work from yourself or others.
    • All work must cite co-group members (if any) and the source of any code snippets used online.

Grading Rationale

Homework points will only be awarded for correct, working code and correct algorithmic analysis, while the homework problems will become progressively tougher. Undergraduates should be able to pass the course with an A if they have correctly answered most of the homework, and made a strong attempt at one of the projects. Graduate students should both perform well on the homework and successfully complete one or two projects. Essentially, this means you should do your own homework when possible and may do a project in a small group. The re-grading and group options for homework allow making up for missed assignments, and encourage returning to core concepts at a later point in the class. Students who have completed significant portions of the homework have thus demonstrated programming proficiency, and are qualified for at least B/C grades.

Projects

Midterm

A description for the midterm project is now available here. The MD section will be updated as we discuss it in class. The due date for the midterm will be Friday, March 11.

Final

TBA

Textbooks and Resources

Other (possibly useful) materials:

  • The Jargon File
  • Chapters 7&8 of Modelling and Simulation, Birta and Arbez, Springer 2007 (eBook avail. from USF Library).
  • Chapters 4-6 of Models and Algorithms for Intelligent Data Analysis, Runkler, Springer 2012 (eBook avail. from USF Library).
  • Guide to Scientific Computing in C++, Francis and Whiteley, Springer, 2012. (eBook avail. from USF Library)
  • Extra info. On the basics:
    • Chapters 3 and 7 of Mathematics in Computing, Regan, Springer 2013. (eBook avail. from USF Library)
    • Instant feedback graphical programming with Khan Academy
  • Local PyBulls Meetings

Code:

Interactive Interpreters:

  • CodeWars Recommended for building experience with practice problems.
  • Exercism A command-line client with a similar learn-through-challenge philosophy.
  • repl.it A read-eval-print loop for several computer languages.
  • CppReference Documentation with an online evaluator for C++ code.

Notes

  • Notes for Week 1
    • Over the first two weeks or so, we'll be practicing the basics - so read through Chapters 1-3 of Hetland's Beginning Python during this time.
    • Important Definitions
  • Notes for Week 2
    • Oware code
    • Solutions for some problems in Week 2's notes:

<source lang="python">

  1. simple data types

"a string" #  : str x = [1, 2, 3] # : [int]

  1. compound data type

(1, "name", (x, x)) # : (int, str, ([int], [int]))

  1. add_one : int -> int
  2. str.__add__ : str -> str -> str
  3. str.split : str -> [str]
  4. str.__mod__ : str -> (Objects) -> str

</source>

  • Notes for Week 3-4
    • Reading assignment - read through Chapter 5 and 6 (and practice dictionaries from Ch. 4)
    • Abstracting patterns in for loops.
  • Notes for Week 5-6
    • Reading assignment - Read Chapter 10-11 (and refer to Ch. 4)
  • By this point, we've covered all the basics:
    • base types: str, int, float, [a]
    • variables and substitution: j vs "4" vs 4
    • indexing and slicing into lists / strings: x[1:4] or x[i:j]
    • control flow: if and for syntax
    • functions implementing patterns: def next(r, x): return r*x*(1-x)
  • You should be able to use these for:
    • finding and abstracting the pattern
    • naming the type of a function
    • determining which variable names are in scope
  • All that's left is learning common uses, patterns and even more syntax!
  • Notes for Week 7-8
  • Notes for Week 9-10
  • Notes for Week 11

Homework

Group Work Pages

Group 1 [1]: Group 2 [2] Group 3 [3] Group 4 [4]

<source lang="python"> import numpy as np import matplotlib.path as mpath import matplotlib.patches as mpatches import matplotlib.pyplot as plt

Path = mpath.Path

fig, ax = plt.subplots()

  1. arrows = np.array([[[0.0, 0.0], [0.0, 2.0]]])

arrows = np.array([[0.0, 2.0], [-1,-1], [3,-0.5]])

codes = [Path.MOVETO, Path.LINETO, Path.LINETO,

                     Path.LINETO, Path.LINETO, Path.LINETO]

def path_from_vec(x,y,dx,dy):

   r = (dx*dx+dy*dy)**0.5
   a = 0.5
   c = 0.2*dx/r
   s = 0.2*dy/r
   x1 = x + (r-0.2)*dx/r
   y1 = y + (r-0.2)*dy/r
   pathdata = [(x,y),
               (x1,y1),
               (x1+s-a*c, y1-c-a*s),
               (x1+c, y1+s),
               (x1-s-a*c, y1+c-a*s),
               (x1,y1)]
   return pathdata

def to_path(v, color='green'):

   verts = path_from_vec(0., 0., *v)
   path = mpath.Path(verts, codes)
   patch = mpatches.PathPatch(path, facecolor=color, edgecolor='k', alpha=0.5)
   ax.add_patch(patch)
   return patch

class PathInteractor(object):

   """
   An path editor.
   Key-bindings
     't' toggle vertex markers on and off.  When vertex markers are on,
         you can move them, delete them


   """
   showverts = True
   epsilon = 5  # max pixel distance to count as a vertex hit
   def __init__(self, vecs):
       self.paths = []
       for v in vecs:
           path = to_path(v)
           self.paths.append(path)
           path.set_animated(True)
       self.ax = self.paths[0].axes
       canvas = self.ax.figure.canvas
       self.vecs = vecs
       print vecs
       self.line, = ax.plot(vecs[:,0], vecs[:,1], 'o',
                            markerfacecolor='r', animated=True)
       self._ind = None  # the active vert
       canvas.mpl_connect('draw_event', self.draw_callback)
       canvas.mpl_connect('button_press_event', self.button_press_callback)
       canvas.mpl_connect('key_press_event', self.key_press_callback)
       canvas.mpl_connect('button_release_event', self.button_release_callback)
       canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)
       self.canvas = canvas
   def draw_callback(self, event):
       self.background = self.canvas.copy_from_bbox(self.ax.bbox)
       for path in self.paths:
           self.ax.draw_artist(path)
       self.ax.draw_artist(self.line)
       self.canvas.blit(self.ax.bbox)
   #def pathpatch_changed(self, pathpatch):
   #    'this method is called whenever the pathpatchgon object is called'
   #    # only copy the artist props to the line (except visibility)
   #    vis = self.line.get_visible()
   #    #plt.Artist.update_from(self.line, pathpatch)
   #    #self.pathpatch.get_path().vertices[:] = self.vecs ?
   #    self.vecs[self._ind] = x, y
   #    self.line.set_data(zip(*self.vecs))
  1. plt.Artist.update_from(self.line, self.vecs)
  2. self.line.set_visible(vis) # don't use the pathpatch visibility state
   def get_ind_under_point(self, event):
       'get the index of the vertex under point if within epsilon tolerance'
       # display coords
       xy = self.vecs
       xyt = self.paths[0].get_transform().transform(xy)
       xt, yt = xyt[:, 0], xyt[:, 1]
       d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
       ind = d.argmin()
       if d[ind] >= self.epsilon:
           ind = None
       return ind
   def button_press_callback(self, event):
       'whenever a mouse button is pressed'
       if not self.showverts:
           return
       if event.inaxes is None:
           return
       if event.button != 1:
           return
       self._ind = self.get_ind_under_point(event)
   def button_release_callback(self, event):
       'whenever a mouse button is released'
       if not self.showverts:
           return
       if event.button != 1:
           return
       self._ind = None
   def key_press_callback(self, event):
       'whenever a key is pressed'
       if not event.inaxes:
           return
       if event.key == 't':
           self.showverts = not self.showverts
           self.line.set_visible(self.showverts)
           if not self.showverts:
               self._ind = None
       self.canvas.draw()
   def motion_notify_callback(self, event):
       'on mouse movement'
       if not self.showverts:
           return
       if self._ind is None:
           return
       if event.inaxes is None:
           return
       if event.button != 1:
           return
       x, y = event.xdata, event.ydata
       self.vecs[self._ind] = x, y
       self.line.set_data(zip(*self.vecs))
       self.paths[self._ind].get_path().vertices[:] = \
                   path_from_vec(0., 0., *self.vecs[self._ind])
       # update vec 0 based on callback
       if self._ind != 0:
           self.vecs[0] = update_vec(self.vecs)
           self.paths[0].get_path().vertices[:] = \
                   path_from_vec(0., 0., *self.vecs[0])
       self.canvas.restore_region(self.background)
       for path in self.paths:
           self.ax.draw_artist(path)
       self.ax.draw_artist(self.line)
       self.canvas.blit(self.ax.bbox)

def update_vec(x):

   return x[1]+1.0

interactor = PathInteractor(arrows) ax.set_title('drag vertices to update path') ax.set_xlim(-3, 4) ax.set_ylim(-3, 4)

plt.show() </source>