Esempio n. 1
0
def prefix_suffix_feasible(problem_data, verbosity=1, solver=None):
    """
    Define and solve a mode-counting synthesis problem
    with a prefix-suffix strategy.
     
    Inputs:
        
    * *problem_data*: dictionary with the following fields:

      * ``'graph'``			: mode-transition graph G
      * ``'init'``			: initial configuration in G    
      * ``'horizon'``       : length of strategy prefix part
      * ``'cycle_set'``     : set of cycles from which suffix part is formed
      * ``'mode'``          : mode to count
      * ``'lb_suffix'``     : lower mode-counting bound in suffix phase
      * ``'ub_suffix'``     : upper mode-counting bound in suffix phase

      Optional fields

      * ``'lb_prefix'``       : lower mode-counting bound in prefix phase (default: lb_suffix)
      * ``'ub_prefix'``       : upper mode-counting bound in prefix phase (default: ub_suffix)
      * ``'order_function'``  : a function that is a bijection that maps nodes in G to integers :math:`[0, 1, \ldots , N]`  (default: G.nodes().index)
      * ``'forbidden_nodes'`` : nodes in G that can not be visited (default: [])
      * ``'ilp'``             : if true, solve as ILP (default: ``True``)

    * *verbosity*: level of verbosity

    Output: a dictionary with the following fields:

    * ``'controls'``        : prefix part u of strategy, u[:,t] is control at time t
    * ``'states'``          : states x generated by u, x[:,t] is state at time t
    * ``'cycles'``          : suffix cycles
    * ``'assignments'``     : suffix assignments
     
    Example: see example_simple.py
    """

    G, T, N, ilp, order_fcn, forbidden_nodes = _extract_arguments(problem_data)

    # clean cycle set from forbidden nodes
    cycle_set = _clean_cycle_set(problem_data["cycle_set"], forbidden_nodes)

    # variables: u[0], ..., u[T-1], x[0], ..., x[T], a[0], ..., a[C-1],
    # 		     lb[0], ..., lb[C-1], ub[0], ... ub[C-1]
    N_u = T * N  # input vars
    N_x = (T + 1) * N  # state vars
    N_cycle_tot = sum([len(cycle) for cycle in cycle_set])  # cycle vars
    N_bound = len(cycle_set)  # lb/ub vars

    N_tot = N_u + N_x + N_cycle_tot + 2 * N_bound

    print "Setting up LP.. \n"
    lp_start = time.time()

    ################################
    # Initialize basic constraints #
    ################################
    Aeq, beq, Aiq, biq = _ux_constraints(G, problem_data["init"], T, order_fcn, forbidden_nodes)
    Aeq = scipy.sparse.bmat([[Aeq, _coo_zeros(Aeq.shape[0], N_cycle_tot + 2 * N_bound)]])
    Aiq = scipy.sparse.bmat([[Aiq, _coo_zeros(Aiq.shape[0], N_cycle_tot + 2 * N_bound)]])

    ###############################
    ##### Time T constraints ######
    ###############################
    Psi_mats = [_cycle_indices(G, cycle, order_fcn) for cycle in cycle_set]
    Aeq = _sparse_vstack(Aeq, scipy.sparse.bmat([[_stacked_eye(G), -scipy.sparse.bmat([Psi_mats])]]), N_u + N * T)
    beq = np.hstack([beq, np.zeros(len(G))])

    ###############################
    ##### Prefix mode-count #######
    ###############################
    try:
        lb_prefix = problem_data["lb_prefix"]
        ub_prefix = problem_data["ub_prefix"]
    except:
        lb_prefix = problem_data["lb_suffix"]
        ub_prefix = problem_data["ub_suffix"]

    Aiq_new, biq_new = _prefix_mc(G, T, N, problem_data["mode"], lb_prefix, ub_prefix)
    Aiq = _sparse_vstack(Aiq, Aiq_new, N_u)
    biq = np.hstack([biq, biq_new])

    ###############################
    ##### Suffix mode-count #######
    ###############################

    # Individual cycles bounds
    Aiq_new, biq_new = _suffix_mc(G, cycle_set, problem_data["mode"])
    Aiq = _sparse_vstack(Aiq, Aiq_new, N_u + N_x)
    biq = np.hstack([biq, biq_new])

    # Aggregate cycle bounds: sum(ub) < ub_tot, lb_tot < sum(lb)
    Aiq_new = scipy.sparse.block_diag((-np.ones([1, N_bound]), np.ones([1, N_bound])))
    Aiq = _sparse_vstack(Aiq, Aiq_new, N_u + N_x + N_cycle_tot)
    biq = np.hstack([biq, np.array([-problem_data["lb_suffix"], problem_data["ub_suffix"]])])

    ###############################
    #### Positive assignments #####
    ###############################
    Aiq = _sparse_vstack(Aiq, -scipy.sparse.identity(N_cycle_tot), N_u + N_x)
    biq = np.hstack([biq, np.zeros(N_cycle_tot)])

    if verbosity >= 1:
        time.time()
        print "It took ", time.time() - lp_start, " to set up (I)LP"

    ##############################################################
    ##############################################################
    ##############################################################

    if verbosity >= 1:
        print "solving (I)LP..."
        solve_start = time.time()

    if ilp:
        lp_sln = solve_mip(np.zeros(N_tot), Aiq, biq, Aeq, beq, set(range(N_u)), solver=solver)
    else:
        lp_sln = solve_lp(np.zeros(N_tot), Aiq, biq, Aeq, beq, solver=solver)

    if verbosity >= 1:
        print "It took ", time.time() - solve_start, " to solve (I)LP"

    sol = _extract_solution(lp_sln["x"], N, T, cycle_set)

    if verbosity >= 2:
        _print_sol(G, problem_data["mode"], sol)

    return sol
