def propagate(self, control, change) -> Optional[List[Tuple]]: """ For any relevant change, check the assignment of the whole nogood for the assigned times it is in. If it it conflicting or unit add the nogood to the solver After the check, replace the watch if possible. :param control: clingo PropagateControl object :param change: watch and assigned time pair :return None if propagation has to stop, A list of (delete, add) pairs of watches if propagation can continue """ lit, assigned_time = change if not self.is_valid_time(assigned_time): return [], ConstraintCheck.UNIT ng = form_nogood(self.t_atom_info, assigned_time) if ng is None: return [], ConstraintCheck.UNIT update_result = check_assignment(ng, control) if update_result == ConstraintCheck.NONE: return ng, update_result lock = self.check_if_lock(assigned_time) if not control.add_nogood(ng, lock=lock) or not control.propagate(): util.Count.add(StatNames.CONF_COUNT_MSG.value) return None util.Count.add(StatNames.UNITS_COUNT_MSG.value) return ng, update_result
def propagate(self, control, change) -> Optional[List[Tuple]]: """ For any relevant change, immediately form the nogood for the assigned times it is in and add it to the solver :param control: clingo PropagateControl object :param change: lit and assigned time pair :return None if propagation has to stop, A list of (delete, add) pairs of watches if propagation can continue """ lit, assigned_time = change if not self.is_valid_time(assigned_time): return [], ConstraintCheck.UNIT ng = form_nogood(self.t_atom_info, assigned_time) if ng is None: return [], ConstraintCheck.UNIT if check_assignment(ng, control) == ConstraintCheck.NONE: return [], ConstraintCheck.UNIT lock = self.check_if_lock(assigned_time) if not control.add_nogood(ng, lock=lock) or not control.propagate(): util.Count.add(StatNames.CONF_COUNT_MSG.value) return None util.Count.add(StatNames.UNITS_COUNT_MSG.value) # always return UNIT so that it doesnt attempt to change the watches for size 2 return [], ConstraintCheck.UNIT
def build_constraints(self, init, t_atom) -> List[int]: t_atom_info, min_time, max_time = parse_atoms(t_atom) for assigned_time in range(min_time, max_time + 1): lits = form_nogood(t_atom_info, assigned_time) if lits is None: continue init.add_clause([-l for l in lits if l != 1])
def test_form_nogood(self): reset_mappings() TimeAtomToSolverLit.add((1, "a(1,", 2), 1) TimeAtomToSolverLit.add((1, "a(2,", 1), 2) TimeAtomToSolverLit.add((1, "b(1,", 2), 3) TimeAtomToSolverLit.add((-1, "c(1,", 2), -4) real_info = { "+.a(1,": atom_info(sign=1, time_mod=0, name="a(1,"), "+~a(2,": atom_info(sign=1, time_mod=1, name="a(2,"), "+.b(1,": atom_info(sign=1, time_mod=0, name="b(1,"), "-.c(1,": atom_info(sign=-1, time_mod=0, name="c(1,") } ng = form_nogood(real_info, 2) actual_ng = [-4, 1, 2, 3] self.assertEqual(sorted(ng), actual_ng) self.assertIsNone(form_nogood(real_info, 1))
def propagate(self, control, change) -> Optional[List[Tuple]]: """ For any relevant change, check the assignment of the whole nogood for the assigned times it is in. If it it conflicting or unit add the nogood to the solver After the check, replace the watch if possible. :param control: clingo PropagateControl object :param change: watch that was assigned :return None if propagation has to stop, A list of (delete, add) pairs of watches if propagation can continue """ delete_add = [] replacement_info: List[List[int]] = [] for assigned_time in self.watches_to_at[change]: if not self.is_valid_time(assigned_time): continue ng = form_nogood(self.t_atom_info, assigned_time) if ng is None: continue result = self.check_assignment(ng, control, assigned_time) if result is None: return None elif result == ConstraintCheck.UNIT: continue else: # only look for replacement if nogood is not conflicting nor unit for lit, ats in self.watches_to_at.items(): if lit != change: if assigned_time in ats: second_watch = lit break new_watch = get_replacement_watch(ng, [change, second_watch], control) if new_watch is not None: delete_add.append((change, new_watch)) replacement_info.append([change, new_watch, assigned_time]) self.replace_watches(replacement_info, control) return delete_add
def propagate(self, control, change) -> Optional[List[Tuple]]: """ For any relevant change, check the assignment of the whole nogood for the assigned times it is in. If it it conflicting or unit add the nogood to the solver After the check, replace the watch if possible. :param control: clingo PropagateControl object :param change: watch that was assigned :return None if propagation has to stop, A list of (delete, add) pairs of watches if propagation can continue """ delete_add = [] replacement_info: List[List[int]] = [] for assigned_time in self.watches_to_at[change]: if not self.is_valid_time(assigned_time): continue ng = form_nogood(self.t_atom_info, assigned_time) if ng is None: continue result = self.check_assignment(ng, control, assigned_time) if result is None: return None elif result == ConstraintCheck.UNIT: return [] else: for lit in ng: if lit == change: continue if control.assignment.value is None: self.watches_to_at[change].remove(assigned_time) self.watches_to_at[lit].add(assigned_time) delete_add.append([change, lit]) break return delete_add
def propagate(self, control, change) -> Optional[List[Tuple]]: """ :param control: clingo PropagateControl object :param change: literal that was assigned :return None if propagation has to stop, A list of (delete, add) pairs of watches if propagation can continue """ ats = get_at_from_internal_lit(change, self.t_atom_info) for assigned_time in ats: if not self.is_valid_time(assigned_time): continue self.counts[assigned_time] += 1 if self.counts[assigned_time] >= self.size - 1: ng = form_nogood(self.t_atom_info, assigned_time) if ng is None: continue if self.check_assignment(ng, control, assigned_time) is None: return None return 1