def minimize(self, direction, result, error_if_infeasible=False):
        '''
        minimize a constraint in the standard basis. this returns True of False, depending on
        whether the LP was feasible. If it was feasible, the passed-in 'result' vector is assigned
        '''

        assert len(direction) == self.num_standard_vars, \
            "minimize objective length({}) should match number of standard variables({})".format(
                len(direction), self.num_standard_vars)

        dir_len, = direction.shape
        res_len, = result.shape

        Timers.tic("lp minimize")
        res = LpInstance._minimize(self.lp_data, direction, dir_len, result,
                                   res_len)
        Timers.toc("lp minimize")

        is_feasible = (res == 0)

        if not is_feasible and error_if_infeasible:
            raise RuntimeError(
                'minimize LP was infeasible when error_if_infeasible=True')

        return is_feasible
Exemple #2
0
    def do_step_pop(self):
        'do a step where we pop from the waiting list'

        Timers.tic('do_step_pop')

        self.plotman.state_popped() # reset certain per-mode plot variables
        self.aggdag.print_waiting_list()

        self.result.last_cur_state = cur_state = self.aggdag.pop_waiting_list()

        self.print_normal("Removed state in mode '{}' at step {} ({} in mode) (Waiting list has {} left)".format( \
                cur_state.mode.name, cur_state.cur_steps_since_start, cur_state.cur_step_in_mode, \
                len(self.aggdag.waiting_list)))

        # if a_matrix is None, it's an error mode
        if cur_state.mode.a_csr is None:
            self.print_normal("Mode '{}' was an error mode; skipping.".format(cur_state.mode.name))

            self.aggdag.cur_state_left_invariant()
        else:
            self.max_steps_remaining = self.settings.num_steps - cur_state.cur_steps_since_start[0]

            still_feasible = self.intersect_invariant(cur_state)

            if not still_feasible:
                self.print_normal("Continuous state was outside of the mode's invariant; skipping.")
                self.aggdag.cur_state_left_invariant()
            else:
                cur_state.apply_approx_model(self.settings.approx_model)

        # pause plot
        self.print_verbose("Pausing due to step_pop()")
        self.plotman.pause()

        Timers.toc('do_step_pop')
Exemple #3
0
    def simulate_vecs_disc(self, start_list, steps, cur_step):
        Timers.tic("simulation")
        sim_start_time = time.time()
        result = []
        prev_val = start_list
        for idx in range(cur_step, cur_step + steps, 1):
            new_val = np.matmul(self.dy_data.dense_a_matrix.transpose(),
                                prev_val)
            # print(new_val.shape)
            single_step_result = np.empty((self.num_dims, self.num_dims))
            for dim in range(self.num_dims):
                single_step_result[dim] = np.array(new_val.tolist()[dim])
            result.append(single_step_result)
            prev_val = new_val

        if self.settings.stdout:
            SHARED_NEXT_PRINT.value = sim_start_time + self.settings.print_interval_secs
            SHARED_COMPLETED_SIMS.value = 0

            mb_per_step = np.dtype(
                float
            ).itemsize * self.num_dims * self.num_dims / 1024.0 / 1024.0
            print("Simulating {} steps (~{:.2f} GB in memory)...".format(
                steps, steps * mb_per_step / 1024.0))

        if self.settings.stdout:
            print("Total Simulation Time: {:.2f} secs".format(time.time() -
                                                              sim_start_time))

        Timers.toc("simulation")
        return result
