def post_milp(self, x, x_label, nn, output_flag, t, template): """milp method""" post = [] for split_angle in itertools.product( [True, False], repeat=2): # split successor if theta is within safe_angle for chosen_action in range(self.n_actions): # if (chosen_action == 2 or chosen_action == 1) and x_label == 1: # skip actions when battery is dead # continue gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) gurobi_model.setParam('Threads', 2) input = generate_input_region(gurobi_model, template, x, self.env_input_size) max_theta, min_theta, max_theta_dot, min_theta_dot = self.get_theta_bounds( gurobi_model, input) feasible_action = PendulumExperiment.generate_nn_guard( gurobi_model, input, nn, action_ego=chosen_action, M=1e03) if feasible_action: # performs action 2 automatically when battery is dead sin_cos_table = self.get_sin_cos_table( max_theta, min_theta, max_theta_dot, min_theta_dot, action=chosen_action) # for normalisation_split in [True,False]: newthdot, newtheta = PendulumExperiment.generate_angle_milp( gurobi_model, input, sin_cos_table) # gurobi_model.addConstr(newtheta >) # apply dynamic x_prime = self.apply_dynamic( input, gurobi_model, newthdot=newthdot, newtheta=newtheta, env_input_size=self.env_input_size, action=chosen_action) for i, (A, b) in enumerate(self.angle_split): generate_region_constraints(gurobi_model, A, x_prime, b, self.env_input_size, invert=not split_angle[i]) gurobi_model.update() gurobi_model.optimize() if gurobi_model.status != 2: continue found_successor, x_prime_results = self.h_repr_to_plot( gurobi_model, template, x_prime) if found_successor: post.append((tuple(x_prime_results), (x, x_label))) return post
def check_unsafe(self, template, bnds, x_label): for A, b in self.unsafe_zone: gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', False) input = gurobi_model.addMVar(shape=(self.env_input_size,), lb=float("-inf"), name="input") generate_region_constraints(gurobi_model, template, input, bnds, self.env_input_size) generate_region_constraints(gurobi_model, A, input, b, self.env_input_size) gurobi_model.update() gurobi_model.optimize() if gurobi_model.status == 2: return True return False
def post_milp(self, x, nn, output_flag, t, template): """milp method""" post = [] for chosen_action in range(2): observable_template = self.observable_templates[chosen_action] observable_result = self.observable_results[chosen_action] gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) gurobi_model.setParam('Threads', 2) input = generate_input_region(gurobi_model, template, x, self.env_input_size) observation = gurobi_model.addMVar(shape=(2, ), lb=float("-inf"), ub=float("inf"), name="input") gurobi_model.addConstr( observation[1] <= input[0] - input[1] + self.input_epsilon / 2, name=f"obs_constr21") gurobi_model.addConstr( observation[1] >= input[0] - input[1] - self.input_epsilon / 2, name=f"obs_constr22") gurobi_model.addConstr( observation[0] <= input[2] - input[3] + self.input_epsilon / 2, name=f"obs_constr11") gurobi_model.addConstr( observation[0] >= input[2] - input[3] - self.input_epsilon / 2, name=f"obs_constr12") # feasible_action = Experiment.generate_nn_guard(gurobi_model, observation, nn, action_ego=chosen_action) # feasible_action = Experiment.generate_nn_guard(gurobi_model, input, nn, action_ego=chosen_action) generate_region_constraints(gurobi_model, observable_template, observation, observable_result, 2) gurobi_model.optimize() feasible_action = gurobi_model.status if feasible_action: # apply dynamic # x_prime_results = self.optimise(template, gurobi_model, input) # h representation # x_prime = Experiment.generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = StoppingCarExperiment.apply_dynamic( input, gurobi_model, action=chosen_action, env_input_size=self.env_input_size) gurobi_model.update() gurobi_model.optimize() found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) return post
def assign_label(self, x_prime, parent, parent_lbl) -> int: for A, b in self.unsafe_zone: gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', False) input = gurobi_model.addMVar(shape=(self.env_input_size, ), lb=float("-inf"), name="input") generate_region_constraints(gurobi_model, self.analysis_template, input, x_prime, self.env_input_size) generate_region_constraints(gurobi_model, A, input, b, self.env_input_size) gurobi_model.update() gurobi_model.optimize() if gurobi_model.status == 2: return parent_lbl + 1 # still balancing return 0 # unsafe count up to 20
def check_intersection(self, poly1, poly2, eps=1e-5): '''checks if a polytope is inside another (even partially)''' gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', self.output_flag) input1 = generate_input_region(gurobi_model, self.analysis_template, poly1, self.env_input_size) generate_region_constraints( gurobi_model, self.analysis_template, input1, poly2, self.env_input_size, eps=eps) # use epsilon to prevent single points x_results = optimise(self.analysis_template, gurobi_model, input1) if x_results is None: # not contained return False else: return True
def post_milp(self, x, x_label, nn, output_flag, t, template): post = [] for unsafe_check in [True, False]: for chosen_action in range(self.n_actions): gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) gurobi_model.setParam('Threads', 2) gurobi_model.params.NonConvex = 2 input = generate_input_region(gurobi_model, template, x, self.env_input_size) feasible_action = WaterTankExperiment.generate_nn_guard( gurobi_model, input, nn, action_ego=chosen_action) if feasible_action: # apply dynamic x_prime = self.apply_dynamic( input, gurobi_model, chosen_action, env_input_size=self.env_input_size) for A, b in self.unsafe_zone: # splits the input based on the decision boundary of the ltl property if unsafe_check: generate_region_constraints( gurobi_model, A, x_prime, b, self.env_input_size) else: generate_region_constraints(gurobi_model, A, x_prime, b, self.env_input_size, invert=True) gurobi_model.update() gurobi_model.optimize() found_successor, x_prime_results = self.h_repr_to_plot( gurobi_model, template, x_prime) if found_successor: post.append((tuple(x_prime_results), (x, x_label))) return post
def post_milp(self, x, nn, output_flag, t, template): post = [] observable_template_action1 = self.observable_templates[1] observable_result_action1 = self.observable_results[1] observable_template_action0 = self.observable_templates[0] observable_result_action0 = self.observable_results[0] def standard_op(): gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input = generate_input_region(gurobi_model, template, x, self.env_input_size) z = self.apply_dynamic(input, gurobi_model, self.env_input_size) return gurobi_model, z, input # case 0 gurobi_model, z, input = standard_op() feasible0 = self.generate_guard(gurobi_model, z, case=0) # bounce if feasible0: # action is irrelevant in this case # apply dynamic x_prime_results = optimise(template, gurobi_model, z) gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input2 = generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = self.apply_dynamic2(input2, gurobi_model, case=0, env_input_size=self.env_input_size) found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) # case 1 : ball going down and hit gurobi_model, z, input = standard_op() feasible11 = self.generate_guard(gurobi_model, z, case=1) if feasible11: generate_region_constraints(gurobi_model, observable_template_action1, input, observable_result_action1, 2) gurobi_model.optimize() feasible12 = gurobi_model.status # feasible12 = self.generate_nn_guard(gurobi_model, input, nn, action_ego=1) # check for action =1 over input (not z!) if feasible12: # apply dynamic x_prime_results = optimise(template, gurobi_model, z) gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input2 = generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = self.apply_dynamic2( input2, gurobi_model, case=1, env_input_size=self.env_input_size) found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) # case 2 : ball going up and hit gurobi_model, z, input = standard_op() feasible21 = self.generate_guard(gurobi_model, z, case=2) if feasible21: generate_region_constraints(gurobi_model, observable_template_action1, input, observable_result_action1, 2) gurobi_model.optimize() feasible22 = gurobi_model.status # feasible22 = self.generate_nn_guard(gurobi_model, input, nn, action_ego=1) # check for action =1 over input (not z!) if feasible22: # apply dynamic x_prime_results = optimise(template, gurobi_model, z) gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input2 = generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = self.apply_dynamic2( input2, gurobi_model, case=2, env_input_size=self.env_input_size) found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) # case 1 alt : ball going down and NO hit gurobi_model, z, input = standard_op() feasible11_alt = self.generate_guard(gurobi_model, z, case=1) if feasible11_alt: generate_region_constraints(gurobi_model, observable_template_action0, input, observable_result_action0, 2) gurobi_model.optimize() feasible12_alt = gurobi_model.status # feasible12_alt = self.generate_nn_guard(gurobi_model, input, nn, action_ego=0) # check for action = 0 over input (not z!) if feasible12_alt: # apply dynamic x_prime_results = optimise(template, gurobi_model, z) gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input2 = generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = self.apply_dynamic2( input2, gurobi_model, case=3, env_input_size=self.env_input_size) found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) # case 2 alt : ball going up and NO hit gurobi_model, z, input = standard_op() feasible21_alt = self.generate_guard(gurobi_model, z, case=2) if feasible21_alt: generate_region_constraints(gurobi_model, observable_template_action0, input, observable_result_action0, 2) gurobi_model.optimize() feasible22_alt = gurobi_model.status # feasible22_alt = self.generate_nn_guard(gurobi_model, input, nn, action_ego=0) # check for action = 0 over input (not z!) if feasible22_alt: # apply dynamic x_prime_results = optimise(template, gurobi_model, z) gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input2 = generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = self.apply_dynamic2( input2, gurobi_model, case=3, env_input_size=self.env_input_size) found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) # case 3 : ball out of reach and not bounce gurobi_model, z, input = standard_op() feasible3 = self.generate_guard(gurobi_model, z, case=3) # out of reach if feasible3: # action is irrelevant in this case # apply dynamic x_prime_results = optimise(template, gurobi_model, z) gurobi_model = grb.Model() gurobi_model.setParam('OutputFlag', output_flag) input2 = generate_input_region(gurobi_model, template, x_prime_results, self.env_input_size) x_second = self.apply_dynamic2(input2, gurobi_model, case=3, env_input_size=self.env_input_size) found_successor, x_second_results = self.h_repr_to_plot( gurobi_model, template, x_second) if found_successor: post.append(tuple(x_second_results)) return post
def generate_input_region(gurobi_model, templates, boundaries, env_input_size): input = gurobi_model.addMVar(shape=env_input_size, lb=float("-inf"), ub=float("inf"), name="input") generate_region_constraints(gurobi_model, templates, input, boundaries, env_input_size) return input