def test_rotated_aggregate(): 'tests rotated aggregation' mode = HybridAutomaton().new_mode('mode_name') lpi1 = lputil.from_box([[0, 1], [0, 1]], mode) lpi2 = lputil.from_box([[1, 2], [1, 2]], mode) sq2 = math.sqrt(2) / 2.0 agg_dirs = np.array([[sq2, sq2], [sq2, -sq2]], dtype=float) lpi = lputil.aggregate([lpi1, lpi2], agg_dirs, mode) assert lputil.is_point_in_lpi([0, 0], lpi) assert lputil.is_point_in_lpi([2, 2], lpi) assert lputil.is_point_in_lpi([1, 2], lpi) assert lputil.is_point_in_lpi([2, 1], lpi) assert lputil.is_point_in_lpi([0, 1], lpi) assert lputil.is_point_in_lpi([1, 0], lpi) verts = lpplot.get_verts(lpi) assert len(verts) == 5 for p in [(0.5, -0.5), (-0.5, 0.5), (2.5, 1.5), (1.5, 2.5)]: assert pair_almost_in(p, verts) assert verts[0] == verts[-1]
def test_box_aggregate3(): 'tests box aggregation with 3 boxes' mode = HybridAutomaton().new_mode('mode_name') lpi1 = lputil.from_box([[-2, -1], [-0.5, 0.5]], mode) lpi2 = lpi1.clone() lpi3 = lpi1.clone() basis2 = np.array([[0, 1], [-1, 0]], dtype=float) lputil.set_basis_matrix(lpi2, basis2) basis3 = np.array([[-1, 0], [0, -1]], dtype=float) lputil.set_basis_matrix(lpi3, basis3) plot_vecs = lpplot.make_plot_vecs(256, offset=0.1) # use an offset to prevent LP dir from being aligned with axis # bounds for lpi1 should be [[-2, -1], [-0.5, 0.5]] verts = lpplot.get_verts(lpi1, plot_vecs=plot_vecs) assert_verts_is_box(verts, [[-2, -1], [-0.5, 0.5]]) # bounds for lpi2 should be [[-0.5, 0.5], [1, 2]] verts = lpplot.get_verts(lpi2, plot_vecs=plot_vecs) assert_verts_is_box(verts, [[-0.5, 0.5], [1, 2]]) # bounds for lpi3 should be [[2, 1], [-0.5, 0.5]] verts = lpplot.get_verts(lpi3, plot_vecs=plot_vecs) assert_verts_is_box(verts, [[2, 1], [-0.5, 0.5]]) # box aggregation, bounds should be [[-2, 2], [-0.5, 2]] agg_dirs = np.identity(2) lpi = lputil.aggregate([lpi1, lpi2, lpi3], agg_dirs, mode) verts = lpplot.get_verts(lpi, plot_vecs=plot_vecs) assert_verts_is_box(verts, [[-2, 2], [-0.5, 2]])
def test_box_aggregate2(): 'tests box aggregation' mode = HybridAutomaton().new_mode('mode_name') lpi1 = lputil.from_box([[0, 1], [0, 1]], mode) lpi2 = lputil.from_box([[1, 2], [1, 2]], mode) agg_dirs = np.identity(2) # box aggregation lpi = lputil.aggregate([lpi1, lpi2], agg_dirs, mode) verts = lpplot.get_verts(lpi) assert_verts_is_box(verts, [[0, 2], [0, 2]]) # test setting basis matrix after aggregation lputil.set_basis_matrix(lpi, np.identity(2)) verts = lpplot.get_verts(lpi) assert_verts_is_box(verts, [[0, 2], [0, 2]]) lputil.set_basis_matrix(lpi, -1 * np.identity(2)) verts = lpplot.get_verts(lpi) assert_verts_is_box(verts, [[-2, 0], [-2, 0]])
def test_aggregate_self(): ''' test aggregation on an identical set. ''' mode = HybridAutomaton().new_mode('mode_name') lpi1 = lputil.from_box([[-2, -1], [-10, 20], [100, 200]], mode) lpi2 = lputil.from_box([[-2, -1], [-10, 20], [100, 200]], mode) agg_dirs = np.identity(3) # box aggregation lpi = lputil.aggregate([lpi1, lpi2], agg_dirs, mode) assert lpi.is_feasible() verts = lpplot.get_verts(lpi, xdim=0, ydim=1) assert_verts_is_box(verts, [[-2, -1], [-10, 20]]) verts = lpplot.get_verts(lpi, xdim=0, ydim=2) assert_verts_is_box(verts, [[-2, -1], [100, 200]]) # make sure no extra variables in lp names = lpi.get_names() expected_names = ["m0_i0", "m0_i1", "m0_i2", "m0_c0", "m0_c1", "m0_c2"] assert names == expected_names assert lpi.get_num_rows() == 3 + 3*2
def test_aggregate3(): 'tests aggregation of 3 sets, inspired by the harmonic oscillator system' mode = HybridAutomaton().new_mode('mode_name') lpi1 = lputil.from_box([[0, 1], [0, 1]], mode) # middle set is a diamond mat = [[1, 1], [-1, -1], [1, -1], [-1, 1]] s = 3.5 rhs = [6+s, -(6-s), s, s] lpi2 = lputil.from_constraints(mat, rhs, mode) lpi3 = lputil.from_box([[5, 6], [5, 6]], mode) lpi_list = [lpi1, lpi2, lpi3] verts = [] for lpi in lpi_list: verts += lpplot.get_verts(lpi) #xs, ys = zip(*lpplot.get_verts(lpi)) #plt.plot(xs, ys, 'k-') random.seed(0) for _ in range(10): random_mat = np.random.rand(2, 2) agg_dirs = lputil.reorthogonalize_matrix(random_mat, 2) lpi = lputil.aggregate(lpi_list, agg_dirs, mode) #xs, ys = zip(*lpplot.get_verts(lpi)) #plt.plot(xs, ys, 'r--') for vert in verts: assert lputil.is_point_in_lpi(vert, lpi)
def test_aggregate_on_subspace(): ''' test aggregation when the dynamics and sets are only on a subspace. ''' # dynamics are x' == 1, y' == 0, a' == 0 # lpi1 is [0, 1] x [0, 1] x [1, 1] # lpi2 is [3, 4] x [0, 1] x [1, 1] # aggregation shouldn't need to introduce a variable along the y direction mode = HybridAutomaton().new_mode('mode_name') lpi1 = lputil.from_box([[0, 1], [0, 1], [1, 1]], mode) lpi2 = lputil.from_box([[4, 5], [0, 1], [1, 1]], mode) #a_csr = csr_matrix(np.array([[0, 0, 1], [0, 0, 0], [0, 0, 0]], dtype=float)) sqr = math.sqrt(2) / 2 agg_dirs = np.array([[1, 0, 0], [0, sqr, sqr], [0, sqr, -sqr]], dtype=float) # box aggregation lpi = lputil.aggregate([lpi1, lpi2], agg_dirs, mode) # lpi1 corners for pt in [(0, 0, 1), (0, 1, 1), (1, 0, 1), (1, 1, 1)]: assert lputil.is_point_in_lpi(pt, lpi) # lpi2 corners for pt in [(4, 0, 1), (4, 1, 1), (5, 0, 1), (5, 1, 1)]: assert lputil.is_point_in_lpi(pt, lpi) # make sure we have new variable names names = lpi.get_names() expected_names = ["m0_i0", "m0_i1", "m0_i2", "m0_c0", "m0_c1", "m0_c2"] assert names == expected_names
def aggregate_box_arnoldi(agg_list, op_list, is_box, is_arnoldi, add_guard, print_func): ''' perform template-based aggregation on the passed-in list of states Currently, this can either use box template directions or arnoldi (+box) template directions ''' assert is_box or is_arnoldi min_step = min([state.cur_steps_since_start[0] for state in agg_list]) max_step = max([state.cur_steps_since_start[1] for state in agg_list]) step_interval = [min_step, max_step] print_func("Aggregation time step interval: {}".format(step_interval)) # create a new state from the aggregation postmode = agg_list[0].mode postmode_dims = postmode.a_csr.shape[0] mid_index = len(agg_list) // 2 op = op_list[mid_index] if is_box or op is None: agg_dir_mat = np.identity(postmode_dims) elif is_arnoldi: # aggregation with a predecessor, use arnoldi directions in predecessor mode in center of # middle aggregagted state, then project using the reset, and reorthogonalize premode = op.parent_node.stateset.mode t = op.transition print_func("aggregation point: {}".format(op.premode_center)) premode_dir_mat = lputil.make_direction_matrix(op.premode_center, premode.a_csr) print_func("premode dir mat:\n{}".format(premode_dir_mat)) if t.reset_csr is None: agg_dir_mat = premode_dir_mat else: projected_dir_mat = premode_dir_mat * t.reset_csr.transpose() print_func("projected dir mat:\n{}".format(projected_dir_mat)) # re-orthgohonalize (and create new vectors if necessary) agg_dir_mat = lputil.reorthogonalize_matrix(projected_dir_mat, postmode_dims) # also add box directions in target mode (if they don't already exist) box_dirs = [] for dim in range(postmode_dims): direction = [0 if d != dim else 1 for d in range(postmode_dims)] exists = False for row in agg_dir_mat: if np.allclose(direction, row): exists = True break if not exists: box_dirs.append(direction) if box_dirs: agg_dir_mat = np.concatenate((agg_dir_mat, box_dirs), axis=0) if op and add_guard: # add all the guard conditions to the agg_dir_mat t = op.transition if t.reset_csr is None: # identity reset guard_dir_mat = t.guard_csr else: # multiply each direction in the guard by the reset guard_dir_mat = t.guard_csr * t.reset_csr.transpose() if guard_dir_mat.shape[0] > 0: agg_dir_mat = np.concatenate((agg_dir_mat, guard_dir_mat.toarray()), axis=0) print_func("agg dir mat:\n{}".format(agg_dir_mat)) lpi_list = [state.lpi for state in agg_list] new_lpi = lputil.aggregate(lpi_list, agg_dir_mat, postmode) return StateSet(new_lpi, agg_list[0].mode, step_interval, op_list, is_concrete=False)