def test_ConnectivityConverter(self): converter = ConnectivityConverter(self.env.action_space) converter.init_converter() converter.seed(0) assert np.all(converter.subs_ids == np.array([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12 ])) assert len(converter.obj_type) == converter.n assert len(set(converter.obj_type)) == converter.n assert converter.pos_topo.shape[0] == converter.n assert len(set([tuple(sorted(el)) for el in converter.pos_topo])) == converter.n coded_act = np.random.rand(converter.n) pred = converter._compute_disagreement(coded_act, np.ones(converter.n)) assert np.abs((converter.n - coded_act.sum()) / converter.n - pred) <= self.tol_one pred = converter._compute_disagreement(coded_act, np.arange(converter.n)) assert np.abs(coded_act.sum() / converter.n - pred) <= self.tol_one # and not test i can produce an action that can be implemented act = converter.convert_act(encoded_act=coded_act) obs, reward, done, info = self.env.step(act) # test sample obs = self.env.reset() act = converter.sample() obs, reward, done, info = self.env.step(act)
def test_max_sub_changed(self): for ms_sub in [1, 2, 3]: converter = ConnectivityConverter(self.env.action_space) converter.init_converter(max_sub_changed=ms_sub) converter.seed(0) coded_act = np.random.rand(converter.n) # and not test i can produce an action that can be implemented act = converter.convert_act(encoded_act=coded_act) lines_impacted, subs_impacted = act.get_topological_impact() assert np.sum( subs_impacted ) == ms_sub, "wrong number of substations affected. It should be {}".format( ms_sub) obs, reward, done, info = self.env.step(act) # test sample obs = self.env.reset() act = converter.sample() lines_impacted, subs_impacted = act.get_topological_impact() assert np.sum( subs_impacted ) == ms_sub, "wrong number of substations affected. It should be {}".format( ms_sub) obs, reward, done, info = self.env.step(act)
def test_ConnectivityConverter(self): converter = ConnectivityConverter(self.env.action_space) converter.seed(0) converter.init_converter() res = np.array([ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12 ]) assert np.array_equal(converter.subs_ids, res) assert len(converter.obj_type) == converter.n assert len(set(converter.obj_type)) == converter.n assert converter.pos_topo.shape[0] == converter.n assert len(set([tuple(sorted(el)) for el in converter.pos_topo])) == converter.n n_trial = 100 preds = np.zeros(n_trial) for i in range(n_trial): coded_act = np.random.rand(converter.n) * 2. - 1. preds[i] = converter._compute_disagreement(coded_act, np.ones(converter.n)) # check the formula is properly implemented in case of "everything connected together" assert np.abs(preds[i] - 0.5 * (1 - np.mean(coded_act))) <= self.tol_one # check that on average over "a lot" of stuff the distance to the "everything connected" is 0.5 assert np.abs(np.mean(preds) - 0.5) <= 1 / np.sqrt(n_trial) # and not test i can produce an action that can be implemented act = converter.convert_act(encoded_act=coded_act) obs, reward, done, info = self.env.step(act) # test sample obs = self.env.reset() act = converter.sample() obs, reward, done, info = self.env.step(act)
def test_bug_in_doc(self): with warnings.catch_warnings(): warnings.filterwarnings("ignore") env = make("rte_case14_realistic", test=True) converter = ConnectivityConverter(env.action_space) # it's a good practice to seed the element that can be, for reproducibility converter.seed(0) # to avoid creating illegal actions affecting more than the allowed number of parameters converter.init_converter( max_sub_changed=env.parameters.MAX_SUB_CHANGED) encoded_act = np.zeros(converter.n) encoded_act[ 0] = 1 # i want to connect "line_ex id 0" and the "line_or id 2" encoded_act[ 1] = -1 # i don't want to connect "line_ex id 0" and the "line_or id 3" encoded_act[ 2] = -1 # i don't want to connect "line_ex id 0" and the "line_or id 4" encoded_act[ 3] = -1 # i don't want to connect "line_ex id 0" and the "gen id 0" encoded_act[ 4] = 1 # i want to connect "line_ex id 0" and the "load id 0" # and now retrieve the corresponding grid2op action: grid2op_act = converter.convert_act(encoded_act) assert converter.last_disagreement == 0. assert np.array_equal(grid2op_act.set_bus[3:9], [1, 1, 2, 2, 2, 1]) # second way to express the same action encoded_act2 = np.zeros(converter.n) encoded_act2[ 0] = 1 # i want to connect "line_ex id 0" and the "line_or id 2" encoded_act2[ 4] = 1 # i want to connect "line_ex id 0" and the "load id 0" encoded_act2[ 9] = 1 # i want to connect "line_or id 3" and the "line_or id 4" encoded_act2[ 10] = 1 # i want to connect "line_or id 3" and the "gen id 0" encoded_act2[ 14] = -1 # i don't want to connect "gen id 0" and the "load id 0" # and now retrieve the corresponding grid2op action: grid2op_act2 = converter.convert_act(encoded_act2) assert converter.last_disagreement == 0. assert np.array_equal(grid2op_act2.set_bus[3:9], [1, 1, 2, 2, 2, 1]) # trick it: i don't specified enough constraints (used to be infinite loop) encoded_act3 = np.zeros(converter.n) encoded_act3[ 0] = 1 # i want to connect "line_ex id 0" and the "line_or id 2" encoded_act3[ 4] = 1 # i want to connect "line_ex id 0" and the "load id 0" encoded_act3[ 9] = 1 # i want to connect "line_or id 3" and the "line_or id 4" encoded_act3[ 10] = 1 # i want to connect "line_or id 3" and the "gen id 0" grid2op_act3 = converter.convert_act(encoded_act3) assert converter.last_disagreement == 0. assert np.array_equal(grid2op_act3.set_bus[3:9], [1, 1, 1, 1, 1, 1]) size_ = converter.n # trick (the compute_disagreement function) in another way: not all components are set missing = np.ones(converter.n) missing[3] = 0 # encodes for line_ex id O disag0 = converter._compute_disagreement(encoded_act3, missing) # 2 constraints not met because the line_ex id O is not set in the action assert abs(disag0 - 2. / size_) <= self.tol_one missing2 = np.ones(converter.n) missing2[8] = 0 # encodes for load id 0 disag2 = converter._compute_disagreement(encoded_act3, missing2) # 1 constraints not met because the load id 0 O is not set in the action assert abs(disag2 - 1. / size_) <= self.tol_one missing3 = np.ones(converter.n) missing3[3:9] = 0 # all constraints not met disag3 = converter._compute_disagreement(encoded_act3, missing3) # one component not set in the "action candidate" among 4 constraints assert abs(disag3 - 4. / size_) <= self.tol_one
def test_can_make_action(self): converter = ConnectivityConverter(self.env.action_space) converter.init_converter( max_sub_changed=self.env.parameters.MAX_SUB_CHANGED) converter.seed(0) with self.assertRaises(Exception): # one too shot tmp = np.zeros(converter.n - 1) converter.convert_act(tmp) with self.assertRaises(Exception): # one too long tmp = np.zeros(converter.n + 1) converter.convert_act(tmp) with self.assertRaises(Exception): # one too low tmp = np.zeros(converter.n) tmp[3] = -1.1 converter.convert_act(tmp) with self.assertRaises(Exception): # one too high tmp = np.zeros(converter.n) tmp[3] = 1.1 converter.convert_act(tmp) size_ = converter.n # test do nothing gives do nothing indeed dn_enc = converter.do_nothing_encoded_act() glop_dn_act = converter.convert_act(dn_enc) assert glop_dn_act == self.env.action_space() # encode the topology [1,1 ,2,2] at sub 12, meaning: line_ex 9 / line_ex 13 together, # and line or 14 / load 9 together complex_act = 1.0 * dn_enc complex_act[84] = 1. # line ex 9 and line ex 13 together complex_act[85] = -1. # line ex 9 and line or 14 not together complex_act[86] = -1. # line ex 9 and load 9 not together glop_act = converter.convert_act(complex_act) aff_line, aff_sub = glop_act.get_topological_impact() assert np.sum(aff_line) == 0 assert np.sum(aff_sub) == 1 assert aff_sub[12] assert glop_act.line_ex_set_bus[9] != 0 assert glop_act.line_ex_set_bus[13] != 0 assert glop_act.line_or_set_bus[14] != 0 assert glop_act.load_set_bus[9] != 0 assert glop_act.line_ex_set_bus[9] == glop_act.line_ex_set_bus[13] assert glop_act.line_ex_set_bus[9] != glop_act.line_or_set_bus[14] assert glop_act.line_ex_set_bus[9] != glop_act.load_set_bus[9] assert glop_act.line_or_set_bus[14] == glop_act.load_set_bus[9] # encode the topology [1,1 ,2,2] at sub 12, meaning: line_ex 9 / line_ex 13 together, # and line or 14 / load 9 together but in a "soft" manner complex_act = 1.0 * dn_enc complex_act[84] = 0.8 # line ex 9 and line ex 13 together complex_act[85] = -0.9 # line ex 9 and line or 14 not together complex_act[86] = -0.9 # line ex 9 and load 9 not together glop_act2 = converter.convert_act(complex_act) assert abs(converter.last_disagreement - 0.5 * (0.2 + 0.1 + 0.1) / size_) <= self.tol_one assert glop_act == glop_act2 # now tricky stuff, such that the greedy do not work and i need to explore a bit # line_ex 9 / line_ex 13 together and line or 14 / load 9 together complex_act = 1.0 * dn_enc complex_act[84] = 0.6 # line ex 9 and line ex 13 together complex_act[85] = -0.9 # line ex 9 and line or 14 not together complex_act[86] = -0.9 # line ex 9 and load 9 not together complex_act[ 87] = 0.61 # "line_ex id 13" and the "line_or id 14" together complex_act[88] = -0.2 # "line_ex id 13" and the "load id 9" together complex_act[ 89] = 0. # "line_or id 14" and the "load id 9" no preferences glop_act3 = converter.convert_act(complex_act) # this gives : [ 1 2 2 2 ], which is sub optimal # Lex9 Lex13 lor14 loa9 frst_disag = converter.last_disagreement assert abs(frst_disag - 0.5 * (1.6 + 0.1 + 0.1 + 0.39 + 1.2) / size_) <= self.tol_one assert glop_act != glop_act3 # but glop_act should be better ! glop_act4 = converter.convert_act(complex_act, explore=3) this_disag = converter.last_disagreement assert this_disag < frst_disag, "this disagreement should always be lower !" assert converter.indx_sel != 0, "the first has been selected, it should not !" assert glop_act == glop_act4, "the same action first action should be optimal" assert abs(this_disag - 0.5 * (0.4 + 0.1 + 0.1 + 1.61 + 0.8) / size_) <= self.tol_one