Пример #1
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
Пример #2
0
def test_from_box():
    'tests from_box constructor'

    l = [[-5, -4], [0, 1]]
    box = lpset.from_box(l)

    assert_verts_is_box(box.verts(), l)
Пример #3
0
def test_verts():
    'tests verts'

    lpi = lputil.from_box([[-5, -4], [0, 1]],
                          HybridAutomaton().new_mode('mode_name'))

    plot_vecs = lpplot.make_plot_vecs(4, offset=(math.pi / 4.0))
    verts = lpplot.get_verts(lpi, plot_vecs=plot_vecs)

    assert_verts_is_box(verts, [(-5, -4), (0, 1)])
Пример #4
0
def test_scale():
    'tests scale'

    lpi = lputil.from_box([[4, 5], [-1, 1]],
                          HybridAutomaton().new_mode('mode_name'))

    lputil.scale_with_bm(lpi, 2.0)

    verts = lpplot.get_verts(lpi)

    assert_verts_is_box(verts, [(8, 10), (-2, 2)])
Пример #5
0
def test_bloat():
    'tests bloat'

    lpi = lputil.from_box([[-5, -4], [0, 1]],
                          HybridAutomaton().new_mode('mode_name'))

    lputil.bloat(lpi, 0.5)

    verts = lpplot.get_verts(lpi)

    assert_verts_is_box(verts, [(-5.5, -3.5), (-0.5, 1.5)])
Пример #6
0
def test_minkowski_sum_box():
    'tests minkowski_sum with 2 box sets'

    mode = HybridAutomaton().new_mode('mode_name')

    lpi1 = lputil.from_box([[-1, 1], [-2, 2]], mode)
    lpi2 = lputil.from_box([[-.1, .1], [-.2, .2]], mode)

    lpi = lputil.minkowski_sum([lpi1, lpi2], mode)

    verts = lpplot.get_verts(lpi)

    assert_verts_is_box(verts, [(-1.1, 1.1), (-2.2, 2.2)])
Пример #7
0
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]])
Пример #8
0
def test_over_time_range():
    'test plotting over time with aggergation (time range)'

    ha = HybridAutomaton()

    mode_a = ha.new_mode('A')
    mode_b = ha.new_mode('B')
 
    # dynamics: x' = a, a' = 0
    mode_a.set_dynamics([[0, 1], [0, 0]])
    mode_b.set_dynamics([[0, 1], [0, 0]])

    # invariant: x <= 2.5
    mode_a.set_invariant([[1, 0]], [2.5])

    trans1 = ha.new_transition(mode_a, mode_b, 'first')
    trans1.set_guard_true()

    # initial set has x0 = [0, 0]
    init_lpi = lputil.from_box([(0, 0), (1, 1)], mode_a)
    init_list = [StateSet(init_lpi, mode_a)]

    # settings, step size = 1.0
    settings = HylaaSettings(1.0, 4.0)
    settings.stdout = HylaaSettings.STDOUT_DEBUG
    settings.process_urgent_guards = True
    settings.plot.plot_mode = PlotSettings.PLOT_NONE
    settings.plot.store_plot_result = True
    settings.plot.xdim_dir = None
    settings.plot.ydim_dir = 0

    result = Core(ha, settings).run(init_list)

    polys = [obj[0] for obj in result.plot_data.mode_to_obj_list[0][mode_b.name]]
    # expected with aggegregation: [0, 2.5] -> [1, 3.5] -> [2, 4.5] -> [3, 5.5] -> [4, 6.5]

    # 4 steps because invariant is allowed to be false for the final step
    assert len(polys) == 5, "expected invariant to become false after 5 steps"

    for i in range(5):
        assert_verts_is_box(polys[i], [[i, i + 3.0], [i, i + 3.0]])
