def main(args=["E:\\workspace\\spf\\geoquery"]): resource_dir = os.path.join(args[0], "resources/") experiments_dir = os.path.join(args[0], "experiments/") data_dir = os.path.join(experiments_dir, "data") types_files = os.path.join(resource_dir, "geo.types") predicate_ontology = os.path.join(resource_dir, "geo.preds.ont") simple_ontology = os.path.join(resource_dir, "geo.consts.ont") LogicLanguageServices.set_instance( LogicLanguageServices.Builder(TypeRepository(types_files), FlexibleTypeComparator()) .add_constants_to_ontology(simple_ontology) .add_constants_to_ontology(predicate_ontology) .set_numeral_type_name("i") .close_ontology(True) .build() ) expr = LogicalExpressionBuilder.read("(size:<lo,i> (argmax:<<e,t>,<<e,i>,e>> (lambda $0:e (and:<t*,t> (city:<c,t> $0) (loc:<lo,<lo,t>> $0 alaska:s))) (lambda $1:e (size:<lo,i> $1))))") import sys sys.exit(0) category_services = LogicalExpressionCategoryServices(True, True) unfactored_constants = {LogicalConstant.read("the:<<e,t>,e>"), LogicalConstant.read("exists:<<e,t>,t>")} FactoredLexiconServices.set(unfactored_constants) read_lexicon = Lexicon() def text_filter(x): return x read_lexicon.add_entries_from_file(os.path.join(resource_dir, "seed.lex"), text_filter, category_services, LexicalEntry.Origin.FIXED_DOMAIN)
def __init__(self, predicate, arguments, *args): """ :param predicate: :param arguments: :param args: :return: """ super(Literal, self).__init__() self.predicate = predicate self.arguments = tuple(arguments) if len(args) == 0: from spf.mr.lambda_.logic_language_services import LogicLanguageServices type_comparator = LogicLanguageServices.get_type_comparator() type_repository = LogicLanguageServices.get_type_repository() elif len(args) == 2: type_comparator = args[0] type_repository = args[1] else: raise RuntimeError("Wrong number of arguments") if not predicate.get_type().is_complex(): raise LogicalExpressionRuntimeError("Predicate must have a complex type, not %s" % predicate.get_type()) literal_typing = Literal.compute_literal_typing( self.predicate.get_type(), [arg.get_type() for arg in self.arguments], type_comparator, type_repository ) self.type_ = None if literal_typing is None else literal_typing[0]
def simplify(self, expr): """ Simplify the and:<t*,t> predicate. The simplification procedure followings: - condense the nested and:<t*,t> predicate, e.g. (and:<t*,t> (and:<t*,t> (foo:<e,t> $0) (bar:<e,t> $0)) true:t) -> (and:<t*,t> (foo:<e,t> $0) (bar:<e,t> $0) true:t) - remove the expression that always true (and:<t*,t> (foo:<e,t> $0) (bar:<e,t> $0) true:t) -> (and:<t*,t> (foo:<e,t> $0) (bar:<e,t> $0)) If false:t is found, return false:t LogicalExpression :param expr: LogicalExpression :return: LogicalExpression """ from spf.mr.lambda_.logic_language_services import LogicLanguageServices expr_changed = False if isinstance(expr, Literal): literal = expr consolidated_args = [] for arg in literal.get_arguments(): if isinstance(arg, Literal) and arg.get_predicate() == literal.get_predicate(): consolidated_args.extend(arg.get_arguments()) expr_changed = True else: consolidated_args.append(arg) # Remove all the 'true:t' argument in (and:<t*,t> ...) original_length = len(consolidated_args) false_arg_exist = False non_true_false_arg_exist = False for arg in consolidated_args: if arg == LogicLanguageServices.get_true(): expr_changed = True elif arg == LogicLanguageServices.get_false(): false_arg_exist = True else: non_true_false_arg_exist = True if false_arg_exist: return LogicLanguageServices.get_false() consolidated_args = [arg for arg in consolidated_args if arg == LogicLanguageServices.get_true()] if len(consolidated_args) != original_length: if not non_true_false_arg_exist: # corresponding to (and:<t*,t> true:t true:t), this condition doesn't hold when # (and:<t*,t> (predicate:<e,t> $0) true:t) return LogicLanguageServices.get_true() elif len(consolidated_args) < 2: return consolidated_args[0] if expr_changed: return Literal(literal.get_predicate(), consolidated_args) else: return expr else: return expr
def visit_literal(self, literal): """ Basiclly, it seems erase all the last parameter :param literal: spf.mr.lambda_.literal.Literal, the input literal :return: """ literal.get_predicate().accept(self) simplified_predicate = self.temp_return new_args = [] args_changed = False for arg in literal.get_arguments(): arg.accept(self) if self.temp_return != arg: args_changed = True new_args.append(self.temp_return) if args_changed: simplified_args = new_args else: simplified_args = literal.get_arguments() new_predicate = simplified_predicate if self.should_consume_args(new_predicate): change_due_to_lambda_application = False for arg in simplified_args: if not self.should_consume_args(new_predicate): break apply_result = ApplyAndSimplify.of(new_predicate, arg) if apply_result is None: break else: new_predicate = apply_result change_due_to_lambda_application = True if change_due_to_lambda_application: final_args = None else: final_args = simplified_args else: final_args = simplified_args if new_predicate != literal.get_predicate() or final_args != literal.get_arguments(): if len(final_args) == 0: new_expr = new_predicate else: new_expr = Literal(new_predicate, final_args) else: new_expr = literal self.temp_return = new_expr if len(final_args) > 0: simplifier = LogicLanguageServices.get_simplifier(new_predicate) if simplifier is not None: simplified_expr = simplifier.simplify(new_expr) if simplified_expr != new_expr: self.temp_return = simplified_expr return
def read(cls, string, mapping=None, type_repository=None, type_comparator=None): if mapping is None: mapping = {} if type_repository is None: type_repository = LogicLanguageServices.get_type_repository() if type_comparator is None: type_comparator = LogicLanguageServices.get_type_comparator() flat_string = cls.WHITE_SPACE.sub(string, " ") try: for reader in cls.readers: if reader.is_valid(flat_string): return reader.read(flat_string, mapping, type_repository, type_comparator, cls) raise AttributeError("Invalid logical expression syntax: %s" % string) except Exception, e: cls.LOG.error("Logic expression syntax error: %s" % flat_string) raise e
def __init__(self, argument, body, type_repository=None): super(Lambda, self).__init__() if type_repository is None: from spf.mr.lambda_.logic_language_services import LogicLanguageServices type_repository = LogicLanguageServices.get_type_repository() self.argument = argument self.body = body self.type_ = type_repository.get_type_create_if_needed(self.body.get_type(), self.argument.get_type())
def create(name, type_, dynamic=False): if name.startswith(LogicalConstant.DYNAMIC_MARKER): name = name[len(LogicalConstant.DYNAMIC_MARKER):] dynamic = True from spf.mr.lambda_.logic_language_services import LogicLanguageServices ontology = LogicLanguageServices.get_ontology() if ontology is None: return LogicalConstant(name, type_) else: return ontology.get_or_add(LogicalConstant(name, type_), dynamic)
def simplify(self, expr): from spf.mr.lambda_.logic_language_services import LogicLanguageServices if isinstance(expr, Literal): literal = expr if len(literal.get_arguments()) == 1: arg = literal.get_arguments()[0] if isinstance(arg, Literal) and arg.get_predicate() == literal.get_predicate(): # two not predicate, e.g. (not:<t,t> (not:<t,t> (foo:<e,t> bar:e))) -> (foo:<e,t> bar:e) sub_not = arg if len(sub_not.get_arguments()) == 1: return sub_not.get_arguments()[0] elif arg == LogicLanguageServices.get_true(): # (not:<t,t> true:t) -> false:t return LogicLanguageServices.get_false() elif arg == LogicLanguageServices.get_false(): # (not:<t,t> false:t) -> true:t return LogicLanguageServices.get_true() return expr else: return expr
def read(string, type_repository=None): if type_repository is None: from spf.mr.lambda_.logic_language_services import LogicLanguageServices type_repository = LogicLanguageServices.get_type_repository() split = string.split(Term.TYPE_SEPARATOR) if len(split) != 2: raise LogicalExpressionRuntimeError('Constant syntax error: %s' % string) type_ = type_repository.get_type(split[1]) if type_ is None: type_ = type_repository.get_type_create_if_needed(split[1]) if type_ is None: raise LogicalExpressionRuntimeError('Unknown type for: %s' % string) return LogicalConstant.create(string, type_)
def visit_literal(self, literal): literal.get_predicate().accept(self) literal_typing = LogicLanguageServices.compute_literal_typing_for_args( literal.get_predicate_type(), literal.get_arguments()) if literal_typing is None: raise RuntimeError('Failed to compute literal typing for. This should never ' 'have happened, typing is computed during creation: %s' % literal) for signature_type, arg in zip(literal_typing[1], literal.get_arguments()): arg.accept(self) self.well_typed = self.well_typed and self.verify_literal_arg_typing(arg, signature_type) if not self.well_typed: self.LOG.debug('Literal %s is not well-typed. Mismatch between signature type ' '%s to argument %s.' % (literal, signature_type, arg)) return
def simplify(self, expr): from spf.mr.lambda_.logic_language_services import LogicLanguageServices expr_changed = False if isinstance(expr, Literal): literal = expr consolidated_args = [] for arg in literal.get_arguments(): if isinstance(arg, Literal) and arg.get_predicate() == literal.get_predicate(): expr_changed = True consolidated_args.extend(arg.get_arguments()) else: consolidated_args.append(arg) # remove all false:t expression original_length = len(consolidated_args) true_arg_exist = False non_true_false_arg_exist = False for arg in consolidated_args: if arg == LogicLanguageServices.get_false(): expr_changed = True elif arg == LogicLanguageServices.get_true(): true_arg_exist = True else: non_true_false_arg_exist = True if true_arg_exist: return LogicLanguageServices.get_false() consolidated_args = [arg for arg in consolidated_args if arg == LogicLanguageServices.get_false()] if true_arg_exist: return LogicLanguageServices.get_true() if len(consolidated_args) != original_length: if not non_true_false_arg_exist: # corresponding to (and:<t*,t> false:t false:t), this condition doesn't hold when # (and:<t*,t> (predicate:<e,t> $0) false:t) return LogicLanguageServices.get_false() elif len(consolidated_args) < 2: return consolidated_args[0] if expr_changed: return Literal(literal.get_predicate(), consolidated_args) else: return expr else: return expr
def of(func, arg): """ :param func: :param arg: :return: """ if (not func.get_type().is_complex() or not LogicLanguageServices.get_type_comparator().verfiy_arg_type( func.get_type().get_domain(), arg.get_type())): return None elif isinstance(func, Lambda): lambda_ = func variable = lambda_.get_argument() visitor = ApplyAndSimplify(arg, variable) visitor.visit(lambda_.get_body()) return visitor.temp_return elif isinstance(func, Literal): return Simplify.of(ApplyAndSimplify.literal_application(func, arg)) elif isinstance(func, Term): return Simplify.of(ApplyAndSimplify.term_application(func, arg)) else: raise LogicalExpressionRuntimeError('Impossible condition: unhandled logical expression object.')
def verify_arg_type(self, signature_type, arg_type): return arg_type.is_extending_or_extended_by( LogicLanguageServices.get_type_repository().generalize_type(signature_type))
def get_signature(constants): return [LogicLanguageServices.get_type_repository().generalize_type(constant.get_type()) for constant in constants]
def visit_logical_constant(self, logical_constant): if (isinstance(logical_constant.get_type(), ComplexType) and not LogicLanguageServices.is_coordination_predicate(logical_constant) and not LogicLanguageServices.is_array_index_predicate(logical_constant) and not LogicLanguageServices.is_array_sub_predicate(logical_constant)): self.predicates.add(logical_constant)
def do_is_factorable(cls, constant): return not LogicLanguageServices.is_coordination_predicate(constant) and \ not LogicLanguageServices.is_array_index_predicate(constant) and \ not LogicLanguageServices.is_array_sub_predicate(constant) and \ LogicLanguageServices.get_type_repository().get_index_type() != constant.get_type() and \ constant not in cls.unfactored_constants
def is_valid_name(cls, name): from spf.mr.lambda_.logic_language_services import LogicLanguageServices split = name.split(':', 2) type_repository = LogicLanguageServices.get_type_repository() return cls.REGEXP_NAME_PATTERN.match(split[0]) is not None and \ type_repository.get_type_create_if_needed(split[1]) is not None
def equals(self, other, mapping=None): from spf.mr.lambda_.logic_language_services import LogicLanguageServices if LogicLanguageServices.get_ontology() is None: return isinstance(other, LogicalConstant) and self.do_equals(other) else: return id(self) == id(other)