def convert(self): ''' Performs a conversion from an MLN into a WCSP. ''' # mln to be restored after inference self._weights = list(self.mrf.mln.weights) mln = self.mrf.mln logic = mln.logic # preprocess the formulas formulas = [] for f in self.mrf.formulas: if f.weight == 0: continue if f.weight < 0: f = logic.negate(f) f.weight = -f.weight formulas.append(f.nnf()) # preprocess the ground formulas # grounder = DefaultGroundingFactory(self.mrf, formulas=formulas, simplify=True, unsatfailure=True, multicore=self.multicore, verbose=self.verbose) grounder = FastConjunctionGrounding(self.mrf, simplify=True, unsatfailure=True, formulas=formulas, multicore=self.multicore, verbose=self.verbose, cache=0) for gf in grounder.itergroundings(): if isinstance(gf, Logic.TrueFalse): if gf.weight == HARD and gf.truth() == 0: raise SatisfiabilityException('MLN is unsatisfiable: hard constraint %s violated' % self.mrf.mln.formulas[gf.idx]) else:# formula is rendered true/false by the evidence -> equal in every possible world continue self.generate_constraint(gf) self.mrf.mln.weights = self._weights return self.wcsp
def __init__(self, mrf, queries=ALL, state=None, **params): MCMCInference.__init__(self, mrf, queries, **params) if state is None: self.state = self.random_world(self.mrf.evidence) else: self.state = state self.sum = 0 self.var2gf = defaultdict(set) self.weights = list(self.mrf.mln.weights) formulas = [] for f in self.mrf.formulas: if f.weight < 0: f_ = self.mrf.mln.logic.negate(f) f_.weight = -f.weight formulas.append(f_.nnf()) grounder = FastConjunctionGrounding(mrf, formulas=formulas, simplify=True, unsatfailure=True) for gf in grounder.itergroundings(): if isinstance(gf, Logic.TrueFalse): continue vars_ = set(map(lambda a: self.mrf.variable(a).idx, gf.gndatoms())) for v in vars_: self.var2gf[v].add(gf) self.sum += (self.hardw if gf.weight == HARD else gf.weight) * (1 - gf(self.state))
def __init__(self, mrf, queries=ALL, **params): MCMCInference.__init__(self, mrf, queries, **params) self.var2gf = defaultdict(set) grounder = FastConjunctionGrounding(mrf, simplify=True, unsatfailure=True, cache=None) for gf in grounder.itergroundings(): if isinstance(gf, Logic.TrueFalse): continue vars_ = set(map(lambda a: self.mrf.variable(a).idx, gf.gndatoms())) for v in vars_: self.var2gf[v].add(gf)
def __init__(self, mrf, formulas=None, cache=None, **params): FastConjunctionGrounding.__init__(self, mrf, simplify=False, unsatfailure=False, formulas=formulas, cache=cache, **params) self._stat = {} self._varidx2fidx = defaultdict(set)
def __init__(self, mrf, queries, **params): Inference.__init__(self, mrf, queries, **params) self.grounder = FastConjunctionGrounding(mrf, simplify=False, unsatfailure=False, formulas=mrf.formulas, cache=auto, verbose=False, multicore=False) # self.grounder = DefaultGroundingFactory(mrf, simplify=False, unsatfailure=False, formulas=list(mrf.formulas), cache=auto, verbose=False) # check consistency of fuzzy and functional variables for variable in self.mrf.variables: variable.consistent(self.mrf.evidence, strict=isinstance(variable, FuzzyVariable))
def __init__(self, mrf, queries=ALL, state=None, **params): MCMCInference.__init__(self, mrf, queries, **params) if state is None: self.state = self.random_world(self.mrf.evidence) else: self.state = state self.sum = 0 self.var2gf = defaultdict(set) self.weights = list(self.mrf.mln.weights) formulas = [] for f in self.mrf.formulas: if f.weight < 0: f_ = self.mrf.mln.logic.negate(f) f_.weight = - f.weight formulas.append(f_.nnf()) grounder = FastConjunctionGrounding(mrf, formulas=formulas, simplify=True, unsatfailure=True) for gf in grounder.itergroundings(): if isinstance(gf, Logic.TrueFalse): continue vars_ = set(map(lambda a: self.mrf.variable(a).idx, gf.gndatoms())) for v in vars_: self.var2gf[v].add(gf) self.sum += (self.hardw if gf.weight == HARD else gf.weight) * (1 - gf(self.state))
def _run(self): """ verbose: whether to print results (or anything at all, in fact) details: (given that verbose is true) whether to output additional status information debug: (given that verbose is true) if true, outputs debug information, in particular the distribution over possible worlds debugLevel: level of detail for debug mode """ # check consistency with hard constraints: self._watch.tag('check hard constraints', verbose=self.verbose) hcgrounder = FastConjunctionGrounding(self.mrf, simplify=False, unsatfailure=True, formulas=[f for f in self.mrf.formulas if f.weight == HARD], **(self._params + {'multicore': False, 'verbose': False})) for gf in hcgrounder.itergroundings(): if isinstance(gf, Logic.TrueFalse) and gf.truth() == .0: raise SatisfiabilityException('MLN is unsatisfiable due to hard constraint violation by evidence: {} ({})'.format(str(gf), str(self.mln.formula(gf.idx)))) self._watch.finish('check hard constraints') # compute number of possible worlds worlds = 1 for variable in self.mrf.variables: values = variable.valuecount(self.mrf.evidence) worlds *= values numerators = [0.0 for i in range(len(self.queries))] denominator = 0. # start summing logger.debug("Summing over %d possible worlds..." % worlds) if worlds > 500000 and self.verbose: print colorize('!!! %d WORLDS WILL BE ENUMERATED !!!' % worlds, (None, 'red', True), True) k = 0 self._watch.tag('enumerating worlds', verbose=self.verbose) global global_enumAsk global_enumAsk = self bar = None if self.verbose: bar = ProgressBar(width=100, steps=worlds, color='green') if self.multicore: pool = Pool() logger.debug('Using multiprocessing on {} core(s)...'.format(pool._processes)) try: for num, denum in pool.imap(with_tracing(eval_queries), self.mrf.worlds()): denominator += denum k += 1 for i, v in enumerate(num): numerators[i] += v if self.verbose: bar.inc() except Exception as e: logger.error('Error in child process. Terminating pool...') pool.close() raise e finally: pool.terminate() pool.join() else: # do it single core for world in self.mrf.worlds(): # compute exp. sum of weights for this world num, denom = eval_queries(world) denominator += denom for i, _ in enumerate(self.queries): numerators[i] += num[i] k += 1 if self.verbose: bar.update(float(k) / worlds) logger.debug("%d worlds enumerated" % k) self._watch.finish('enumerating worlds') if 'grounding' in self.grounder.watch.tags: self._watch.tags['grounding'] = self.grounder.watch['grounding'] if denominator == 0: raise SatisfiabilityException( 'MLN is unsatisfiable. All probability masses returned 0.') # normalize answers dist = map(lambda x: float(x) / denominator, numerators) result = {} for q, p in zip(self.queries, dist): result[str(q)] = p return result
def _initkb(self, verbose=False): ''' Initialize the knowledge base to the required format and collect structural information for optimization purposes ''' # convert the MLN ground formulas to CNF logger.debug("converting formulas to cnf...") #self.mln._toCNF(allPositive=True) self.formulas = [] for f in self.mrf.formulas: if f.weight < 0: f.weight = -f.weight f = self.mln.logic.negate(f) self.formulas.append(f) # softweights = [1 - 1 / numpy.exp(w) for w in self.mln.weights if w != HARD] # stop(sorted(softweights, reverse=True)) # w_mean = numpy.mean(softweights) # w_stdev = numpy.std(softweights) # for f in self.mrf.formulas: # if f.ishard: continue # f.weight = min(w_stdev, f.weight) grounder = FastConjunctionGrounding(self.mrf, formulas=self.formulas, simplify=True, verbose=self.verbose) self.gndformulas = [] for gf in grounder.itergroundings(): if isinstance(gf, Logic.TrueFalse): continue self.gndformulas.append(gf.cnf()) self._watch.tags.update(grounder.watch.tags) # self.gndformulas, self.formulas = Logic.cnf(grounder.itergroundings(), self.mln.formulas, self.mln.logic, allpos=True) # get clause data logger.debug("gathering clause data...") self.gf2clauseidx = { } # ground formula index -> tuple (idxFirstClause, idxLastClause+1) for use with range self.clauses = [ ] # list of clauses, where each entry is a list of ground literals #self.GAoccurrences = {} # ground atom index -> list of clause indices (into self.clauses) i_clause = 0 # process all ground formulas for i_gf, gf in enumerate(self.gndformulas): # get the list of clauses if isinstance(gf, Logic.Conjunction): clauses = [ clause for clause in gf.children if not isinstance(clause, Logic.TrueFalse) ] elif not isinstance(gf, Logic.TrueFalse): clauses = [gf] else: continue self.gf2clauseidx[i_gf] = (i_clause, i_clause + len(clauses)) # process each clause for c in clauses: if hasattr(c, "children"): lits = c.children else: # unit clause lits = [c] # add clause to list self.clauses.append(lits) # next clause index i_clause += 1 # add clauses for soft evidence atoms for se in []: #self.softEvidence: se["numTrue"] = 0.0 formula = self.mln.logic.parseFormula(se["expr"]) se["formula"] = formula.ground(self.mrf, {}) cnf = formula.toCNF().ground(self.mrf, {}) idxFirst = i_clause for clause in self._formulaClauses(cnf): self.clauses.append(clause) #print clause i_clause += 1 se["idxClausePositive"] = (idxFirst, i_clause) cnf = self.mln.logic.negation([formula ]).toCNF().ground(self.mrf, {}) idxFirst = i_clause for clause in self._formulaClauses(cnf): self.clauses.append(clause) #print clause i_clause += 1 se["idxClauseNegative"] = (idxFirst, i_clause)
def _initkb(self, verbose=False): ''' Initialize the knowledge base to the required format and collect structural information for optimization purposes ''' # convert the MLN ground formulas to CNF logger.debug("converting formulas to cnf...") #self.mln._toCNF(allPositive=True) self.formulas = [] for f in self.mrf.formulas: if f.weight < 0: f.weight = -f.weight f = self.mln.logic.negate(f) self.formulas.append(f) # softweights = [1 - 1 / numpy.exp(w) for w in self.mln.weights if w != HARD] # stop(sorted(softweights, reverse=True)) # w_mean = numpy.mean(softweights) # w_stdev = numpy.std(softweights) # for f in self.mrf.formulas: # if f.ishard: continue # f.weight = min(w_stdev, f.weight) grounder = FastConjunctionGrounding(self.mrf, formulas=self.formulas, simplify=True, verbose=self.verbose) self.gndformulas = [] for gf in grounder.itergroundings(): if isinstance(gf, Logic.TrueFalse): continue self.gndformulas.append(gf.cnf()) self._watch.tags.update(grounder.watch.tags) # self.gndformulas, self.formulas = Logic.cnf(grounder.itergroundings(), self.mln.formulas, self.mln.logic, allpos=True) # get clause data logger.debug("gathering clause data...") self.gf2clauseidx = {} # ground formula index -> tuple (idxFirstClause, idxLastClause+1) for use with range self.clauses = [] # list of clauses, where each entry is a list of ground literals #self.GAoccurrences = {} # ground atom index -> list of clause indices (into self.clauses) i_clause = 0 # process all ground formulas for i_gf, gf in enumerate(self.gndformulas): # get the list of clauses if isinstance(gf, Logic.Conjunction): clauses = [clause for clause in gf.children if not isinstance(clause, Logic.TrueFalse)] elif not isinstance(gf, Logic.TrueFalse): clauses = [gf] else: continue self.gf2clauseidx[i_gf] = (i_clause, i_clause + len(clauses)) # process each clause for c in clauses: if hasattr(c, "children"): lits = c.children else: # unit clause lits = [c] # add clause to list self.clauses.append(lits) # next clause index i_clause += 1 # add clauses for soft evidence atoms for se in []:#self.softEvidence: se["numTrue"] = 0.0 formula = self.mln.logic.parseFormula(se["expr"]) se["formula"] = formula.ground(self.mrf, {}) cnf = formula.toCNF().ground(self.mrf, {}) idxFirst = i_clause for clause in self._formulaClauses(cnf): self.clauses.append(clause) #print clause i_clause += 1 se["idxClausePositive"] = (idxFirst, i_clause) cnf = self.mln.logic.negation([formula]).toCNF().ground(self.mrf, {}) idxFirst = i_clause for clause in self._formulaClauses(cnf): self.clauses.append(clause) #print clause i_clause += 1 se["idxClauseNegative"] = (idxFirst, i_clause)