Пример #9
0
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]])
Пример #10
0
def test_invariants():
    'test invariant trimming'

    ha = HybridAutomaton()

    mode = ha.new_mode('mode')
 
    # dynamics: x' = 1, y' = 1, a' = 0
    mode.set_dynamics([[0, 0, 1], [0, 0, 1], [0, 0, 0]])

    # invariant: x <= 2.5
    mode.set_invariant([[1, 0, 0]], [2.5])

    # initial set has x0 = [0, 1]
    init_lpi = lputil.from_box([(0, 1), (0, 1), (1, 1)], mode)
    init_list = [StateSet(init_lpi, mode)]

    # settings, step size = 1.0
    settings = HylaaSettings(1.0, 5.0)
    settings.stdout = HylaaSettings.STDOUT_VERBOSE
    settings.plot.store_plot_result = True

    result = Core(ha, settings).run(init_list)

    # check the reachable state
    polys = [obj[0] for obj in result.plot_data.mode_to_obj_list[0][mode.name]]

    # 4 steps because invariant is allowed to be false for the final step
    assert len(polys) == 4, "expected invariant to become false after 4 steps"

    assert_verts_is_box(polys[0], [[0, 1], [0, 1]])

    assert_verts_is_box(polys[1], [[1, 2], [1, 2]])

    assert_verts_is_box(polys[2], [[2, 3], [2, 3]])

    assert_verts_is_box(polys[3], [[3, 3.5], [3, 4]])
Пример #11
0
def test_agg_to_more_vars():
    'test the aggregation of states with a reset to a mode with new variables'

    ha = HybridAutomaton()

    # mode one: x' = 1, a' = 0 
    m1 = ha.new_mode('m1')
    m1.set_dynamics([[0, 1], [0, 0]])

    # mode two: x' = 0, a' = 0, y' == 1 
    m2 = ha.new_mode('m2')
    m2.set_dynamics([[0, 0, 0], [0, 0, 0], [0, 1, 0]])

    # invariant: x <= 3.0
    m1.set_invariant([[1, 0]], [3.0])

    # guard: True
    trans1 = ha.new_transition(m1, m2, 'trans1')
    trans1.set_guard_true()

    reset_mat = [[1, 0], [0, 1], [0, 0]]
    reset_minkowski = [[0], [0], [1]]
    reset_minkowski_constraints = [[1], [-1]]
    reset_minkowski_rhs = [3, -3] # y0 == 3
    
    trans1.set_reset(reset_mat, reset_minkowski, reset_minkowski_constraints, reset_minkowski_rhs)

    # initial set has x0 = [0, 1], a = 1
    init_lpi = lputil.from_box([(0, 1), (1, 1)], m1)
    init_list = [StateSet(init_lpi, m1)]

    # settings, step size = 1.0
    settings = HylaaSettings(1.0, 4.0)
    settings.stdout = HylaaSettings.STDOUT_DEBUG
    settings.plot.plot_mode = PlotSettings.PLOT_NONE
    settings.plot.store_plot_result = True
    settings.plot.xdim_dir = 0
    settings.plot.ydim_dir = {'m1': 1, 'm2': 2}

    result = Core(ha, settings).run(init_list)

    polys = [obj[0] for obj in result.plot_data.mode_to_obj_list[0]['m1']]

    # 4 steps because invariant is allowed to be false for the final step
    assert 4 <= len(polys) <= 5, "expected invariant to become false after 4/5 steps"

    assert_verts_is_box(polys[0], [[0, 1], [1, 1]])
    assert_verts_is_box(polys[1], [[1, 2], [1, 1]])
    assert_verts_is_box(polys[2], [[2, 3], [1, 1]])
    assert_verts_is_box(polys[3], [[3, 4], [1, 1]])

    polys = [obj[0] for obj in result.plot_data.mode_to_obj_list[0]['m2']]

    assert_verts_is_box(polys[0], [[1, 4], [3, 3]])
    assert_verts_is_box(polys[1], [[1, 4], [4, 4]])