Exemple #4
0
def get_box_center(lpi):
    '''get the center of the box overapproximation of the passed-in lpi

    may return None if lp solving fails (numerical issues)
    '''

    Timers.tic('get_box_center')

    dims = lpi.dims
    pt = []

    for dim in range(dims):
        col = lpi.cur_vars_offset + dim
        min_dir = [1 if i == dim else 0 for i in range(dims)]
        max_dir = [-1 if i == dim else 0 for i in range(dims)]

        min_val = lpi.minimize(direction_vec=min_dir,
                               columns=[col],
                               fail_on_unsat=False)
        max_val = lpi.minimize(direction_vec=max_dir,
                               columns=[col],
                               fail_on_unsat=False)

        if min_val is None or max_val is None:
            pt = None
            break

        min_val = min_val[0]
        max_val = max_val[0]

        pt.append((min_val + max_val) / 2.0)

    Timers.toc('get_box_center')

    return pt
    def add_input_star(self, a_matrix_t, b_vec, input_basis_matrix):
        '''minkowski add an input star into the lp (creates 1 new variable for each input)'''

        assert len(a_matrix_t.shape) == 2
        assert len(b_vec.shape) == 1

        assert a_matrix_t.shape[1] == b_vec.shape[
            0], "number of rows in constraints must match"
        assert a_matrix_t.shape[0] == input_basis_matrix.shape[0], \
            "number of columns in constraint matix / rows in input basis matrix must match"

        assert input_basis_matrix.shape[
            1] == self.num_standard_vars, "input basis matrix cols must match standard vars"

        if self.num_inputs is None:
            self.num_inputs = input_basis_matrix.shape[0]
        else:
            assert input_basis_matrix.shape[
                0] == self.num_inputs, "num_inputs changed between calls to add_input_star"

        Timers.tic("lp add_input_star")
        LpInstance._add_input_star(self.lp_data, a_matrix_t, a_matrix_t.shape[1], a_matrix_t.shape[0], b_vec, \
            b_vec.shape[0], input_basis_matrix, input_basis_matrix.shape[1], input_basis_matrix.shape[0])

        Timers.toc("lp add_input_star")
Exemple #6
0
    def do_step_reach(self):
        'do a single reach step of the computation'

        Timers.tic('do_step')

        if not self.is_finished():
            if self.aggdag.get_cur_state():
                self.do_step_continuous_post()
                self.continuous_steps += 1
            elif self.aggdag.deagg_man.doing_replay():
                # in the middle of a deaggregation replay
                self.aggdag.deagg_man.do_step_replay()
            else:
                # begin a deaggregation replay or pop a state off the waiting list
                deagg_node = self.settings.aggstrat.get_deagg_node(self.aggdag)

                if deagg_node:
                    self.aggdag.deagg_man.begin_replay(deagg_node)
                    self.aggdag.deagg_man.do_step_replay()
                else:
                    #print(".core popping, calling aggdag.save_viz()")
                    #self.aggdag.save_viz()

                    # pop state off waiting list
                    self.do_step_pop()

                    if self.settings.process_urgent_guards and self.aggdag.get_cur_state(
                    ) is not None:
                        self.check_guards()

        Timers.toc('do_step')
Exemple #7
0
 def compute_robust_ce(self):
     Timers.tic('Robust counter-example generation time')
     lce_object = self.compute_longest_ce()
     longest_ce_lpi = lce_object.usafe_lpi
     # longest_ce_lpi = self.create_lpi(lce_object)
     directions = np.identity(self.num_dims, dtype=float)
     robust_point = np.zeros(self.num_dims)
     for index in range(self.num_dims):
         direction = directions[index]
         result = np.zeros(self.num_dims)
         is_feasible = longest_ce_lpi.minimize(-1 * direction,
                                               result,
                                               error_if_infeasible=False)
         basis_matrix = self.init_star.basis_matrix
         if is_feasible:
             point1 = np.dot(basis_matrix, result)
             print("Depth {}".format(sum(direction * result)))
         result = np.zeros(self.num_dims)
         is_feasible = longest_ce_lpi.minimize(direction,
                                               result,
                                               error_if_infeasible=False)
         if is_feasible:
             point2 = np.dot(basis_matrix, result)
             print("Depth {}".format(sum(direction * result)))
         # print ("Points for the direction {} are {} and {}".format(direction, point1, point2))
         current_point = (point1 + point2) / 2
         robust_point[index] = np.dot(current_point, direction)
     print("Robust point is '{}'".format(robust_point))
     Timers.toc('Robust counter-example generation time')
     return robust_point
