Ejemplo n.º 1
0
    def set_transition_constrs(self):
        self.constrs['transition'] = []

        for k in range(self.num_futures):
            for h in range(1, self.problem.horizon):
                for v in self.problem.variables:
                    # Clique: MSB[n1(h-1), n2(h-1),..., v(h-1), v(h), set(v, h-1)]LSB
                    neighbours = self.neighbours[v]
                    var_indices = [
                        self.var_to_idx[(self.find_matching_action(v), k,
                                         h - 1)], self.var_to_idx[(v, k, h)],
                        self.var_to_idx[(v, k, h - 1)]
                    ]
                    var_indices.extend(
                        [self.var_to_idx[(n, k, h - 1)] for n in neighbours])
                    num_vars = len(var_indices)
                    determinized_transition = {}

                    clique = MRFClique(var_indices)
                    clique.function_table = []

                    for clique_bitmask in range(2**num_vars):
                        dependencies_bitmask = (
                            (clique_bitmask >> 2) << 1) | (clique_bitmask & 1)

                        if dependencies_bitmask in determinized_transition:
                            determinized_val = determinized_transition[
                                dependencies_bitmask]
                        else:
                            is_set = (clique_bitmask & 1) != 0
                            num_set_neighbours = self.count_set_neighbours(
                                clique_bitmask, len(neighbours))
                            is_alive = (clique_bitmask & 2) != 0

                            if (is_alive and num_set_neighbours in (2, 3)) \
                               or (not is_alive and num_set_neighbours == 3) \
                               or is_set:
                                if random.random() <= (1. -
                                                       self.noise_probs[v]):
                                    determinized_val = 1
                                else:
                                    determinized_val = 0
                            else:
                                if random.random() <= self.noise_probs[v]:
                                    determinized_val = 1
                                else:
                                    determinized_val = 0

                            determinized_transition[
                                dependencies_bitmask] = determinized_val

                        if (clique_bitmask & 2) >> 1 == determinized_val:
                            clique.function_table.append(1)
                        else:
                            clique.function_table.append(
                                mrf.INVALID_POTENTIAL_VAL)

                    self.constrs['transition'].append(clique)

        logger.info('set_transition_constraints')
Ejemplo n.º 2
0
 def add_reward_constrs(self):
     for k in range(self.num_futures):
         for h in range(self.problem.horizon):
             clique = MRFClique([self.var_to_idx[(self.goal, k, h)]])
             clique.function_table = [math.exp(x) for x in [-1, 0]]
             self.constrs['reward'].append(clique)
     logger.info('Added reward constraints')
Ejemplo n.º 3
0
    def add_reward_constrs(self):
        for k in range(self.num_futures):
            for h in range(self.problem.horizon):
                for y in self.inst_params['ys']:
                    clique = MRFClique([self.var_to_idx[y, k, h]])
                    clique.function_table = [math.exp(i) for i in [0, 1]]
                    self.constrs['reward'].append(clique)

        logger.info('Added reward constraints')
Ejemplo n.º 4
0
    def add_reward_constrs(self):
        right_dir_penalty = self.inst_params['ELEVATOR-PENALTY-RIGHT-DIR']
        wrong_dir_penalty = self.inst_params['ELEVATOR-PENALTY-WRONG-DIR']
        for k in range(self.num_futures):
            for h in range(self.problem.horizon):
                for elevator in self.inst_params['elevators']:
                    elevator_dir_up = self.get_elevator_dir_state(elevator, 'up')
                    person_going_up = self.get_person_in_elevator_state(elevator, 'up')
                    person_going_down = self.get_person_in_elevator_state(elevator, 'down')

                    clique = MRFClique([self.var_to_idx[elevator_dir_up, k, h],
                                        self.var_to_idx[person_going_up, k, h]])
                    clique.function_table = [1, 1,
                                             math.exp(-wrong_dir_penalty), math.exp(-right_dir_penalty)]
                    self.constrs['reward'].append(clique)

                    clique = MRFClique([self.var_to_idx[elevator_dir_up, k, h],
                                        self.var_to_idx[person_going_down, k, h]])
                    clique.function_table = [1, 1,
                                             math.exp(-right_dir_penalty), math.exp(-wrong_dir_penalty)]
                    self.constrs['reward'].append(clique)
                for fl in self.inst_params['floors']:
                    person_waiting_up = self.get_person_waiting_state(fl, 'up')
                    person_waiting_down = self.get_person_waiting_state(fl, 'down')
                    clique = MRFClique([self.var_to_idx[person_waiting_up, k, h],
                                        self.var_to_idx[person_waiting_down, k, h]])
                    clique.function_table = [math.exp(val) for val in [0, -1, -1, -2]]
                    self.constrs['reward'].append(clique)

        logger.info('Added reward constraints')