Пример #12
0
def test_plain():
    'test plain aggregation of states across discrete transitions'

    # m1 dynamics: x' == 1, y' == 0, x0, y0: [0, 1], step: 1.0
    # m1 invariant: x <= 3
    # m1 -> m2 guard: True
    # m2 dynamics: x' == 0, y' == 1
    # time bound: 4
    # excepted final states to be: x: [0, 4], y: [4,5]
    # x is [1, 4] because no transitions are allowed at step 0 (simulation-equiv semantics) and a transition is
    #        allowed one step after the invariant becomes false
    # y is [4,5] because after aggregation, the time elapsed for the aggregated set will be 0.0, the minimum

    ha = HybridAutomaton()

    # mode one: x' = 1, y' = 0, a' = 0 
    m1 = ha.new_mode('m1')
    m1.set_dynamics([[0, 0, 1], [0, 0, 0], [0, 0, 0]])

    # mode two: x' = 0, y' = 1, a' = 0 
    m2 = ha.new_mode('m2')
    m2.set_dynamics([[0, 0, 0], [0, 0, 1], [0, 0, 0]])

    # invariant: x <= 3.0
    m1.set_invariant([[1, 0, 0]], [3.0])

    # guard: True
    trans1 = ha.new_transition(m1, m2, 'trans1')
    trans1.set_guard(csr_matrix((0, 0)), [])

    # initial set has x0 = [0, 1], t = [0, 1], a = 1
    init_lpi = lputil.from_box([(0, 1), (0, 1), (1, 1)], m1)
    init_list = [StateSet(init_lpi, m1)]

    # settings, step size = 1.0
    settings = HylaaSettings(1.0, 4.0)
    settings.stdout = HylaaSettings.STDOUT_DEBUG
    settings.plot.plot_mode = PlotSettings.PLOT_NONE
    settings.plot.store_plot_result = True

    core = Core(ha, settings)
    result = core.run(init_list)

    # check history
    state = result.last_cur_state

    assert state.mode == m2
    assert len(state.aggdag_op_list) > 1
    
    op0 = state.aggdag_op_list[0]
    op1 = state.aggdag_op_list[1]
    assert isinstance(op0, OpTransition)

    assert len(core.aggdag.roots) == 1
   
    assert op0.child_node.stateset.mode is m2
    assert op0.transition == trans1
    assert op0.parent_node == core.aggdag.roots[0]
    assert isinstance(op0.poststate, StateSet)
    assert op0.step == 1
    assert isinstance(op0.child_node, AggDagNode)
    assert op0.child_node == op1.child_node
    assert op0.child_node not in core.aggdag.roots

    assert len(op0.parent_node.stateset.aggdag_op_list) == 1
    assert op0.parent_node.stateset.aggdag_op_list[0] is None
     
    # check polygons in m2
    polys2 = [obj[0] for obj in result.plot_data.mode_to_obj_list[0]['m2']]

    assert 4 <= len(polys2) <= 5

    assert_verts_is_box(polys2[0], [[1, 4], [0, 1]])
    assert_verts_is_box(polys2[1], [[1, 4], [1, 2]])
    assert_verts_is_box(polys2[2], [[1, 4], [2, 3]])
    assert_verts_is_box(polys2[3], [[1, 4], [3, 4]])