Exemple #8
0
    def replay_op(self, op_list, i):
        '''
        replay a single operation in the current node
        this is used when nodes are split, to leverage parent information
        '''

        Timers.tic('replay_op')

        assert not self.node_left_invariant()

        op = op_list[i]

        cur_state = self.get_cur_state()
        assert cur_state is not None

        self.aggdag.core.print_verbose(f"replaying {i}: {op}")

        if isinstance(op, OpLeftInvariant):
            self.op_list.append(op)
        elif isinstance(op, OpTransition):
            self.replay_op_transition(cur_state, op)
        elif isinstance(op, OpInvIntersect):
            # if there is a later invariant intersection with the same hyperplane and it's stronger, skip this one

            skip = False

            for future_i in range(i + 1, len(op_list)):
                future_op = op_list[future_i]

                if not isinstance(future_op, OpInvIntersect):
                    # another op (such as a transition, can't skip current one)
                    break

                if future_op.i_index == op.i_index:
                    if future_op.is_stronger:
                        skip = True

                    break

            #print(".aggdag %%%% debug never skipping invariant intersection")
            # hmm, skipping invariant intersections is only valid if deaggregation is a subset of aggregated set...
            # for our krylov aggregation, this isn't really the case though... so in general you need to invaraint
            # intersect at every step... plus this is really an optimization rather than the main algorithm

            if True or not skip:
                self.aggdag.core.print_verbose(
                    f"doing invariant intersection in replay at step {cur_state.cur_step_in_mode}"
                )

                is_feasible = self.replay_op_intersect_invariant(cur_state, op)

                if not is_feasible:
                    op = OpLeftInvariant(op.step, self, False)
                    self.op_list.append(op)
            else:
                self.aggdag.core.print_verbose(
                    "skipping invariant intersection because stronger one is coming up"
                )

        Timers.toc('replay_op')
Exemple #9
0
    def presimulate(self, desired_step):
        '''
        as an optimization, run simulations up to some bound in preperation for many consecutive calls to
        get_vecs_origin_at_step(). This may get truncated due to memory limits.
        '''

        Timers.tic("sim + overhead")

        # if there are currently no simulations, or if the offset != 0
        if self.settings.sim_mode == SimulationSettings.SIMULATION and self.step_offset != 0:
            self.step_offset = 0

            # try to ensure step [0, desired_step] is in memory
            if desired_step >= self.max_steps_in_mem:
                desired_step = self.max_steps_in_mem - 1

            # presimulate origin
            start = np.zeros((self.num_dims))
            self.origin_sim = self.simulate_origin(start,
                                                   desired_step,
                                                   include_step_zero=True)

            assert len(self.origin_sim) == 1 + desired_step

            # presimulate vec_values
            start_list = np.identity(self.num_dims)
            self.vec_values = self.simulate_vecs(start_list,
                                                 desired_step,
                                                 include_step_zero=True)

            assert len(self.vec_values) == 1 + desired_step
            assert len(self.vec_values) == len(self.origin_sim)

        Timers.toc("sim + overhead")
Exemple #10
0
    def check_guards(self):
        '''check for discrete successors with the guards'''

        Timers.tic("check_guards")

        cur_state = self.aggdag.get_cur_state()

        for t in cur_state.mode.transitions:
            t_lpi = t.get_guard_intersection(cur_state.lpi)

            if t_lpi:
                if t.to_mode.is_error():
                    self.error_reached(cur_state, t, t_lpi)

                    if self.settings.stop_on_aggregated_error:
                        break

                    if cur_state.is_concrete and self.settings.stop_on_concrete_error:
                        break
                
                self.aggdag.add_transition_successor(t, t_lpi)

                self.print_verbose(f"Took transition {t} at steps {cur_state.cur_steps_since_start}")

                # if it's a time-triggered transition, we may remove cur_state immediately
                if self.settings.optimize_tt_transitions and t.time_triggered:
                    if was_tt_taken(cur_state.lpi, t, self.settings.step_size, self.settings.num_steps):
                        self.print_verbose("Transition was time-triggered, finished with current state analysis")
                        self.took_tt_transition = True
                    else:
                        self.print_verbose("Transition was NOT taken as time-triggered, due to runtime checks")

        Timers.toc("check_guards")
