Raw File
gen_SDPA_upper.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Oct  8 17:25:15 2020

@author: pemeriau


In this file, we create a SDP and output it as a text file with
extension dat-s to it is readable by SDPA-GMP.
"""

# Import useful libraries. 
import picos as pc
from math import factorial, sqrt
import numpy as np
from scipy.special import binom
import os


def get_Qi(Q,i,const_ij,m):
    """
    Aim: 
    ----    
     Equalising two polynomials where one is obtained by a SOS 
     decomposition in the canonical basis and the other one is expressed
     in the Laguerre basis.
     
    Parameters
    ----------
     Q : matrix for the SOS decomposition
     i : integer
         degree at which we compte the coefficients.     
     const_ij : list
                contains indices of Q at which coefficients i+j= const.

    Returns
    -------
     Real that is a sum of coefficients
     """
    return sum(factorial(l)*binom(l,i)*\
               sum(Q[j]/sqrt(factorial(j[0])*factorial(j[1])) \
                   for j in const_ij[2*l]) for l in np.arange(i,m+1))


def write_SDPA_pb_upper(m,a,filename):
    """
    Aim
    ---
    Producing a text file for the SDP problem of computing an upper bound at 
    rank m in the hierarchy associated to the witness sum_k a_k |k><k|

    Parameters
    ----------
    m : integer
        rank in the hierarchy of SDP.
    a : list
        description of the witness.

    Returns
    -------
    Nothing
    But create a text file in the format ".dat-s" that can be later read by SDPA-GMP

    """          
    
    # Create list of indices (i,j) for which i+j= const 
    const_ij = [None]*(2*m+1)
    for i in range(m+1):
        for j in range(m+1):
            if const_ij[i+j] == None:
                const_ij[i+j] = []
            const_ij[i+j].append((i,j))

    # Create a picos problem
    D = pc.Problem()

    # Variables
    y = pc.RealVariable("y",1)
    mu = pc.RealVariable("mu",m+1)
    Q = pc.SymmetricVariable("Q",(m+1,m+1))
       
    # Objective
    D.set_objective("min",y)
    
    # Constraints
    for i in range(m+1):
        if i < len(a):
            D.add_constraint(y >= a[i]+mu[i])
            #D.add_constraint(mu[i] >= -1)
        else:
            D.add_constraint(y >= mu[i])
            #D.add_constraint(mu[i] >= -1)
        
    
    for i in range(m+1):
        D.add_constraint(get_Qi(Q,i,const_ij,m) == mu[i])
    
    D.add_constraint(Q >> 0)
    print(D)
    
    D.write_to_file(filename)
    

    
    
if __name__ == "__main__":
    # Location of the solver SDPA-GMP
    path_to_sdpa = '/home/pemeriau/Softwares/sdpa/sdpa-gmp-7.1.3/'
    
    if not os.path.isfile('param.sdpa'):
        os.system('cp '+path_to_sdpa+"param.sdpa"+" .")
    
    # Parameters
    t = 4 # rescaling coefficients. Won't affect the objective but might play an 
          # imporant role for the stability

    a = [1]  # vector defining the witness sum_k a_k |k><k| for which
                 # we will compute an upper bound an the threshold value.
                 # Careful, contrary to the conventionns of the main text, 
                 # vector a is written from Fock state 0 to Fock state len(a).
                 # Note that the level of the hierarchy should be higher than len(a).
                 # 
                 # Forall k, 0 <= a_k <= 1
                 # Normlisation: max_k a_k = 1
    
    m = 2 # rank in the hierarchy
    
    filename = "upper"
    for j in range(len(a)):
        filename += str(a[j])+"_"
    filename += "r"+str(m)+".dat-s"
    
    write_SDPA_pb_upper(m,a,filename)
    
    os.system(path_to_sdpa+"sdpa_gmp "+filename+" "+filename[0:-6]+".out")
    
back to top