Пример #13
0
def test_inputs_reset():
    'test a system with both inputs and a reset'

    # 2-d system with one input
    # x' = x, y' = u, u \in [1, 1]
    # x0 = 1, y0 = 0
    # inv1: y <= 2.5
    
    # guard: y >= 2.5
    # reset: x := 1, y += 2 [should go from (e^3, 3.0) -> (1, 5.0)]

    # mode2:
    # x' = 2x, y' = Bu, u \in [1, 2], B = 2
    # (1, 5.0) -> (e^2, [7, 9]) -> (e^4, [9, 13])

    # mode2 -> error y >= 13

    ha = HybridAutomaton()
    m1 = ha.new_mode('m1')
    m1.set_dynamics([[1, 0], [0, 0]])
    m1.set_inputs([[0], [1]], [[1], [-1]], [1, -1], allow_constants=True)
    m1.set_invariant([[0, 1]], [2.5])

    m2 = ha.new_mode('m2')
    m2.set_dynamics([[2, 0], [0, 0]])
    m2.set_inputs([[0], [2]], [[1], [-1]], [2, -1])

    error = ha.new_mode('error')

    t1 = ha.new_transition(m1, m2)
    t1.set_guard([[0, -1]], [-2.5]) # y >= 2.5
    reset_mat = [[0, 0], [0, 1]]
    min_mat = np.identity(2)
    min_cons = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    min_rhs = [1, -1, 2, -2]
    t1.set_reset(reset_mat, min_mat, min_cons, min_rhs)

    t2 = ha.new_transition(m2, error)
    t2.set_guard([0, -1], [-13]) # y >= 13

    init_box = [[1, 1], [0, 0]]
    lpi = lputil.from_box(init_box, m1)

    settings = HylaaSettings(1.0, 10.0)
    settings.stdout = HylaaSettings.STDOUT_VERBOSE
    settings.plot.store_plot_result = True
    settings.plot.plot_mode = PlotSettings.PLOT_NONE

    core = Core(ha, settings)
    init_list = [StateSet(lpi, m1)]
    core.setup(init_list)

    core.do_step() # pop
    core.do_step() # continuous_post() to time 1

    lpi = core.result.last_cur_state.lpi

    assert lpi.get_names() == ['m0_i0', 'm0_i1', 'm0_c0', 'm0_c1', 'm0_ti0', 'm0_ti1', 'm0_I0']

    assert_verts_is_box(lpplot.get_verts(lpi), [[math.exp(1), math.exp(1)], [1, 1]])

    core.do_step() # continuous_post() to time 2
    assert_verts_is_box(lpplot.get_verts(core.result.last_cur_state.lpi), [[math.exp(2), math.exp(2)], [2, 2]])

    core.do_step() # continuous_post() to time 3
    assert_verts_is_box(lpplot.get_verts(core.result.last_cur_state.lpi), [[math.exp(3), math.exp(3)], [3, 3]])

    core.do_step() # trim to invariant
    assert core.aggdag.get_cur_state() is None
    assert len(core.aggdag.waiting_list) == 1

    core.run_to_completion()

    result = core.result

    # reset: x := 1, y += 2 [should go from (e^3, 3.0) -> (1, 5.0)]
    # (1, 5.0) -> (e^2, [7, 9]) -> (e^4, [9, 13])
    polys2 = [obj[0] for obj in result.plot_data.mode_to_obj_list[0]['m2']]
    assert_verts_is_box(polys2[0], [[1, 1], [5, 5]])
    assert_verts_is_box(polys2[1], [[math.exp(2), math.exp(2)], [7, 9]])
    assert_verts_is_box(polys2[2], [[math.exp(4), math.exp(4)], [9, 13]])
    assert len(polys2) == 3

    # check counterexamples
    assert len(result.counterexample) == 2
    
    c1 = result.counterexample[0]
    assert c1.mode == m1
    assert c1.outgoing_transition == t1
    assert np.allclose(c1.start, [1, 0])
    assert np.allclose(c1.end, [math.exp(3), 3])
    assert len(c1.reset_minkowski_vars) == 2
    assert abs(c1.reset_minkowski_vars[0] - 1) < 1e-9
    assert abs(c1.reset_minkowski_vars[1] - 2) < 1e-9

    assert len(c1.inputs) == 3
    for i in c1.inputs:
        assert len(i) == 1
        assert abs(i[0] - 1) < 1e-9

    c2 = result.counterexample[1]
    assert c2.mode == m2
    assert c2.outgoing_transition == t2
    assert np.allclose(c2.start, [1, 5])
    assert np.allclose(c2.end, [math.exp(4), 13])
    assert not c2.reset_minkowski_vars
    assert len(c2.inputs) == 2

    for i in c2.inputs:
        assert len(i) == 1
        assert abs(i[0] - 2) < 1e-9
