pythoncvxpyconvex-optimization

DCPError: Problem does not follow DCP rules - TV minimization using CVXPY library


I want to solve a compressed sensing problem which I wish to minimize total variation(TV) of my object vector. Here is representation of my code:

import numpy as np
import matplotlib.pyplot as plt
import os
import numpy as np
from scipy.optimize import minimize
import scipy.io
import pandas as pd
import math

# A and Y are (2323,6561) and (2323,1) complex array respectively.
A = scipy.io.loadmat(r'C:\Users\mohammad\Desktop\feko1\feko\A.mat')
Y = scipy.io.loadmat(r'C:\Users\mohammad\Desktop\feko1\feko\Y.mat')

A = np.array(A["A"])
Y = np.array(Y["Y"])

import cvxpy as cp
delta = 10

# Define the variables
s_L1 = cp.Variable(A.shape[1])

# Define the objective function

xydim = int(math.sqrt(A.shape[1]))
            
print(xydim)

s_L1_2d = s_L1.reshape((xydim,xydim))

dim1diff = s_L1_2d[1:,:] - s_L1_2d[:-1,:]
dim2diff = s_L1_2d[:,1:]- s_L1_2d[:,:-1]
dim1diff = cp.square(dim1diff)
dim2diff = cp.square(dim2diff)
dim2diff2 = dim2diff.T

tot_var = cp.sum(cp.sqrt(dim1diff + dim2diff2))

s_L1 = s_L1.reshape((A.shape[1],1))
objective = tot_var

constraints = [cp.norm(A@s_L1 - Y,2) <= delta]

# Define the optimization problem
problem = cp.Problem(cp.Minimize(objective), constraints)

# Solve the optimization problem
problem.solve()

but it gives the following error in jupyter:

---------------------------------------------------------------------------
DCPError                                  Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_15028\3075150186.py in <module>
      5 
      6 # Solve the optimization problem
----> 7 problem.solve()

~\AppData\Roaming\Python\Python39\site-packages\cvxpy\problems\problem.py in solve(self, *args, **kwargs)
    501         else:
    502             solve_func = Problem._solve
--> 503         return solve_func(self, *args, **kwargs)
    504 
    505     @classmethod

~\AppData\Roaming\Python\Python39\site-packages\cvxpy\problems\problem.py in _solve(self, solver, warm_start, verbose, gp, qcp, requires_grad, enforce_dpp, ignore_dpp, canon_backend, **kwargs)
   1070                 return self.value
   1071 
-> 1072         data, solving_chain, inverse_data = self.get_problem_data(
   1073             solver, gp, enforce_dpp, ignore_dpp, verbose, canon_backend, kwargs
   1074         )

~\AppData\Roaming\Python\Python39\site-packages\cvxpy\problems\problem.py in get_problem_data(self, solver, gp, enforce_dpp, ignore_dpp, verbose, canon_backend, solver_opts)
    644         if key != self._cache.key:
    645             self._cache.invalidate()
--> 646             solving_chain = self._construct_chain(
    647                 solver=solver, gp=gp,
    648                 enforce_dpp=enforce_dpp,

~\AppData\Roaming\Python\Python39\site-packages\cvxpy\problems\problem.py in _construct_chain(self, solver, gp, enforce_dpp, ignore_dpp, canon_backend, solver_opts)
    896         candidate_solvers = self._find_candidate_solvers(solver=solver, gp=gp)
    897         self._sort_candidate_solvers(candidate_solvers)
--> 898         return construct_solving_chain(self, candidate_solvers, gp=gp,
    899                                        enforce_dpp=enforce_dpp,
    900                                        ignore_dpp=ignore_dpp,

~\AppData\Roaming\Python\Python39\site-packages\cvxpy\reductions\solvers\solving_chain.py in construct_solving_chain(problem, candidates, gp, enforce_dpp, ignore_dpp, canon_backend, solver_opts, specified_solver)
    215     if len(problem.variables()) == 0:
    216         return SolvingChain(reductions=[ConstantSolver()])
--> 217     reductions = _reductions_for_problem_class(problem, candidates, gp, solver_opts)
    218 
    219     # Process DPP status of the problem.

~\AppData\Roaming\Python\Python39\site-packages\cvxpy\reductions\solvers\solving_chain.py in _reductions_for_problem_class(problem, candidates, gp, solver_opts)
    130             append += ("\nHowever, the problem does follow DQCP rules. "
    131                        "Consider calling solve() with `qcp=True`.")
--> 132         raise DCPError(
    133             "Problem does not follow DCP rules. Specifically:\n" + append)
    134     elif gp and not problem.is_dgp():

DCPError: Problem does not follow DCP rules. Specifically:
The objective is not DCP. Its following subexpressions are not:
power(power(reshape(var117, (81, 81), F)[1:81, 0:81] + -reshape(var117, (81, 81), F)[0:80, 0:81], 2.0) + power(reshape(var117, (81, 81), F)[0:81, 1:81] + -reshape(var117, (81, 81), F)[0:81, 0:80], 2.0).T, 0.5)

You may ask about the way that I have obtained TV. I have to say that my variable vector in convex problem is reflectivity of an image which its rows' pixels are stacked together to create a vector.

How can I solve this problem?

Any help would be appreciated.


Solution

  • Don't bother yourself! needless to define new commands for implementation of 2D total variation. The only thing you need to do, is using function "tv" in "cvxpy" library. Definitely you need to define a variable of desired length and then take "cvxpy.tv" from your variable. After that, in order to use your 2D variable in vector form, you can use command "variable.reshape(total lenght,)".