Exemple #11
0
def check_intersection(lpi, lc, tol=1e-13):
    '''check if there is an intersection between the LP constriants and the LinearConstraint object lc

    This solves an LP optimizing in the given direction... without adding the constraint to the LP

    This returns True/False if an intersection is possible

    it also can return None if the lp is infeasible
    '''

    Timers.tic("check_intersection")

    lpi.set_minimize_direction(lc.csr, is_csr=True)

    columns = lc.csr.indices[0:lc.csr.indptr[1]]
    lp_columns = [lpi.cur_vars_offset + c for c in columns]

    lp_res = lpi.minimize(columns=lp_columns, fail_on_unsat=False)

    if lp_res is None:
        # sometimes, changing optimization direction makes lp infeasible (up to numerical accuracy)
        # this happens in gearbox with small time steps. In this case, return no intersection
        rv = None
    else:
        dot_res = np.dot(lc.csr.data, lp_res)
        rv = dot_res + tol <= lc.rhs

    Timers.toc("check_intersection")

    return rv
Exemple #12
0
    def vector_to_star_basis(self, standard_vec):
        '''
        convert a vector in the standard basis to a point in the star's basis.

        This solves basis_matrix * rv = input, which is essentially computing the
        inverse of basis_matrix, which can become ill-conditioned.
        '''

        Timers.tic("vector_to_star_basis()")

        rv = np.linalg.solve(self.basis_matrix.T, standard_vec)

        #rv = lstsq(self.basis_matrix.T, np.array(standard_vec, dtype=float))[0]

        # double-check that we've found the solution within some tolerance
        if not np.allclose(np.dot(self.basis_matrix.T, rv), standard_vec):
            raise RuntimeError(
                "basis matrix was ill-conditioned, vector_to_star_basis() failed"
            )

        Timers.toc("vector_to_star_basis()")

        assert isinstance(rv, np.ndarray)

        return rv
Exemple #13
0
    def compute_counterexample(self, benchmark, regex=None):
        start_node = self.pv_object.reach_tree.nodes[0]
        current_path = []
        paths = []
        Timers.tic("Time taken by MILP")
        self.pv_object.explore_tree_for_error_stars(start_node, current_path,
                                                    paths)
        for path in paths:

            prev_node_state = start_node.state
            print("No of nodes in the path is: '{}'".format(len(path)))

            milp_instance = ReachabilityInstance(benchmark, self.num_dims,
                                                 len(path))
            if regex is not None:
                milp_instance = RegexInstance(benchmark, self.num_dims,
                                              len(path))

            basis_centers = []
            for node in path:

                if prev_node_state.mode.name != node.state.mode.name:
                    if isinstance(node.state.parent.star.parent,
                                  DiscretePostParent):
                        basis_centers.append(
                            node.state.parent.star.parent.prestar_basis_center)
                        prev_node_state = node.state
                usafe_basis_preds = self.pv_object.compute_usafe_set_pred_in_star_basis(
                    node.state)
                for index in range(len(usafe_basis_preds)):
                    pred = usafe_basis_preds[index]
                    for basis_center in basis_centers[::-1]:
                        pred = self.pv_object.convert_usafe_basis_pred_in_basis_center(
                            pred, basis_center)
                    usafe_basis_preds[index] = pred

                no_of_constraints = len(usafe_basis_preds)
                con_matrix = np.zeros((no_of_constraints, self.num_dims),
                                      dtype=float)
                rhs = np.zeros(no_of_constraints, dtype=float)
                for idx in range(len(usafe_basis_preds)):
                    pred = usafe_basis_preds[idx]
                    pred_list = pred.vector.tolist()
                    for idy in range(len(pred_list)):
                        if pred_list[idy] != 0:
                            con_matrix[idx][idy] = pred_list[idy]
                    rhs[idx] = pred.value
                # print(con_matrix)
                polytope = Polytope(con_matrix, rhs)

                milp_instance.addPolytope(polytope)

            if regex is None:
                milp_instance.solve()
            else:
                milp_instance.solve(regex)

        Timers.toc("Time taken by MILP")
