def _run(self): result_ = {} with temporary_evidence(self.mrf): self.converter = WCSPConverter(self.mrf, multicore=self.multicore, verbose=self.verbose) result = self.result_dict(verbose=self.verbose) for query in self.queries: query = str(query) result_[query] = result[query] if query in result else self.mrf[query] return result_
def _compute_statistics(self): ''' computes the statistics upon which the optimization is based ''' self._stat = {} self._varidx2fidx = defaultdict(set) grounder = DefaultGroundingFactory(self.mrf, simplify=False, unsatfailure=True, verbose=self.verbose, cache=0) for f in grounder.itergroundings(): for gndatom in f.gndatoms(): var = self.mrf.variable(gndatom) with temporary_evidence(self.mrf): for validx, value in var.itervalues(): var.setval(value, self.mrf.evidence) truth = f(self.mrf.evidence) if truth != 0: self._varidx2fidx[var.idx].add(f.idx) self._addstat(f.idx, var.idx, validx, truth)
def _compute_stat_rec(self, literals, gndliterals, var_assign, formula, f_gndlit_parts=None, processed=None, isconj=False): ''' TODO: make sure that there are no equality constraints in the conjunction! ''' if len(literals) == 0: # at this point, we have a fully grounded conjunction in gndliterals # create a mapping from a partition to the ground literals in this formula # (criterion no. 1, applies to all kinds of formulas) part2gndlits = defaultdict(list) part_with_f_lit = None for gndlit in gndliterals: if isinstance(gndlit, Logic.Equality) or hasattr(self, 'qpreds') and gndlit.gndatom.predname not in self.qpreds: continue part = self.atomidx2partition[gndlit.gndatom.idx] part2gndlits[part].append(gndlit) if gndlit(self.mrf.evidence) == 0: part_with_f_lit = part # if there is a false ground literal we only need to take into account # the partition comprising this literal (criterion no. 2) # there is maximally one such partition with false literals in the conjunction # because of criterion no. 5 if isconj and part_with_f_lit is not None: gndlits = part2gndlits[part_with_f_lit] part2gndlits = {part_with_f_lit: gndlits} if not isconj: # if we don't have a conjunction, ground the formula with the given variable assignment gndformula = formula.ground(self.mrf, var_assign) for partition, gndlits in part2gndlits.iteritems(): # for each partition, select the ground atom truth assignments # in such a way that the conjunction is rendered true. There # is precisely one such assignment for each partition. (criterion 3/4) evidence = {} if isconj: for gndlit in gndlits: evidence[gndlit.gndatom.idx] = 0 if gndlit.negated else 1 for world in partition.itervalues(evidence): # update the sufficient statistics for the given formula, partition and world value worldidx = partition.valueidx(world) if isconj: truth = 1 else: # temporarily set the evidence in the MRF, compute the truth value of the # formula and remove the temp evidence with temporary_evidence(self.mrf): for atomidx, value in partition.value2dict(world).iteritems(): self.mrf[atomidx] = value truth = gndformula(self.mrf.evidence) if truth != 0: self.partition2formulas[partition.idx].add(formula.idx) self._addstat(formula.idx, partition.idx, worldidx, truth) return lit = literals[0] # ground the literal with the existing assignments gndlit = lit.ground(self.mrf, var_assign, partial=True) for assign in Logic.iter_eq_varassignments(gndlit, formula, self.mrf) if isinstance(gndlit, Logic.Equality) else gndlit.itervargroundings(self.mrf): # copy the arguments to avoid side effects # if f_gndlit_parts is None: f_gndlit_parts = set() # else: f_gndlit_parts = set(f_gndlit_parts) if processed is None: processed = [] else: processed = list(processed) # ground with the remaining free variables gndlit_ = gndlit.ground(self.mrf, assign) truth = gndlit_(self.mrf.evidence) # treatment of equality constraints if isinstance(gndlit_, Logic.Equality): if isconj: if truth == 1: self._compute_stat_rec(literals[1:], gndliterals, dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj) else: continue else: self._compute_stat_rec(literals[1:], gndliterals + [gndlit_], dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj) continue atom = gndlit_.gndatom if atom.idx in processed: continue # if we encounter a gnd literal that is false by the evidence # and there is already a false one in this grounding from a different # partition, we can stop the grounding process here. The gnd conjunction # will never ever be rendered true by any of this partitions values (criterion no. 5) isevidence = hasattr(self, 'qpreds') and gndlit_.gndatom.predname not in self.qpreds #assert isEvidence == False if isconj and truth == 0: if f_gndlit_parts is not None and atom not in f_gndlit_parts: continue elif isevidence: continue else: self._compute_stat_rec(literals[1:], gndliterals + [gndlit_], dict_union(var_assign, assign), formula, self.atomidx2partition[atom.idx], processed, isconj) continue elif isconj and isevidence: self._compute_stat_rec(literals[1:], gndliterals, dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj) continue self._compute_stat_rec(literals[1:], gndliterals + [gndlit_], dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj)
def _compute_stat_rec(self, literals, gndliterals, var_assign, formula, f_gndlit_parts=None, processed=None, isconj=False): ''' TODO: make sure that there are no equality constraints in the conjunction! ''' if len(literals) == 0: # at this point, we have a fully grounded conjunction in gndliterals # create a mapping from a partition to the ground literals in this formula # (criterion no. 1, applies to all kinds of formulas) part2gndlits = defaultdict(list) part_with_f_lit = None for gndlit in gndliterals: if isinstance(gndlit, Logic.Equality) or hasattr( self, 'qpreds' ) and gndlit.gndatom.predname not in self.qpreds: continue part = self.atomidx2partition[gndlit.gndatom.idx] part2gndlits[part].append(gndlit) if gndlit(self.mrf.evidence) == 0: part_with_f_lit = part # if there is a false ground literal we only need to take into account # the partition comprising this literal (criterion no. 2) # there is maximally one such partition with false literals in the conjunction # because of criterion no. 5 if isconj and part_with_f_lit is not None: gndlits = part2gndlits[part_with_f_lit] part2gndlits = {part_with_f_lit: gndlits} if not isconj: # if we don't have a conjunction, ground the formula with the given variable assignment # print 'formula', formula gndformula = formula.ground(self.mrf, var_assign) # print 'gndformula', gndformula # stop() for partition, gndlits in part2gndlits.iteritems(): # for each partition, select the ground atom truth assignments # in such a way that the conjunction is rendered true. There # is precisely one such assignment for each partition. (criterion 3/4) evidence = {} if isconj: for gndlit in gndlits: evidence[ gndlit.gndatom.idx] = 0 if gndlit.negated else 1 for world in partition.itervalues(evidence): # update the sufficient statistics for the given formula, partition and world value worldidx = partition.valueidx(world) if isconj: truth = 1 else: # temporarily set the evidence in the MRF, compute the truth value of the # formula and remove the temp evidence with temporary_evidence(self.mrf): for atomidx, value in partition.value2dict( world).iteritems(): self.mrf.set_evidence({atomidx: value}, erase=True) truth = gndformula(self.mrf.evidence) if truth is None: print gndformula print gndformula.print_structure( self.mrf.evidence) if truth != 0: self.partition2formulas[partition.idx].add(formula.idx) self._addstat(formula.idx, partition.idx, worldidx, truth) return lit = literals[0] # ground the literal with the existing assignments gndlit = lit.ground(self.mrf, var_assign, partial=True) for assign in Logic.iter_eq_varassignments( gndlit, formula, self.mrf) if isinstance( gndlit, Logic.Equality) else gndlit.itervargroundings( self.mrf): # copy the arguments to avoid side effects # if f_gndlit_parts is None: f_gndlit_parts = set() # else: f_gndlit_parts = set(f_gndlit_parts) if processed is None: processed = [] else: processed = list(processed) # ground with the remaining free variables gndlit_ = gndlit.ground(self.mrf, assign) truth = gndlit_(self.mrf.evidence) # treatment of equality constraints if isinstance(gndlit_, Logic.Equality): if isconj: if truth == 1: self._compute_stat_rec(literals[1:], gndliterals, dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj) else: continue else: self._compute_stat_rec(literals[1:], gndliterals + [gndlit_], dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj) continue atom = gndlit_.gndatom if atom.idx in processed: continue # if we encounter a gnd literal that is false by the evidence # and there is already a false one in this grounding from a different # partition, we can stop the grounding process here. The gnd conjunction # will never ever be rendered true by any of this partitions values (criterion no. 5) isevidence = hasattr( self, 'qpreds') and gndlit_.gndatom.predname not in self.qpreds #assert isEvidence == False if isconj and truth == 0: if f_gndlit_parts is not None and atom not in f_gndlit_parts: continue elif isevidence: continue else: self._compute_stat_rec(literals[1:], gndliterals + [gndlit_], dict_union(var_assign, assign), formula, self.atomidx2partition[atom.idx], processed, isconj) continue elif isconj and isevidence: self._compute_stat_rec(literals[1:], gndliterals, dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj) continue self._compute_stat_rec(literals[1:], gndliterals + [gndlit_], dict_union(var_assign, assign), formula, f_gndlit_parts, processed, isconj)