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)
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()
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)
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')