Пример #14
0
def test_box_inputs():
    'tests from_box with a simple input effects matrix'

    # x' = Ax + Bu
    # A = 0
    # B = [[1, 0], [0, 2]]
    # u1 and u2 are bounded between [1, 10]

    # (init) step 0: [0, 1] x [0, 1]
    # step 1: [1, 11] x [2, 21]
    # step 2: [2, 21] x [4, 41]

    mode = HybridAutomaton().new_mode('mode_name')
    mode.set_dynamics(np.zeros((2, 2)))
    mode.set_inputs([[1, 0], [0, 2]], [[1, 0], [-1, 0], [0, 1], [0, -1]],
                    [10, -1, 10, -1])

    init_box = [[0, 1], [0, 1]]
    lpi = lputil.from_box(init_box, mode)

    assert lpi.basis_mat_pos == (0, 0)
    assert lpi.dims == 2
    assert lpi.cur_vars_offset == 2
    assert lpi.input_effects_offsets == (
        6, 4)  # row 6, column 4 for total input effects offsets

    # step 0
    mat = lpi.get_full_constraints()
    types = lpi.get_types()
    rhs = lpi.get_rhs()
    names = lpi.get_names()

    expected_mat = np.array([\
        [1, 0, -1, 0, 1, 0], \
        [0, 1, 0, -1, 0, 1], \
        [-1, 0, 0, 0, 0, 0], \
        [1, 0, 0, 0, 0, 0], \
        [0, -1, 0, 0, 0, 0], \
        [0, 1, 0, 0, 0, 0], \
        [0, 0, 0, 0, -1, 0], \
        [0, 0, 0, 0, 0, -1]], dtype=float)

    expected_vec = np.array([0, 0, 0, 1, 0, 1, 0, 0], dtype=float)

    fx = glpk.GLP_FX
    up = glpk.GLP_UP
    expected_types = [fx, fx, up, up, up, up, fx, fx]

    expected_names = ["m0_i0", "m0_i1", "m0_c0", "m0_c1", "m0_ti0", "m0_ti1"]

    assert np.allclose(rhs, expected_vec)
    assert types == expected_types
    assert np.allclose(mat.toarray(), expected_mat)
    assert names == expected_names

    verts = lpplot.get_verts(lpi)
    assert_verts_is_box(verts, init_box)

    # do step 1
    mode.init_time_elapse(1.0)
    basis_mat, input_mat = mode.time_elapse.get_basis_matrix(1)

    lputil.set_basis_matrix(lpi, basis_mat)
    lputil.add_input_effects_matrix(lpi, input_mat, mode)

    mat = lpi.get_full_constraints()
    types = lpi.get_types()
    rhs = lpi.get_rhs()
    names = lpi.get_names()

    expected_mat = np.array([\
        [1, 0, -1, 0, 1, 0, 0, 0], \
        [0, 1, 0, -1, 0, 1, 0, 0], \
        [-1, 0, 0, 0, 0, 0, 0, 0], \
        [1, 0, 0, 0, 0, 0, 0, 0], \
        [0, -1, 0, 0, 0, 0, 0, 0], \
        [0, 1, 0, 0, 0, 0, 0, 0], \
        [0, 0, 0, 0, -1, 0, 1, 0], \
        [0, 0, 0, 0, 0, -1, 0, 2], \
        [0, 0, 0, 0, 0, 0, 1, 0], \
        [0, 0, 0, 0, 0, 0, -1, 0], \
        [0, 0, 0, 0, 0, 0, 0, 1], \
        [0, 0, 0, 0, 0, 0, 0, -1]], dtype=float)

    expected_vec = np.array([0, 0, 0, 1, 0, 1, 0, 0, 10, -1, 10, -1],
                            dtype=float)

    fx = glpk.GLP_FX
    up = glpk.GLP_UP
    expected_types = [fx, fx, up, up, up, up, fx, fx, up, up, up, up]

    expected_names = [
        "m0_i0", "m0_i1", "m0_c0", "m0_c1", "m0_ti0", "m0_ti1", "m0_I0",
        "m0_I1"
    ]

    assert np.allclose(rhs, expected_vec)
    assert types == expected_types
    assert np.allclose(mat.toarray(), expected_mat)
    assert names == expected_names

    verts = lpplot.get_verts(lpi)

    assert_verts_is_box(verts, [(1, 11), (2, 21)])

    # do step 2
    basis_mat, input_mat = mode.time_elapse.get_basis_matrix(2)
    lputil.set_basis_matrix(lpi, basis_mat)
    lputil.add_input_effects_matrix(lpi, input_mat, mode)

    verts = lpplot.get_verts(lpi)
    assert_verts_is_box(verts, [(2, 21), (4, 41)])