Example #1
0
def json_to_csp(graph_json, widget_model=None):
    """Converts a CSP represented by a JSON dictionary into a Python CSP instance.
    Note that because a CSP doesn't use the concept of IDs, unlike the JSON graph representation,
    IDs will be lost and will be different if you convert the result of this function back to JSON.
    Args:
        graph_json (dict): A dictionary representing JSON to be converted into a CSP instance.
        widget_model: Instance of widget model passed by ipywidgets during conversion. Never used; you can ignore it.
    Returns:
        (aipython.cspProblem.CSP or None):
             An instance of CSP that was converted from the provided JSON. None if no JSON was provided.
    """
    if not graph_json:
        return None

    true = True
    false = False

    domains = {
        node['name']: set(node['domain'])
        for node in graph_json['nodes'] if node['type'] == 'csp:variable'
    }

    constraints = []

    for node in graph_json['nodes']:
        scope = []
        if node['type'] == 'csp:constraint':
            condition_name = node['condition_name']
            condition_fn = LessThan
            callable = "condition_fn = " + condition_name
            exec(callable)
            # Find the links with the target as this constraint
            for link in graph_json['edges']:
                if link['target'] == node['id']:
                    source_node = next(n for n in graph_json['nodes']
                                       if n['id'] == link['source'])
                    scope.append(source_node['name'])
                elif link['source'] == node['id']:
                    source_node = next(n for n in graph_json['nodes']
                                       if n['id'] == link['target'])
                    scope.append(source_node['name'])

            if scope:
                c = Constraint(tuple(scope), condition_fn)
                c.condition_name = condition_name
                constraints.append(c)

    positions = {
        node['name']: (int(node['x']), int(node['y']))
        for node in graph_json['nodes']
    }

    return CSP(domains, constraints, positions)
Example #2
0
    def __init__(self):
        super().__init__()
        self.visualizer = self

        ##############################
        ### SLS-specific variables ###
        ##############################
        # Tracks if this is the first conflict reported.
        # If so, will also compute non-conflicts to highlight green the first time around.
        self._sls_first_conflict = True

        ##########################################
        ### Arc consistency-specific variables ###
        ##########################################
        # A reference to the arc the user has selected for arc consistency. A tuple of (variable name, Constraint instance).
        self._selected_arc = None
        # True if the user has selected an arc to perform arc-consistency on. Otherwise, an arc is automatically chosen.
        self._has_user_selected_arc = False
        # True if the algorithm is at a point where an arc is waiting to be chosen. Used to filter out extraneous clicks otherwise.
        self._is_waiting_for_arc_selection = False

        ###########################################
        ### Domain splitting-specific variables ###
        ##########################################
        # A reference to the variable the user has selected for domain splitting.
        self._selected_var = None
        # True if the user has selected a var to perform domain splitting on. Otherwise, a variable is automatically chosen.
        self._has_user_selected_var = False
        # True if the algorithm is at a point where a var is waiting to be chosen. Used to filter out extraneous clicks otherwise.
        self._is_waiting_for_var_selection = False
        # The domain the user has chosen as their first split for `_selected_var`.
        self._domain_split = None

        # self.graph = self.csp
        self.graph = CSP(self.csp.domains, self.csp.constraints,
                         self.csp.positions)
        (self._domain_map,
         self._edge_map) = generate_csp_graph_mappings(self.csp)

        self._initialize_controls()
