コード例 #1
0
    def test_FISTA_catch_Lipschitz(self):
        if debug_print:
            print("Test FISTA catch Lipschitz")
        ig = ImageGeometry(127, 139, 149)
        initial = ImageData(geometry=ig)
        initial = ig.allocate()
        b = initial.copy()
        # fill with random numbers
        b.fill(numpy.random.random(initial.shape))
        initial = ig.allocate(ImageGeometry.RANDOM)
        identity = IdentityOperator(ig)

        #### it seems FISTA does not work with Nowm2Sq
        norm2sq = LeastSquares(identity, b)
        if debug_print:
            print('Lipschitz', norm2sq.L)
        # norm2sq.L = None
        #norm2sq.L = 2 * norm2sq.c * identity.norm()**2
        #norm2sq = OperatorCompositionFunction(L2NormSquared(b=b), identity)
        opt = {'tol': 1e-4, 'memopt': False}
        if debug_print:
            print("initial objective", norm2sq(initial))
        try:
            alg = FISTA(initial=initial, f=L1Norm(), g=ZeroFunction())
            self.assertTrue(False)
        except ValueError as ve:
            print(ve)
            self.assertTrue(True)
コード例 #2
0
    def test_GD(self):
        print("Test GD")
        ig = ImageGeometry(12, 13, 14)
        initial = ig.allocate()
        # b = initial.copy()
        # fill with random numbers
        # b.fill(numpy.random.random(initial.shape))
        b = ig.allocate('random')
        identity = IdentityOperator(ig)

        norm2sq = LeastSquares(identity, b)
        rate = norm2sq.L / 3.

        alg = GD(initial=initial,
                 objective_function=norm2sq,
                 rate=rate,
                 atol=1e-9,
                 rtol=1e-6)
        alg.max_iteration = 1000
        alg.run(verbose=0)
        self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
        alg = GD(initial=initial,
                 objective_function=norm2sq,
                 rate=rate,
                 max_iteration=20,
                 update_objective_interval=2,
                 atol=1e-9,
                 rtol=1e-6)
        alg.max_iteration = 20
        self.assertTrue(alg.max_iteration == 20)
        self.assertTrue(alg.update_objective_interval == 2)
        alg.run(20, verbose=0)
        self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
コード例 #3
0
    def test_Lipschitz(self):
        print('Test for OperatorCompositionFunction')

        M, N = 50, 50
        ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N)
        b = ig.allocate('random', seed=1)

        print('Check call with IdentityOperator operator... OK\n')
        operator = 3 * IdentityOperator(ig)

        u = ig.allocate('random_int', seed=50)
        func2 = LeastSquares(operator, b, 0.5)
        assert func2.L != 2
        print(func2.L)
        func2.L = 2
        assert func2.L == 2
コード例 #4
0
    def test_FISTA_Norm2Sq(self):
        print("Test FISTA Norm2Sq")
        ig = ImageGeometry(127, 139, 149)
        b = ig.allocate(ImageGeometry.RANDOM)
        # fill with random numbers
        initial = ig.allocate(ImageGeometry.RANDOM)
        identity = IdentityOperator(ig)

        #### it seems FISTA does not work with Nowm2Sq
        norm2sq = LeastSquares(identity, b)
        #norm2sq.L = 2 * norm2sq.c * identity.norm()**2
        #norm2sq = OperatorCompositionFunction(L2NormSquared(b=b), identity)
        opt = {'tol': 1e-4, 'memopt': False}
        if debug_print:
            print("initial objective", norm2sq(initial))
        alg = FISTA(initial=initial, f=norm2sq, g=ZeroFunction())
        alg.max_iteration = 2
        alg.run(20, verbose=0)
        self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())

        alg = FISTA(initial=initial,
                    f=norm2sq,
                    g=ZeroFunction(),
                    max_iteration=2,
                    update_objective_interval=3)
        self.assertTrue(alg.max_iteration == 2)
        self.assertTrue(alg.update_objective_interval == 3)

        alg.run(20, verbose=0)
        self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