Ejemplo n.º 5
0
    def add_reward_constrs(self):
        function_table = [math.exp(x) for x in [0, 1, -1, 0]]
        for k in range(self.num_futures):
            for h in range(self.problem.horizon):
                for v in self.problem.variables:
                    a = self.find_matching_action(v)
                    vars_indices = [
                        self.var_to_idx[(v, k, h)], self.var_to_idx[(a, k, h)]
                    ]
                    clique = MRFClique(vars_indices)
                    clique.function_table = function_table
                    self.constrs['reward'].append(clique)

        logger.info('Added reward constraints')
Ejemplo n.º 6
0
 def add_states_clique(self, determinized_tree, tree_vars, k, t, v):
     """
     Adds a clique i.e. a potential function that represents a determinized transition tree.
     The function maps to 1 or 0 whether the values assigned to the variables in the tree
     satisfies the determinized value or not respectively
     :param determinized_tree: a determinized transition tree
     :param tree_vars: all variables in the transition tree
     :param k: the future value
     :param t: the horizon step
     :param v: name of state variable to make the transition to
     """
     var_indices = [self.get_state_var_index(v, k, t + 1)]
     var_indices.extend(self.state_vars_to_indices(tree_vars, k, t))
     clique = MRFClique(var_indices)
     clique.generate_states_function_table(determinized_tree, tree_vars)
     self.cliques['states'].append(clique)
Ejemplo n.º 7
0
    def set_person_waiting_transition(self, k, h):
        for floor in self.inst_params['floors']:
            person_waiting_up = self.get_person_waiting_state(floor, 'up')
            elevator_states = [(self.get_elevator_at_state(e, floor),
                                self.get_elevator_dir_state(e, 'up'),
                                self.get_elevator_closed_state(e))
                               for e in self.inst_params['elevators']]
            var_indices = [self.var_to_idx[person_waiting_up, k, h],
                           self.var_to_idx[person_waiting_up, k, h-1]]
            var_indices += [self.var_to_idx[es, k, h-1] for es in itertools.chain(*elevator_states)]
            clique = MRFClique(var_indices)
            for bitmask in range(2**len(var_indices)):
                is_elevator_available = False
                for i in range(len(elevator_states)):
                    if (utils.is_set(bitmask, 2+i*3)
                            and utils.is_set(bitmask, 3+i*3)
                            and not utils.is_set(bitmask, 4+i*3)):
                        is_elevator_available = True
                if utils.is_set(bitmask, 1) and not is_elevator_available:
                    if utils.is_set(bitmask, 0):
                        clique.function_table.append(1)
                    else:
                        clique.function_table.append(mrf.INVALID_POTENTIAL_VAL)
                else:
                    determinized_val = 0
                    if random.random() < self.get_arrive_prob(floor):
                        determinized_val = 1

                    if utils.match_determinized_val(bitmask, 0, determinized_val):
                        clique.function_table.append(1)
                    else:
                        clique.function_table.append(mrf.INVALID_POTENTIAL_VAL)
            self.constrs['transition'].append(clique)
Ejemplo n.º 8
0
    def set_init_states_constrs(self, init_state_vals):
        self.constrs['init_states'] = []

        function_table_0 = [1, mrf.INVALID_POTENTIAL_VAL_2]
        function_table_1 = [mrf.INVALID_POTENTIAL_VAL_2, 1]

        for k in range(self.num_futures):
            for v in self.problem.variables:
                vars_indices = [self.var_to_idx[(v, k, 0)]]
                clique = MRFClique(vars_indices)
                if init_state_vals[v] == 0:
                    clique.function_table = function_table_0
                else:
                    clique.function_table = function_table_1
                self.constrs['init_states'].append(clique)

        logger.info('set_init_states_constraints')
Ejemplo n.º 9
0
    def add_init_actions_cliques(self):
        function_table = []
        allset = 2**self.num_futures - 1
        for i in range(2**self.num_futures):
            if i == 0 or i == allset:
                function_table.append(1)
            else:
                function_table.append(INVALID_POTENTIAL_VAL)

        for action in self.problem.actions:
            vars_indices = [self.get_state_var_index(action, k, 0) for k in range(self.num_futures)]
            clique = MRFClique(vars_indices)
            clique.function_table = function_table
            self.cliques['init_actions'].append(clique)

        logger.info('added_init_actions_cliques|#init_actions_cliques={}'
                    .format(len(self.cliques['init_actions'])))
