

import numpy as np #for all numerical computations
import pandas as pd #similar to dataframe in R
import scipy as sp #scientific computations (includes stats)
import matplotlib.pyplot as plt #plotting 
import scipy.io as sio
import cvxpy as cp # convex optimization
import random
import sys
import time
import gc
import math

from sklearn.preprocessing import normalize
from scipy.sparse import lil_matrix

m=2**7
n=2**(12)
theta=0.27*np.pi
G_n=lil_matrix(np.identity(n))
i=2*np.array(range(int(n/4)))+int(n/2)-1
j=i+1
for k in range(int(n/4)):
    G=lil_matrix(np.identity(n))
    G[i[k],i[k]]=np.cos(theta)
    G[i[k],j[k]]=-np.sin(theta)
    G[j[k],i[k]]=np.sin(theta)
    G[j[k],j[k]]=np.cos(theta)
    G_n=G_n @ G

###-----------------####
### Construct Sigma ####
###-----------------####
a=np.identity(m)
for k in range(m):
    a[k,k]= math.exp(-k)

b=np.zeros((m,n-m))
SIG=lil_matrix(np.column_stack((a,b)))
SIG[0,0]=100

###-------------------####
### Construct U,V_til ####
###-------------------####
U = normalize(sp.linalg.hadamard(m), axis=0, norm='l2')
V_til=normalize(sp.linalg.hadamard(n), axis=0, norm='l2')
V=G_n @ V_til

####----------------####
####--Construct Z---####
####----------------####
Z=U@SIG @ V.T+np.random.normal(0, 10**(-3), size=(m, n))
Z