def solve(A, b, method, tol=1e-3):
    """ General sparse solver interface.

    method can be one of
    - spsolve_umfpack_mmd_ata
    - spsolve_umfpack_colamd
    - spsolve_superlu_mmd_ata
    - spsolve_superlu_colamd
    - bicg
    - bicgstab
    - cg
    - cgs
    - gmres
    - lgmres
    - minres
    - qmr
    - lsqr
    - lsmr
    """

    if method == 'spsolve_umfpack_mmd_ata':
        return spla.spsolve(A, b, use_umfpack=True, permc_spec='MMD_ATA')
    elif method == 'spsolve_umfpack_colamd':
        return spla.spsolve(A, b, use_umfpack=True, permc_spec='COLAMD')
    elif method == 'spsolve_superlu_mmd_ata':
        return spla.spsolve(A, b, use_umfpack=False, permc_spec='MMD_ATA')
    elif method == 'spsolve_superlu_colamd':
        return spla.spsolve(A, b, use_umfpack=False, permc_spec='COLAMD')
    elif method == 'bicg':
        res = spla.bicg(A, b, tol=tol)
        return res[0]
    elif method == 'bicgstab':
        res = spla.bicgstab(A, b, tol=tol)
        return res[0]
    elif method == 'cg':
        res = spla.cg(A, b, tol=tol)
        return res[0]
    elif method == 'cgs':
        res = spla.cgs(A, b, tol=tol)
        return res[0]
    elif method == 'gmres':
        res = spla.gmres(A, b, tol=tol)
        return res[0]
    elif method == 'lgmres':
        res = spla.lgmres(A, b, tol=tol)
        return res[0]
    elif method == 'minres':
        res = spla.minres(A, b, tol=tol)
        return res[0]
    elif method == 'qmr':
        res = spla.qmr(A, b, tol=tol)
        return res[0]
    elif method == 'lsqr':
        res = spla.lsqr(A, b, atol=tol, btol=tol)
        return res[0]
    elif method == 'lsmr':
        res = spla.lsmr(A, b, atol=tol, btol=tol)
        return res[0]
    else:
        raise Exception('UnknownSolverType')
예제 #2
0
 def solve(self):
     A, b = list(
         zip(self.triangle_consistency(), self.vertex_consistency(),
             self.wheel_consistency()))
     A, b = sps.vstack(A), np.concatenate(b)
     W = sps.diags(self.preprocess_angles())
     A = A * W
     x, success = qmr(A * A.T, b)
     delta = W * A.T * x
     error = np.linalg.norm(delta) / (3 * self.num_faces)
     return (self.preprocess_angles() + delta).reshape(
         self.faces.shape), True if not success else False, error
예제 #3
0
def qmr_solve(A, u, b, tol=1e-08):
    print("Solving system using QMR solver")
    """ Solves the linear system A*u = b
        Input
            A: numpy array of NxN components (LHS)
            b: numpy array of Nx1 components (RHS)
            u: numpy array of Nx1 components (Solution)
    """

    # Change RHS representation
    A = sp.csr_matrix(A)

    # Solve system
    u[:] = spla.qmr(A, b, tol=tol)[0]
