33
44
55def PrimalDual (proxf , proxg , A , x0 , tau , mu , z = None , theta = 1. , niter = 10 ,
6- gfirst = True , callback = None , show = False ):
6+ gfirst = True , callback = None , callbacky = False , show = False ):
77 r"""Primal-dual algorithm
88
99 Solves the following (possibly) nonlinear minimization problem using
@@ -39,10 +39,12 @@ def PrimalDual(proxf, proxg, A, x0, tau, mu, z=None, theta=1., niter=10,
3939 Linear operator of g
4040 x0 : :obj:`numpy.ndarray`
4141 Initial vector
42- tau : :obj:`float`
43- Stepsize of subgradient of :math:`f`
44- mu : :obj:`float`
45- Stepsize of subgradient of :math:`g^*`
42+ tau : :obj:`float` or :obj:`np.ndarray`
43+ Stepsize of subgradient of :math:`f`. This can be constant
44+ or function of iterations (in the latter cases provided as np.ndarray)
45+ mu : :obj:`float` or :obj:`np.ndarray`
46+ Stepsize of subgradient of :math:`g^*`. This can be constant
47+ or function of iterations (in the latter cases provided as np.ndarray)
4648 z : :obj:`numpy.ndarray`, optional
4749 Additional vector
4850 theta : :obj:`float`
@@ -58,6 +60,8 @@ def PrimalDual(proxf, proxg, A, x0, tau, mu, z=None, theta=1., niter=10,
5860 callback : :obj:`callable`, optional
5961 Function with signature (``callback(x)``) to call after each iteration
6062 where ``x`` is the current model vector
63+ callbacky : :obj:`bool`, optional
64+ Modify callback signature to (``callback(x, y)``) when ``callbacky=True``
6165 show : :obj:`bool`, optional
6266 Display iterations log
6367
@@ -98,6 +102,15 @@ def PrimalDual(proxf, proxg, A, x0, tau, mu, z=None, theta=1., niter=10,
98102 Imaging and Vision, 40, 8pp. 120-145. 2011.
99103
100104 """
105+ # check if tau and mu are scalars or arrays
106+ fixedtau = fixedmu = False
107+ if isinstance (tau , (int , float )):
108+ tau = tau * np .ones (niter )
109+ fixedtau = True
110+ if isinstance (mu , (int , float )):
111+ mu = mu * np .ones (niter )
112+ fixedmu = True
113+
101114 if show :
102115 tstart = time .time ()
103116 print ('Primal-dual: min_x f(Ax) + x^T z + g(x)\n '
@@ -106,9 +119,10 @@ def PrimalDual(proxf, proxg, A, x0, tau, mu, z=None, theta=1., niter=10,
106119 'Proximal operator (g): %s\n '
107120 'Linear operator (A): %s\n '
108121 'Additional vector (z): %s\n '
109- 'tau = %10e \ t mu = %10e \n theta = %.2f\t \t niter = %d\n ' %
122+ 'tau = %s \t \ t mu = %s \n theta = %.2f\t \t niter = %d\n ' %
110123 (type (proxf ), type (proxg ), type (A ),
111- None if z is None else 'vector' , tau , mu , theta , niter ))
124+ None if z is None else 'vector' , str (tau [0 ]) if fixedtau else 'Variable' ,
125+ str (mu [0 ]) if fixedmu else 'Variable' , theta , niter ))
112126 head = ' Itn x[0] f g z^x J = f + g + z^x'
113127 print (head )
114128
@@ -119,24 +133,26 @@ def PrimalDual(proxf, proxg, A, x0, tau, mu, z=None, theta=1., niter=10,
119133 for iiter in range (niter ):
120134 xold = x .copy ()
121135 if gfirst :
122- y = proxg .proxdual (y + mu * A .matvec (xhat ), mu )
136+ y = proxg .proxdual (y + mu [ iiter ] * A .matvec (xhat ), mu [ iiter ] )
123137 ATy = A .rmatvec (y )
124138 if z is not None :
125139 ATy += z
126- x = proxf .prox (x - tau * ATy , tau )
140+ x = proxf .prox (x - tau [ iiter ] * ATy , tau [ iiter ] )
127141 xhat = x + theta * (x - xold )
128142 else :
129143 ATy = A .rmatvec (y )
130144 if z is not None :
131145 ATy += z
132- x = proxf .prox (x - tau * ATy , tau )
146+ x = proxf .prox (x - tau [ iiter ] * ATy , tau [ iiter ] )
133147 xhat = x + theta * (x - xold )
134- y = proxg .proxdual (y + mu * A .matvec (xhat ), mu )
148+ y = proxg .proxdual (y + mu [ iiter ] * A .matvec (xhat ), mu [ iiter ] )
135149
136150 # run callback
137151 if callback is not None :
138- callback (x )
139-
152+ if callbacky :
153+ callback (x , y )
154+ else :
155+ callback (x )
140156 if show :
141157 if iiter < 10 or niter - iiter < 10 or iiter % (niter // 10 ) == 0 :
142158 pf , pg = proxf (x ), proxg (A .matvec (x ))
0 commit comments