Ejemplo n.º 10
0
    def set_transition_constrs(self):
        self.constrs['transition'] = []

        for k in range(self.num_futures):
            for h in range(1, self.problem.horizon):
                xindices = [
                    self.var_to_idx[x, k, h - 1]
                    for x in self.inst_params['xs']
                ]
                aindices = [
                    self.var_to_idx[a, k, h - 1] for a in self.problem.actions
                ]
                num_xs = len(xindices)

                for x in self.inst_params['xs']:
                    clique = MRFClique([self.var_to_idx[x, k, h]])
                    determinized_val = 1 if random.random() < 0.5 else 0
                    utils.append_function_entry(clique, 0, 0, determinized_val)
                    utils.append_function_entry(clique, 1, 0, determinized_val)
                    self.constrs['transition'].append(clique)

                for y in self.inst_params['ys']:
                    var_indices = [
                        self.var_to_idx[y, k, h], self.var_to_idx[y, k, h - 1]
                    ]
                    var_indices.extend(xindices)
                    var_indices.extend(aindices)
                    clique = MRFClique(var_indices)
                    for bitmask in range(2**len(var_indices)):
                        if utils.is_set(bitmask, 1):
                            utils.append_function_entry(clique, bitmask, 0, 1)
                            continue

                        matched = True
                        for i in range(2, 2 + num_xs):
                            if utils.is_set(bitmask, i) != utils.is_set(
                                    bitmask, i + num_xs):
                                matched = False
                                break
                        if matched and random.random() < 0.49:
                            utils.append_function_entry(clique, bitmask, 0, 1)
                        else:
                            utils.append_function_entry(clique, bitmask, 0, 0)
                    self.constrs['transition'].append(clique)

        logger.info('set_transition_constraints')
Ejemplo n.º 11
0
    def add_concurrency_constrs(self):
        function_table = []

        for i in range(2**len(self.problem.actions)):
            if utils.count_set_bits(i) > self.problem.max_concurrency:
                function_table.append(INVALID_POTENTIAL_VAL)
            else:
                function_table.append(1)

        for k in range(self.num_futures):
            for t in range(self.problem.horizon):
                vars_indices = self.state_vars_to_indices(self.problem.actions, k, t)
                clique = MRFClique(vars_indices)
                clique.function_table = function_table
                self.cliques['concurrency'].append(clique)

        logger.info('added_concurrency_constrs|#concurrency_constrs_cliques={}'
                    .format(len(self.cliques['concurrency'])))
Ejemplo n.º 12
0
    def add_concurrency_constrs(self):
        function_table = []
        for i in range(2**len(self.problem.actions)):
            if utils.count_set_bits(i) > self.problem.max_concurrency:
                function_table.append(mrf.INVALID_POTENTIAL_VAL_2)
            else:
                function_table.append(1)

        for k in range(self.num_futures):
            for h in range(self.problem.horizon):
                vars_indices = [
                    self.var_to_idx[(action, k, h)]
                    for action in self.problem.actions
                ]
                clique = MRFClique(vars_indices)
                clique.function_table = function_table
                self.constrs['concurrency'].append(clique)

        logger.info('Added concurrency constraints')
Ejemplo n.º 13
0
    def add_init_actions_constrs(self):
        function_table = []
        allset = 2**self.num_futures - 1
        for i in range(2**self.num_futures):
            if i == 0 or i == allset:
                function_table.append(1)
            else:
                function_table.append(mrf.INVALID_POTENTIAL_VAL)

        for action in self.problem.actions:
            vars_indices = [
                self.var_to_idx[(action, k, 0)]
                for k in range(self.num_futures)
            ]
            clique = MRFClique(vars_indices)
            clique.function_table = function_table
            self.constrs['init_actions'].append(clique)

        logger.info('Added init actions constraints')
