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
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