Esempio n. 2
0
def prefix_feasible(problem_data, verbosity=1, solver=None):
    """
    Define and solve the prefix part of a mode-counting 
    synthesis problem (requires a given suffix part)
     
    Inputs:

    * *problem_data*: dictionary with the following fields:

      * ``'graph'``			: mode-transition graph G
      * ``'init'``			: initial configuration in G    
      * ``'horizon'``		: length of strategy prefix part
      * ``'cycle_set'``     : cycles to form suffix part
      * ``'assignments'``   : assignments to ``'cycle_set'``
      * ``'mode'``          : mode to count
      * ``'lb_prefix'``     : lower mode-counting bound in prefix phase
      * ``'ub_prefix'``     : upper mode-counting bound in prefix phase

      Optional fields

      * ``'order_function'`` : a function that is a bijection that maps nodes in G to integers :math:`[0, 1, \ldots , N]`  (default: G.nodes().index)
      * ``'forbidden_nodes'``: nodes in G that can not be visited (default: [])
      * ``'ilp'``            : if true, solve as ILP (default: ``True``)

    * *verbosity*: level of verbosity
        
    Output: a dictionary with the following fields:

    * ``'controls'``       : prefix part u of strategy, u[:,t] is control at time t
    * ``'states'``         : states x generated by u, x[:,t] is state at time t
    * ``'cycles'``         : suffix cycles (same as input)
    * ``'assignments'``    : suffix assignments (same as input)
	"""
    G, T, N, ilp, order_fcn, forbidden_nodes = _extract_arguments(problem_data)

    # variables: u[0], ..., u[T-1], x[0], ..., x[T]
    N_u = T * N  # input vars
    N_x = (T + 1) * N  # state vars

    N_tot = N_u + N_x

    if verbosity:
        lp_start = time.time()
        print "Setting up LP.."

    ################################
    # Initialize basic constraints #
    ################################
    Aeq, beq, Aiq, biq = _ux_constraints(G, problem_data["init"], T, order_fcn, forbidden_nodes)

    ###############################
    ##### Time T constraints ######
    ###############################
    Psi_mats = [_cycle_indices(G, cycle, order_fcn) for cycle in problem_data["cycle_set"]]
    Aeq = _sparse_vstack(Aeq, _stacked_eye(G), N_u + N * T)
    beq = np.hstack(
        [
            beq,
            np.sum(
                [
                    _cycle_indices(G, cycle, order_fcn).dot(ass)
                    for cycle, ass in zip(problem_data["cycle_set"], problem_data["assignments"])
                ],
                0,
            ),
        ]
    )

    ###############################
    ##### Prefix mode-count #######
    ###############################
    Aiq_new, biq_new = _prefix_mc(G, T, N, problem_data["mode"], problem_data["lb_prefix"], problem_data["ub_prefix"])
    Aiq = _sparse_vstack(Aiq, Aiq_new, N_u)
    biq = np.hstack([biq, biq_new])

    if verbosity >= 1:
        print "It took ", time.time() - lp_start, " to set up (I)LP"

    ##############################################################
    ##############################################################
    ##############################################################

    if verbosity >= 1:
        print "solving (I)LP..."
        solve_start = time.time()

    if ilp:
        lp_sln = solve_mip(np.zeros(N_tot), Aiq, biq, Aeq, beq, set(range(N_u)), solver=solver)
    else:
        lp_sln = solve_lp(np.zeros(N_tot), Aiq, biq, Aeq, beq, solver=solver)

    if verbosity >= 1:
        print "It took ", time.time() - solve_start, " to solve (I)LP"

    sol = _extract_solution_state(lp_sln["x"], N, T)
    sol["assignments"] = problem_data["assignments"]
    sol["cycles"] = problem_data["cycle_set"]

    if verbosity >= 2:
        _print_sol(G, problem_data["mode"], sol)

    return sol