Exemplo n.º 1
0
 def find_important_dimensions(self, poly1, poly2):
     '''assuming check_contained(poly1,poly2) returns true, we are interested in the halfspaces that matters
     poly1 = root, poly2 = candidate
     '''
     # #Binary Space Partitioning
     gurobi_model = grb.Model()
     gurobi_model.setParam('OutputFlag', self.output_flag)
     input1 = Experiment.generate_input_region(gurobi_model, self.analysis_template, poly1, self.env_input_size)
     relevant_directions = []
     for j, template in enumerate(self.analysis_template):
         multiplication = 0
         for i in range(self.env_input_size):
             multiplication += template[i] * input1[i]
         previous_constraint = gurobi_model.getConstrByName("check_contained_constraint")
         if previous_constraint is not None:
             gurobi_model.remove(previous_constraint)
             gurobi_model.update()
         gurobi_model.addConstr(multiplication <= poly2[j], name=f"check_contained_constraint")
         gurobi_model.update()
         x_results = self.optimise(self.analysis_template, gurobi_model, input1)
         if np.allclose(np.array(poly1), x_results) is False:
             vertices = np.stack(self.pypoman_compute_polytope_vertices(self.analysis_template, np.array(x_results)))
             samples = polytope.sample(1000, self.analysis_template, x_results)
             from scipy.spatial import ConvexHull
             hull = ConvexHull(samples)
             volume = hull.volume  # estimated volume
             relevant_directions.append((j, volume))
     return relevant_directions
Exemplo n.º 2
0
 def generate_root_polytope(self, input_boundaries):
     gurobi_model = grb.Model()
     gurobi_model.setParam('OutputFlag', self.output_flag)
     input = Experiment.generate_input_region(gurobi_model, self.input_template, input_boundaries, self.env_input_size)
     x_results = self.optimise(self.analysis_template, gurobi_model, input)
     if x_results is None:
         print("Model unsatisfiable")
         return None
     root = tuple(x_results)
     return root
Exemplo n.º 3
0
 def check_contained(self, poly1, poly2):
     gurobi_model = grb.Model()
     gurobi_model.setParam('OutputFlag', self.output_flag)
     input1 = Experiment.generate_input_region(gurobi_model, self.analysis_template, poly1, self.env_input_size)
     Experiment.generate_region_constraints(gurobi_model, self.analysis_template, input1, poly2, self.env_input_size, eps=1e-5)  # use epsilon to prevent single points
     x_results = self.optimise(self.analysis_template, gurobi_model, input1)
     if x_results is None:
         # not contained
         return False
     else:
         return True