コード例 #5
0
    def setUp(self, *args, **kwargs):

        M, N, K = 3, 4, 5
        self.ig = ImageGeometry(M, N, K)

        self.x = self.ig.allocate('random', seed=1)
        self.b = self.ig.allocate('random', seed=2)
        self.eta = self.ig.allocate(0.1)

        self.operator = IdentityOperator(self.ig)

        scalar = 0.25
        self.f1 = L2NormSquared()
        self.f2 = L1Norm()
        self.f3 = scalar * L2NormSquared()
        self.f4 = scalar * L1Norm()
        self.f5 = scalar * L2NormSquared(b=self.b)
        self.f6 = scalar * L1Norm(b=self.b)
        self.f7 = ZeroFunction()
        self.f8 = 5 * ConstantFunction(10)
        self.f9 = LeastSquares(self.operator, self.b, c=scalar)
        self.f10 = 0.5 * KullbackLeibler(b=self.b, eta=self.eta)
        self.f11 = KullbackLeibler(b=self.b, eta=self.eta)
        self.f12 = 10

        self.list1 = [self.f1, self.f2, self.f3, self.f4, self.f5, \
                    self.f6, self.f7, self.f8, self.f9, self.f10, self.f11, self.f12]
コード例 #6
0
    def test_Norm2sq_as_OperatorCompositionFunction(self):

        print('Test for OperatorCompositionFunction')

        M, N = 50, 50
        ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N)
        #numpy.random.seed(1)
        b = ig.allocate('random', seed=1)

        print('Check call with IdentityOperator operator... OK\n')
        operator = 3 * IdentityOperator(ig)

        u = ig.allocate('random', seed=50)
        f = 0.5 * L2NormSquared(b=b)
        func1 = OperatorCompositionFunction(f, operator)
        func2 = LeastSquares(operator, b, 0.5)
        print("f.L {}".format(f.L))
        print("0.5*f.L {}".format((0.5 * f).L))
        print("type func1 {}".format(type(func1)))
        print("func1.L {}".format(func1.L))
        print("func2.L {}".format(func2.L))
        print("operator.norm() {}".format(operator.norm()))

        numpy.testing.assert_almost_equal(func1(u), func2(u))

        print('Check gradient with IdentityOperator operator... OK\n')

        tmp1 = ig.allocate()
        tmp2 = ig.allocate()
        res_gradient1 = func1.gradient(u)
        res_gradient2 = func2.gradient(u)
        func1.gradient(u, out=tmp1)
        func2.gradient(u, out=tmp2)

        self.assertNumpyArrayAlmostEqual(res_gradient1.as_array(),
                                         res_gradient2.as_array())
        self.assertNumpyArrayAlmostEqual(tmp1.as_array(), tmp2.as_array())

        print('Check call with MatrixOperator... OK\n')
        mat = np.random.randn(M, N)
        operator = MatrixOperator(mat)
        vg = VectorGeometry(N)
        b = vg.allocate('random')
        u = vg.allocate('random')

        func1 = OperatorCompositionFunction(0.5 * L2NormSquared(b=b), operator)
        func2 = LeastSquares(operator, b, 0.5)

        self.assertNumpyArrayAlmostEqual(func1(u), func2(u))
        numpy.testing.assert_almost_equal(func1.L, func2.L)
コード例 #7
0
    def test_Lipschitz4(self):
        print('Test for test_Lipschitz4')

        M, N = 50, 50
        ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N)
        b = ig.allocate('random', seed=1)

        print('Check call with IdentityOperator operator... OK\n')
        operator = 3 * IdentityOperator(ig)

        u = ig.allocate('random_int', seed=50)
        # func2 = LeastSquares(operator, b, 0.5)
        func1 = ConstantFunction(0.3)
        f3 = func1 + 3
        assert f3.L == 0
        print("OK")
        print(f3.L)
        f3.L = 2
        assert f3.L == 2
        print("OK")
        assert func1.L == 0
        print("OK")
        try:
            func1.L = 2
            assert False
        except AttributeError as ve:
            assert True
        print("OK")
        f2 = LeastSquares(operator, b, 0.5)
        f4 = 2 * f2
        assert f4.L == 2 * f2.L

        print("OK")
        f4.L = 10
        assert f4.L != 2 * f2.L
        print("OK")

        f4 = -2 * f2
        assert f4.L == 2 * f2.L