예제 #4
0
파일: stencil.py 프로젝트: DiMoser/PyPinT
    def iterative_solver_list(self, which, rhs, *args):
        """Solves the linear problem Ab = x using the sparse matrix

            Parameters
            ----------
            rhs : ndarray
                the right hand side
            which : string
                choose which solver is used
                    bicg(A, b[, x0, tol, maxiter, xtype, M, ...])
                        Use BIConjugate Gradient iteration to solve A x = b

                    bicgstab(A, b[, x0, tol, maxiter, xtype, M, ...])
                        Use BIConjugate Gradient STABilized iteration to solve A x = b

                    cg(A, b[, x0, tol, maxiter, xtype, M, callback])
                        Use Conjugate Gradient iteration to solve A x = b

                    cgs(A, b[, x0, tol, maxiter, xtype, M, callback])
                        Use Conjugate Gradient Squared iteration to solve A x = b

                    gmres(A, b[, x0, tol, restart, maxiter, ...])
                        Use Generalized Minimal RESidual iteration to solve A x = b.

                    lgmres(A, b[, x0, tol, maxiter, M, ...])
                        Solve a matrix equation using the LGMRES algorithm.

                    minres(A, b[, x0, shift, tol, maxiter, ...])
                        Use MINimum RESidual iteration to solve Ax=b

                    qmr(A, b[, x0, tol, maxiter, xtype, M1, M2, ...])
                        Use Quasi-Minimal Residual iteration to solve A x = b
        """
        if which == 'bicg':
            return spla.bicg(self.sp_matrix, rhs, args)
        elif which == "cg":
            return spla.cg(self.sp_matrix, rhs, args)
        elif which == "bicgstab":
            return spla.bicgstab(self.sp_matrix, rhs, args)
        elif which == "cgs":
            return spla.cgs(self.sp_matrix, rhs, args)
        elif which == "gmres":
            return spla.gmres(self.sp_matrix, rhs, args)
        elif which == "lgmres":
            return spla.lgmres(self.sp_matrix, rhs, args)
        elif which == "qmr":
            return spla.qmr(self.sp_matrix, rhs, args)
        else:
            raise NotImplementedError("this solver is unknown")
def runFastSinkSource(P,
                      positives,
                      negatives=None,
                      max_iters=1000,
                      eps=0.0001,
                      a=0.8,
                      tol=1e-5,
                      solver=None,
                      Milu=None,
                      verbose=False):
    """
    *P*: Network ags a scipy sparse matrix. Should already be normalized
    *positives*: numpy array of node ids to be used as positives
    *negatives*: numpy array of node ids to be used as negatives. 
        If not given, will be run as FastSinkSourcePlus. 
        For FastSinkSourcePlus, if the lambda parameter is desired, it should already have been included in the graph normalization process. 
        See the function normalizeGraphEdgeWeights in alg_utils.py 
    *max_iters*: max # of iterations to run SinkSource. 
        If 0, use spsolve to solve the equation directly 
    """
    num_nodes = P.shape[0]
    if len(positives) == 0:
        print("WARNING: No positive examples given. Skipping.")
        return np.zeros(num_nodes), 0, 0, 0
    # remove the positive and negative nodes from the graph
    # and setup the f vector which contains the influence from positive and negative nodes
    newP, f, = alg_utils.setup_fixed_scores(P,
                                            positives,
                                            negatives,
                                            a=a,
                                            remove_nonreachable=False)

    if solver is None:
        s, process_time, wall_time, num_iters = FastSinkSource(
            newP, f, max_iters=max_iters, eps=eps, a=a, verbose=verbose)
    else:
        # Solve for s directly. Scipy uses the form Ax=b to solve for x
        # SinkSource equation: (I - aP)s = f
        #solvers = ['bicg', 'bicgstab', 'cg', 'cgs', 'gmres', 'lgmres', 'minres', 'qmr', 'gcrotmk']#, 'lsmr']
        # eye is the identity matrix
        #M = eye(P.shape[0]) - a*P
        M = eye(newP.shape[0]) - a * newP

        # keep track of the number of iterations
        def callback(xk):
            # keep the reference to the variable within the callback function (Python 3)
            nonlocal num_iters
            num_iters += 1

        # this measures the amount of time taken by all processors
        start_process_time = time.process_time()
        # this measures the amount of time that has passed
        start_wall_time = time.time()
        num_iters = 0
        # spsolve basically stalls for large or dense networks (e.g., e-value cutoff 0.1)
        if solver == 'spsolve':
            s = linalg.spsolve(M, f)
        elif solver == 'bicg':
            s, info = linalg.bicg(M,
                                  f,
                                  tol=tol,
                                  maxiter=max_iters,
                                  M=Milu,
                                  callback=callback)
        elif solver == 'bicgstab':
            s, info = linalg.bicgstab(M,
                                      f,
                                      tol=tol,
                                      maxiter=max_iters,
                                      M=Milu,
                                      callback=callback)
        elif solver == 'cg':
            s, info = linalg.cg(M,
                                f,
                                tol=tol,
                                maxiter=max_iters,
                                M=Milu,
                                callback=callback)
        elif solver == 'cgs':
            s, info = linalg.cgs(M,
                                 f,
                                 tol=tol,
                                 maxiter=max_iters,
                                 M=Milu,
                                 callback=callback)
        elif solver == 'gmres':
            s, info = linalg.gmres(M,
                                   f,
                                   tol=tol,
                                   maxiter=max_iters,
                                   M=Milu,
                                   callback=callback)
        elif solver == 'lgmres':
            s, info = linalg.lgmres(M,
                                    f,
                                    tol=tol,
                                    maxiter=max_iters,
                                    M=Milu,
                                    callback=callback)
        elif solver == 'minres':
            s, info = linalg.minres(M,
                                    f,
                                    tol=tol,
                                    maxiter=max_iters,
                                    M=Milu,
                                    callback=callback)
        elif solver == 'qmr':
            s, info = linalg.qmr(M,
                                 f,
                                 tol=tol,
                                 maxiter=max_iters,
                                 M=Milu,
                                 callback=callback)
        elif solver == 'gcrotmk':
            s, info = linalg.gcrotmk(M,
                                     f,
                                     tol=tol,
                                     maxiter=max_iters,
                                     M=Milu,
                                     callback=callback)
        #elif solver == 'lsmr':
        #    s, info = linalg.lsmr(M, f, maxiter=max_iters, callback=callback)

        process_time = time.process_time() - start_process_time
        wall_time = time.time() - start_wall_time
        if verbose:
            print("Solved SS using %s (%0.3f sec, %0.3f process time). %s" %
                  (solver, wall_time, process_time,
                   "iters: %d, max_iters: %d, info: %s" %
                   (num_iters, 1000, info) if solver != 'spsolve' else ''))

    # keep the positive examples at 1
    s[positives] = 1

    return s, process_time, wall_time, num_iters
