11import numpy as np
2+ import pysensors
23
34from pysensors .optimizers ._qr import QR
45
89from mpl_toolkits .axes_grid1 import make_axes_locatable
910
1011import pysensors as ps
12+ from matplotlib .patches import Circle
13+ from pydmd import DMD
1114
1215
1316class GQR (QR ):
@@ -27,7 +30,7 @@ class GQR(QR):
2730
2831 @ authors: Niharika Karnik (@nkarnik2999), Mohammad Abdo (@Jimmy-INL), and Krithika Manohar (@kmanohar)
2932 """
30- def __init__ (self ,idx_constrained ,n_sensors ,n_const_sensors ,all_sensors ,constraint_option ):
33+ def __init__ (self ,idx_constrained ,n_sensors ,n_const_sensors ,all_sensors ,constraint_option , nx , ny , r ):
3134 """
3235 Attributes
3336 ----------
@@ -47,11 +50,15 @@ def __init__(self,idx_constrained,n_sensors,n_const_sensors,all_sensors,constrai
4750 """
4851 self .pivots_ = None
4952 self .optimality = None
53+
5054 self .constrainedIndices = idx_constrained
5155 self .nSensors = n_sensors
5256 self .nConstrainedSensors = n_const_sensors
5357 self .all_sensorloc = all_sensors
5458 self .constraint_option = constraint_option
59+ self ._nx = nx
60+ self ._ny = ny
61+ self ._r = r
5562
5663 def fit (
5764 self ,
@@ -75,11 +82,11 @@ def fit(
7582 max_const_sensors = len (self .constrainedIndices ) #Maximum number of sensors allowed in the constrained region
7683
7784 ## Assertions and checks:
78- if self .nSensors > n_features - max_const_sensors + self .nConstrainedSensors :
79- raise IOError ("n_sensors cannot be larger than n_features - all possible locations in the constrained area + allowed constrained sensors" )
80- if self .nSensors > n_samples + self .nConstrainedSensors : ## Handling zero constraint?
81- raise IOError ("Currently n_sensors should be less than min(number of samples, number of modes) + number of constrained sensors,\
82- got: n_sensors = {}, n_samples + const_sensors = {} + {} = {}" .format (self .nSensors ,n_samples ,self .nConstrainedSensors ,n_samples + self .nConstrainedSensors ))
85+ # if self.nSensors > n_features - max_const_sensors + self.nConstrainedSensors:
86+ # raise IOError ("n_sensors cannot be larger than n_features - all possible locations in the constrained area + allowed constrained sensors")
87+ # if self.nSensors > n_samples + self.nConstrainedSensors: ## Handling zero constraint?
88+ # raise IOError ("Currently n_sensors should be less than min(number of samples, number of modes) + number of constrained sensors,\
89+ # got: n_sensors = {}, n_samples + const_sensors = {} + {} = {}".format(self.nSensors,n_samples,self.nConstrainedSensors,n_samples+self.nConstrainedSensors))
8390
8491 # Initialize helper variables
8592 R = basis_matrix .conj ().T .copy ()
@@ -92,14 +99,34 @@ def fit(
9299 # Norm of each column
93100 dlens = np .sqrt (np .sum (np .abs (r ) ** 2 , axis = 0 ))
94101 if self .constraint_option == "max_n_const_sensors" :
95- dlens_updated = norm_calc_max_n_const_sensors (self .constrainedIndices ,dlens ,p ,j , self .nConstrainedSensors ,self .all_sensorloc ,self .nSensors )
102+ dlens_updated = ps .utils ._norm_calc .norm_calc_max_n_const_sensors (self .constrainedIndices ,dlens ,p ,j , self .nConstrainedSensors ,self .all_sensorloc ,self .nSensors )
103+ i_piv = np .argmax (dlens_updated )
104+ dlen = dlens_updated [i_piv ]
96105 elif self .constraint_option == "exact_n_const_sensors" :
97- dlens_updated = norm_calc_exact_n_const_sensors (self .constrainedIndices ,dlens ,p ,j ,self .nConstrainedSensors )
98-
106+ dlens_updated = ps .utils ._norm_calc .norm_calc_exact_n_const_sensors (self .constrainedIndices ,dlens ,p ,j ,self .nConstrainedSensors )
107+ i_piv = np .argmax (dlens_updated )
108+ dlen = dlens_updated [i_piv ]
109+ elif self .constraint_option == "predetermined_end" :
110+ dlens_updated = ps .utils ._norm_calc .predetermined_norm_calc (self .constrainedIndices , dlens , p , j , self .nConstrainedSensors , self .nSensors )
111+ i_piv = np .argmax (dlens_updated )
112+ dlen = dlens_updated [i_piv ]
113+ elif self .constraint_option == "radii_constraints" :
114+
115+ if j == 0 :
116+ i_piv = np .argmax (dlens )
117+ dlen = dlens [i_piv ]
118+ dlens_old = dlens
119+ else :
120+
121+ dlens_updated = ps .utils ._norm_calc .f_radii_constraint (j ,dlens ,dlens_old ,p ,self ._nx ,self ._ny ,self ._r ,self .all_sensorloc , self .nSensors ) #( self.radius,self._nx,self._ny,self.all_sensorloc,dlens,p,j)
122+ i_piv = np .argmax (dlens_updated )
123+ dlen = dlens_updated [i_piv ]
124+ dlens_old = dlens_updated
125+
99126 # Choose pivot
100- i_piv = np .argmax (dlens_updated )
127+ # i_piv = np.argmax(dlens_updated)
101128
102- dlen = dlens_updated [i_piv ]
129+ # dlen = dlens_updated[i_piv]
103130
104131 if dlen > 0 :
105132 u = r [:, i_piv ] / dlen
@@ -121,108 +148,30 @@ def fit(
121148 R [j + 1 :, j ] = 0
122149
123150 self .pivots_ = p
124- self .optimality = np .trace (np .real (R ))
125- print ("The trace(R) = {}" .format (self .optimality ))
126-
151+
127152 return self
128153
129- ## TODO: why not a part of the class?
130-
131- #function for mapping sensor locations with constraints
132- def norm_calc_exact_n_const_sensors (lin_idx , dlens , piv , j , n_const_sensors ): ##Will first force sensors into constrained region
133- #num_sensors should be fixed for each custom constraint (for now)
134- #num_sensors must be <= size of constraint region
135- """
136- Function for mapping constrained sensor locations with the QR procedure.
137-
138- Parameters
139- ----------
140- lin_idx: np.ndarray, shape [No. of constrained locations]
141- Array which contains the constrained locationsof the grid in terms of column indices of basis_matrix.
142- dlens: np.ndarray, shape [Variable based on j]
143- Array which contains the norm of columns of basis matrix.
144- piv: np.ndarray, shape [n_features]
145- Ranked list of sensor locations.
146- n_const_sensors: int,
147- Number of sensors to be placed in the constrained area.
148- j: int,
149- Iterative variable in the QR algorithm.
150-
151- Returns
152- -------
153- dlens : np.darray, shape [Variable based on j] with constraints mapped into it.
154- """
155- if j < n_const_sensors : # force sensors into constraint region
156- #idx = np.arange(dlens.shape[0])
157- #dlens[np.delete(idx, lin_idx)] = 0
158-
159- didx = np .isin (piv [j :],lin_idx ,invert = True )
160- dlens [didx ] = 0
161- else :
162- didx = np .isin (piv [j :],lin_idx ,invert = False )
163- dlens [didx ] = 0
164- return dlens
165-
166- def norm_calc_max_n_const_sensors (lin_idx , dlens , piv , j , const_sensors ,all_sensors ,n_sensors ): ##Optimal sensor placement with constraints (will place sensors in the order of QR)
167- """
168- Function for mapping constrained sensor locations with the QR procedure (Optimally).
169-
170- Parameters
171- ----------
172- lin_idx: np.ndarray, shape [No. of constrained locations]
173- Array which contains the constrained locationsof the grid in terms of column indices of basis_matrix.
174- dlens: np.ndarray, shape [Variable based on j]
175- Array which contains the norm of columns of basis matrix.
176- piv: np.ndarray, shape [n_features]
177- Ranked list of sensor locations.
178- j: int,
179- Iterative variable in the QR algorithm.
180- const_sensors: int,
181- Number of sensors to be placed in the constrained area.
182- all_sensors: np.ndarray, shape [n_features]
183- Ranked list of sensor locations.
184- n_sensors: integer,
185- Total number of sensors
186-
187- Returns
188- -------
189- dlens : np.darray, shape [Variable based on j] with constraints mapped into it.
190- """
191- counter = 0
192- mask = np .isin (all_sensors ,lin_idx ,invert = False )
193- const_idx = all_sensors [mask ]
194- updated_lin_idx = const_idx [const_sensors :]
195- for i in range (n_sensors ):
196- if np .isin (all_sensors [i ],lin_idx ,invert = False ):
197- counter += 1
198- if counter < const_sensors :
199- dlens = dlens
200- else :
201- didx = np .isin (piv [j :],updated_lin_idx ,invert = False )
202- dlens [didx ] = 0
203- return dlens
204-
205-
206-
207154if __name__ == '__main__' :
208155 faces = datasets .fetch_olivetti_faces (shuffle = True )
209156 X = faces .data
210157
211- n_samples , n_features = X .shape
158+ # n_samples, n_features = X.shape
159+ X_small = X [:,:256 ]
160+ n_samples , n_features = X_small .shape
212161 print ('Number of samples:' , n_samples )
213162 print ('Number of features (sensors):' , n_features )
214163
215164 # Global centering
216- X = X - X .mean (axis = 0 )
165+ X_small = X_small - X_small .mean (axis = 0 )
217166
218167 # Local centering
219- X -= X .mean (axis = 1 ).reshape (n_samples , - 1 )
168+ X_small -= X_small .mean (axis = 1 ).reshape (n_samples , - 1 )
220169
221170 n_row , n_col = 2 , 3
222171 n_components = n_row * n_col
223- image_shape = (64 , 64 )
224- nx = 64
225- ny = 64
172+ image_shape = (16 , 16 )
173+ nx = 16
174+ ny = 16
226175
227176 def plot_gallery (title , images , n_col = n_col , n_row = n_row , cmap = plt .cm .gray ):
228177 '''Function for plotting faces'''
@@ -241,25 +190,44 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
241190 # plot_gallery("First few centered faces", X[:n_components])
242191
243192 #Find all sensor locations using built in QR optimizer
244- max_const_sensors = 230
245- n_const_sensors = 2
246- n_sensors = 200
193+ #max_const_sensors = 230
194+ n_const_sensors = 3
195+ n_sensors = 4
196+ n_modes = 40
197+ r = 2
198+ # dmd = DMD(svd_rank=0,exact=True,opt=False)
199+ # dmd.fit(X.T)
200+ # U = dmd.modes.real
201+ # np.shape(U)
202+ # max_basis_modes = 200
203+
204+ # model_dmd_unconstrained = ps.SSPOR(n_sensors=n_sensors, basis=ps.basis.Custom(n_basis_modes=n_modes, U=U))
205+ # model_dmd_unconstrained.fit(X)
206+ # basis_matrix_dmd = model_dmd_unconstrained.basis_matrix_
207+
208+ # all_sensors_dmd_unconstrained = model_dmd_unconstrained.get_all_sensors()
209+ # top_sensors_dmd_unconstrained = model_dmd_unconstrained.get_selected_sensors()
210+ # optimality_dmd = ps.utils._validation.determinant(top_sensors_dmd_unconstrained, n_features, basis_matrix_dmd)
211+ # print(optimality0)
212+ #basis = ps.basis.SVD(n_basis_modes=n_modes)
247213 optimizer = ps .optimizers .QR ()
248214 model = ps .SSPOR (optimizer = optimizer , n_sensors = n_sensors )
249- model .fit (X )
250-
215+ model .fit (X_small )
216+ top_sensors0 = model . get_selected_sensors ()
251217 all_sensors = model .get_all_sensors ()
252-
218+ # basis_matrix0 = model.basis_matrix_
219+ # optimality0 = ps.utils._validation.determinant(top_sensors0, n_features, basis_matrix0)
220+ # print(optimality0)
253221 ##Constrained sensor location on the grid:
254- xmin = 20
255- xmax = 40
256- ymin = 25
257- ymax = 45
222+ xmin = 0
223+ xmax = 64
224+ ymin = 10
225+ ymax = 30
258226 sensors_constrained = ps .utils ._constraints .get_constraind_sensors_indices (xmin ,xmax ,ymin ,ymax ,nx ,ny ,all_sensors ) #Constrained column indices
259-
260227 # didx = np.isin(all_sensors,sensors_constrained,invert=False)
261228 # const_index = np.nonzero(didx)
262229 # j =
230+
263231
264232
265233 ##Plotting the constrained region
@@ -276,24 +244,51 @@ def plot_gallery(title, images, n_col=n_col, n_row=n_row, cmap=plt.cm.gray):
276244 # plt.title('Constrained region');
277245
278246 ## Fit the dataset with the optimizer GQR
279- optimizer1 = GQR (sensors_constrained ,n_sensors ,n_const_sensors ,all_sensors , constraint_option = "exact_n_const_sensors" )
280- model1 = ps .SSPOR (optimizer = optimizer1 , n_sensors = n_sensors )
281- model1 .fit (X )
247+ optimizer1 = GQR (sensors_constrained ,n_sensors ,n_const_sensors ,all_sensors , constraint_option = "radii_constraints" , nx = nx , ny = ny , r = r )
248+ model1 = ps .SSPOR ( optimizer = optimizer1 , n_sensors = n_sensors )
249+ model1 .fit (X_small )
282250 all_sensors1 = model1 .get_all_sensors ()
283-
251+ basis_matrix = model1 . basis_matrix_
284252 top_sensors = model1 .get_selected_sensors ()
285253 print (top_sensors )
254+ # optimality = ps.utils._validation.determinant(top_sensors, n_features, basis_matrix)
255+ # print(optimality)
256+ # optimizer_dmd_constrained = ps.optimizers.GQR(sensors_constrained,n_sensors,n_const_sensors,all_sensors_dmd_unconstrained,constraint_option = "exact_n_const_sensors",nx = nx, ny = ny, r = r)
257+ # model_dmd_constrained = ps.SSPOR(n_sensors=n_sensors, basis=ps.basis.Custom(n_basis_modes=n_modes, U=U), optimizer = optimizer_dmd_constrained)
258+ # model_dmd_constrained.fit(X)
259+ # all_sensors_dmd_constrained = model_dmd_constrained.get_all_sensors()
260+
261+ # top_sensors_dmd_constrained = model_dmd_constrained.get_selected_sensors()
262+ # basis_matrix_dmd_constrained = model_dmd_constrained.basis_matrix_
263+ # optimality = ps.utils._validation.determinant(top_sensors_dmd_constrained, n_features, basis_matrix_dmd_constrained)
264+ # print(optimality)
265+
286266 ## TODO: this can be done using ravel and unravel more elegantly
287267 #yConstrained = np.floor(top_sensors[:n_const_sensors]/np.sqrt(n_features))
288268 #xConstrained = np.mod(top_sensors[:n_const_sensors],np.sqrt(n_features))
289269
270+ # img = np.zeros(n_features)
271+ # img[top_sensors_dmd_constrained] = 16
272+ # #plt.plot(xConstrained,yConstrained,'*r')
273+ # plt.plot([xmin,xmin],[ymin,ymax],'r')
274+ # plt.plot([xmin,xmax],[ymax,ymax],'r')
275+ # plt.plot([xmax,xmax],[ymin,ymax],'r')
276+ # plt.plot([xmin,xmax],[ymin,ymin],'r')
277+ # plt.imshow(img.reshape(image_shape),cmap=plt.cm.binary)
278+ # plt.title('n_sensors = {}, n_constr_sensors = {}'.format(n_sensors,n_const_sensors))
279+ # plt.show()
280+
290281 img = np .zeros (n_features )
291282 img [top_sensors ] = 16
292- #plt.plot(xConstrained,yConstrained,'*r')
293- plt .plot ([xmin ,xmin ],[ymin ,ymax ],'r' )
294- plt .plot ([xmin ,xmax ],[ymax ,ymax ],'r' )
295- plt .plot ([xmax ,xmax ],[ymin ,ymax ],'r' )
296- plt .plot ([xmin ,xmax ],[ymin ,ymin ],'r' )
297- plt .imshow (img .reshape (image_shape ),cmap = plt .cm .binary )
298- plt .title ('n_sensors = {}, n_constr_sensors = {}' .format (n_sensors ,n_const_sensors ))
283+ fig ,ax = plt .subplots (1 )
284+ ax .set_aspect ('equal' )
285+ ax .imshow (img .reshape (image_shape ),cmap = plt .cm .binary )
286+ print (top_sensors )
287+ top_sensors_grid = np .unravel_index (top_sensors , (nx ,ny ))
288+ # figure, axes = plt.subplots()
289+ for i in range (len (top_sensors_grid [0 ])):
290+ circ = Circle ( (top_sensors_grid [1 ][i ], top_sensors_grid [0 ][i ]), r ,color = 'r' ,fill = False )
291+ ax .add_patch (circ )
299292 plt .show ()
293+
294+
0 commit comments