Example #3
0
    def __init__(self, planning_problem, horizon=2):
        prob_domain = planning_problem.prob_domain
        initial_state = planning_problem.initial_state
        goal = planning_problem.goal

        old_pos = planning_problem.positions

        if 'action' not in old_pos:
            old_pos['action'] = (100, 100)

        maxwidth = max([x for x, y in old_pos.values()])
        minwidth = min([x for x, y in old_pos.values()])

        diff = max(100, maxwidth - minwidth)

        self.act_vars = [st('action', stage) for stage in range(horizon)]

        domains = {av: prob_domain.actions for av in self.act_vars}
        domains.update({
            st(var, stage): dom
            for (var, dom) in prob_domain.feats_vals.items()
            for stage in range(horizon + 1)
        })

        # intial state constraints:

        constraints = [
            prefixConstraint(Constraint((st(var, 0), ), is_(val)),
                             ['Initial', var])
            for (var, val) in initial_state.items()
        ]
        # goal constraints on the final state:

        constraints += [
            prefixConstraint(Constraint((st(var, horizon), ), is_(val)),
                             ['Goal', var]) for (var, val) in goal.items()
        ]

        # precondition constraints:
        constraints += [
            prefixConstraint(
                Constraint((st(var, stage), st('action', stage)),
                           if_(val, act)),
                ['Pre', act, st(var, stage)
                 ])  # st(var,stage)==val if st('action',stage)=act
            for act, strps in prob_domain.strips_map.items()
            for var, val in strps.preconditions.items()
            for stage in range(horizon)
        ]

        # effect constraints:
        constraints += [
            prefixConstraint(
                Constraint((st(var, stage + 1), st('action', stage)),
                           if_(val, act)),
                ['Effect', act, st(var, stage + 1)
                 ])  # st(var,stage+1)==val if st('action',stage)==act
            for act, strps in prob_domain.strips_map.items()
            for var, val in strps.effects.items() for stage in range(horizon)
        ]
        # frame constraints:
        constraints += [
            prefixConstraint(
                Constraint(
                    (st(var, stage), st('action', stage), st(var, stage + 1)),
                    eq_if_not_in_({
                        act
                        for act in prob_domain.actions
                        if var in prob_domain.strips_map[act].effects
                    })), ['Frame', st(var, stage)])
            for var in prob_domain.feats_vals for stage in range(horizon)
        ]
        try:
            positions = {}
            # precondition positions
            positions.update({
                ' '.join(['Pre', act, st(var, stage)]):
                (minwidth + (diff) * (2 * (stage + 1) - 1.5),
                 old_pos['action'][1])
                for act, strps in prob_domain.strips_map.items()
                for var, val in strps.preconditions.items()
                for stage in range(horizon)
            })
            # effect positions
            positions.update({
                ' '.join(['Effect', act, st(var, stage + 1)]):
                (minwidth + (diff) * (2 * (stage + 1) - 0.5),
                 old_pos['action'][1])
                for act, strps in prob_domain.strips_map.items()
                for var, val in strps.effects.items()
                for stage in range(horizon)
            })
            pos_keys = list(positions.keys())
            for i in range(len(pos_keys)):
                for j in range(i + 1, len(pos_keys)):
                    if positions[pos_keys[i]] == positions[pos_keys[j]]:
                        positions[pos_keys[j]] = (positions[pos_keys[j]][0],
                                                  positions[pos_keys[j]][1] -
                                                  200)

            domainCount = len(prob_domain.feats_vals.items())
            maxheight = max([y for x, y in positions.values()])
            minheight = min([y for x, y in positions.values()])
            if domainCount > 1:
                diffy = max(100, (maxheight - minheight) / (domainCount - 1))
            else:
                diffy = 0

            # position of the variable
            for stage in range(horizon + 1):
                index = 0
                for (var, dom) in prob_domain.feats_vals.items():
                    positions[st(var,
                                 stage)] = (old_pos[var][0] + (diff) * 2 *
                                            (stage), minheight + index * diffy)
                    old_pos[var] = positions[st(var, 0)]
                    index += 1
            # Position of Actions
            positions.update({
                st('action', stage):
                (minwidth + (diff) * (2 * (stage + 1) - 0.75),
                 (maxheight + minheight) / 2)
                for stage in range(horizon)
            })

            maxcurrwidth = max([x for x, y in positions.values()])

            # initial state positions
            positions.update({
                ' '.join(['Initial', var]): (minwidth - 50, old_pos[var][1])
                for (var, val) in initial_state.items()
            })
            # goal state positions
            positions.update({
                ' '.join(['Goal', var]): (maxcurrwidth + 50, old_pos[var][1])
                for (var, val) in goal.items()
            })

            # frame positions
            positions.update({
                ' '.join(['Frame', st(var, stage)]):
                (old_pos[var][0] + (diff) * (2 * (stage + 1) - 1),
                 old_pos[var][1])
                for var in prob_domain.feats_vals for stage in range(horizon)
            })
        except:
            pass
        CSP.__init__(self, domains, constraints, positions)
Example #4
0
    def handle_custom_msgs(self, _, content, buffers=None):
        super().handle_custom_msgs(None, content, buffers)
        event = content.get('event', '')

        if event == 'arc:click':
            """
            Expects a dictionary containing:
                varName (string): The name of the variable connected to this arc.
                constId (string): The id of the constraint connected to this arc.
            """
            if self._is_waiting_for_arc_selection:
                var_name = content.get('varName')
                const = self.csp.constraints[content.get('constId')]
                self.max_display_level = 2

                self._selected_arc = (var_name, const)
                self._has_user_selected_arc = True
                self._block_for_user_input.set()
                self._block_for_user_input.clear()
                self._is_waiting_for_arc_selection = False

        elif event == 'var:click':
            """
            Expects a dictionary containing:
                varName (string): The name of the variable to split on.
            """
            if not self._is_waiting_for_var_selection and content.get('varType') == 'csp:variable':
                self.send({'action': 'chooseDomainSplitBeforeAC'})

        elif event == 'domain_split':
            """
            Expects a dictionary containing:
                domain (string[]|None):
                    An array of the elements in the domain to first split on, or None if no choice is made.
                    In this case, splits the domain in half as a default.
            """
            domain = content.get('domain')
            var_name = content.get('var')
            self._selected_var = var_name
            self._domain_split = domain
            self._has_user_selected_var = True
            self._block_for_user_input.set()
            self._block_for_user_input.clear()
            self._is_waiting_for_var_selection = False

        elif event == 'reset':
            """
            Reset the algorithm and graph
            """
            # Before resetting backend, freeze the execution of queued function to avoid undetermined state
            self._pause()
            # Wait until freezeing completed
            sleep(0.2)

            # Reset algorithm related variables

            user_sleep_time = getattr(self, 'sleep_time', None)
            super().__init__()
            self.sleep_time = user_sleep_time
            self.visualizer = self
            self._sls_first_conflict = True
            self._selected_arc = None
            self._has_user_selected_arc = False
            self._is_waiting_for_arc_selection = False
            self._selected_var = None
            self._has_user_selected_var = False
            self._is_waiting_for_var_selection = False
            self._domain_split = None
            self.graph = CSP(self.csp.domains,
                             self.csp.constraints, self.csp.positions)
            (self._domain_map, self._edge_map) = generate_csp_graph_mappings(self.csp)

            # Tell frontend that it is ready to reset frontend graph and able to restart algorithm
            self.send({'action': 'frontReset'})

            # Terminate current running thread
            if self._thread:
                self.stop_thread(self._thread)

        elif event == 'initial_render':
            queued_func = getattr(self, '_queued_func', None)

            # Run queued function after we know the frontend view exists
            if queued_func:
                func = queued_func['func']
                args = queued_func['args']
                kwargs = queued_func['kwargs']
                self._previously_rendered = True
                self._thread = ReturnableThread(
                    target=func, args=args, kwargs=kwargs)
                self._thread.start()
        
        elif event == 'update_sleep_time':
            self.sleep_time = content.get('sleepTime')