예제 #6
0
 def __init__(self, **kwargs):
     self.resource_pool = kwargs
     Y = kwargs[TRAIN_LABELS]
     self.label_row_inds = np.array(kwargs["label_row_inds"], dtype = np.int32)
     self.label_col_inds = np.array(kwargs["label_col_inds"], dtype = np.int32)
     self.Y = Y
     self.trained = False
     if "regparam" in kwargs:
         self.regparam = kwargs["regparam"]
     else:
         self.regparam = 1.0
     if CALLBACK_FUNCTION in kwargs:
         self.callbackfun = kwargs[CALLBACK_FUNCTION]
     else:
         self.callbackfun = None
     if "compute_risk" in kwargs:
         self.compute_risk = kwargs["compute_risk"]
     else:
         self.compute_risk = False
     
     regparam = self.regparam
     
     if not 'K1' in self.resource_pool:
         self.regparam = regparam
         X1 = self.resource_pool['X1']
         X2 = self.resource_pool['X2']
         self.X1, self.X2 = X1, X2
         
         if 'maxiter' in self.resource_pool: maxiter = int(self.resource_pool['maxiter'])
         else: maxiter = 1000
 
         if 'inneriter' in self.resource_pool: inneriter = int(self.resource_pool['inneriter'])
         else: inneriter = 50
         
         x1tsize, x1fsize = X1.shape #m, d
         x2tsize, x2fsize = X2.shape #q, r
         
         label_row_inds = np.array(self.label_row_inds, dtype = np.int32)
         label_col_inds = np.array(self.label_col_inds, dtype = np.int32)
         
 
 
         Y = self.Y
         rowind = label_row_inds
         colind = label_col_inds
         lamb = self.regparam
         rowind = np.array(rowind, dtype = np.int32)
         colind = np.array(colind, dtype = np.int32)
         fdim = X1.shape[1]*X2.shape[1]
         w = np.zeros(fdim)
         #np.random.seed(1)
         #w = np.random.random(fdim)
         self.bestloss = float("inf")
         def mv(v):
             return hessian(w, v, X1, X2, Y, rowind, colind, lamb)
             
         for i in range(maxiter):
             g = gradient(w, X1, X2, Y, rowind, colind, lamb)
             G = LinearOperator((fdim, fdim), matvec=mv, rmatvec=mv, dtype=np.float64)
             self.best_residual = float("inf")
             self.w_new = qmr(G, g, tol=1e-10, maxiter=inneriter)[0]
             if np.all(w == w - self.w_new):
                 break
             w = w - self.w_new
             if self.compute_risk:
                 P = sampled_kronecker_products.sampled_vec_trick(w, X1, X2, rowind, colind)
                 z = (1. - Y*P)
                 z = np.where(z>0, z, 0)
                 loss = 0.5*(np.dot(z,z)+lamb*np.dot(w,w))
                 if loss < self.bestloss:
                     self.W = w.reshape((x1fsize, x2fsize), order='F')
                     self.bestloss = loss
             else:
                 self.W = w.reshape((x1fsize, x2fsize), order='F')             
             if self.callbackfun is not None:
                 self.callbackfun.callback(self)
         self.predictor = LinearPairwisePredictor(self.W)
     else:
         K1 = self.resource_pool['K1']
         K2 = self.resource_pool['K2']
         if 'maxiter' in self.resource_pool: maxiter = int(self.resource_pool['maxiter'])
         else: maxiter = 100
         if 'inneriter' in self.resource_pool: inneriter = int(self.resource_pool['inneriter'])
         else: inneriter = 1000
         label_row_inds = np.array(self.label_row_inds, dtype = np.int32)
         label_col_inds = np.array(self.label_col_inds, dtype = np.int32)
         
         Y = self.Y
         rowind = label_row_inds
         colind = label_col_inds
         lamb = self.regparam
         rowind = np.array(rowind, dtype = np.int32)
         colind = np.array(colind, dtype = np.int32)
         ddim = len(rowind)
         a = np.zeros(ddim)
         self.bestloss = float("inf")
         def func(a):
             P =  sampled_kronecker_products.sampled_vec_trick(a, K2, K1, colind, rowind, colind, rowind)
             z = (1. - Y*P)
             z = np.where(z>0, z, 0)
             Ka = sampled_kronecker_products.sampled_vec_trick(a, K2, K1, colind, rowind, colind, rowind)
             return 0.5*(np.dot(z,z)+lamb*np.dot(a, Ka))
         def mv(v):
             rows = rowind[sv]
             cols = colind[sv]
             p = np.zeros(len(rowind))
             A =  sampled_kronecker_products.sampled_vec_trick(v, K2, K1, cols, rows, colind, rowind)
             p[sv] = A
             return p + lamb * v
         def rv(v):
             rows = rowind[sv]
             cols = colind[sv]
             p = sampled_kronecker_products.sampled_vec_trick(v[sv], K2, K1, colind, rowind, cols, rows)
             return p + lamb * v
         for i in range(maxiter):
             P =  sampled_kronecker_products.sampled_vec_trick(a, K2, K1, colind, rowind, colind, rowind)
             z = (1. - Y*P)
             z = np.where(z>0, z, 0)
             sv = np.nonzero(z)[0]
             B = np.zeros(P.shape)
             B[sv] = P[sv]-Y[sv]
             B = B + lamb*a
             #solve Ax = B
             A = LinearOperator((ddim, ddim), matvec=mv, rmatvec=rv, dtype=np.float64)
             self.a_new = qmr(A, B, tol=1e-10, maxiter=inneriter)[0]
             if np.all(a == a - self.a_new):
                 break
             a = a - self.a_new
             if self.compute_risk:
                 loss = func(a)
                 if loss < self.bestloss:
                     self.A = a
                     self.bestloss = loss
             else:
                 self.A = a
             self.predictor = KernelPairwisePredictor(a, rowind, colind)
             if self.callbackfun is not None:
                 self.callbackfun.callback(self)
         self.predictor = KernelPairwisePredictor(a, rowind, colind)
         if self.callbackfun is not None:
             self.callbackfun.finished(self)