Ejemplo n.º 14
0
    def set_elevator_at_floor_transition(self, k, h):
        for elevator in self.inst_params['elevators']:
            for floor in self.inst_params['floors']:
                adjacent_floors = []
                upper_floor_idx = len(adjacent_floors) if floor in self.inst_params['ADJACENT-UP'] else None
                if upper_floor_idx is not None:
                    adjacent_floors.append(self.inst_params['ADJACENT-UP'][floor])
                lower_floor_idx = len(adjacent_floors) if floor in self.inst_params['ADJACENT-DOWN'] else None
                if lower_floor_idx is not None:
                    adjacent_floors.append(self.inst_params['ADJACENT-DOWN'][floor])

                elevator_at_floor = self.get_elevator_at_state(elevator, floor)
                elevator_closed = self.get_elevator_closed_state(elevator)
                elevator_dir_up = self.get_elevator_dir_state(elevator, 'up')
                move_cur_dir = self.get_move_current_dir_action(elevator)
                at_adjacent_floors = [self.get_elevator_at_state(elevator, fl) for fl in adjacent_floors]

                var_indices = [elevator_at_floor, elevator_at_floor,
                               elevator_closed, elevator_dir_up, move_cur_dir]
                var_indices += at_adjacent_floors
                var_indices[0] = self.var_to_idx[var_indices[0], k, h]
                var_indices[1:] = [self.var_to_idx[v, k, h - 1] for v in var_indices[1:]]
                adjacent_floors_offset = 5

                clique = MRFClique(var_indices)
                for bitmask in range(2**len(var_indices)):
                    prev_val = utils.btoi(utils.is_set(bitmask, 1))

                    if not utils.is_set(bitmask, 2) or not utils.is_set(bitmask, 4):
                        utils.append_function_entry(clique, bitmask, 0, prev_val)
                        continue

                    if utils.is_set(bitmask, 4) and utils.is_set(bitmask, 3):
                        if lower_floor_idx is not None:
                            if utils.is_set(bitmask, adjacent_floors_offset + lower_floor_idx):
                                utils.append_function_entry(clique, bitmask, 0, 1)
                            else:
                                utils.append_function_entry(clique, bitmask, 0, 0)
                        else:
                            utils.append_function_entry(clique, bitmask, 0, prev_val)
                        continue

                    if utils.is_set(bitmask, 4) and not utils.is_set(bitmask, 3):
                        if upper_floor_idx is not None:
                            if utils.is_set(bitmask, adjacent_floors_offset + upper_floor_idx):
                                utils.append_function_entry(clique, bitmask, 0, 1)
                            else:
                                utils.append_function_entry(clique, bitmask, 0, 0)
                        else:
                            utils.append_function_entry(clique, bitmask, 0, prev_val)
                        continue

                    utils.append_function_entry(clique, bitmask, 0, prev_val)

                self.constrs['transition'].append(clique)
Ejemplo n.º 15
0
    def add_init_states_cliques(self):
        vars_list = list(self.problem.variables)
        vars_vals_bitset = 0
        for i, v in enumerate(vars_list):
            vars_vals_bitset |= (int(self.problem.variables[v]) << i)

        for k in range(self.num_futures):
            vars_indices = self.state_vars_to_indices(vars_list, k, 0)
            clique = MRFClique(vars_indices)
            for i in range(2**len(vars_list)):
                if i == vars_vals_bitset:
                    clique.function_table.append(1)
                else:
                    clique.function_table.append(INVALID_POTENTIAL_VAL)

            self.cliques['init_states'].append(clique)
        logger.info('added_init_states_cliques|#init_states_cliques={}'
                    .format(len(self.cliques['init_states'])))
Ejemplo n.º 16
0
    def set_elevator_closed_transition(self, k, h):
        for elevator in self.inst_params['elevators']:
            var_indices = [self.get_elevator_closed_state(elevator),
                           self.get_elevator_closed_state(elevator),
                           self.get_open_door_action(elevator, 'up'),
                           self.get_open_door_action(elevator, 'down'),
                           self.get_close_door_action(elevator)]
            var_indices[0] = self.var_to_idx[var_indices[0], k, h]
            var_indices[1:] = [self.var_to_idx[v, k, h - 1] for v in var_indices[1:]]

            clique = MRFClique(var_indices)
            for bitmask in range(2**len(var_indices)):
                if utils.is_set(bitmask, 1) and not utils.is_set(bitmask, 2) \
                        and not utils.is_set(bitmask, 3) and utils.is_set(bitmask, 4):
                    utils.append_function_entry(clique, bitmask, 0, 1)
                else:
                    utils.append_function_entry(clique, bitmask, 0, 0)
            self.constrs['transition'].append(clique)
Ejemplo n.º 17
0
    def add_reward_cliques(self, reward_tree, tree_vars):
        assert(self.num_futures > 0 and self.problem.horizon > 0)
        var_indices = self.state_vars_to_indices(tree_vars, 0, 0)
        var_indices.append(self.get_reward_var_index(0, 0))
        clique_proto = MRFClique(var_indices)
        clique_proto.generate_reward_function_table(reward_tree, tree_vars)
        self.cliques['reward'].append(clique_proto)

        for k in range(self.num_futures):
            for t in range(self.problem.horizon):
                if k == 0 and t == 0:
                    continue
                var_indices = self.state_vars_to_indices(tree_vars, k, t)
                var_indices.append(self.get_reward_var_index(k, t))
                clique = MRFClique(var_indices)
                clique.function_table = clique_proto.function_table
                self.cliques['reward'].append(clique)