Exemple #14
0
 def generate_expressions(self):
     Timers.tic('BDD Traversal Time')
     current_node = self.root
     current_regex = ''
     valid_exps = []
     invalid_exps = []
     valid_exps, invalid_exps = self.traverse_subtree(current_node, current_regex, valid_exps, invalid_exps)
     Timers.toc('BDD Traversal Time')
     return valid_exps, invalid_exps
    def set_last_input_statuses(self, row_statuses, col_statuses):
        'set the statuses for the last-added input star'

        row_size = row_statuses.shape[0]
        col_size = col_statuses.shape[0]

        Timers.tic("lp set_statuses")
        LpInstance._set_last_input_statuses(self.lp_data, row_statuses,
                                            row_size, col_statuses, col_size)
        Timers.toc("lp set_statuses")
Exemple #16
0
    def simulate_vecs(self, start_list, steps, include_step_zero=False):
        '''simulate from each of the vector points, from the last state in self.vec_values'''

        Timers.tic("simulation")

        # create the linear (nonaffine) dynamics
        linear_dy = DyData(self.dy_data.sparse_a_matrix, None,
                           self.settings.sparse)

        sim_start_time = time.time()
        args = []

        for dim in range(self.num_dims):
            args.append([
                sim_start_time, start_list[dim], steps, include_step_zero,
                linear_dy, self.settings
            ])

        if self.settings.stdout:
            SHARED_NEXT_PRINT.value = sim_start_time + self.settings.print_interval_secs
            SHARED_COMPLETED_SIMS.value = 0

            mb_per_step = np.dtype(
                float
            ).itemsize * self.num_dims * self.num_dims / 1024.0 / 1024.0
            print("Simulating {} steps (~{:.2f} GB in memory)...".format(
                steps, steps * mb_per_step / 1024.0))

        result = self.parallel_sim(args)

        if self.settings.stdout:
            print("Total Simulation Time: {:.2f} secs".format(time.time() -
                                                              sim_start_time))

        Timers.toc("simulation")

        # need to convert the results to a list at each time step before returning
        transpose_start = time.time()

        rv = []

        for step in range(result[0].shape[0]):
            single_step_result = np.empty((self.num_dims, self.num_dims))

            for dim in range(self.num_dims):
                single_step_result[dim] = result[dim][step]

            rv.append(single_step_result)

        # was like 11.5 seconds for PDE transpose time
        if self.settings.stdout:
            print("Transpose time: {:.2f} secs".format(time.time() -
                                                       transpose_start))

        return rv
    def get_col_statuses(self, store):
        'get the col statuses of the current lp solution, and store then in the passed-in variable'

        size = store.shape[0]

        Timers.tic("lp get_statuses")
        rv = LpInstance._get_col_statuses(self.lp_data, store, size)
        Timers.toc("lp get_statuses")

        if rv != 0:
            raise RuntimeError("get_col_statuses failed")
    def set_standard_basis_statuses(self, row_statuses, col_statuses):
        'set the statuses for the standard variables / constraints and basis variables / constraints'

        row_size = row_statuses.shape[0]
        col_size = col_statuses.shape[0]

        Timers.tic("lp set_statuses")
        LpInstance._set_standard_basis_statuses(self.lp_data, row_statuses,
                                                row_size, col_statuses,
                                                col_size)
        Timers.toc("lp set_statuses")
