
import numpy
import logging
import sys
import scipy.sparse.linalg
from apgl.util.Sampling import Sampling 
from apgl.util.ProfileUtils import ProfileUtils
from exp.util.SparseUtils import SparseUtils
from exp.util.LinOperatorUtils import LinOperatorUtils

logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)

class LinOperatorUtilsProfile(object):
    def __init__(self):
        numpy.random.seed(21)        
        
        #Create a low rank matrix  
        n = 100000 
        m = 100000 
        self.r = 200 
        k = 10**6
        
        self.X = SparseUtils.generateSparseLowRank((n, m), self.r, k)

    def profileParallelSparseOp(self):
        L = LinOperatorUtils.parallelSparseOp(self.X)
        
        def run(): 
            numRuns = 10 
            for i in range(numRuns): 
                p = numpy.random.rand(self.X.shape[0])
                q = numpy.random.rand(self.X.shape[1])
                
                L.matvec(q)
                L.rmatvec(p)
        
        ProfileUtils.profile('run()', globals(), locals())

    def profileParallelSparseOp2(self):
        L = LinOperatorUtils.parallelSparseOp(self.X)
        
        def run(): 
            numRuns = 10 
            for i in range(numRuns): 
                p = 200
                W = numpy.random.rand(self.X.shape[1], p)
                
                L.matmat(W)
        
        ProfileUtils.profile('run()', globals(), locals())
        
        
    def profileAsLinearOperator(self):
        L = scipy.sparse.linalg.aslinearoperator(self.X)
        
        def run(): 
            numRuns = 10 
            for i in range(numRuns): 
                p = numpy.random.rand(self.X.shape[0])
                q = numpy.random.rand(self.X.shape[1])
                
                L.matvec(q)
                L.rmatvec(p)
        
        ProfileUtils.profile('run()', globals(), locals())

    def profileAsLinearOperator2(self):
        L = scipy.sparse.linalg.aslinearoperator(self.X)
        
        def run(): 
            numRuns = 10 
            for i in range(numRuns): 
                p = 200
                W = numpy.random.rand(self.X.shape[1], p)
                
                L.matmat(W)
        
        ProfileUtils.profile('run()', globals(), locals())
        
profiler = LinOperatorUtilsProfile()
profiler.profileParallelSparseOp()
#profiler.profileAsLinearOperator()
#profiler.profileParallelSparseOp2() # 78.77
#profiler.profileAsLinearOperator2() #44 
@@ -539,9 +539,9 @@
 10**
-6
+8
 %0A   
@@ -1167,38 +1167,32 @@
         
-def run(): %0A  
+p = 300%0A
         
   numRun
@@ -1187,77 +1187,66 @@
     
- 
+W =
  num
-Runs = 10 %0A            for i in range(numRuns): %0A
+py.random.rand(self.X.shape%5B1%5D, p) 
        
+%0A
         
  p =
@@ -1241,32 +1241,24 @@
         
- p = 200
 %0A       
         
@@ -1241,32 +1241,45 @@
         %0A       
+ def run(): %0A
          W = num
@@ -1275,65 +1275,59 @@
     
-W =
+  
  num
-py.random.rand(self.X.shape%5B1%5D, p)%0A               
+Runs = 1%0A            for i in range(numRuns):
  %0A  
@@ -1978,32 +1978,107 @@
 elf.X)%0A        %0A
+        p = 300%0A        W = numpy.random.rand(self.X.shape%5B1%5D, p)%0A        %0A
         def run(
@@ -2096,33 +2096,32 @@
      numRuns = 1
-0
  %0A            fo
@@ -2148,107 +2148,8 @@
 ): %0A
-                p = 200%0A                W = numpy.random.rand(self.X.shape%5B1%5D, p)%0A                %0A
     
@@ -2290,44 +2290,54 @@
 e()%0A
-profiler.profileParallelSparseOp()%0A#
+#An advantage to be parallel when nnz %3E 10%5E8 %0A
 prof
@@ -2364,18 +2364,25 @@
 Operator
+2
 ()
+ #42s 
 %0A#profil
@@ -2416,52 +2416,8 @@
 () #
- 78.77%0A#profiler.profileAsLinearOperator2() #44 
+37s%0A

Test matmat on large matrices