예제 #7
0
 def _action(self, act=1):
     if QSMODE == MODE_MPMATH:
         args = {}
         if act==0:
             self.typeStr = "mpmath_qr_solve_dps"+getArgDesc(mpmath.qr_solve, args)+" DPS"+str(DPS)
             self.matrixType = 1
             self.indexType = 1
         else:
             self.coeffVec = mpmath.qr_solve(self.sysMat, self.resVec, **args)
             self.printCalStr()
     else:
         if PYTYPE_COEFF_SOLVE_METHOD == "numpy_solve":
             args = {}
             if act==0:
                 self.typeStr = "numpy_solve"+getArgDesc(np.linalg.solve, args)
                 self.matrixType = 0
                 self.indexType = 0
             else:
                 self.coeffVec = np.linalg.solve(self.sysMat, self.resVec, **args)
                 self.printCalStr()
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_lstsq":
             args = {}
             if act==0:
                 self.typeStr = "numpy_lstsq"+getArgDesc(np.linalg.lstsq, args)
                 self.matrixType = 0
                 self.indexType = 0
             else:
                 self.coeffVec = np.linalg.lstsq(self.sysMat, self.resVec, **args)[0]
                 self.printCalStr()
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_sparse_bicg": 
             args = {}
             if act==0:
                 self.typeStr = "numpy_sparse_bicg"+getArgDesc(sp_sparse_linalg.bicg, args)
                 self.matrixType = 0
                 self.indexType = 1
             else:
                 self.coeffVec = self._sparseRet(sp_sparse_linalg.bicg(self.sysMat, self.resVec, **args))#, tol=1e-05, maxiter=10*len(self.resVec)
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_sparse_bicgstab":
             args = {}
             if act==0:
                 self.typeStr = "numpy_sparse_bicgstab"+getArgDesc(sp_sparse_linalg.bicgstab, args)
                 self.matrixType = 0
                 self.indexType = 1
             else:
                 self.coeffVec = self._sparseRet(sp_sparse_linalg.bicgstab(self.sysMat, self.resVec, **args))#, tol=1e-05, maxiter=10*len(self.resVec)
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_sparse_lgmres":
             args = {}
             if act==0:
                 self.typeStr = "numpy_sparse_lgmres"+getArgDesc(sp_sparse_linalg.lgmres, args)
                 self.matrixType = 0
                 self.indexType = 1
             else:
                 self.coeffVec = self._sparseRet(sp_sparse_linalg.lgmres(self.sysMat, self.resVec, **args))#, tol=1e-05, maxiter=1000
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_sparse_minres":
             args = {}
             if act==0:
                 self.typeStr = "numpy_sparse_minres"+getArgDesc(sp_sparse_linalg.minres, args)
                 self.matrixType = 0
                 self.indexType = 1
             else:
                 self.coeffVec = self._sparseRet(sp_sparse_linalg.minres(self.sysMat, self.resVec, **args))#, tol=1e-05, maxiter=5*self.sysMat.shape[0]
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_sparse_qmr":
             args = {}
             if act==0:
                 self.typeStr = "numpy_sparse_qmr"+getArgDesc(sp_sparse_linalg.qmr, args)
                 self.matrixType = 0
                 self.indexType = 1
             else:
                 self.coeffVec = self._sparseRet(sp_sparse_linalg.qmr(self.sysMat, self.resVec, **args))#, tol=1e-05, maxiter=10*len(self.resVec)
         elif PYTYPE_COEFF_SOLVE_METHOD == "numpy_qr":
             args_qr = {}
             args_s = {}
             if act==0:
                 self.typeStr = "numpy_qr"+getArgDesc(np.linalg.qr, args_qr)+",numpy_solve"+getArgDesc(np.linalg.solve, args_s)
                 self.matrixType = 0
                 self.indexType = 0
             else:
                 Q,R = np.linalg.qr(self.sysMat, **args_qr)
                 y = np.dot(Q.T,self.resVec)
                 self.coeffVec = np.linalg.solve(R,y, **args_s) 
                 self.printCalStr()