Ejemplo n.º 18
0
    def set_elevator_dir_up_transition(self, k, h):
        for elevator in self.inst_params['elevators']:
            var_indices = [self.get_elevator_dir_state(elevator, 'up'),
                           self.get_elevator_dir_state(elevator, 'up'),
                           self.get_open_door_action(elevator, 'up'),
                           self.get_open_door_action(elevator, 'down')]
            var_indices[0] = self.var_to_idx[var_indices[0], k, h]
            var_indices[1:] = [self.var_to_idx[v, k, h - 1] for v in var_indices[1:]]
            clique = MRFClique(var_indices)
            for bitmask in range(2**len(var_indices)):
                if utils.is_set(bitmask, 2):
                    utils.append_function_entry(clique, bitmask, 0, 1)
                    continue

                if utils.is_set(bitmask, 3):
                    utils.append_function_entry(clique, bitmask, 0, 0)
                    continue

                val = 1 if utils.is_set(bitmask, 1) else 0
                utils.append_function_entry(clique, bitmask, 0, val)
            self.constrs['transition'].append(clique)
Ejemplo n.º 19
0
    def set_transition_constrs(self):
        self.constrs['transition'] = []

        for k in range(self.num_futures):
            for h in range(1, self.problem.horizon):
                for v in self.problem.variables:
                    # Clique: LSB{v(h), v(h-1)[, g(h-1)], move-*(h-1),..., n(h-1),...}MSB
                    x, y = self.get_coords_from_state(v)
                    var_indices = [
                        self.var_to_idx[(v, k, h)],
                        self.var_to_idx[(v, k, h - 1)]
                    ]

                    if v != self.goal:
                        var_indices.append(self.var_to_idx[(self.goal, k,
                                                            h - 1)])

                    action_to_bit_idx = {}
                    action_bit_idx_start = len(var_indices)
                    move_away_actions = self.grid[x].keys(
                    ) + self.grid[y].keys()
                    for action in move_away_actions:
                        if action in action_to_bit_idx:
                            continue
                        action_to_bit_idx[action] = len(var_indices)
                        var_indices.append(self.var_to_idx[(action, k, h - 1)])
                        action_to_bit_idx[self.opposite_action[action]] = len(
                            var_indices)
                        var_indices.append(
                            self.var_to_idx[(self.opposite_action[action], k,
                                             h - 1)])

                    neighbor_info = {}  # {n: (action to reach v from n, idx)}
                    neighbor_bit_idx_start = len(var_indices)
                    for action in self.grid[x]:
                        nx, ny = self.grid[x][action], y
                        n = self.get_state_from_coords(nx, ny)
                        neighbor_info[n] = (
                            action_to_bit_idx[self.opposite_action[action]],
                            len(var_indices))
                        var_indices.append(self.var_to_idx[(n, k, h - 1)])
                    for action in self.grid[y]:
                        nx, ny = x, self.grid[y][action]
                        n = self.get_state_from_coords(nx, ny)
                        neighbor_info[n] = (
                            action_to_bit_idx[self.opposite_action[action]],
                            len(var_indices))
                        var_indices.append(self.var_to_idx[(n, k, h - 1)])

                    clique = MRFClique(var_indices)
                    for clique_bitmask in range(2**len(var_indices)):
                        # Concurrency constraints
                        num_set_action = utils.count_set_bit(
                            clique_bitmask, action_bit_idx_start,
                            neighbor_bit_idx_start)
                        if num_set_action > self.problem.max_concurrency:
                            clique.function_table.append(
                                mrf.INVALID_POTENTIAL_VAL_2)
                            continue

                        # At most 1 state is set
                        num_set_state = utils.count_set_bit(
                            clique_bitmask, neighbor_bit_idx_start,
                            len(var_indices))
                        num_set_state += 1 if clique_bitmask & 2 != 0 else 0
                        num_set_state += 1 if v != self.goal and clique_bitmask & 4 != 0 else 0
                        if num_set_state > 1:
                            clique.function_table.append(
                                mrf.INVALID_POTENTIAL_VAL_2)
                            continue

                        # If at goal, stays at goal
                        if v == self.goal and clique_bitmask & 2 != 0:
                            if clique_bitmask & 1 != 0:
                                clique.function_table.append(1)
                            else:
                                clique.function_table.append(
                                    mrf.INVALID_POTENTIAL_VAL)
                            continue
                        if clique_bitmask & 4 != 0:
                            if clique_bitmask & 1 != 0:
                                clique.function_table.append(
                                    mrf.INVALID_POTENTIAL_VAL)
                            else:
                                clique.function_table.append(1)
                            continue

                        # Move to neighbors
                        if clique_bitmask & 2 != 0:
                            set_func_table = False
                            for action in move_away_actions:
                                if clique_bitmask & (
                                        1 << action_to_bit_idx[action]) != 0:
                                    if clique_bitmask & 1 == 0:
                                        clique.function_table.append(1)
                                    else:
                                        clique.function_table.append(
                                            mrf.INVALID_POTENTIAL_VAL)
                                    set_func_table = True
                                    break
                            if set_func_table:
                                continue
                        # Move from neighbors
                        else:
                            set_func_table = False
                            for neighbor in neighbor_info:
                                is_action_set = (
                                    clique_bitmask &
                                    (1 << neighbor_info[neighbor][0])) != 0
                                is_at_neighbor = (
                                    clique_bitmask &
                                    (1 << neighbor_info[neighbor][1])) != 0
                                if is_at_neighbor and is_action_set:
                                    if random.random(
                                    ) < self.get_disappear_prob(v):
                                        determinized_val = 0
                                    else:
                                        determinized_val = 1

                                    if (clique_bitmask
                                            & 1) == determinized_val:
                                        clique.function_table.append(1)
                                    else:
                                        clique.function_table.append(
                                            mrf.INVALID_POTENTIAL_VAL)
                                    set_func_table = True
                                    break
                            if set_func_table:
                                continue

                        if (clique_bitmask & 1) == ((clique_bitmask >> 1) & 1):
                            clique.function_table.append(1)
                        else:
                            clique.function_table.append(
                                mrf.INVALID_POTENTIAL_VAL)

                    self.constrs['transition'].append(clique)

        logger.info('set_transition_constraints')
