def test_random_bs(): nTests = 100 aFile = 'Archive/A.txt' maxL = 1e-3 nCols = 100000 for i in range(nTests): print('Test ' + str(i)) bFile = 'fakes/b' + str(i) + '.txt' xFile = 'fakes/x' + str(i) + '.txt' (A,b) = l.read_data(aFile, bFile) (x, L, reason, nIters, aLists, b, aSparse) = l.lsqr(aFile, bFile, nCols, verbose = False) myCost = l.cost(l.difference_vector(A, x, b)) if myCost > maxL: print('Error in file ' + str(i))
def test_lsqr(): aFile = 'Archive/A.txt' bFile = 'Archive/b.txt' nCols = 100000 aTol = 1e-6 bTol = 1e-7 verbose = False maxIter = None (x, L, reason, nIters, aLists, b, aSparse) = l.lsqr(aFile, bFile, nCols, aTol, bTol, verbose, maxIter) success = len(x) == nCols if not success: print('ERROR!!! in LSQR') print(len(x)) print(nCols) print(reason)
def smooth(boundary_list, cocycle_list): dimension = max((max(d[1], d[2]) for d in boundary_list)) dimension += 1 # NB: D is a coboundary matrix; 1 and 2 below are transposed D = spmatrix([d[0] for d in boundary_list], [d[2] for d in boundary_list], [d[1] for d in boundary_list], (dimension, dimension)) z = spmatrix([zz[0] for zz in cocycle_list], [zz[1] for zz in cocycle_list], [0 for zz in cocycle_list], (dimension, 1)) v1 = D * z # print "D^2 is zero:", not bool(D*D) # print "D*z is zero:", not bool(v1) z = matrix(z) def Dfun(x, y, trans='N'): if trans == 'N': copy(D * x, y) elif trans == 'T': copy(D.T * x, y) else: assert False, "Unexpected trans parameter" tol = 1e-10 show = False maxit = None solution = lsqr(Dfun, matrix(z), show=show, atol=tol, btol=tol, itnlim=maxit) v = z - D * solution[0] # print sum(v**2) # assert sum((D*v)**2) < tol and sum((D.T*v)**2) < tol, "Expected a harmonic cocycle" if not (sum((D * v)**2) < tol and sum((D.T * v)**2) < tol): print "Expected a harmonic cocycle:", sum((D * v)**2), sum( (D.T * v)**2) return solution[0], v
def smooth(boundary_list, cocycle_list): dimension = max((max(d[1], d[2]) for d in boundary_list)) dimension += 1 # NB: D is a coboundary matrix; 1 and 2 below are transposed D = spmatrix([d[0] for d in boundary_list], [d[2] for d in boundary_list], [d[1] for d in boundary_list], (dimension, dimension)) z = spmatrix([zz[0] for zz in cocycle_list], [zz[1] for zz in cocycle_list], [0 for zz in cocycle_list], (dimension, 1)) v1 = D * z # print "D^2 is zero:", not bool(D*D) # print "D*z is zero:", not bool(v1) z = matrix(z) def Dfun(x,y,trans = 'N'): if trans == 'N': copy(D * x, y) elif trans == 'T': copy(D.T * x, y) else: assert False, "Unexpected trans parameter" tol = 1e-10 show = False maxit = None solution = lsqr(Dfun, matrix(z), show = show, atol = tol, btol = tol, itnlim = maxit) v = z - D*solution[0] # print sum(v**2) # assert sum((D*v)**2) < tol and sum((D.T*v)**2) < tol, "Expected a harmonic cocycle" if not (sum((D*v)**2) < tol and sum((D.T*v)**2) < tol): print "Expected a harmonic cocycle:", sum((D*v)**2), sum((D.T*v)**2) return solution[0], v
def solve(images, tf_matrices, scale, x0=None, tol=1e-10, iter_lim=None, damp=1e-1, method='CG', operator='bilinear', norm=1, standard_form=False): """Super-resolve a set of low-resolution images by solving a large, sparse set of linear equations. This method approximates the camera with a downsampling operator, using bilinear or polygon interpolation. The LSQR method is used to solve the equation :math:`A\mathbf{x} = b` where :math:`A` is the downsampling operator, :math:`\mathbf{x}` is the high-resolution estimate (flattened in raster scan/ lexicographic order), and :math:`\mathbf{b}` is a stacked vector of all the low-resolution images. Parameters ---------- images : list of ndarrays Low-resolution input frames. tf_matrices : list of (3, 3) ndarrays Transformation matrices that relate all low-resolution frames to a reference low-resolution frame (usually ``images[0]``). scale : float The resolution of the output image is `scale` times the resolution of the input images. x0 : ndarray, optional Initial guess of HR image. damp : float, optional If an initial guess is provided, `damp` specifies how much that estimate is weighed in the entire process. A larger value of `damp` results in a solution closer to `x0`, whereas a smaller version of `damp` yields a solution closer to the solution obtained without any initial estimate. method : {'CG', 'LSQR', 'descent', 'L-BFGS-B'} Whether to use conjugate gradients, least-squares, gradient descent or L-BFGS-B to determine the solution. operator : {'bilinear', 'polygon'} The camera model is approximated as an interpolation process. The bilinear interpolation operator only works well for zoom ratios < 2. norm : {1, 2} Whether to use the L1 or L2 norm to measure errors between images. standard_form : bool Whether to convert the matrix operator to standard form before processing. Returns ------- HR : ndarray High-resolution estimate. """ assert len(images) == len(tf_matrices) HH = [H.copy() for H in tf_matrices] HH_scaled = [] scale = float(scale) for H in HH: HS = np.array([[scale, 0, 0], [0, scale, 0], [0, 0, 1]]) HH_scaled.append(np.linalg.inv(np.dot(HS, H))) HH = HH_scaled oshape = np.floor(np.array(images[0].shape) * scale) LR_shape = images[0].shape print "Constructing camera operator (%s)..." % operator if operator == 'bilinear': op = bilinear(oshape[0], oshape[1], HH, *LR_shape, boundary=0) elif operator == 'polygon': sub_ops = [] for H in HH: sub_ops.append( poly_interp_op(oshape[0], oshape[1], H, *LR_shape, search_win=round(scale) * 2 + 1)) op = sparse.vstack(sub_ops, format='csr') else: raise ValueError('Invalid operator requested (%s).' % operator) ## Visualise mapping of frames ## ## import matplotlib.pyplot as plt ## P = np.prod(LR_shape) ## img = (op * x0.flat).reshape(LR_shape) ## plt.subplot(1, 4, 1) ## plt.imshow(x0, cmap=plt.cm.gray) ## plt.title('x0') ## plt.subplot(1, 4, 2) ## plt.imshow(images[0], cmap=plt.cm.gray) ## plt.title('LR frame') ## plt.subplot(1, 4, 3) ## plt.imshow(img, cmap=plt.cm.gray) ## plt.title('LR image Ax0') ## plt.subplot(1, 4, 4) ## plt.imshow(images[0] - img, cmap=plt.cm.gray) ## plt.title('diff images[0] - Ax') ## plt.show() if standard_form: print "Bringing matrix to standard form..." P = ordering.standard_form(op) op = P * op k = len(images) M = np.prod(LR_shape) b = np.empty(k * M) for i in range(k): b[i * M:(i + 1) * M] = images[i].flat if standard_form: b = P * b atol = btol = conlim = tol show = True # Error and gradient functions, used in conjugate gradient optimisation def sr_func(x, norm=norm): return (np.linalg.norm(op * x - b, norm) ** 2 + \ damp * np.linalg.norm(x - x0.flat, norm) ** 2) def sr_gradient(x, norm=norm): # Careful! Mixture of sparse and dense operators. #Axb = op * x - b #nrm_sq = np.dot(Axb, Axb) # Dense #Axbop = (op.T * Axb).T # Sparse #return nrm_sq * Axbop Axb = op * x - b L = len(x) if norm == 1: xmx0 = x - x0.flat term1 = np.linalg.norm(Axb, 1) * np.sign(Axb.T) * op term2 = damp * np.linalg.norm(xmx0, 1) * np.sign(xmx0.flat) elif norm == 2: term1 = (Axb.T * op) term2 = damp * (x - x0.flat) else: raise ValueError('Invalid norm for error measure (%s).' % norm) return 2 * (term1 + term2) print "Super resolving..." ## Conjugate Gradient Optimisation if method == 'CG': x, fopt, f_calls, gcalls, warnflag = \ opt.fmin_cg(sr_func, x0, fprime=sr_gradient, gtol=0, disp=True, maxiter=iter_lim, full_output=True) elif method == 'LSQR': ## LSQR Optimisation ## x0 = x0.flat b = b - op * x0 x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var = \ lsqr(op, b, atol=atol, btol=btol, conlim=conlim, damp=damp, show=show, iter_lim=iter_lim) x = x0 + x elif method == 'descent': ## Steepest Descent Optimisation ## x = np.array(x0, copy=True).reshape(np.prod(x0.shape)) for i in range(50): print(op.T * ((op * x) - b)).shape print "Gradient descent step %d" % i x += damp * -1 * (op.T * ((op * x) - b)) # Could add prior: + lam * (x - x0.flat)) ## L-BFGS-B elif method == 'L-BFGS-B': x, f, d = opt.fmin_l_bfgs_b(sr_func, x0.flat, fprime=sr_gradient) print "L-BFGS-B converged after %d function calls." % d['funcalls'] print "Final function value:", f print "Reason for termination:", d['task'] elif method == 'direct': x = sparse.linalg.spsolve(op, b) else: raise ValueError('Invalid method (%s) specified.' % method) return x.reshape(oshape.astype(int))
def solve(images, tf_matrices, scale, x0=None, tol=1e-10, iter_lim=None, damp=1e-1, method='CG', operator='bilinear', norm=1, standard_form=False): """Super-resolve a set of low-resolution images by solving a large, sparse set of linear equations. This method approximates the camera with a downsampling operator, using bilinear or polygon interpolation. The LSQR method is used to solve the equation :math:`A\mathbf{x} = b` where :math:`A` is the downsampling operator, :math:`\mathbf{x}` is the high-resolution estimate (flattened in raster scan/ lexicographic order), and :math:`\mathbf{b}` is a stacked vector of all the low-resolution images. Parameters ---------- images : list of ndarrays Low-resolution input frames. tf_matrices : list of (3, 3) ndarrays Transformation matrices that relate all low-resolution frames to a reference low-resolution frame (usually ``images[0]``). scale : float The resolution of the output image is `scale` times the resolution of the input images. x0 : ndarray, optional Initial guess of HR image. damp : float, optional If an initial guess is provided, `damp` specifies how much that estimate is weighed in the entire process. A larger value of `damp` results in a solution closer to `x0`, whereas a smaller version of `damp` yields a solution closer to the solution obtained without any initial estimate. method : {'CG', 'LSQR', 'descent', 'L-BFGS-B'} Whether to use conjugate gradients, least-squares, gradient descent or L-BFGS-B to determine the solution. operator : {'bilinear', 'polygon'} The camera model is approximated as an interpolation process. The bilinear interpolation operator only works well for zoom ratios < 2. norm : {1, 2} Whether to use the L1 or L2 norm to measure errors between images. standard_form : bool Whether to convert the matrix operator to standard form before processing. Returns ------- HR : ndarray High-resolution estimate. """ assert len(images) == len(tf_matrices) HH = [H.copy() for H in tf_matrices] HH_scaled = [] scale = float(scale) for H in HH: HS = np.array([[scale, 0, 0], [0, scale, 0], [0, 0, 1]]) HH_scaled.append(np.linalg.inv(np.dot(HS, H))) HH = HH_scaled oshape = np.floor(np.array(images[0].shape) * scale) LR_shape = images[0].shape print "Constructing camera operator (%s)..." % operator if operator == 'bilinear': op = bilinear(oshape[0], oshape[1], HH, *LR_shape, boundary=0) elif operator == 'polygon': sub_ops = [] for H in HH: sub_ops.append(poly_interp_op(oshape[0], oshape[1], H, *LR_shape, search_win=round(scale) * 2 + 1)) op = sparse.vstack(sub_ops, format='csr') else: raise ValueError('Invalid operator requested (%s).' % operator) ## Visualise mapping of frames ## ## import matplotlib.pyplot as plt ## P = np.prod(LR_shape) ## img = (op * x0.flat).reshape(LR_shape) ## plt.subplot(1, 4, 1) ## plt.imshow(x0, cmap=plt.cm.gray) ## plt.title('x0') ## plt.subplot(1, 4, 2) ## plt.imshow(images[0], cmap=plt.cm.gray) ## plt.title('LR frame') ## plt.subplot(1, 4, 3) ## plt.imshow(img, cmap=plt.cm.gray) ## plt.title('LR image Ax0') ## plt.subplot(1, 4, 4) ## plt.imshow(images[0] - img, cmap=plt.cm.gray) ## plt.title('diff images[0] - Ax') ## plt.show() if standard_form: print "Bringing matrix to standard form..." P = ordering.standard_form(op) op = P * op k = len(images) M = np.prod(LR_shape) b = np.empty(k * M) for i in range(k): b[i * M:(i + 1) * M] = images[i].flat if standard_form: b = P * b atol = btol = conlim = tol show = True # Construct the prior opT = op.T opT_sum1 = opT.sum(axis=1).flatten() + 0.00001 # add small bias to avoid division by zero opTb = opT.dot(b) x0 = opTb / opT_sum1 #return x0.reshape(oshape) # Error and gradient functions, used in conjugate gradient optimisation def sr_func(x, norm=norm): return (np.linalg.norm(op * x - b, norm) ** 2 + \ damp * np.linalg.norm(x - x0.flat, norm) ** 2) def sr_gradient(x, norm=norm): # Careful! Mixture of sparse and dense operators. #Axb = op * x - b #nrm_sq = np.dot(Axb, Axb) # Dense #Axbop = (op.T * Axb).T # Sparse #return nrm_sq * Axbop Axb = op * x - b L = len(x) if norm == 1: xmx0 = x - x0.flat term1 = np.linalg.norm(Axb, 1) * np.sign(Axb.T) * op term2 = damp * np.linalg.norm(xmx0, 1) * np.sign(xmx0.flat) elif norm == 2: term1 = (Axb.T * op) term2 = damp * (x - x0.flat) else: raise ValueError('Invalid norm for error measure (%s).' % norm) return 2 * (term1 + term2) print "Super resolving..." ## Conjugate Gradient Optimisation if method == 'CG': x, fopt, f_calls, gcalls, warnflag = \ opt.fmin_cg(sr_func, x0, fprime=sr_gradient, gtol=0, disp=True, maxiter=iter_lim, full_output=True) elif method == 'LSQR': ## LSQR Optimisation ## x0 = x0.flat b = b - op * x0 x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var = \ lsqr(op, b, atol=atol, btol=btol, conlim=conlim, damp=damp, show=show, iter_lim=iter_lim) x = x0 + x elif method == 'descent': ## Steepest Descent Optimisation ## x = np.array(x0, copy=True).reshape(np.prod(x0.shape)) for i in range(50): print (op.T * ((op * x) - b)).shape print "Gradient descent step %d" % i x += damp * -1 * (op.T * ((op * x) - b)) # Could add prior: + lam * (x - x0.flat)) ## L-BFGS-B elif method == 'L-BFGS-B': x, f, d = opt.fmin_l_bfgs_b(sr_func, x0.flat, fprime=sr_gradient) print "L-BFGS-B converged after %d function calls." % d['funcalls'] print "Final function value:", f print "Reason for termination:", d['task'] elif method == 'direct': x = sparse.linalg.spsolve(op, b) else: raise ValueError('Invalid method (%s) specified.' % method) return x.reshape(oshape)
def yaw_solve(yaw_image, yaw, scale, tol=1e-10, iter_lim=None, damp=1e-1, method='CG', norm=2): """Super-resolve a nonzero yaw image by solving a large, sparse set of linear equations. This method approximates the camera with a downsampling operator, using polygon interpolation. The LSQR method is used to solve the equation :math:`A\mathbf{x} = b` where :math:`A` is the downsampling operator, :math:`\mathbf{x}` is the high-resolution estimate (flattened in raster scan/ lexicographic order), and :math:`\mathbf{b}` is a vector of all the yaw_image pixels. Parameters ---------- yaw_image : ndarray Nonzero yaw input frame. tf_matrix : (3, 3) ndarray Transformation matrix that relates all yaw_image pixels to a reference high-resolution frame. scale : float The resolution of the output image is `scale` times the resolution of the input images. damp : float, optional If an initial guess is provided, `damp` specifies how much that estimate is weighed in the entire process. A larger value of `damp` results in a solution closer to `x0`, whereas a smaller version of `damp` yields a solution closer to the solution obtained without any initial estimate. method : {'CG', 'LSQR', 'descent', 'L-BFGS-B'} Whether to use conjugate gradients, least-squares, gradient descent or L-BFGS-B to determine the solution. norm : {1, 2} Whether to use the L1 or L2 norm to measure errors between images. Returns ------- HR : ndarray High-resolution estimate. """ ishape = yaw_image.shape oshape = yaw_image.shape print "Constructing camera operator..." op = poly_interp_op_yaw(oshape[0], oshape[1], ishape[0], ishape[1], yaw, scale, search_win=round(scale) * 2 + 1) #dop = op.todense() #dsDebug = gdal.GetDriverByName("GTIFF").Create('/tmp/debug.tif', opd.shape[1], opd.shape[0], 1, gdal.GDT_Float32) #dsDebug.GetRasterBand(1).WriteArray(opd) #dsDebug.FlushCache() M = np.prod(ishape) b = yaw_image.flat atol = btol = conlim = tol show = True # Construct the prior opT = op.T opT_sum1 = opT.sum(axis=1).flatten() + 0.00001 # add small bias to avoid division by zero opTb = opT.dot(b) x0 = opTb / opT_sum1 #return x0.reshape(oshape) # Error and gradient functions, used in conjugate gradient optimisation def sr_func(x, norm=norm): return (np.linalg.norm(op * x - b, norm) ** 2 + \ damp * np.linalg.norm(x - x0.flat, norm) ** 2) def sr_gradient(x, norm=norm): # Careful! Mixture of sparse and dense operators. #Axb = op * x - b #nrm_sq = np.dot(Axb, Axb) # Dense #Axbop = (op.T * Axb).T # Sparse #return nrm_sq * Axbop Axb = op * x - b L = len(x) if norm == 1: xmx0 = x - x0.flat term1 = np.linalg.norm(Axb, 1) * np.sign(Axb.T) * op term2 = damp * np.linalg.norm(xmx0, 1) * np.sign(xmx0.flat) elif norm == 2: term1 = (Axb.T * op) term2 = damp * (x - x0.flat) else: raise ValueError('Invalid norm for error measure (%s).' % norm) return 2 * (term1 + term2) print "Super resolving..." ## Conjugate Gradient Optimisation if method == 'CG': x, fopt, f_calls, gcalls, warnflag = \ opt.fmin_cg(sr_func, x0, fprime=sr_gradient, gtol=0, disp=True, maxiter=iter_lim, full_output=True) elif method == 'LSQR': ## LSQR Optimisation ## x0 = x0.flat b = b - op * x0 x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var = \ lsqr(op, b, atol=atol, btol=btol, conlim=conlim, damp=damp, show=show, iter_lim=iter_lim) x = x0 + x elif method == 'descent': ## Steepest Descent Optimisation ## x = np.array(x0, copy=True).reshape(np.prod(x0.shape)) for i in range(50): print (op.T * ((op * x) - b)).shape print "Gradient descent step %d" % i x += damp * -1 * (op.T * ((op * x) - b)) # Could add prior: + lam * (x - x0.flat)) ## L-BFGS-B elif method == 'L-BFGS-B': x, f, d = opt.fmin_l_bfgs_b(sr_func, x0.flat, fprime=sr_gradient) print "L-BFGS-B converged after %d function calls." % d['funcalls'] print "Final function value:", f print "Reason for termination:", d['task'] elif method == 'direct': x = sparse.linalg.spsolve(op, b) else: raise ValueError('Invalid method (%s) specified.' % method) return x.reshape(oshape), x0.reshape(oshape)
def yaw_solve(yaw_image, yaw, scale, tol=1e-10, iter_lim=None, damp=1e-1, method='CG', norm=2): """Super-resolve a nonzero yaw image by solving a large, sparse set of linear equations. This method approximates the camera with a downsampling operator, using polygon interpolation. The LSQR method is used to solve the equation :math:`A\mathbf{x} = b` where :math:`A` is the downsampling operator, :math:`\mathbf{x}` is the high-resolution estimate (flattened in raster scan/ lexicographic order), and :math:`\mathbf{b}` is a vector of all the yaw_image pixels. Parameters ---------- yaw_image : ndarray Nonzero yaw input frame. tf_matrix : (3, 3) ndarray Transformation matrix that relates all yaw_image pixels to a reference high-resolution frame. scale : float The resolution of the output image is `scale` times the resolution of the input images. damp : float, optional If an initial guess is provided, `damp` specifies how much that estimate is weighed in the entire process. A larger value of `damp` results in a solution closer to `x0`, whereas a smaller version of `damp` yields a solution closer to the solution obtained without any initial estimate. method : {'CG', 'LSQR', 'descent', 'L-BFGS-B'} Whether to use conjugate gradients, least-squares, gradient descent or L-BFGS-B to determine the solution. norm : {1, 2} Whether to use the L1 or L2 norm to measure errors between images. Returns ------- HR : ndarray High-resolution estimate. """ ishape = yaw_image.shape oshape = yaw_image.shape print "Constructing camera operator..." op = poly_interp_op_yaw(oshape[0], oshape[1], ishape[0], ishape[1], yaw, scale, search_win=round(scale) * 2 + 1) #dop = op.todense() #dsDebug = gdal.GetDriverByName("GTIFF").Create('/tmp/debug.tif', opd.shape[1], opd.shape[0], 1, gdal.GDT_Float32) #dsDebug.GetRasterBand(1).WriteArray(opd) #dsDebug.FlushCache() M = np.prod(ishape) b = yaw_image.flat atol = btol = conlim = tol show = True # Construct the prior opT = op.T opT_sum1 = opT.sum( axis=1).flatten() + 0.00001 # add small bias to avoid division by zero opTb = opT.dot(b) x0 = opTb / opT_sum1 #return x0.reshape(oshape) # Error and gradient functions, used in conjugate gradient optimisation def sr_func(x, norm=norm): return (np.linalg.norm(op * x - b, norm) ** 2 + \ damp * np.linalg.norm(x - x0.flat, norm) ** 2) def sr_gradient(x, norm=norm): # Careful! Mixture of sparse and dense operators. #Axb = op * x - b #nrm_sq = np.dot(Axb, Axb) # Dense #Axbop = (op.T * Axb).T # Sparse #return nrm_sq * Axbop Axb = op * x - b L = len(x) if norm == 1: xmx0 = x - x0.flat term1 = np.linalg.norm(Axb, 1) * np.sign(Axb.T) * op term2 = damp * np.linalg.norm(xmx0, 1) * np.sign(xmx0.flat) elif norm == 2: term1 = (Axb.T * op) term2 = damp * (x - x0.flat) else: raise ValueError('Invalid norm for error measure (%s).' % norm) return 2 * (term1 + term2) print "Super resolving..." ## Conjugate Gradient Optimisation if method == 'CG': x, fopt, f_calls, gcalls, warnflag = \ opt.fmin_cg(sr_func, x0, fprime=sr_gradient, gtol=0, disp=True, maxiter=iter_lim, full_output=True) elif method == 'LSQR': ## LSQR Optimisation ## x0 = x0.flat b = b - op * x0 x, istop, itn, r1norm, r2norm, anorm, acond, arnorm, xnorm, var = \ lsqr(op, b, atol=atol, btol=btol, conlim=conlim, damp=damp, show=show, iter_lim=iter_lim) x = x0 + x elif method == 'descent': ## Steepest Descent Optimisation ## x = np.array(x0, copy=True).reshape(np.prod(x0.shape)) for i in range(50): print(op.T * ((op * x) - b)).shape print "Gradient descent step %d" % i x += damp * -1 * (op.T * ((op * x) - b)) # Could add prior: + lam * (x - x0.flat)) ## L-BFGS-B elif method == 'L-BFGS-B': x, f, d = opt.fmin_l_bfgs_b(sr_func, x0.flat, fprime=sr_gradient) print "L-BFGS-B converged after %d function calls." % d['funcalls'] print "Final function value:", f print "Reason for termination:", d['task'] elif method == 'direct': x = sparse.linalg.spsolve(op, b) else: raise ValueError('Invalid method (%s) specified.' % method) return x.reshape(oshape), x0.reshape(oshape)
def smooth(filtration, cocycle): from cvxopt import spmatrix, matrix from cvxopt.blas import copy from lsqr import lsqr coefficient = [] coface_indices = [] face_indices = [] for i, s in enumerate(filtration): if s.dimension() > 2: continue c = 1 for sb in s.boundary: j = filtration(sb) coefficient.append(c) coface_indices.append(i) face_indices.append(j) c *= -1 # Cocycle can be larger than D; we implicitly project it down cocycle_max = max(zz[1] for zz in cocycle) # D is a coboundary matrix dimension = max(max(coface_indices), max(face_indices), cocycle_max) + 1 D = spmatrix(coefficient, coface_indices, face_indices, (dimension, dimension)) z = spmatrix([zz[0] for zz in cocycle], [zz[1] for zz in cocycle], [0 for zz in cocycle], (dimension, 1)) v1 = D * z if bool(D * D): raise Exception('D^2 is not 0') if bool(v1): raise Exception('Expected a cocycle as input') z = matrix(z) def Dfun(x, y, trans='N'): if trans == 'N': copy(D * x, y) elif trans == 'T': copy(D.T * x, y) else: assert False, "Unexpected trans parameter" tol = 1e-10 show = False maxit = None solution = lsqr(Dfun, matrix(z), show=False, atol=tol, btol=tol, itnlim=maxit) z_smooth = z - D * solution[0] # print sum(z_smooth**2) # assert sum((D*z_smooth)**2) < tol and sum((D.T*z_smooth)**2) < tol, "Expected a harmonic cocycle" if not (sum((D * z_smooth)**2) < tol and sum((D.T * z_smooth)**2) < tol): raise Exception("Expected a harmonic cocycle: %f %f" % (sum( (D * z_smooth)**2), sum((D.T * z_smooth)**2))) values = [] vertices = ((i, s) for (i, s) in enumerate(filtration) if s.dimension() == 0) for i, s in vertices: v = [v for v in s.vertices][0] if v >= len(values): values.extend((None for i in range(len(values), v + 1))) values[v] = solution[0][i] return values
def smooth(filtration, cocycle): from cvxopt import spmatrix, matrix from cvxopt.blas import copy from lsqr import lsqr coefficient = [] coface_indices = [] face_indices = [] for i,s in enumerate(filtration): if s.dimension() > 2: continue c = 1 for sb in s.boundary: j = filtration(sb) coefficient.append(c) coface_indices.append(i) face_indices.append(j) c *= -1 # Cocycle can be larger than D; we implicitly project it down cocycle_max = max(zz[1] for zz in cocycle) # D is a coboundary matrix dimension = max(max(coface_indices), max(face_indices), cocycle_max) + 1 D = spmatrix(coefficient, coface_indices, face_indices, (dimension, dimension)) z = spmatrix([zz[0] for zz in cocycle], [zz[1] for zz in cocycle], [0 for zz in cocycle], (dimension, 1)) v1 = D * z if bool(D*D): raise Exception('D^2 is not 0') if bool(v1): raise Exception('Expected a cocycle as input') z = matrix(z) def Dfun(x,y,trans = 'N'): if trans == 'N': copy(D * x, y) elif trans == 'T': copy(D.T * x, y) else: assert False, "Unexpected trans parameter" tol = 1e-10 show = False maxit = None solution = lsqr(Dfun, matrix(z), show = show, atol = tol, btol = tol, itnlim = maxit) z_smooth = z - D*solution[0] # print sum(z_smooth**2) # assert sum((D*z_smooth)**2) < tol and sum((D.T*z_smooth)**2) < tol, "Expected a harmonic cocycle" if not (sum((D*z_smooth)**2) < tol and sum((D.T*z_smooth)**2) < tol): raise Exception("Expected a harmonic cocycle: %f %f" % (sum((D*z_smooth)**2), sum((D.T*z_smooth)**2))) values = [] vertices = ((i,s) for (i,s) in enumerate(filtration) if s.dimension() == 0) for i,s in vertices: v = [v for v in s.vertices][0] if v >= len(values): values.extend((None for i in xrange(len(values), v+1))) values[v] = solution[0][i] return values