Exemplo n.º 4
0
 def create_range_bounds_model(self, template, x, env_input_size, nn, round=-1):
     gurobi_model = grb.Model()
     gurobi_model.setParam('OutputFlag', False)
     input = Experiment.generate_input_region(gurobi_model, template, x, env_input_size)
     gurobi_model.update()
     gurobi_model.optimize()
     assert gurobi_model.status == 2, "LP wasn't optimally solved"
     observation = self.get_observation_variable(input, gurobi_model)  # get the observation from the input
     ranges = Experiment.get_range_bounds(observation, nn, gurobi_model)
     if self.use_softmax:
         ranges_probs = unroll_methods.softmax_interval(ranges)
     else:
         ranges_probs = ranges
     if round >= 0:
         pass
         # todo round the probabilities
     return ranges_probs
 def post_milp(self, x, x_label, nn, output_flag, t, template):
     """milp method"""
     post = []
     for chosen_action in range(2):
         gurobi_model = grb.Model()
         gurobi_model.setParam('OutputFlag', output_flag)
         input = Experiment.generate_input_region(gurobi_model, template, x,
                                                  self.env_input_size)
         # gurobi_model.addConstr(input[0] >= 0, name=f"input_base_constr1")
         # gurobi_model.addConstr(input[1] >= 0, name=f"input_base_constr2")
         # gurobi_model.addConstr(input[2] >= 20, name=f"input_base_constr3")
         observation = gurobi_model.addMVar(shape=(2, ),
                                            lb=float("-inf"),
                                            ub=float("inf"),
                                            name="observation")
         gurobi_model.addConstr(
             observation[1] <= input[0] - input[1] + self.input_epsilon / 2,
             name=f"obs_constr21")  # delta_x
         gurobi_model.addConstr(
             observation[1] >= input[0] - input[1] - self.input_epsilon / 2,
             name=f"obs_constr22")
         gurobi_model.addConstr(observation[0] <= self.v_lead - input[2] +
                                self.input_epsilon / 2,
                                name=f"obs_constr11")  # delta_v
         gurobi_model.addConstr(observation[0] >= self.v_lead - input[2] -
                                self.input_epsilon / 2,
                                name=f"obs_constr12")
         # gurobi_model.addConstr(input[3] <= self.max_speed, name=f"v_constr_input")
         # gurobi_model.addConstr(input[3] >= -self.max_speed, name=f"v_constr_input")
         feasible_action = Experiment.generate_nn_guard(
             gurobi_model, observation, nn, action_ego=chosen_action, M=1e6)
         # feasible_action = Experiment.generate_nn_guard(gurobi_model, input, nn, action_ego=chosen_action)
         if feasible_action:
             # apply dynamic
             x_prime = 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_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 main_loop(self, nn, template, template_2d):
     assert self.post_fn_continuous is not None
     root = self.generate_root_polytope()
     root_list = [root]
     vertices_list = defaultdict(list)
     seen = []
     frontier = [(0, x) for x in root_list]
     max_t = 0
     num_already_visited = 0
     widgets = [progressbar.Variable('n_workers'), ', ', progressbar.Variable('frontier'), ', ', progressbar.Variable('seen'), ', ', progressbar.Variable('num_already_visited'), ", ",
                progressbar.Variable('max_t'), ", ", progressbar.Variable('last_visited_state')]
     last_time_plot = None
     if self.before_start_fn is not None:
         self.before_start_fn(nn)
     self.internal_model = grb.Model()
     self.internal_model.setParam('OutputFlag', self.output_flag)
     input = Experiment.generate_input_region(self.internal_model, self.input_template, self.input_boundaries, self.env_input_size)
     self.last_input = input
     with progressbar.ProgressBar(widgets=widgets) if self.show_progressbar else nullcontext() as bar:
         while len(frontier) != 0:
             t, x = frontier.pop(0) if self.use_bfs else frontier.pop()
             if max_t > self.time_horizon:
                 print(f"Reached horizon t={t}")
                 self.plot_fn(vertices_list, template, template_2d)
                 return max_t, num_already_visited, vertices_list, False
             contained_flag = False
             to_remove = []
             for s in seen:
                 if contained(x, s):
                     contained_flag = True
                     break
                 if contained(s, x):
                     to_remove.append(s)
             for rem in to_remove:
                 num_already_visited += 1
                 seen.remove(rem)
             if contained_flag:
                 num_already_visited += 1
                 continue
             max_t = max(max_t, t)
             vertices_list[t].append(np.array(x))
             if self.check_unsafe(template, x):
                 print(f"Unsafe state found at timestep t={t}")
                 print(x)
                 self.plot_fn(vertices_list, template, template_2d)
                 return max_t, num_already_visited, vertices_list, True
             seen.append(x)
             x_primes_list = self.post_fn_continuous(x, nn, self.output_flag, t, template)
             if last_time_plot is None or time.time() - last_time_plot >= self.plotting_time_interval:
                 if last_time_plot is not None:
                     self.plot_fn(vertices_list, template, template_2d)
                 last_time_plot = time.time()
             if self.update_progress_fn is not None:
                 self.update_progress_fn(seen=len(seen), frontier=len(frontier), num_already_visited=num_already_visited, max_t=max_t)
             if self.show_progressbar:
                 bar.update(value=bar.value + 1, seen=len(seen), frontier=len(frontier), num_already_visited=num_already_visited, last_visited_state=str(x), max_t=max_t)
             assert len(x_primes_list) != 0, "something is wrong with the calculation of the successor"
             # for x_primes in x_primes_list:
             for x_prime in x_primes_list:
                 if self.use_rounding:
                     # x_prime_rounded = tuple(np.trunc(np.array(x_prime) * self.rounding_value) / self.rounding_value)  # todo should we round to prevent numerical errors?
                     x_prime_rounded = self.round_tuple(x_prime, self.rounding_value)
                     # x_prime_rounded should always be bigger than x_prime
                     assert contained(x_prime, x_prime_rounded)
                     x_prime = x_prime_rounded
                 frontier = [(u, y) for u, y in frontier if not contained(y, x_prime)]
                 if not any([contained(x_prime, y) for u, y in frontier]):
                     frontier.append(((t + 1), x_prime))
                     # print(x_prime)
                 else:
                     num_already_visited += 1
     self.plot_fn(vertices_list, template, template_2d)
     return max_t, num_already_visited, vertices_list, False