diff options
author | epapoutsellis <epapoutsellis@gmail.com> | 2019-04-02 12:41:29 +0100 |
---|---|---|
committer | epapoutsellis <epapoutsellis@gmail.com> | 2019-04-02 12:41:29 +0100 |
commit | ab2d7b0f23c1851ab85203583d8cdff0b2b8341f (patch) | |
tree | c48ca80639a8f0a0283a1a89140b990f87c7616f /Wrappers | |
parent | 4702a82d1e5db55e8a1017eedab79cd0504b42ed (diff) | |
download | framework-ab2d7b0f23c1851ab85203583d8cdff0b2b8341f.tar.gz framework-ab2d7b0f23c1851ab85203583d8cdff0b2b8341f.tar.bz2 framework-ab2d7b0f23c1851ab85203583d8cdff0b2b8341f.tar.xz framework-ab2d7b0f23c1851ab85203583d8cdff0b2b8341f.zip |
add old pdhg, test gap
Diffstat (limited to 'Wrappers')
-rw-r--r-- | Wrappers/Python/ccpi/optimisation/algorithms/PDHG.py | 69 | ||||
-rw-r--r-- | Wrappers/Python/ccpi/optimisation/algorithms/__init__.py | 1 | ||||
-rw-r--r-- | Wrappers/Python/wip/test_pdhg_gap.py | 129 |
3 files changed, 199 insertions, 0 deletions
diff --git a/Wrappers/Python/ccpi/optimisation/algorithms/PDHG.py b/Wrappers/Python/ccpi/optimisation/algorithms/PDHG.py index 043fe38..8600e07 100644 --- a/Wrappers/Python/ccpi/optimisation/algorithms/PDHG.py +++ b/Wrappers/Python/ccpi/optimisation/algorithms/PDHG.py @@ -13,6 +13,9 @@ import time from ccpi.optimisation.operators import BlockOperator from ccpi.framework import BlockDataContainer + +import matplotlib.pyplot as plt + class PDHG(Algorithm): '''Primal Dual Hybrid Gradient''' @@ -80,3 +83,69 @@ class PDHG(Algorithm): ]) + +def PDHG_old(f, g, operator, tau = None, sigma = None, opt = None, **kwargs): + + # algorithmic parameters + if opt is None: + opt = {'tol': 1e-6, 'niter': 500, 'show_iter': 100, \ + 'memopt': False} + + if sigma is None and tau is None: + raise ValueError('Need sigma*tau||K||^2<1') + + niter = opt['niter'] if 'niter' in opt.keys() else 1000 + tol = opt['tol'] if 'tol' in opt.keys() else 1e-4 + memopt = opt['memopt'] if 'memopt' in opt.keys() else False + show_iter = opt['show_iter'] if 'show_iter' in opt.keys() else False + stop_crit = opt['stop_crit'] if 'stop_crit' in opt.keys() else False + + + x_old = operator.domain_geometry().allocate() + y_old = operator.range_geometry().allocate() + + + xbar = x_old + x_tmp = x_old + x = x_old + + y_tmp = y_old + y = y_tmp + + # relaxation parameter + theta = 1 + + t = time.time() + + objective = [] + + for i in range(niter): + + # Gradient descent, Dual problem solution + y_tmp = y_old + sigma * operator.direct(xbar) + y = f.proximal_conjugate(y_tmp, sigma) + + # Gradient ascent, Primal problem solution + x_tmp = x_old - tau * operator.adjoint(y) + x = g.proximal(x_tmp, tau) + + #Update + xbar = x + theta * (x - x_old) + + x_old = x + y_old = y + + if i%100==0: + + primal = f(operator.direct(x)) + g(x) + dual = -(f.convex_conjugate(y) + g(-1*operator.adjoint(y))) + print( i, primal, dual) + + plt.imshow(x.as_array()) + plt.show() +# print(f(operator.direct(x)) + g(x), i) + + t_end = time.time() + + return x, t_end - t, objective + diff --git a/Wrappers/Python/ccpi/optimisation/algorithms/__init__.py b/Wrappers/Python/ccpi/optimisation/algorithms/__init__.py index 443bc78..a28c0bf 100644 --- a/Wrappers/Python/ccpi/optimisation/algorithms/__init__.py +++ b/Wrappers/Python/ccpi/optimisation/algorithms/__init__.py @@ -28,3 +28,4 @@ from .GradientDescent import GradientDescent from .FISTA import FISTA from .FBPD import FBPD from .PDHG import PDHG +from .PDHG import PDHG_old diff --git a/Wrappers/Python/wip/test_pdhg_gap.py b/Wrappers/Python/wip/test_pdhg_gap.py new file mode 100644 index 0000000..b196e36 --- /dev/null +++ b/Wrappers/Python/wip/test_pdhg_gap.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Created on Tue Apr 2 12:26:24 2019 + +@author: vaggelis +""" + + +from ccpi.framework import ImageData, ImageGeometry, BlockDataContainer, AcquisitionGeometry, AcquisitionData + +import numpy as np +import matplotlib.pyplot as plt + +from ccpi.optimisation.algorithms import PDHG, PDHG_old + +from ccpi.optimisation.operators import BlockOperator, Identity, Gradient +from ccpi.optimisation.functions import ZeroFun, L2NormSquared, \ + MixedL21Norm, BlockFunction, ScaledFunction + +from ccpi.astra.ops import AstraProjectorSimple +from skimage.util import random_noise + + +#%%############################################################################### +# Create phantom for TV tomography + +#import os +#import tomophantom +#from tomophantom import TomoP2D +#from tomophantom.supp.qualitymetrics import QualityTools + +#model = 1 # select a model number from the library +#N = 150 # set dimension of the phantom +## one can specify an exact path to the parameters file +## path_library2D = '../../../PhantomLibrary/models/Phantom2DLibrary.dat' +#path = os.path.dirname(tomophantom.__file__) +#path_library2D = os.path.join(path, "Phantom2DLibrary.dat") +##This will generate a N_size x N_size phantom (2D) +#phantom_2D = TomoP2D.Model(model, N, path_library2D) +#ig = ImageGeometry(voxel_num_x = N, voxel_num_y = N) +#data = ImageData(phantom_2D, geometry=ig) + +N = 150 +x = np.zeros((N,N)) +x[round(N/4):round(3*N/4),round(N/4):round(3*N/4)] = 0.5 +x[round(N/8):round(7*N/8),round(3*N/8):round(5*N/8)] = 1 + +data = ImageData(x) +ig = ImageGeometry(voxel_num_x = N, voxel_num_y = N) + + +detectors = 150 +angles = np.linspace(0,np.pi,100) + +ag = AcquisitionGeometry('parallel','2D',angles, detectors) +Aop = AstraProjectorSimple(ig, ag, 'cpu') +sin = Aop.direct(data) + +plt.imshow(sin.as_array()) +plt.title('Sinogram') +plt.colorbar() +plt.show() + +# Add Gaussian noise to the sinogram data +np.random.seed(10) +n1 = np.random.random(sin.shape) + +noisy_data = sin + ImageData(5*n1) + +plt.imshow(noisy_data.as_array()) +plt.title('Noisy Sinogram') +plt.colorbar() +plt.show() + + +#%% Works only with Composite Operator Structure of PDHG + +#ig = ImageGeometry(voxel_num_x = N, voxel_num_y = N) + +# Create operators +op1 = Gradient(ig) +op2 = Aop + +# Form Composite Operator +operator = BlockOperator(op1, op2, shape=(2,1) ) + +alpha = 50 +f = BlockFunction( alpha * MixedL21Norm(), \ + 0.5 * L2NormSquared(b = noisy_data) ) +g = ZeroFun() + +# Compute operator Norm +normK = operator.norm() + +## Primal & dual stepsizes + +sigma = 10 +tau = 1/(sigma*normK**2) + +pdhg = PDHG(f=f,g=g,operator=operator, tau=tau, sigma=sigma) +pdhg.max_iteration = 2000 +pdhg.update_objective_interval = 100 + +#pdhg.run(5000) + +opt = {'niter':2000} + +res = PDHG_old(f, g, operator, tau = tau, sigma = sigma, opt = opt) + +#%% +#sol = pdhg.get_output().as_array() +#fig = plt.figure() +#plt.subplot(1,2,1) +#plt.imshow(noisy_data.as_array()) +##plt.colorbar() +#plt.subplot(1,2,2) +#plt.imshow(sol) +##plt.colorbar() +#plt.show() +# +# +##%% +#plt.plot(np.linspace(0,N,N), data.as_array()[int(N/2),:], label = 'GTruth') +#plt.plot(np.linspace(0,N,N), sol[int(N/2),:], label = 'Recon') +#plt.legend() +#plt.show() + + |