Exemple #19
0
    def set_minimize_direction(self, direction_vec, is_csr=False, offset=None):
        '''set the direction for the optimization

        if offset is None, will use cur_vars_offset (direction is in terms of current-time variables)
        '''

        Timers.tic("set_minimize_direction")

        if offset is None:
            offset = self.cur_vars_offset

            size = direction_vec.shape[1] if is_csr else len(direction_vec)

            assert size <= self.dims, "len(direction_vec) ({}) > number of cur_vars({})".format(
                size, self.dims)
        else:
            assert direction_vec.shape[1] + offset <= self.get_num_cols()

        # set the previous objective columns to zero
        for i in self.obj_cols:
            glpk.glp_set_obj_coef(self.lp, i, 0)

        self.obj_cols = []

        if is_csr:
            assert isinstance(direction_vec, csr_matrix)
            assert direction_vec.shape[0] == 1

            data, inds, indptr = direction_vec.data, direction_vec.indices, direction_vec.indptr
            
            for n in range(indptr[1]):
                col = int(1 + offset + inds[n])
                self.obj_cols.append(col)

                if col > len(self.names):
                    print(self)
                    
                assert col <= len(self.names) 
                glpk.glp_set_obj_coef(self.lp, col, data[n])

        else: # non-csr
            if not isinstance(direction_vec, np.ndarray):
                direction_vec = np.array(direction_vec, dtype=float)

            assert len(direction_vec.shape) == 1
            assert len(direction_vec) <= self.dims, "dirLen({}) > dims({})".format(len(direction_vec), self.dims)

            for i, direction in enumerate(direction_vec):
                col = int(1 + offset + i)
                self.obj_cols.append(col)
                glpk.glp_set_obj_coef(self.lp, col, float(direction))

        Timers.toc("set_minimize_direction")
    def begin_replay(self, node):
        'begin a deaggregation replay with the passed-in node'

        Timers.tic('begin deagg replay')

        # remove all states in the waiting list that come from this node
        self.aggdag.remove_node_decendants_from_waiting_list(node)

        # start to populate waiting_nodes
        self.waiting_nodes.append((node, node.split()))

        Timers.toc('begin deagg replay')
Exemple #21
0
    def simulate_origin(self, start, steps, include_step_zero=False):
        '''simulate the origin, from the last point in self.origin_sim, for a certain number of steps'''

        Timers.tic("simulation")
        result = raw_sim_one(start,
                             steps,
                             self.dy_data,
                             self.settings,
                             include_step_zero=include_step_zero)
        Timers.toc("simulation")

        return result
Exemple #22
0
    def run(self, init_state_list):
        '''
        Run the computation (main entry point)

        init_star is the initial state

        fixed_dim_list, if used, is a list of dimensions with fixed initial values
        '''

        Timers.reset()
        Timers.tic("total")

        self.setup(init_state_list)

        if self.settings.plot.plot_mode == PlotSettings.PLOT_INTERACTIVE:
            # make sure to store plot result for on_click listener to report on
            self.print_verbose(
                f"Setting store_plot_result to true since PLOT_INTERACTIVE has click listener"
            )
            self.settings.plot.store_plot_result = True

        if self.settings.plot.store_plot_result:
            self.result.plot_data = PlotData(self.plotman.num_subplots)

        if self.settings.plot.plot_mode == PlotSettings.PLOT_NONE:
            self.run_to_completion()
        else:
            self.plotman.compute_and_animate()

        Timers.toc("total")

        if self.settings.stdout >= HylaaSettings.STDOUT_VERBOSE:
            Timers.print_stats()

        if self.result.has_concrete_error:
            self.print_normal(
                "Result: Error modes are reachable (found counter-example).\n")
        elif self.result.has_aggregated_error:
            self.print_normal("Result: System is safe, although error modes were reachable when aggregation " + \
                              "(overapproximation) was used.\n")
        else:
            self.print_normal(
                "Result: System is safe. Error modes are NOT reachable.\n")

        self.print_normal("Total Runtime: {:.2f} sec".format(
            Timers.top_level_timer.total_secs))

        # assign results
        self.result.top_level_timer = Timers.top_level_timer
        Timers.reset()

        return self.result
