@@ -72,14 +72,13 @@ class BOPDMDOperator(DMDOperator):
7272 function that will be applied to the computed eigenvalues at each step
7373 of the variable projection routine.
7474 :type eig_constraints: set(str) or function
75- :param mode_prox: Optional proximal operator function to apply to the DMD
76- modes at every iteration of variable projection routine.
77- :type mode_prox: function
75+ :param bag_warning: Number of consecutive non-converged trials of BOP-DMD
76+ at which to produce a warning message for the user. Default is 100.
77+ Use arguments less than or equal to zero for no warning condition.
78+ :type bag_warning: int
7879 :param bag_maxfail: Number of consecutive non-converged trials of BOP-DMD
79- at which to terminate the fit. Set this parameter to infinity for no
80- stopping condition. Set to a non-positive value to simply use the
81- results of the non-converged trials. This is the default behavior.
82- :type bag_maxfail: int or float
80+ at which to terminate the fit. Default is -1, no stopping condition.
81+ :type bag_maxfail: int
8382 :param init_lambda: Initial value used for the regularization parameter in
8483 the Levenberg method. Default is 1.0.
8584 Note: Larger lambda values make the method more like gradient descent.
@@ -129,7 +128,7 @@ def __init__(
129128 trial_size ,
130129 eig_sort ,
131130 eig_constraints ,
132- mode_prox ,
131+ bag_warning ,
133132 bag_maxfail ,
134133 init_lambda = 1.0 ,
135134 maxlam = 52 ,
@@ -149,7 +148,7 @@ def __init__(
149148 self ._trial_size = trial_size
150149 self ._eig_sort = eig_sort
151150 self ._eig_constraints = eig_constraints
152- self ._mode_prox = mode_prox
151+ self ._bag_warning = bag_warning
153152 self ._bag_maxfail = bag_maxfail
154153 self ._varpro_opts = [
155154 init_lambda ,
@@ -504,15 +503,9 @@ def compute_residual(alpha):
504503 which is used as an error indicator.
505504 """
506505 Phi_matrix = Phi (alpha , t )
507-
508- # Update B matrix.
509506 B = np .linalg .lstsq (Phi_matrix , H , rcond = None )[0 ]
510- if self ._mode_prox is not None :
511- B = self ._mode_prox (B )
512-
513507 residual = H - Phi_matrix .dot (B )
514508 error = 0.5 * np .linalg .norm (residual ) ** 2
515-
516509 return B , residual , error
517510
518511 # Define M, IS, and IA.
@@ -766,22 +759,13 @@ def compute_operator(self, H, t):
766759 self ._A = A_0
767760 return b_0
768761
769- # Otherwise, perform BOP-DMD:
762+ # Otherwise, perform BOP-DMD.
770763 verbose = self ._varpro_opts [- 1 ]
771764 if verbose :
772765 num_trial_print = 5
773766 msg = "\n Displaying the results of the next {} trials...\n "
774767 print (msg .format (num_trial_print ))
775768
776- # We'll consider non-converged trials successful if the user didn't
777- # request a positive amount of bagging trials at which to terminate.
778- use_bad_bags = self ._bag_maxfail <= 0.0
779- if verbose :
780- if use_bad_bags :
781- print ("Using all bag trial results...\n " )
782- else :
783- print ("Non-converged trial results will be removed...\n " )
784-
785769 # Initialize storage for values needed for stat computations.
786770 w_sum = np .zeros (w_0 .shape , dtype = "complex" )
787771 e_sum = np .zeros (e_0 .shape , dtype = "complex" )
@@ -807,8 +791,9 @@ def compute_operator(self, H, t):
807791 verbose = num_trial_print > 0
808792 self ._varpro_opts [- 1 ] = verbose
809793
810- # Incorporate trial results into the running average if successful.
811- if converged or use_bad_bags :
794+ # Incorporate results into the running average
795+ # ONLY IF the trial successfully converged.
796+ if converged :
812797 sorted_inds = self ._argsort_eigenvalues (e_i )
813798
814799 # Add to iterative sums.
@@ -825,21 +810,22 @@ def compute_operator(self, H, t):
825810 # and reset the consecutive fails counter.
826811 num_successful_trials += 1
827812 num_consecutive_fails = 0
828-
829- # Trial did not converge, and we are throwing away bad bags.
830813 else :
831814 num_consecutive_fails += 1
832815
833- if not runtime_warning_given and num_consecutive_fails == 100 :
816+ if (
817+ not runtime_warning_given
818+ and num_consecutive_fails == self ._bag_warning
819+ ):
834820 msg = (
835- "100 trials without convergence. "
821+ "{} many trials without convergence. "
836822 "Consider loosening the tol requirements "
837823 "of the variable projection routine."
838824 )
839- print (msg )
825+ print (msg . format ( num_consecutive_fails ) )
840826 runtime_warning_given = True
841827
842- if num_consecutive_fails >= self ._bag_maxfail and not use_bad_bags :
828+ elif num_consecutive_fails == self ._bag_maxfail :
843829 msg = (
844830 "Terminating the bagging routine due to "
845831 "{} many trials without convergence."
@@ -938,14 +924,13 @@ class BOPDMD(DMDBase):
938924 function that will be applied to the computed eigenvalues at each step
939925 of the variable projection routine.
940926 :type eig_constraints: set(str) or function
941- :param mode_prox: Optional proximal operator function to apply to the DMD
942- modes at every iteration of variable projection routine.
943- :type mode_prox: function
927+ :param bag_warning: Number of consecutive non-converged trials of BOP-DMD
928+ at which to produce a warning message for the user. Default is 100.
929+ Use arguments less than or equal to zero for no warning condition.
930+ :type bag_warning: int
944931 :param bag_maxfail: Number of consecutive non-converged trials of BOP-DMD
945- at which to terminate the fit. Set this parameter to infinity for no
946- stopping condition. Set to a non-positive value to simply use the
947- results of the non-converged trials. This is the default behavior.
948- :type bag_maxfail: int or float
932+ at which to terminate the fit. Default is -1, no stopping condition.
933+ :type bag_maxfail: int
949934 :param varpro_opts_dict: Dictionary containing the desired parameter values
950935 for variable projection. The following parameters may be specified:
951936 `init_lambda`, `maxlam`, `lamup`, `use_levmarq`, `maxiter`, `tol`,
@@ -967,8 +952,8 @@ def __init__(
967952 trial_size = 0.6 ,
968953 eig_sort = "auto" ,
969954 eig_constraints = None ,
970- mode_prox = None ,
971- bag_maxfail = 0 ,
955+ bag_warning = 100 ,
956+ bag_maxfail = - 1 ,
972957 varpro_opts_dict = None ,
973958 ):
974959 self ._svd_rank = svd_rank
@@ -980,6 +965,16 @@ def __init__(
980965 self ._trial_size = trial_size
981966 self ._eig_sort = eig_sort
982967
968+ if not isinstance (bag_warning , int ) or not isinstance (bag_maxfail , int ):
969+ msg = (
970+ "bag_warning and bag_maxfail must be integers. "
971+ "Please use a non-positive integer if no warning "
972+ "or stopping condition is desired."
973+ )
974+ raise TypeError (msg )
975+ self ._bag_warning = bag_warning
976+ self ._bag_maxfail = bag_maxfail
977+
983978 if varpro_opts_dict is None :
984979 self ._varpro_opts_dict = {}
985980 elif not isinstance (varpro_opts_dict , dict ):
@@ -995,8 +990,6 @@ def __init__(
995990 raise TypeError ("eig_constraints must be a set or a function." )
996991 self ._check_eig_constraints (eig_constraints )
997992 self ._eig_constraints = eig_constraints
998- self ._mode_prox = mode_prox
999- self ._bag_maxfail = bag_maxfail
1000993
1001994 self ._snapshots_holder = None
1002995 self ._time = None
@@ -1349,7 +1342,7 @@ def fit(self, X, t):
13491342 self ._trial_size ,
13501343 self ._eig_sort ,
13511344 self ._eig_constraints ,
1352- self ._mode_prox ,
1345+ self ._bag_warning ,
13531346 self ._bag_maxfail ,
13541347 ** self ._varpro_opts_dict ,
13551348 )
0 commit comments