Ejemplo n.º 20
0
    def set_transition_constrs(self):
        """
        Each logical expression used to specify the transition function corresponds to a clique and
        an additional variable. If an entry in a clique is sufficient to decide the outcome of the
        next state or the outcome is already decided by earlier clauses, its extended variable is
        constrained to 1. Otherwise, it's constrained to 0.
        :return:
        """
        self.constrs['transition'] = []

        for k in range(self.num_futures):
            for h in range(1, self.problem.horizon):
                for v in self.problem.variables:
                    # If at goal stays at goal
                    clique = MRFClique([])
                    goal_ext_var = self.get_ext_variables('goal')
                    if v == self.goal:
                        clique.vars = [
                            self.var_to_idx[(v, k, h)],
                            self.var_to_idx[(v, k, h - 1)],
                            self.add_var((goal_ext_var, k, h))
                        ]
                        for bitmask in range(2**len(clique.vars)):
                            if utils.is_set(bitmask, 1):
                                if not utils.is_set(bitmask, 2):
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                    continue
                                if utils.is_set(bitmask, 0):
                                    clique.function_table.append(1)
                                else:
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                    else:
                        clique.vars = [
                            self.var_to_idx[(v, k, h)],
                            self.var_to_idx[(self.goal, k, h - 1)],
                            self.add_var((goal_ext_var, k, h))
                        ]
                        for bitmask in range(2**len(clique.vars)):
                            if utils.is_set(bitmask, 1):
                                if not utils.is_set(bitmask, 2):
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                    continue
                                if utils.is_set(bitmask, 0):
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                else:
                                    clique.function_table.append(1)
                    self.constrs['transition'].append(clique)

                    x, y = self.get_coords_from_state(v)
                    all_actions = self.grid[x].keys() + self.grid[y].keys()

                    # Moving to neighbours
                    prev_ext_var = goal_ext_var
                    for level, action in enumerate(all_actions):
                        cur_ext_var = self.get_ext_variables('moveto', level)
                        cur_ext_var_idx = self.add_var((cur_ext_var, k, h))

                        clique = MRFClique([
                            self.var_to_idx[(v, k, h)],
                            self.var_to_idx[(v, k, h - 1)],
                            self.var_to_idx[(action, k, h - 1)],
                            self.var_to_idx[(prev_ext_var, k, h)],
                            cur_ext_var_idx
                        ])

                        for bitmask in range(2**len(clique.vars)):
                            if utils.is_set(bitmask, 3):
                                if utils.is_set(bitmask, 4):
                                    clique.function_table.append(1)
                                else:
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                continue

                            if utils.is_set(bitmask, 1) and utils.is_set(
                                    bitmask, 2):
                                if not utils.is_set(bitmask, 4):
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                    continue
                                if utils.is_set(bitmask, 0):
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                else:
                                    clique.function_table.append(1)

                        prev_ext_var = self.get_ext_variables('moveto', level)
                        self.constrs['transition'].append(clique)

                    # Moving from neighbours
                    for level, action in enumerate(all_actions):
                        cur_ext_var = self.get_ext_variables('movefrom', level)
                        cur_ext_var_idx = self.add_var((cur_ext_var, k, h))

                        neighbour_action = self.opposite_action[action]
                        nx, ny = x, y
                        if action in self.grid[x]:
                            nx = self.grid[x][action]
                        else:
                            ny = self.grid[y][action]
                        neighbour = self.get_state_from_coords(nx, ny)

                        clique = MRFClique([
                            self.var_to_idx[(v, k, h)],
                            self.var_to_idx[(neighbour, k, h - 1)],
                            self.var_to_idx[(neighbour_action, k, h - 1)],
                            self.var_to_idx[(prev_ext_var, k, h)],
                            cur_ext_var_idx
                        ])

                        for bitmask in range(2**len(clique.vars)):
                            if utils.is_set(bitmask, 3):
                                if utils.is_set(bitmask, 4):
                                    clique.function_table.append(1)
                                else:
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                continue

                            if utils.is_set(bitmask, 1) and utils.is_set(
                                    bitmask, 2):
                                if not utils.is_set(bitmask, 4):
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)
                                    continue
                                if random.random() < self.get_disappear_prob(
                                        v):
                                    determinized_val = 0
                                else:
                                    determinized_val = 1
                                if utils.is_set(bitmask,
                                                0) == (determinized_val == 1):
                                    clique.function_table.append(1)
                                else:
                                    clique.function_table.append(
                                        mrf.INVALID_POTENTIAL_VAL)

                        prev_ext_var = self.get_ext_variables('moveto', level)
                        self.constrs['transition'].append(clique)

                    # Otherwise keeps the same state
                    clique = MRFClique([
                        self.var_to_idx[(v, k, h)],
                        self.var_to_idx[(v, k, h - 1)],
                        self.var_to_idx[(prev_ext_var, k, h)]
                    ])
                    for bitmask in range(2**len(clique.vars)):
                        if utils.is_set(bitmask, 2):
                            clique.function_table.append(1)
                            continue
                        if utils.is_set(bitmask,
                                        0) == utils.is_set(bitmask, 1):
                            clique.function_table.append(1)
                        else:
                            clique.function_table.append(
                                mrf.INVALID_POTENTIAL_VAL)
                    self.constrs['transition'].append(clique)

        logger.info('set_transition_constraints')