Exemple #23
0
def _find_init_simplex(dims, supp_point_func):
    '''
    find an n-dimensional initial simplex
    '''

    Timers.tic('init_simplex')

    # first, construct the initial simplex and determine a basis for the convex set (it may be degenerate)
    init_simplex = _find_two_points(dims, supp_point_func)

    if len(init_simplex
           ) == 2:  # S may be a degenerate shape consisting of a single point
        init_vec = init_simplex[1] - init_simplex[0]

        spanning_dirs = [init_vec]
        degenerate_dirs = []
        vecs = [init_vec]

        for _ in range(dims - 1):
            new_dir, rank = _get_orthonormal_rank(vecs)

            # min/max in direction v, checking if it increases the rank of vecs
            pt = supp_point_func(new_dir)
            vecs.append(pt - init_simplex[0])

            if _get_rank(vecs) > rank:
                init_simplex.append(pt)
                spanning_dirs.append(vecs[-1])
                continue

            # rank did not increase with maximize, try minimize
            vecs = vecs[0:-1]  # pop vec

            pt = supp_point_func(-1 * new_dir)
            vecs.append(pt - init_simplex[0])

            if _get_rank(vecs) > rank:
                init_simplex.append(pt)
                spanning_dirs.append(vecs[-1])
                continue

            # rank still didn't increase, new_dir is orthogonal to shape S
            vecs = vecs[0:-1]  # pop vec

            vecs.append(
                new_dir
            )  # forces a new orthonormal direction during the next iteration
            degenerate_dirs.append(new_dir)

    Timers.toc('init_simplex')

    return init_simplex
Exemple #24
0
 def simulate_origin_disc(self, start, steps, cur_step):
     Timers.tic("simulation")
     result = []
     prev_val = start
     for idx in range(cur_step, cur_step + steps, 1):
         a_exp = mat_pow(self.dy_data.dense_a_matrix, idx - 1)
         new_val = np.array(
             np.matmul(a_exp, self.dy_data.dense_b_vector).flatten().tolist(
             )[0]) + np.array(prev_val)
         prev_val = new_val
         result.append(new_val)
     Timers.toc("simulation")
     return result
Exemple #25
0
    def set_constraints_swigvec_rows(self, data_vec_list, indices_vec_list, count_list, row_offset):
        '''An optimized / lower level way to set row constraints compared with set_constraints_csr

        The passed in fields are a list of swig data vector and indices vectors (one for each row), as
        well as a row offset.
        '''

        Timers.tic('set_constraints_swigvec_rows')

        for row, (data, indices, count) in enumerate(zip(data_vec_list, indices_vec_list, count_list)):
            glpk.glp_set_mat_row(self.lp, 1 + row_offset + row, count, indices, data)

        Timers.toc('set_constraints_swigvec_rows')
Exemple #26
0
    def init_matrices(self):
        'initialize the one-step basis and input effects matrices'

        dims = self.dims
        Timers.tic('expm')
        self.one_step_matrix_exp = expm(self.a_csc * self.time_elapser.step_size)
        Timers.toc('expm')

        Timers.tic('toarray')
        self.one_step_matrix_exp = self.one_step_matrix_exp.toarray()
        Timers.toc('toarray')

        if self.b_csc is not None:
            self.one_step_input_effects_matrix = np.zeros(self.b_csc.shape, dtype=float)

            for c in range(self.time_elapser.inputs):
                # create the a_matrix augmented with a column of the b_matrix as an affine term
                indptr = self.b_csc.indptr

                data = np.concatenate((self.a_csc.data, self. b_csc.data[indptr[c]:indptr[c+1]]))
                indices = np.concatenate((self.a_csc.indices, self.b_csc.indices[indptr[c]:indptr[c+1]]))
                indptr = np.concatenate((self.a_csc.indptr, [len(data)]))

                aug_a_csc = csc_matrix((data, indices, indptr), shape=(dims + 1, dims + 1))

                mat = aug_a_csc * self.time_elapser.step_size

                # the last column of matrix_exp is the same as multiplying it by the initial state [0, 0, ..., 1]
                init_state = np.zeros(dims + 1, dtype=float)
                init_state[dims] = 1.0
                col = expm_multiply(mat, init_state)

                self.one_step_input_effects_matrix[:, c] = col[:dims]
    def add_standard_constraint(self, a_vec, b_val):
        '''add a constraint in the standard basis'''

        if len(a_vec.shape) == 1:
            w = a_vec.shape[0]
        else:
            h, w = a_vec.shape
            assert h == 1, "expected 1-d vector in add_standard_constaint()"

        Timers.tic("lp add_standard_constraint")
        LpInstance._add_standard_constraint(self.lp_data, a_vec, w, b_val)
        Timers.toc("lp add_standard_constraint")

        self.added_standard_constraint = True