예제 #8
0
import numpy as np
from scipy.sparse.linalg import qmr

A = np.arange(1, 10).reshape((3, 3))
A[2, 2] = 0

b = np.arange(1, 4).reshape((3, 1))
x = np.zeros(())

x = np.linalg.inv(A) @ b

qmr_x = qmr(A, b, np.zeros((3, 1)))
        elif ALGORITHM=="biconjugate-gradient-stabilized":
            x=la.bicgstab(A,y)
        elif ALGORITHM=="conjugate-gradient-iter":
            x=la.cg(A,y)
        elif ALGORITHM == "conjugate-gradient-squared":
            x = la.cgs(A, y)
        elif ALGORITHM == "conjugate-gradient-squared":
            x = la.cgs(A, y)
        elif ALGORITHM == "generalized-min-res":
            x = la.gmres(A, y)
        elif ALGORITHM == "improved-generalized-min-res":
            x = la.lgmres(A, y)
        elif ALGORITHM =="min-res":
            x=la.minres(A,y)
        elif ALGORITHM =="quasi-min-res":
            x=la.qmr(A,y)


        endT=time.process_time()

        '''print(x)
        print(xCorrect)'''
        residue=np.average(np.average(np.abs(x-xCorrect)))/np.average(np.average(np.abs(xCorrect)))

        print("Algorith: "+ALGORITHM+"\tMat Size: "+str(N)+"\tTime: "+str(endT-startT)+"\t Residue: "+str(residue))

        TIME[n]=endT-startT
        RESIDUE[n]=residue

    print("Time List:")
    for n in range(len(NN)):