Ejemplo n.º 21
0
    def set_transition_constrs(self):
        self.constrs['transition'] = []

        for k in range(self.num_futures):
            for h in range(1, self.problem.horizon):
                for v in self.problem.variables:
                    # Clique: MSB[n1(h-1), n2(h-1),..., v(h-1), v(h), reboot(v, h-1)]LSB
                    neighbours = self.topology[v]
                    var_indices = [
                        self.var_to_idx[(self.find_matching_action(v), k,
                                         h - 1)], self.var_to_idx[(v, k, h)],
                        self.var_to_idx[(v, k, h - 1)]
                    ]
                    var_indices.extend(
                        [self.var_to_idx[(n, k, h - 1)] for n in neighbours])
                    num_vars = len(var_indices)
                    determinized_transition = {}

                    clique = MRFClique(var_indices)
                    clique.function_table = []

                    for clique_bitmask in range(2**num_vars):
                        if clique_bitmask & 1 != 0:
                            if clique_bitmask & 2 != 0:
                                clique.function_table.append(1)
                            else:
                                clique.function_table.append(
                                    mrf.INVALID_POTENTIAL_VAL)
                        else:
                            dependencies_bitmask = clique_bitmask >> 2

                            if dependencies_bitmask in determinized_transition:
                                determinized_val = determinized_transition[
                                    dependencies_bitmask]
                            else:
                                if clique_bitmask & 4 != 0:
                                    running_neighbours = self.count_set_neighbours(
                                        clique_bitmask, len(neighbours))
                                    running_prob = 0.45 + 0.5 * (
                                        1 + running_neighbours) / (
                                            1 + len(neighbours))

                                    if random.random() <= running_prob:
                                        determinized_val = 1
                                    else:
                                        determinized_val = 0
                                else:
                                    if random.random() <= self.REBOOT_PROB:
                                        determinized_val = 1
                                    else:
                                        determinized_val = 0

                                determinized_transition[
                                    dependencies_bitmask] = determinized_val

                            if (clique_bitmask & 2) >> 1 == determinized_val:
                                clique.function_table.append(1)
                            else:
                                clique.function_table.append(
                                    mrf.INVALID_POTENTIAL_VAL)

                    self.constrs['transition'].append(clique)

        logger.info('set_transition_constraints')