Exemple #28
0
    def run_to_completion(self):
        'run the computation until it finishes (without plotting)'

        Timers.tic("total")

        while not self.is_finished():
            self.do_step()

        Timers.toc("total")

        if self.settings.print_output:
            LpInstance.print_stats()
            # Timers.print_stats()

        self.result.time = Timers.timers["total"].total_secs
Exemple #29
0
    def plot_current_star(self, star):
        '''
        plot the current SymbolicState according to the plot settings

        returns True if the plot was skipped (due to too many polyons on the screen
        '''

        skipped_plot = True

        if self.settings.plot_mode == PlotSettings.PLOT_MATLAB:
            verts = star.verts()

            self.add_reachable_poly_data(verts, star.mode.name)
        elif self.settings.plot_mode != PlotSettings.PLOT_NONE:
            Timers.tic("plot_current_star()")

            if self.draw_cur_step % self.draw_stride == 0:
                skipped_plot = False

                verts = star.verts()

                if self.settings.print_lp_at_each_step:
                    star.print_lp()

                self.shapes.set_cur_state(verts)

                if self.settings.label.axes_limits is None:
                    self.update_axis_limits(verts)

                # possibly thin out the reachable set of states
                max_polys = self.settings.max_shown_polys

                if max_polys > 0 and self.cur_reachable_polys >= max_polys:
                    self.shapes.thin_reachable_set()
                    self.cur_reachable_polys /= 2
                    self.draw_cur_step = 0
                    self.draw_stride *= 2

                self.cur_reachable_polys += 1

                self.shapes.add_reachable_poly(verts, star.parent,
                                               star.mode.name)

            self.draw_cur_step += 1

            Timers.toc("plot_current_star()")

        return skipped_plot
Exemple #30
0
    def compute_longest_ce(self, control_synth=False):
        start_node = self.reach_tree.nodes[0]
        # Timers.tic('New implementation Longest counter-example-1')
        # basis_centers = []
        # constraints_list = []
        # self.check_path_feasibility(start_node, direction, basis_centers, constraints_list)
        # Timers.toc('New implementation Longest counter-example-1')
        paths = []
        current_path = []
        Timers.tic(
            'New implementation Longest counter-example generation time')
        self.explore_tree_for_error_stars(start_node, current_path, paths)

        if len(paths) == 0:
            print("The system is safe.")
            lce_object = CeObject()
            return lce_object

        # print "Number of paths is '{}'".format(len(paths))
        longest_ce = None
        lce_length = 0
        lce_object = None
        # for node in paths[1]:
        #    print ("Loc: '{}' and time '{}'".format(node.state.mode.name, node.state.total_steps))
        for path in paths:
            ce_object = self.compute_longest_ce_in_a_path(path)
            print(" Paths {} {}\n".format(len(path), ce_object.ce_length))
            # print "Counterexample for this path is '{}' of length '{}'".format(ce, ce_length)
            if ce_object.ce_length >= lce_length:
                # longest_ce = ce_object.counterexample
                lce_length = ce_object.ce_length
                lce_object = ce_object

        if control_synth is True:
            assert len(paths) == 1
            switching_times = self.get_switching_times(paths[0], lce_object)
            print(switching_times)
            lce_object.switching_times = switching_times

        print("length: {} idx_i: {} idx_j: {}".format(lce_object.ce_length,
                                                      lce_object.start_index,
                                                      lce_object.end_index))

        Timers.toc(
            'New implementation Longest counter-example generation time')
        print("The longest counter-example is : '{}' with length '{}'".format(
            lce_object.counterexample, lce_object.ce_length))
        return lce_object