def write(self, stream=sys.stdout, color=None): ''' Writes the MLN to the given stream. The default stream is `sys.stdout`. In order to print the MLN to the console, a simple call of `mln.write()` is sufficient. If color is not specified (is None), then the output to the console will be colored and uncolored for every other stream. :param stream: the stream to write the MLN to. :param color: whether or not output should be colorized. ''' if color is None: if stream != sys.stdout: color = False else: color = True if 'learnwts_message' in dir(self): stream.write("/*\n%s*/\n\n" % self.learnwts_message) # domain declarations if self.domain_decls: stream.write( colorize("// domain declarations\n", comment_color, color)) for d in self.domain_decls: stream.write("%s\n" % d) stream.write('\n') # variable definitions if self.vars: stream.write( colorize('// variable definitions\n', comment_color, color)) for var, val in self.vars.iteritems(): stream.write('%s = %s' % (var, val)) stream.write('\n') stream.write( colorize("\n// predicate declarations\n", comment_color, color)) for predicate in self.iterpreds(): if isinstance(predicate, FuzzyPredicate) or predicate.name in self.fuzzypreds: stream.write('#fuzzy\n') stream.write("%s(%s)\n" % (colorize( predicate.name, predicate_color, color), predicate.argstr())) stream.write(colorize("\n// formulas\n", comment_color, color)) for idx, formula in self.iterformulas(): if self._unique_templvars[idx]: stream.write('#unique{%s}\n' % ','.join(self._unique_templvars[idx])) if formula.weight == HARD: stream.write("%s.\n" % fstr(formula.cstr(color))) else: try: w = colorize("%-10.6f", weight_color, color) % float( eval(str(formula.weight))) except: w = colorize(str(formula.weight), weight_color, color) stream.write("%s %s\n" % (w, fstr(formula.cstr(color))))
def iter_formulas_printable(self): ''' Iterate over all formulas, yield nicely formatted strings. ''' formulas = sorted(self.formulas) for f in formulas: if f.weight == HARD: yield '%s.' % fstr(f) elif type(f.weight) is float: yield "%-10.6f\t%s" % (f.weight, fstr(f)) else: yield "%s\t%s" % (str(f.weight), fstr(f))
def set_soft_evidence(self, soft_evidence): self.soft_evidence = soft_evidence self.softev_counts = {} for se in soft_evidence: if 'formula' not in se: formula = self.infer.mrf.mln.logic.parse_formula(se['expr']) se['formula'] = formula.ground(self.infer.mrf, {}) se['expr'] = fstr(se['formula']) self.softev_counts[se["expr"]] = se["formula"](self.state)
def write(self, stream=sys.stdout, color=None): ''' Writes the MLN to the given stream. The default stream is `sys.stdout`. In order to print the MLN to the console, a simple call of `mln.write()` is sufficient. If color is not specified (is None), then the output to the console will be colored and uncolored for every other stream. :param stream: the stream to write the MLN to. :param color: whether or not output should be colorized. ''' if color is None: if stream != sys.stdout: color = False else: color = True if 'learnwts_message' in dir(self): stream.write("/*\n%s*/\n\n" % self.learnwts_message) # domain declarations if self.domain_decls: stream.write(colorize("// domain declarations\n", comment_color, color)) for d in self.domain_decls: stream.write("%s\n" % d) stream.write('\n') # variable definitions if self.vars: stream.write(colorize('// variable definitions\n', comment_color, color)) for var, val in self.vars.iteritems(): stream.write('%s = %s' % (var, val)) stream.write('\n') stream.write(colorize("\n// predicate declarations\n", comment_color, color)) for predicate in self.iterpreds(): if isinstance(predicate, FuzzyPredicate) or predicate.name in self.fuzzypreds: stream.write('#fuzzy\n') stream.write("%s(%s)\n" % (colorize(predicate.name, predicate_color, color), predicate.argstr())) stream.write(colorize("\n// formulas\n", comment_color, color)) for idx, formula in self.iterformulas(): if self._unique_templvars[idx]: stream.write('#unique{%s}\n' % ','.join(self._unique_templvars[idx])) if formula.weight == HARD: stream.write("%s.\n" % fstr(formula.cstr(color))) else: try: w = colorize("%-10.6f", weight_color, color) % float(eval(str(formula.weight))) except: w = colorize(str(formula.weight), weight_color, color) stream.write("%s %s\n" % (w, fstr(formula.cstr(color))))
def set_soft_evidence(self, soft_evidence): self.soft_evidence = soft_evidence self.softev_counts = {} for se in soft_evidence: if 'formula' not in se: formula = self.infer.mrf.mln.logic.parse_formula( se['expr']) se['formula'] = formula.ground(self.infer.mrf, {}) se['expr'] = fstr(se['formula']) self.softev_counts[se["expr"]] = se["formula"](self.state)
def vardoms_from_formula(mln, formula, *varnames): if isinstance(formula, basestring): formula = mln.logic.parse_formula(formula) vardomains = {} f_vardomains = formula.vardoms(mln) for var in varnames: if var not in f_vardomains: raise Exception( 'Variable %s not bound to a domain by formula %s' % (var, fstr(formula))) vardomains[var] = f_vardomains[var] return vardomains
def materialize(self, *dbs): ''' Materializes this MLN with respect to the databases given. This must be called before learning or inference can take place. Returns a new MLN instance containing expanded formula templates and materialized weights. Normally, this method should not be called from the outside. Also takes into account whether or not particular domain values or predictaes are actually used in the data, i.e. if a predicate is not used in any of the databases, all formulas that make use of this predicate are ignored. :param dbs: list of :class:`database.Database` objects for materialization. ''' logger.debug("materializing formula templates...") # obtain full domain with all objects fulldomain = mergedom(self.domains, *[db.domains for db in dbs]) logger.debug('full domains: %s' % fulldomain) mln_ = self.copy() # collect the admissible formula templates. templates might be not # admissible since the domain of a template variable might be empty. for ft in list(mln_.formulas): domnames = ft.vardoms().values() if any([domname not in fulldomain for domname in domnames]): logger.debug('Discarding formula template %s, since it cannot be grounded (domain(s) %s empty).' % \ (fstr(ft), ','.join([d for d in domnames if d not in fulldomain]))) mln_.rmf(ft) # collect the admissible predicates. a predicate may become inadmissible # if either the domain of one of its arguments is empty or there is # no formula containing the respective predicate. predicates_used = set() for _, f in mln_.iterformulas(): predicates_used.update(f.prednames()) for predicate in self.iterpreds(): remove = False if any([not dom in fulldomain for dom in predicate.argdoms]): logger.debug( 'Discarding predicate %s, since it cannot be grounded.' % (predicate.name)) remove = True if predicate.name not in predicates_used: logger.debug('Discarding predicate %s, since it is unused.' % predicate.name) remove = True if remove: del mln_._predicates[predicate.name] # permanently transfer domains of variables that were expanded from templates for _, ft in mln_.iterformulas(): domnames = ft.template_variables().values() for domname in domnames: mln_.domains[domname] = fulldomain[domname] # materialize the formula templates mln__ = mln_.copy() mln__._rmformulas() for i, template in mln_.iterformulas(): for variant in template.template_variants(): idx = len(mln__._formulas) f = mln__.formula( variant, weight=template.weight if isinstance( template.weight, basestring) else template.weight, fixweight=mln_.fixweights[i]) f.idx = idx mln__._materialized = True return mln__
def __str__(self): return 'P(%s|E) = %.2f' % (fstr(self.formula), self.p)
def soft_evidence_frequency(self, formula): if self.steps == 0: return 0 return float(self.softev_counts[fstr(formula)]) / self.steps
def materialize(self, *dbs): ''' Materializes this MLN with respect to the databases given. This must be called before learning or inference can take place. Returns a new MLN instance containing expanded formula templates and materialized weights. Normally, this method should not be called from the outside. Also takes into account whether or not particular domain values or predictaes are actually used in the data, i.e. if a predicate is not used in any of the databases, all formulas that make use of this predicate are ignored. :param dbs: list of :class:`database.Database` objects for materialization. ''' logger.debug("materializing formula templates...") # obtain full domain with all objects fulldomain = mergedom(self.domains, *[db.domains for db in dbs]) logger.debug('full domains: %s' % fulldomain) mln_ = self.copy() # collect the admissible formula templates. templates might be not # admissible since the domain of a template variable might be empty. for ft in list(mln_.formulas): domnames = ft.vardoms().values() if any([not domname in fulldomain for domname in domnames]): logger.debug('Discarding formula template %s, since it cannot be grounded (domain(s) %s empty).' % \ (fstr(ft), ','.join([d for d in domnames if d not in fulldomain]))) mln_.rmf(ft) # collect the admissible predicates. a predicate may become inadmissible # if either the domain of one of its arguments is empty or there is # no formula containing the respective predicate. predicates_used = set() for _, f in mln_.iterformulas(): predicates_used.update(f.prednames()) for predicate in self.iterpreds(): remove = False if any([not dom in fulldomain for dom in predicate.argdoms]): logger.debug('Discarding predicate %s, since it cannot be grounded.' % (predicate.name)) remove = True if predicate.name not in predicates_used: logger.debug('Discarding predicate %s, since it is unused.' % predicate.name) remove = True if remove: del mln_._predicates[predicate.name] # permanently transfer domains of variables that were expanded from templates for _, ft in mln_.iterformulas(): domnames = ft.template_variables().values() for domname in domnames: mln_.domains[domname] = fulldomain[domname] # materialize the formula templates mln__ = mln_.copy() mln__ ._rmformulas() for i, template in mln_.iterformulas(): for variant in template.template_variants(): idx = len(mln__._formulas) f = mln__.formula(variant, weight=template.weight if isinstance(template.weight, basestring) else template.weight, fixweight=mln_.fixweights[i]) f.idx = idx mln__._materialized = True return mln__
def vardoms_from_formula(mln, formula, *varnames): if isinstance(formula, basestring): formula = mln.logic.parse_formula(formula) vardomains = {} f_vardomains = formula.vardoms(mln) for var in varnames: if var not in f_vardomains: raise Exception('Variable %s not bound to a domain by formula %s' % (var, fstr(formula))) vardomains[var] = f_vardomains[var] return vardomains