def get_sum_D(p, m, Fs, Ys, i): """Calculates each individual D sum. Args: p (:obj:`Parameters`): parameters for the algorithm; for details on each parameter, see the :obj:`Parameters` class. m (:obj:`MJLS`): the corresponding Markov Jump Linear System. Fs: current approximation of the control gains. Ys: current approximation of the CARE solution. i: starting mode, i.e., the mode for the first time step in the current simulation. """ sum_D = np.zeros_like(Ys[0]) Upsilon = np.eye(m.n) theta = i for k in range(0, p.K + 1): next_theta = get_next_theta(theta, m.P) incr = pow(p.lambda_, k) * get_D(m, Fs, Ys, Upsilon, theta, next_theta) sum_D += incr if abs(incr).max() < p.epsilon: return sum_D Upsilon = get_Upsilon(m, Fs, Upsilon, theta) theta = next_theta return sum_D
def test_get_next_theta_works_for_one_dimension(self): P = np.array([[1.]]) theta = 0 changed = False for _ in range(1024): if sam_run_episode.get_next_theta(theta, P) != 0: changed = True break self.assertFalse(changed)
def test_get_next_theta_works_for_eye_two(self): P = np.eye(2) for theta in range(2): changed = False for _ in range(1024): if sam_run_episode.get_next_theta(theta, P) != theta: changed = True break if changed: break self.assertFalse(changed)
def test_get_next_theta_works_for_uniform_three(self): N = 3 P = (1. / N) * np.ones((N, N)) num_samples = 10240 P_sample = np.zeros_like(P) for theta in range(N): for _ in range(num_samples): next_theta = sam_run_episode.get_next_theta(theta, P) P_sample[theta, next_theta] += 1 theta = next_theta P_sample /= num_samples npt.assert_array_almost_equal(P, P_sample, decimal=2)
def get_Y(p, m, Fs, Ys, Ys_hist): """Calculates Y. Args: p (:obj:`Parameters`): parameters for the algorithm; for details on each parameter, see the :obj:`Parameters` class. m (:obj:`MJLS`): the corresponding Markov Jump Linear System. Fs: current approximation of the control gains. Ys: current approximation of the CARE solution. Ys_hist: the `Ys' history (i.e., a sequence with the `Ys' calculated so far.) """ gamma = 1.0 # TODO: do we really want it constant? lambda_ = 0.1 # TODO: do we really want it constant? for t in range(1, p.T + 1): Upsilon = np.eye(m.n) # TODO: parametrize theta = np.random.randint(0, m.N) e = np.zeros(m.N) for k in range(1, p.K): alpha = 0.1 / k next_theta = get_next_theta(theta, m.P) delta = get_delta(m, Fs, Ys, Upsilon, gamma, theta, next_theta) if e[theta] == 0: e[theta] = 1 for i in range(m.N): Ys[i] += alpha * e[i] * delta e[i] *= gamma * lambda_ Upsilon = get_Upsilon(m, Fs, Upsilon, theta) theta = next_theta Ys_hist.append(Ys.copy()) try: Fs_new = get_F(m, Fs.copy(), Ys.copy()) except Exception: Fs_new = Fs Fs = Fs_new return (Ys, Ys_hist)
return riccati(**args) for r in range(ap.R): print('r: {:4d}'.format(r)) np.random.seed(r) P_count = np.zeros((ac.N, ac.N)) Fs_H, P_tilde_H = [], [] for l in range(ap.L): print('l: {:4d}'.format(l)) for t in range(ap.T): print('t: {:4d}'.format(t)) theta = get_initial_state(ac.N) for _ in range(ap.K - 1): next_theta = get_next_theta(theta, ac.P) P_count[theta, next_theta] += 1 theta = next_theta print('Normalizing (and flattening)...') P_tilde = normalize_flatten(P_count) print('Calculating F...') [Fs, _] = get_FX(P_tilde, ap.T * (ap.K - 1)) print('Appending F and P to their histories...') Fs_H.append(Fs) P_tilde_H.append(P_tilde) saverep(Fs_H, 'Fs_mjlsmle_H', r) saverep(P_tilde_H, 'P_tilde_mjlsmle_H', r)