Ejemplo n.º 22
0
    def set_person_in_elevator_transition(self, k, h):
        for elevator in self.inst_params['elevators']:
            person_in_elevator_going_up = self.get_person_in_elevator_state(elevator, 'up')
            person_in_elevator_going_down = self.get_person_in_elevator_state(elevator, 'down')
            elevator_closed = self.get_elevator_closed_state(elevator)
            elevator_dir_up = self.get_elevator_dir_state(elevator, 'up')
            elevator_at_floor = [self.get_elevator_at_state(elevator, floor)
                                 for floor in self.inst_params['floors']]
            person_waiting_up = [self.get_person_waiting_state(floor, 'up')
                                 for floor in self.inst_params['floors']]
            person_waiting_down = [self.get_person_waiting_state(floor, 'down')
                                   for floor in self.inst_params['floors']]

            floor_offset = 4
            waiting_offset = floor_offset + len(elevator_at_floor)
            common_indices = [(elevator_closed, k, h - 1), (elevator_dir_up, k, h - 1)]
            common_indices += [(v, k, h - 1) for v in elevator_at_floor]

            # Going up
            var_indices = [(person_in_elevator_going_up, k, h), (person_in_elevator_going_up, k, h - 1)]
            var_indices += common_indices + [(v, k, h - 1) for v in person_waiting_up]
            var_indices = [self.var_to_idx[v] for v in var_indices]
            elevator_at_top_floor_idx = 4 + self.inst_params['TOP-FLOOR']
            clique = MRFClique(var_indices)
            for bitmask in range(2**len(var_indices)):
                if utils.is_set(bitmask, 1):
                    if utils.is_set(bitmask, elevator_at_top_floor_idx):
                        utils.append_function_entry(clique, bitmask, 0, 0)
                    else:
                        utils.append_function_entry(clique, bitmask, 0, 1)
                    continue

                if utils.is_set(bitmask, 2):
                    utils.append_function_entry(clique, bitmask, 0, 0)
                    continue

                if not utils.is_set(bitmask, 3):
                    utils.append_function_entry(clique, bitmask, 0, 0)
                    continue

                done = False
                for i in range(len(elevator_at_floor)):
                    if utils.is_set(bitmask, floor_offset + i) and utils.is_set(bitmask, waiting_offset + i):
                        utils.append_function_entry(clique, bitmask, 0, 1)
                        done = True
                        break
                if not done:
                    utils.append_function_entry(clique, bitmask, 0, 0)
            self.constrs['transition'].append(clique)

            # Going down
            var_indices = [(person_in_elevator_going_down, k, h), (person_in_elevator_going_down, k, h - 1)]
            var_indices += common_indices + [(v, k, h - 1) for v in person_waiting_down]
            var_indices = [self.var_to_idx[v] for v in var_indices]
            elevator_at_bottom_floor_idx = 4 + self.inst_params['BOTTOM-FLOOR']
            clique = MRFClique(var_indices)
            for bitmask in range(2**len(var_indices)):
                if utils.is_set(bitmask, 1):
                    if utils.is_set(bitmask, elevator_at_bottom_floor_idx):
                        utils.append_function_entry(clique, bitmask, 0, 0)
                    else:
                        utils.append_function_entry(clique, bitmask, 0, 1)
                    continue

                if utils.is_set(bitmask, 2):
                    utils.append_function_entry(clique, bitmask, 0, 0)
                    continue

                if utils.is_set(bitmask, 3):
                    utils.append_function_entry(clique, bitmask, 0, 0)
                    continue

                done = False
                for i in range(len(elevator_at_floor)):
                    if utils.is_set(bitmask, floor_offset + i) and utils.is_set(bitmask, waiting_offset + i):
                        utils.append_function_entry(clique, bitmask, 0, 1)
                        done = True
                        break
                if not done:
                    utils.append_function_entry(clique, bitmask, 0, 0)
            self.constrs['transition'].append(clique)