def get_test_statistic(model, x0_I, x0_II, u_I, u_II, num_exp=1000, nu=1): sys_dim = len(model[0][:, 0]) data_I = simulate_system(model, x0_I, u_I, num_exp=num_exp) data_II = simulate_system(model, x0_II, u_II, num_exp=num_exp) mmd_st = np.zeros((sys_dim, num_exp)) mmd = np.zeros(sys_dim) for test_infl_on in range(sys_dim): for i in range(num_exp): mmd_st[test_infl_on, i] = mmd2(data_I[sys_dim * i + test_infl_on, 1::], data_II[sys_dim * i + test_infl_on, 1::]) mmd[test_infl_on] = mmd_st[test_infl_on, 0] + nu * np.std(mmd_st[test_infl_on, 1::]) return mmd
def real_mmd(sys, test_infl_of, test_infl_on, init_cond1, inp_traj1, init_cond2=0, inp_traj2=0, num_exp=1): sys1 = sys sys2 = copy.deepcopy(sys) for _ in range(num_exp): sys1.state = init_cond1.reshape(-1, 1) try: sys2.state = init_cond2.reshape(-1, 1) except: sys2.state = copy.deepcopy(sys1.state) init_cond2 = init_cond1 try: len(inp_traj2) except: inp_traj2 = inp_traj1 x_st = np.zeros((len(sys1.state), inp_traj1.shape[1] + 1)) y_st = np.zeros((len(sys1.state), inp_traj1.shape[1] + 1)) x_st[:, 0] = init_cond1[:] y_st[:, 0] = init_cond2[:] for i in range(inp_traj1.shape[1]): X = np.vstack((sys1.state, inp_traj1[:, i].reshape(-1, 1))) Y = np.vstack((sys2.state, inp_traj2[:, i].reshape(-1, 1))) sys1.dynamics(inp_traj1[:, i]) sys2.dynamics(inp_traj2[:, i]) x_st[:, i + 1] = sys1.state[:, 0] y_st[:, i + 1] = sys2.state[:, 0] try: x_mult = np.hstack((x_mult, x_st)) y_mult = np.hstack((y_mult, y_st)) except: x_mult = copy.deepcopy(x_st) y_mult = copy.deepcopy(y_st) mmd = np.zeros(len(test_infl_on)) for idx, i in enumerate(test_infl_on): if i == test_infl_of: x_mult[i, :] -= init_cond1[i] y_mult[i, :] -= init_cond2[i] mmd[idx] = mmd2(x_mult[i, :], y_mult[i, :]) return mmd, x_st, y_st
def caus_id(): sys = synthetic_example() sys_dim = len(sys.high_obs) inp_dim = sys.inp_dim # Null hypothesis: no state/input has a causal influence on any state caus = np.zeros((sys_dim, sys_dim + inp_dim)) # Start with standard system identification sys_id_state, sys_id_inp = create_sys_id_data(sys) init_model = sys_id(sys_id_state, sys_id_inp) # Get a controller based on the initial model ctrl = set_point_ctrl(init_model[0], init_model[1], np.diag([1, 1, 1]), np.diag([0.01, 0.01, 0.01])) # Start causal identification for test_infl_of in range(sys_dim + inp_dim): print("new causality test") if test_infl_of < sys_dim: print("testing influence of state ", test_infl_of) # Choose initial conditions as far apart as possible x0_I = np.zeros((sys_dim, 1)) x0_I[test_infl_of, 0] = sys.high_obs[test_infl_of] x0_II = np.zeros((sys_dim, 1)) x0_II[test_infl_of, 0] = -sys.high_obs[test_infl_of] # Choose input trajectory that excites the system u_I = np.random.uniform(-1, 1, (inp_dim, 100)) u_II = u_I else: test_inp = test_infl_of - sys_dim print("testing influence of input ", test_inp) # Choose initial position in 0 x0_I = np.zeros((sys_dim, 1)) x0_II = x0_I # Choose different input trajectories that excite the system u_I = 10 * np.random.uniform(-1, 1, (inp_dim, 100)) u_II = copy.deepcopy(u_I) u_I[test_inp, :] = 100 * np.random.uniform(-1, 1, 100) u_II[test_inp, :] = np.zeros(100) # Do causality experiment exp_data_I, exp_data_II = caus_exp(init_model, sys, x0_I, x0_II, u_I, u_II, ctrl) # Get model assuming variables are non-causal caus_model = sys_id_loc(sys_id_state, sys_id_inp, test_infl_of) # Get test statistic test_stat = get_test_statistic(caus_model, exp_data_I[:, 0].reshape(-1, 1), exp_data_II[:, 0].reshape(-1, 1), u_I, u_II, nu=3) print("Obtained test statistic") # Compute MMD and compare with test statistic for test_infl_on in range(sys_dim): if test_infl_of == test_infl_on: exp_data_I[test_infl_on, :] -= x0_I[test_infl_on, 0] exp_data_II[test_infl_on, :] -= x0_II[test_infl_on, 0] mmd_exp = mmd2(exp_data_I[test_infl_on, :], exp_data_II[test_infl_on, :]) if mmd_exp > test_stat[test_infl_on]: caus[test_infl_on, test_infl_of] = 1 print("new causality matrix:") print(caus) sys.state = np.zeros((3, 1))
def predict_mmd(GPs, sys, test_infl_of, test_infl_on, init_cond1, inp_traj1, init_cond2=0, inp_traj2=0, mont=0, num_exp=0, num_var=0): sys1 = sys sys2 = copy.deepcopy(sys) sys1.state[:, 0] = init_cond1[:] # Check whether we have separate initial conditions for the two systems try: sys2.state[:, 0] = init_cond2[:] except: sys2.state = copy.deepcopy(sys1.state) init_cond2 = init_cond1 # Check whether we have separate input trajectories try: len(inp_traj2) except: inp_traj2 = inp_traj1 # Create arrays depending on whether or not we want to estimate the variance if num_var: x_st = np.zeros( (num_var * num_exp, len(sys1.state) * inp_traj1.shape[1] + len(sys1.state))) y_st = np.zeros( (num_var * num_exp, len(sys1.state) * inp_traj1.shape[1] + len(sys1.state))) x_st[:, 0:len(sys1.state)] = init_cond1[:] y_st[:, 0:len(sys1.state)] = init_cond2[:] else: x_st = np.zeros( (1, len(sys1.state) * inp_traj1.shape[1] + len(sys1.state))) y_st = np.zeros( (1, len(sys1.state) * inp_traj1.shape[1] + len(sys1.state))) x_st[:, 0:len(sys1.state)] = init_cond1[:] y_st[:, 0:len(sys1.state)] = init_cond2[:] # Simulate system and store results for i in range(inp_traj1.shape[1]): if num_var: X = np.hstack((x_st[:, i * len(sys1.state):i * len(sys1.state) + len(sys1.state)], np.matlib.repmat(inp_traj1[:, i], num_var * num_exp, 1))) Y = np.hstack((y_st[:, i * len(sys1.state):i * len(sys1.state) + len(sys1.state)], np.matlib.repmat(inp_traj2[:, i], num_var * num_exp, 1))) else: X = np.hstack((x_st[:, i * len(sys1.state):i * len(sys1.state) + len(sys1.state)], inp_traj1[:, i].reshape(1, -1))) Y = np.hstack((y_st[:, i * len(sys1.state):i * len(sys1.state) + len(sys1.state)], inp_traj2[:, i].reshape(1, -1))) for idx, GP in enumerate(GPs): X_tmp = np.delete(X, GP.indep_var, 1) Y_tmp = np.delete(Y, GP.indep_var, 1) if num_var: x_st[:, (i + 1) * len(sys1.state) + idx] = x_st[:, i * len(sys1.state) + idx] + np.random.normal( GP.model.predict(X_tmp)[0], (GP.model.predict(X_tmp)[1]))[:, 0] y_st[:, (i + 1) * len(sys1.state) + idx] = y_st[:, i * len(sys1.state) + idx] + np.random.normal( GP.model.predict(Y_tmp)[0], (GP.model.predict(Y_tmp)[1]))[:, 0] else: x_st[:, (i + 1) * len(sys1.state) + idx] = x_st[:, i * len(sys1.state) + idx] + GP.model.predict(X_tmp)[0] y_st[:, (i + 1) * len(sys1.state) + idx] = y_st[:, i * len(sys1.state) + idx] + GP.model.predict(Y_tmp)[0] # Calculate MMD if num_var: mmd = np.zeros((num_var, len(test_infl_on))) for idx, i in enumerate(test_infl_on): if i == test_infl_of: x_st[:, i::len(sys1.state)] -= init_cond1[i] y_st[:, i::len(sys1.state)] -= init_cond2[i] for j in range(num_var): mmd[j, idx] = mmd2( x_st[num_exp * j:num_exp * j + num_exp, i::len(sys1.state)].flatten(), y_st[num_exp * j:num_exp * j + num_exp, i::len(sys1.state)].flatten()) mmd = np.std(mmd, axis=0) else: mmd = np.zeros(len(test_infl_on)) for idx, i in enumerate(test_infl_on): if i == test_infl_of: x_st[:, i::len(sys1.state)] -= init_cond1[i] y_st[:, i::len(sys1.state)] -= init_cond2[i] mmd[idx] = mmd2(x_st[:, i::len(sys1.state)].flatten(), y_st[:, i::len(sys1.state)].flatten()) return mmd, x_st, y_st