def parse_db(mln, content, ignore_unknown_preds=False, db=None, dirs=['.'], projectpath=None): ''' Reads one or more databases in a string representation and returns the respective Database objects. :param mln: the MLN object which should be used to load the database. :param content: the string representation of one or multiple ('---'-separated) databases :param ignore_unknown_preds: by default this function raises an Exception when it encounters a predicate in the DB that has not been declared in the associated MLN. ignore_unknown_preds=True simply ignores such predicates. :param db: the Database object that shall receive the facts stored in the new DB. If None, a new `Database` object will be created. ''' log = logging.getLogger('db') content = stripComments(content) allow_multiple = True if db is None: allow_multiple = True db = Database(mln, ignore_unknown_preds=ignore_unknown_preds) dbs = [] # expand domains with dbtext constants and save evidence for line, l in enumerate(content.split("\n")): l = l.strip() if l == '': continue # separator between independent databases elif l == '---' and not db.isempty(): dbs.append(db) db = Database(mln) continue # domain declaration elif "{" in l: domname, constants = db.mln.logic.parse_domain(l) domnames = [domname for _ in constants] # include elif l.startswith('#include'): filename = l[len("#include "):].strip() m = re.match(r'"(?P<filename>.+)"', filename) if m is not None: filename = m.group('filename') # if the path is relative, look for the respective file # relatively to all paths specified. Take the first file matching. if not mlnpath(filename).exists: includefilename = None for d in dirs: mlnp = '/'.join([d, filename]) if mlnpath(mlnp).exists: includefilename = mlnp break if includefilename is None: raise Exception('File not found: %s' % filename) else: includefilename = filename else: m = re.match(r'<(?P<filename>.+)>', filename) if m is not None: filename = m.group('filename') else: raise MLNParsingError('Malformed #include statement: %s' % line) if projectpath is None: raise MLNParsingError('No project specified: Cannot locate import from project: %s' % filename) includefilename = ':'.join([projectpath, filename]) logger.debug('Including file: "%s"' % includefilename) p = mlnpath(includefilename) dbs.extend(parse_db(content=mlnpath(includefilename).content, ignore_unknown_preds=ignore_unknown_preds, dirs=[p.resolve_path()]+dirs, projectpath=ifNone(p.project, projectpath, lambda x: '/'.join(p.path+[x])), mln=mln)) continue # valued evidence elif l[0] in "0123456789": s = l.find(" ") gndatom = l[s + 1:].replace(" ", "") value = float(l[:s]) if value < 0 or value > 1: raise Exception('Valued evidence must be in [0,1]') if gndatom in db.evidence: raise Exception("Duplicate soft evidence for '%s'" % gndatom) try: positive, predname, constants = mln.logic.parse_literal(gndatom) # TODO Should we allow soft evidence on non-atoms here? (This assumes atoms) except NoSuchPredicateError, e: if ignore_unknown_preds: continue else: raise e domnames = mln.predicate(predname).argdoms db << (gndatom, value) # literal else: if l[0] == "?": raise Exception("Unknown literals not supported (%s)" % l) # this is an Alchemy feature try: true, predname, constants = mln.logic.parse_literal(l) except NoSuchPredicateError, e: if ignore_unknown_preds: continue else: raise e except Exception, e: traceback.print_exc() raise MLNParsingError('Error parsing line %d: %s (%s)' % (line+1, l, e.message))
from pracmln.logic.fol import FirstOrderLogic from pracmln.praclog import logging from multiprocessing import Pool from pracmln.utils.multicore import with_tracing from pracmln.mln.mrfvars import FuzzyVariable from pracmln.mln.constants import auto, HARD from pracmln.mln.errors import SatisfiabilityException from pracmln.mln.grounding.fastconj import FastConjunctionGrounding from pracmln.mln.util import Interval, ProgressBar, colorize from numpy.ma.core import exp from pracmln.mln.inference.infer import Inference from pracmln.logic.common import Logic logger = logging.getLogger(__name__) # this readonly global is for multiprocessing to exploit copy-on-write # on linux systems global_enumAsk = None def eval_queries(world): """ Evaluates the queries given a possible world. """ numerators = [0] * len(global_enumAsk.queries) denominator = 0 expsum = 0 for gf in global_enumAsk.grounder.itergroundings(): if global_enumAsk.soft_evidence_formula(gf):
def parse_db(mln, content, ignore_unknown_preds=False, db=None, dirs=['.'], projectpath=None): ''' Reads one or more databases in a string representation and returns the respective Database objects. :param mln: the MLN object which should be used to load the database. :param content: the string representation of one or multiple ('---'-separated) databases :param ignore_unknown_preds: by default this function raises an Exception when it encounters a predicate in the DB that has not been declared in the associated MLN. ignore_unknown_preds=True simply ignores such predicates. :param db: the Database object that shall receive the facts stored in the new DB. If None, a new `Database` object will be created. ''' log = logging.getLogger('db') content = stripComments(content) allow_multiple = True if db is None: allow_multiple = True db = Database(mln, ignore_unknown_preds=ignore_unknown_preds) dbs = [] # expand domains with dbtext constants and save evidence for line, l in enumerate(content.split("\n")): l = l.strip() if l == '': continue # separator between independent databases elif l == '---' and not db.isempty(): dbs.append(db) db = Database(mln) continue # domain declaration elif "{" in l: domname, constants = db.mln.logic.parse_domain(l) domnames = [domname for _ in constants] # include elif l.startswith('#include'): filename = l[len("#include "):].strip() m = re.match(r'"(?P<filename>.+)"', filename) if m is not None: filename = m.group('filename') # if the path is relative, look for the respective file # relatively to all paths specified. Take the first file matching. if not mlnpath(filename).exists: includefilename = None for d in dirs: mlnp = '/'.join([d, filename]) if mlnpath(mlnp).exists: includefilename = mlnp break if includefilename is None: raise Exception('File not found: %s' % filename) else: includefilename = filename else: m = re.match(r'<(?P<filename>.+)>', filename) if m is not None: filename = m.group('filename') else: raise MLNParsingError('Malformed #include statement: %s' % line) if projectpath is None: raise MLNParsingError( 'No project specified: Cannot locate import from project: %s' % filename) includefilename = ':'.join([projectpath, filename]) logger.debug('Including file: "%s"' % includefilename) p = mlnpath(includefilename) dbs.extend( parse_db(content=mlnpath(includefilename).content, ignore_unknown_preds=ignore_unknown_preds, dirs=[p.resolve_path()] + dirs, projectpath=ifNone(p.project, projectpath, lambda x: '/'.join(p.path + [x])), mln=mln)) continue # valued evidence elif l[0] in "0123456789": s = l.find(" ") gndatom = l[s + 1:].replace(" ", "") value = float(l[:s]) if value < 0 or value > 1: raise Exception('Valued evidence must be in [0,1]') if gndatom in db.evidence: raise Exception("Duplicate soft evidence for '%s'" % gndatom) try: positive, predname, constants = mln.logic.parse_literal( gndatom ) # TODO Should we allow soft evidence on non-atoms here? (This assumes atoms) except NoSuchPredicateError, e: if ignore_unknown_preds: continue else: raise e domnames = mln.predicate(predname).argdoms db << (gndatom, value) # literal else: if l[0] == "?": raise Exception("Unknown literals not supported (%s)" % l) # this is an Alchemy feature try: true, predname, constants = mln.logic.parse_literal(l) except NoSuchPredicateError, e: if ignore_unknown_preds: continue else: raise e except Exception, e: traceback.print_exc() raise MLNParsingError('Error parsing line %d: %s (%s)' % (line + 1, l, e.message))