コード例 #8
0
    def test_SumFunction(self):
        
        M, N, K = 3,4,5
        ig = ImageGeometry(M, N, K)
        
        tmp = ig.allocate('random', seed=1)
        b   = ig.allocate('random', seed=2)
        eta = ig.allocate(0.1)
        
        operator = IdentityOperator(ig)

        scalar = 0.25
        f1 = L2NormSquared()
        f2 = L1Norm()
        f3 = scalar * L2NormSquared()
        f4 = scalar * L1Norm()
        f5 = scalar * L2NormSquared(b=b)
        f6 = scalar * L1Norm(b=b)  
        f7 = ZeroFunction()
        f8 = 5 *  ConstantFunction(10)             
        f9 = LeastSquares(operator, b, c=scalar)
        f10 = 0.5*KullbackLeibler(b=b,eta = eta)
        f11 = KullbackLeibler(b=b, eta =eta)
        f12 = 10
        
#        f10 = 0.5 * MixedL21Norm()
#        f11 = IndicatorBox(lower=0)
        
        list1 = [f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12]
                
        print('###################  Check sum of two functions ################## \n')
        
        for func in list1:
               
            
            # check sum of two functions   
            
            if isinstance(func, ScaledFunction):
                type_fun = ' scalar * ' + type(func.function).__name__
            else:    
                type_fun = type(func).__name__
                
            if isinstance(func, Number):
                tmp_fun_eval = func
            else:
                tmp_fun_eval = func(tmp)                
                             
            sumf = f1 + func           
            self.assertNumpyArrayAlmostEqual(sumf(tmp), f1(tmp) + tmp_fun_eval )
            print('{} = ( {} + {} ) is OK'.format(type(sumf).__name__, type(f1).__name__, type_fun))
            
            sumf1 = func + f1 
            self.assertNumpyArrayAlmostEqual(sumf1(tmp), tmp_fun_eval + f1(tmp))
            print('Checking commutative')
            print('{} + ( {} + {} ) is OK\n'.format(type(sumf1).__name__, type_fun, type(f1).__name__))
            
        print('###################  Check Lispchitz constant ################## \n')
        
        for i,func in enumerate(list1):
            
            if isinstance(func, ScaledFunction):
                type_fun = ' scalar * ' + type(func.function).__name__
            else:    
                type_fun = type(func).__name__            
               
            try:
                # check Lispchitz sum of two functions  
                print ("i", i,func.__class__.__name__)
                if isinstance(func, Number):
                    tmp_fun_L = 0
                else:
                    tmp_fun_L = func.L           
                
                sumf = f1 + func   
                
                try:
                    sumf.L==f1.L + tmp_fun_L
                except TypeError:
                    print('Function {} has L = None'.format(type_fun))
            except ValueError as nie:
                print (func.__class__.__name__, nie)
                
        print('\n###################  Check Gradient ################## \n')   
              
              
        for func in list1:
              
            if isinstance(func, ScaledFunction):
                type_fun = ' scalar * ' + type(func.function).__name__
            else:    
                type_fun = type(func).__name__
                                          
            sumf = f1 + func
            # check gradient          
            try:
                if isinstance(func, Number):
                    tmp_fun_gradient = 0
                else:
                    tmp_fun_gradient = func.gradient(tmp)   
                    
                self.assertNumpyArrayAlmostEqual(sumf.gradient(tmp).as_array(), (f1.gradient(tmp) + tmp_fun_gradient).as_array())
            except NotImplementedError:
                print("{} is not differentiable".format(type_fun))
                
        print('\n###################  Check Gradient Out ################## \n')  
         
        out_left = ig.allocate()
        out_right1 = ig.allocate()
        out_right2 = ig.allocate()  
            
        for i, func in enumerate(list1):               
                
            if isinstance(func, ScaledFunction):
                type_fun = ' scalar * ' + type(func.function).__name__
            else:    
                type_fun = type(func).__name__
            
            sumf = f1 + func
            
                                    
            # check gradient out    
            try:
                
                
                if isinstance(func, Number):
                    tmp_fun_gradient_out = 0
                else:
                    func.gradient(tmp, out = out_right2) 
                    tmp_fun_gradient_out = out_right2.as_array()
                    
                #print('Check {} + {}\n'.format(type(f1).__name__, type_fun))
                sumf.gradient(tmp, out = out_left)
                f1.gradient(tmp, out = out_right1)   
                self.assertNumpyArrayAlmostEqual(out_left.as_array(), out_right1.as_array() + tmp_fun_gradient_out)
            except NotImplementedError:
                print("{} is not differentiable".format(type_fun))  
