def smooth_lines(lns, n=<NUM_LIT:1>, inertia=<NUM_LIT:0.5>):
if pimms.is_lazy_map(lns):<EOL><INDENT>return pimms.lazy_map({k:curry(lambda k: smooth_lines(lns[k], n=n, inertia=inertia), k)<EOL>for k in six.iterkeys(lns)})<EOL><DEDENT>elif pimms.is_map(lns):<EOL><INDENT>m = {k:smooth_lines(v,n=n,inertia=inertia) for (k,v) in six.iteritems(lns)}<EOL>return pyr.pmap(m) if pimms.is_pmap(lns) else m<EOL><DEDENT>elif pimms.is_matrix(lns, '<STR_LIT>'):<EOL><INDENT>(p,q) = (inertia, <NUM_LIT:1> - inertia)<EOL>l = lns if lns.shape[<NUM_LIT:0>] in (<NUM_LIT:2>,<NUM_LIT:3>) else lns.T<EOL>if np.allclose(l[:,<NUM_LIT:0>], l[:,-<NUM_LIT:1>]):<EOL><INDENT>for ii in range(n):<EOL><INDENT>lns = p*l + q/<NUM_LIT:2>*(np.roll(l, -<NUM_LIT:1>, <NUM_LIT:1>) + np.roll(l, <NUM_LIT:1>, <NUM_LIT:1>))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>l = np.array(l)<EOL>for ii in range(n):<EOL><INDENT>l[<NUM_LIT:1>:-<NUM_LIT:1>] = p*l[<NUM_LIT:1>:-<NUM_LIT:1>] + q/<NUM_LIT:2>*(l[:-<NUM_LIT:2>] + l[<NUM_LIT:2>:])<EOL><DEDENT><DEDENT>if lns.shape != l.shape: l = l.T<EOL>l.setflags(write=lns.flags['<STR_LIT>'])<EOL>return l<EOL><DEDENT>elif not pimms.is_scalar(lns):<EOL><INDENT>u = [smooth_lines(u, n=n, inertia=inertia) for u in lns]<EOL>return (tuple(u)       if is_tuple(lns)                else<EOL>pyr.pvector(u) if isinstance(lns, pyr.PVector) else<EOL>np.asarray(u)  if pimms.is_nparray(lns)        else<EOL>type(lns)(u))<EOL><DEDENT>else: raise ValueError('<STR_LIT>' % lns)<EOL>
smooth_lines(matrix) runs one smoothing iteration on the lines implied by the {2,3}xN matrix.
smooth_lines(collection) iteratively descends lists, sets, and the values of maps, converting
  all valid matrices that it finds; note that if it encounters anything that cannot be
  interpreted as a line matrix (such as a string), an error is raised.

Smoothing is performed by adding to the coordinates of each vertex with two neighbors half of
the coordinates of each of its neighbors then dividing that sum by 2; i.e.:
  x_new[i] == x_old[i]/2 + x_old[i-1]/4 + x_old[i+1]/4.

The following options may be given:
  * n (default: 1) indicates the number of times to perform the above smoothing operation.
  * inertia (default: 0.5) specifies the fraction of the new value that is derived from the
    old value of a node as opposed to the old values of its neighbors. If intertia is m, then
    x_new[i] == m*x_old[i] + (1-m)/2*(x_old[i-1] + x_old[i+1]).
    A higher intertia will smooth the line less each iteration.