예제 #10
0
파일: kron_svm.py 프로젝트: aatapa/RLScore
 def __init__(self, **kwargs):
     self.resource_pool = kwargs
     Y = kwargs[TRAIN_LABELS]
     self.label_row_inds = np.array(kwargs["label_row_inds"], dtype = np.int32)
     self.label_col_inds = np.array(kwargs["label_col_inds"], dtype = np.int32)
     self.Y = Y
     self.trained = False
     if "regparam" in kwargs:
         self.regparam = kwargs["regparam"]
     else:
         self.regparam = 1.0
     if CALLBACK_FUNCTION in kwargs:
         self.callbackfun = kwargs[CALLBACK_FUNCTION]
     else:
         self.callbackfun = None
     if "compute_risk" in kwargs:
         self.compute_risk = kwargs["compute_risk"]
     else:
         self.compute_risk = False
     
     regparam = self.regparam
     
     if not 'K1' in self.resource_pool:
         self.regparam = regparam
         X1 = self.resource_pool['X1']
         X2 = self.resource_pool['X2']
         self.X1, self.X2 = X1, X2
         
         if 'maxiter' in self.resource_pool: maxiter = int(self.resource_pool['maxiter'])
         else: maxiter = 1000
 
         if 'inneriter' in self.resource_pool: inneriter = int(self.resource_pool['inneriter'])
         else: inneriter = 50
         
         x1tsize, x1fsize = X1.shape #m, d
         x2tsize, x2fsize = X2.shape #q, r
         
         label_row_inds = np.array(self.label_row_inds, dtype = np.int32)
         label_col_inds = np.array(self.label_col_inds, dtype = np.int32)
         
 
 
         Y = self.Y
         rowind = label_row_inds
         colind = label_col_inds
         lamb = self.regparam
         rowind = np.array(rowind, dtype = np.int32)
         colind = np.array(colind, dtype = np.int32)
         fdim = X1.shape[1]*X2.shape[1]
         w = np.zeros(fdim)
         #np.random.seed(1)
         #w = np.random.random(fdim)
         self.bestloss = float("inf")
         def mv(v):
             return hessian(w, v, X1, X2, Y, rowind, colind, lamb)
             
         for i in range(maxiter):
             g = gradient(w, X1, X2, Y, rowind, colind, lamb)
             G = LinearOperator((fdim, fdim), matvec=mv, rmatvec=mv, dtype=np.float64)
             self.best_residual = float("inf")
             self.w_new = qmr(G, g, tol=1e-10, maxiter=inneriter)[0]
             if np.all(w == w - self.w_new):
                 break
             w = w - self.w_new
             if self.compute_risk:
                 P = sampled_kronecker_products.sampled_vec_trick(w, X1, X2, rowind, colind)
                 z = (1. - Y*P)
                 z = np.where(z>0, z, 0)
                 loss = 0.5*(np.dot(z,z)+lamb*np.dot(w,w))
                 if loss < self.bestloss:
                     self.W = w.reshape((x1fsize, x2fsize), order='F')
                     self.bestloss = loss
             else:
                 self.W = w.reshape((x1fsize, x2fsize), order='F')             
             if self.callbackfun is not None:
                 self.callbackfun.callback(self)
         self.predictor = LinearPairwisePredictor(self.W)
     else:
         K1 = self.resource_pool['K1']
         K2 = self.resource_pool['K2']
         if 'maxiter' in self.resource_pool: maxiter = int(self.resource_pool['maxiter'])
         else: maxiter = 100
         if 'inneriter' in self.resource_pool: inneriter = int(self.resource_pool['inneriter'])
         else: inneriter = 1000
         label_row_inds = np.array(self.label_row_inds, dtype = np.int32)
         label_col_inds = np.array(self.label_col_inds, dtype = np.int32)
         
         Y = self.Y
         rowind = label_row_inds
         colind = label_col_inds
         lamb = self.regparam
         rowind = np.array(rowind, dtype = np.int32)
         colind = np.array(colind, dtype = np.int32)
         ddim = len(rowind)
         a = np.zeros(ddim)
         self.bestloss = float("inf")
         
         def func(a):
             P =  sampled_kronecker_products.sampled_vec_trick(a, K2, K1, colind, rowind, colind, rowind)
             z = (1. - Y*P)
             z = np.where(z>0, z, 0)
             Ka = sampled_kronecker_products.sampled_vec_trick(a, K2, K1, colind, rowind, colind, rowind)
             return 0.5*(np.dot(z,z)+lamb*np.dot(a, Ka))
         
         def mv(v):
             rows = rowind[sv]
             cols = colind[sv]
             p = np.zeros(len(rowind))
             A = sampled_kronecker_products.sampled_vec_trick(v, K2, K1, cols, rows, colind, rowind)
             p[sv] = A
             return p + lamb * v
         def mv_mk(v):
             rows = rowind[sv]
             cols = colind[sv]
             p = np.zeros(len(rowind))
             skpsum = np.zeros(len(sv))
             for i in range(len(K1)):
                 K1i = K1[i]
                 K2i = K2[i]
                 skpsum += weights[i] * sampled_kronecker_products.sampled_vec_trick(v, K2i, K1i, cols, rows, colind, rowind)
             p[sv] = skpsum
             return p + lamb * v
         
         def rv(v):
             rows = rowind[sv]
             cols = colind[sv]
             p = sampled_kronecker_products.sampled_vec_trick(v[sv], K2, K1, colind, rowind, cols, rows)
             return p + lamb * v
         
         def rv_mk(v):
             rows = rowind[sv]
             cols = colind[sv]
             psum = np.zeros(len(v))
             for i in range(len(K1)):
                 K1i = K1[i]
                 K2i = K2[i]
                 psum += weights[i] * sampled_kronecker_products.sampled_vec_trick(v[sv], K2i, K1i, colind, rowind, cols, rows)
             return psum + lamb * v
         
         for i in range(maxiter):
             if isinstance(K1, (list, tuple)):
                 if 'weights' in kwargs: weights = kwargs['weights']
                 else: weights = np.ones((len(K1)))
                 A = LinearOperator((ddim, ddim), matvec = mv_mk, rmatvec = rv_mk, dtype = np.float64)
                 P = np.zeros(ddim)
                 for i in range(len(K1)):
                     K1i = K1[i]
                     K2i = K2[i]
                     prod_i = weights[i] * sampled_kronecker_products.sampled_vec_trick(a, K2i, K1i, colind, rowind, colind, rowind)
                     P += prod_i
             else:
                 weights = None
                 A = LinearOperator((ddim, ddim), matvec=mv, rmatvec=rv, dtype=np.float64)
                 P = sampled_kronecker_products.sampled_vec_trick(a, K2, K1, colind, rowind, colind, rowind)
             z = (1. - Y*P)
             z = np.where(z>0, z, 0)
             sv = np.nonzero(z)[0]
             B = np.zeros(P.shape)
             B[sv] = P[sv]-Y[sv]
             B = B + lamb*a
             #solve Ax = B
             self.a_new = qmr(A, B, tol=1e-10, maxiter=inneriter)[0]
             if np.all(a == a - self.a_new):
                 break
             a = a - self.a_new
             if self.compute_risk:
                 loss = func(a)
                 if loss < self.bestloss:
                     self.A = a
                     self.bestloss = loss
             else:
                 self.A = a
             self.predictor = KernelPairwisePredictor(a, rowind, colind)
             if self.callbackfun is not None:
                 self.callbackfun.callback(self)
         self.predictor = KernelPairwisePredictor(a, rowind, colind)
         if self.callbackfun is not None:
             self.callbackfun.finished(self)