def test_multivariate(self): # Real case a = tools.companion_matrix([1, -0.4, 0.5]) q = np.diag([10., 5.]) actual = tools.solve_discrete_lyapunov(a, q) desired = solve_discrete_lyapunov(a, q) assert_allclose(actual, desired) # Complex case (where the Lyapunov equation is taken as a complex # function) a = tools.companion_matrix([1, -0.4+0.1j, 0.5]) q = np.diag([10., 5.]) actual = tools.solve_discrete_lyapunov(a, q, complex_step=False) desired = self.solve_dicrete_lyapunov_direct(a, q, complex_step=False) assert_allclose(actual, desired) # Complex case (where the Lyapunov equation is taken as a real # function) a = tools.companion_matrix([1, -0.4+0.1j, 0.5]) q = np.diag([10., 5.]) actual = tools.solve_discrete_lyapunov(a, q, complex_step=True) desired = self.solve_dicrete_lyapunov_direct(a, q, complex_step=True) assert_allclose(actual, desired)
def test_multivariate(self): # Real case a = tools.companion_matrix([1, -0.4, 0.5]) q = np.diag([10., 5.]) actual = tools.solve_discrete_lyapunov(a, q) desired = solve_discrete_lyapunov(a, q) assert_allclose(actual, desired) # Complex case (where the Lyapunov equation is taken as a complex # function) a = tools.companion_matrix([1, -0.4 + 0.1j, 0.5]) q = np.diag([10., 5.]) actual = tools.solve_discrete_lyapunov(a, q, complex_step=False) desired = self.solve_dicrete_lyapunov_direct(a, q, complex_step=False) assert_allclose(actual, desired) # Complex case (where the Lyapunov equation is taken as a real # function) a = tools.companion_matrix([1, -0.4 + 0.1j, 0.5]) q = np.diag([10., 5.]) actual = tools.solve_discrete_lyapunov(a, q, complex_step=True) desired = self.solve_dicrete_lyapunov_direct(a, q, complex_step=True) assert_allclose(actual, desired)
def test_cases(self): # Test against known results for unconstrained, error_variance, constrained in self.cases: result = tools.constrain_stationary_multivariate( unconstrained, error_variance) assert_allclose(result[0], constrained) # Test that the constrained results correspond to companion matrices # with eigenvalues less than 1 in modulus for unconstrained in self.eigval_cases: if type(unconstrained) == list: cov = np.eye(unconstrained[0].shape[0]) else: cov = np.eye(unconstrained.shape[0]) constrained, _ = tools.constrain_stationary_multivariate(unconstrained, cov) companion = tools.companion_matrix( [1] + [-constrained[i] for i in range(len(constrained))] ).T assert_equal(np.max(np.abs(np.linalg.eigvals(companion))) < 1, True)
def test_cases(self): for polynomial, result in self.cases: assert_equal(tools.companion_matrix(polynomial), result)
def setup(self): """Setup the structural time series representation.""" # Initialize the ordered sets of parameters # self.parameters = {} # self.parameters_obs_intercept = {} # self.parameters_obs_cov = {} # self.parameters_transition = {} # self.parameters_state_cov = {} # Initialize the fixed components of the state space matrices, i = 0 # state offset j = 0 # state covariance offset # if self.irregular: # self.parameters_obs_cov['irregular_var'] = 1 if self.level: self.design[0, i] = 1.0 self.transition[i, i] = 1.0 if self.trend: self.transition[i, i + 1] = 1.0 if self.stochastic_level: # self.ssm['selection', i, j] = 1. # self.parameters_state_cov['level_var'] = 1 j += 1 i += 1 if self.trend: self.transition[i, i] = 1.0 if self.stochastic_trend: # self.ssm['selection', i, j] = 1. # self.parameters_state_cov['trend_var'] = 1 j += 1 i += 1 if self.seasonal: n = self.seasonal_periods - 1 self.design[0, i] = 1.0 self.transition[i : i + n, i : i + n] = companion_matrix( np.r_[1, [1] * n] ).transpose() if self.stochastic_seasonal: # self.ssm['selection', i, j] = 1. # self.parameters_state_cov['seasonal_var'] = 1 j += 1 i += n if self.freq_seasonal: for ix, h in enumerate(self.freq_seasonal_harmonics): # These are the \gamma_jt and \gamma^*_jt terms in D&K (3.8) n = 2 * h p = self.freq_seasonal_periods[ix] lambda_p = 2 * np.pi / float(p) t = 0 # frequency transition matrix offset for block in range(1, h + 1): # ibid. eqn (3.7) self.design[0, i + t] = 1.0 # ibid. eqn (3.8) cos_lambda_block = np.cos(lambda_p * block) sin_lambda_block = np.sin(lambda_p * block) trans = np.array( [ [cos_lambda_block, sin_lambda_block], [-sin_lambda_block, cos_lambda_block], ] ) trans_s = np.s_[i + t : i + t + 2] self.transition[trans_s, trans_s] = trans t += 2 # freq_seasonal is always stochastic j += n i += n # exog regression if self.regression: # add exog to the design matrix (3d matrices are a special case in our KF) if self.exog.ndim == 2: self.design = np.repeat( self.design[np.newaxis, :, :], self.nobs, axis=0 ) self.design[:, 0, i : i + self.k_exog] = self.exog elif self.exog.ndim == 3: self.design = np.repeat( self.design[np.newaxis, :, :], self.nobs, axis=0 ) self.design = np.repeat( self.design[np.newaxis, :, :], self.k_series, axis=0 ) self.design[:, :, 0, i : i + self.k_exog] = self.exog else: raise self.transition[i : i + self.k_exog, i : i + self.k_exog] = np.eye( self.k_exog ) i += self.k_exog