コード例 #9
0
    def tests_for_LS_weightedLS(self):

        ig = ImageGeometry(40, 30)

        numpy.random.seed(1)

        A = IdentityOperator(ig)
        b = ig.allocate('random')
        x = ig.allocate('random')
        c = numpy.float64(0.3)

        weight = ig.allocate('random')

        D = DiagonalOperator(weight)
        norm_weight = numpy.float64(D.norm())
        print("norm_weight", norm_weight)

        f1 = LeastSquares(A, b, c, weight)
        f2 = LeastSquares(A, b, c)

        print("Check LS vs wLS")

        # check Lipshitz
        numpy.testing.assert_almost_equal(f2.L, 2 * c * (A.norm()**2))
        print("unwrapped", 2. * c * norm_weight * (A.norm()**2))
        print("f1.L", f1.L)
        numpy.testing.assert_almost_equal(
            f1.L,
            numpy.float64(2.) * c * norm_weight * (A.norm()**2))
        print("Lipschitz is ... OK")

        # check call with weight
        res1 = c * (A.direct(x) - b).dot(weight * (A.direct(x) - b))
        res2 = f1(x)
        numpy.testing.assert_almost_equal(res1, res2)
        print("Call is ... OK")

        # check call without weight
        #res1 = c * (A.direct(x)-b).dot((A.direct(x) - b))
        res1 = c * (A.direct(x) - b).squared_norm()
        res2 = f2(x)
        numpy.testing.assert_almost_equal(res1, res2)
        print("Call without weight is ... OK")

        # check gradient with weight
        out = ig.allocate(None)
        res1 = f1.gradient(x)
        #out = f1.gradient(x)
        f1.gradient(x, out=out)
        res2 = 2 * c * A.adjoint(weight * (A.direct(x) - b))
        numpy.testing.assert_array_almost_equal(res1.as_array(),
                                                res2.as_array())
        numpy.testing.assert_array_almost_equal(out.as_array(),
                                                res2.as_array())
        print("GradientOperator is ... OK")

        # check gradient without weight
        out = ig.allocate()
        res1 = f2.gradient(x)
        f2.gradient(x, out=out)
        res2 = 2 * c * A.adjoint(A.direct(x) - b)
        numpy.testing.assert_array_almost_equal(res1.as_array(),
                                                res2.as_array())
        numpy.testing.assert_array_almost_equal(out.as_array(),
                                                res2.as_array())

        print("GradientOperator without weight is ... OK")

        print(
            "Compare Least Squares with DiagonalOperator + CompositionOperator"
        )

        ig2 = ImageGeometry(100, 100, 100)
        A = IdentityOperator(ig2)
        b = ig2.allocate('random')
        x = ig2.allocate('random')
        c = 0.3

        weight = ig2.allocate('random')

        weight_operator = DiagonalOperator(weight.sqrt())
        tmp_A = CompositionOperator(weight_operator, A)
        tmp_b = weight_operator.direct(b)

        f1 = LeastSquares(tmp_A, tmp_b, c)
        f2 = LeastSquares(A, b, c, weight)

        t0 = timer()
        res1 = f1(x)
        t1 = timer()
        print("Time with Composition+Diagonal is {}".format(t1 - t0))

        t2 = timer()
        res2 = f2(x)
        t3 = timer()
        print("Time with LS + weight is {}".format(t3 - t2))

        numpy.testing.assert_almost_equal(res1, res2, decimal=2)
コード例 #10
0
    def test_SumFunction_more_inputs(self):

        # Test Lipshchitz value with more than 2 functions
        list2 = [
            LeastSquares(self.operator, self.b, c=0.25),
            LeastSquares(self.operator, self.b, c=4),
            LeastSquares(self.operator, self.b, c=5)
        ]

        F = SumFunction(*list2)
        L = 0.
        for f in list2:
            L += f.L

        self.assertAlmostEqual(L, F.L)

        # assert Lmax property
        self.assertAlmostEqual(max(f.L for f in list2), F.Lmax)

        ## test value of the gradient
        out = list2[0].gradient(self.x)
        out += list2[1].gradient(self.x)
        out += list2[2].gradient(self.x)

        # gradient without out
        out2 = F.gradient(self.x)
        np.testing.assert_allclose(out.as_array(), out2.as_array())

        # gradient with out
        out3 = self.x * 0.
        F.gradient(self.x, out=out3)
        np.testing.assert_allclose(out.as_array(), out3.as_array())

        # check call method
        val = F(self.x)
        val2 = 0.
        for f in F.functions:
            val2 += f(self.x)
        np.testing.assert_almost_equal(val, val2)

        # adding one more function (3 in total)
        scalar = 2.5
        F2 = F + ConstantFunction(scalar)

        # test __add__ method
        assert len(F2.functions) == len(F.functions) + 1

        # test if the sum remains a SumFunction
        self.assertIsInstance(F2, SumFunction)

        # check call
        np.testing.assert_almost_equal(F2(self.x), F(self.x) + scalar)

        # adding one more function (4 in total)
        F3 = F + F2

        np.testing.assert_almost_equal(F2(self.x) + F(self.x), F3(self.x))
        self.assertEqual(len(F3.functions),
                         len(F2.functions) + len(F.functions))

        # test if the sum remains a SumFunction
        self.assertIsInstance(F3, SumFunction)
コード例 #11
0
ig.voxel_num_y = int(num_pixels_x - 600 / bins)
ig.voxel_num_z = int(400 // bins)
print(ig)

#%% Reconstruct with FDK
fbp = FBP(ig, ag)
fbp.set_input(aq_data)
FBP_3D_gpu = fbp.get_output()

show2D(FBP_3D_gpu,
       slice_list=[('vertical', 204 // bins), ('horizontal_y', 570 // bins)],
       title="FBP reconstruction",
       fix_range=(-0.02, 0.07))
#%% Setup least sqaures and force pre-calculation of Lipschitz constant
Projector = ProjectionOperator(ig, ag)
LS = LeastSquares(A=Projector, b=aq_data)
print("Lipschitz constant =", LS.L)

#%% Setup FISTA to solve for least squares
fista = FISTA(x_init=ig.allocate(0),
              f=LS,
              g=ZeroFunction(),
              max_iteration=1000)
fista.update_objective_interval = 10

#%% Run FISTA
fista.run(300)
LS_reco = fista.get_output()
show2D(LS_reco,
       slice_list=[('vertical', 204 // bins), ('horizontal_y', 570 // bins)],
       title="LS reconstruction",
コード例 #12
0
        titles=['no centre', 'COR'],
        cmap='gist_earth',
    )

    #%%
    from cil.optimisation.functions import TotalVariation
    from cil.optimisation.algorithms import FISTA
    from cil.optimisation.functions import LeastSquares
    from cil.plugins.astra.operators import ProjectionOperator as A  #
    from cil.plugins.ccpi_regularisation.functions import FGP_TV

    K = A(ig_cs, ag_shift)
    # the c parameter is used to remove scaling of L2NormSquared in PDHG
    #
    c = 2
    f = LeastSquares(K, ldata, c=0.5 * c)
    if sparse_beads:
        f.L = 1071.1967 * c
    else:
        f.L = 24.4184 * c
    alpha_rgl = 0.003
    alpha = alpha_rgl * ig_cs.voxel_size_x
    g = c * alpha * TotalVariation(lower=0.)
    g = FGP_TV(alpha, 100, 1e-5, 1, 1, 0, 'gpu')

    algo = FISTA(initial=K.domain.allocate(0),
                 f=f,
                 g=g,
                 max_iteration=10000,
                 update_objective_interval=2)
    #%%
コード例 #13
0
#%%
plotter2D(
    [FBP_cs, FBP_output],
    titles=['no centre', 'COR'],
    cmap='gist_earth',
)

#%%
from cil.optimisation.functions import TotalVariation
from cil.optimisation.algorithms import FISTA
from cil.optimisation.functions import LeastSquares
from cil.plugins.astra.operators import ProjectionOperator as A  #
from cil.plugins.ccpi_regularisation.functions import FGP_TV

K = A(ig_cs, ag_shift)
f = LeastSquares(K, ldata, c=0.5)
if sparse_beads:
    f.L = 1071.1967
else:
    f.L = 24.4184
alpha_rgl = 0.003
alpha = alpha_rgl * ig_cs.voxel_size_x
g = alpha * TotalVariation(lower=0.)
g = FGP_TV(alpha, 100, 1e-5, 1, 1, 0, 'gpu')

algo = FISTA(initial=K.domain.allocate(0),
             f=f,
             g=g,
             max_iteration=10000,
             update_objective_interval=2)
#%%