def __init__(self): self.environment = clips.Environment() self.logger = logger.getChild(type(self).__name__) self.clips_types = {} self.preprocess_funcs = [] self.postprocess_funcs = [] RuleFunc._register_engine(self)
def load(self, module_name, package=None, auto_salience=False, debug_rules=False, **module_params): # Prepare for import if isinstance(package, ModuleType): package = package.__name__ if package is not None and '.' not in module_name: module_name = '.' + module_name self.logger.debug('Loading: %s', module_name) # Import module, while keeping track of entities that require compilation existing_modules = set(sys.modules) with self.lock: params.update(module_params) RuleDef._all_instances = [] HasSlots._all_subclasses = [] RuleFunc._set_cur_engine(self.engine) module = import_module(module_name, package) if module.__name__ in existing_modules: reload(module) # TODO: Why are there non-named templates?? templates_to_build = [ x for x in HasSlots._all_subclasses if x._name is not None ] rules_to_build = RuleDef._all_instances # Add name to all unnamed instances (according to variable name) for name in dir(module): entity = getattr(module, name) if isinstance(entity, RuleDef) and entity._rule.name is None: entity._set_name(name) # TODO: include module name if auto_salience: auto_set_salience(RuleDef._all_instances) if debug_rules: self._build_debug_rules() # Sort for clarity templates_to_build.sort(key=lambda x: x._name) if auto_salience: rules_to_build.sort( key=lambda x: (-(x._rule.salience or 0), x._rule.name)) # Compile everything, except unnamed templates (which cannot be compiled) # Note that RuleDefs also may contain TemplateDefs, which would not be named. for entity in templates_to_build + rules_to_build: entity._build(self.engine)
def _add_python_action(self, engine): func = RuleFunc(partial(self._action, engine), Integer, '_'.join(x.__name__ for x in self.python_actions)) params = [ premise.container for premise in self.premises.itervalues() if not premise.negative ] self.actions.append(func(*params).replace_fields(self.variable_map))
def load(self, module_name, package=None, auto_salience=False, debug_rules=False, **module_params): # Prepare for import if isinstance(package, ModuleType): package = package.__name__ if package is not None and '.' not in module_name: module_name = '.' + module_name self.logger.debug('Loading: %s', module_name) # Import module, while keeping track of entities that require compilation existing_modules = set(sys.modules) with self.lock: params.update(module_params) RuleDef._all_instances = [] HasSlots._all_subclasses = [] RuleFunc._set_cur_engine(self.engine) module = import_module(module_name, package) if module.__name__ in existing_modules: reload(module) # TODO: Why are there non-named templates?? templates_to_build = [x for x in HasSlots._all_subclasses if x._name is not None] rules_to_build = RuleDef._all_instances # Add name to all unnamed instances (according to variable name) for name in dir(module): entity = getattr(module, name) if isinstance(entity, RuleDef) and entity._rule.name is None: entity._set_name(name) # TODO: include module name if auto_salience: auto_set_salience(RuleDef._all_instances) if debug_rules: self._build_debug_rules() # Sort for clarity templates_to_build.sort(key=lambda x:x._name) if auto_salience: rules_to_build.sort(key=lambda x:(-(x._rule.salience or 0), x._rule.name)) # Compile everything, except unnamed templates (which cannot be compiled) # Note that RuleDefs also may contain TemplateDefs, which would not be named. for entity in templates_to_build + rules_to_build: entity._build(self.engine)
def run_one_cycle(self, limit_steps=None): """ Run a single cycle of the rule engine limit_steps: maximal number of execution steps (or None to run until completion) """ for preprocess_func in self.preprocess_funcs: self.logger.info('Calling: %s', preprocess_func) preprocess_func() RuleFunc._clear_error() if limit_steps: self.logger.info('Running rule engine (%d steps)', limit_steps) else: self.logger.info('Running rule engine') self.environment.Run(limit_steps) self.logger.info('Rule engine completed') RuleFunc._check_error() for postprocess_func in self.postprocess_funcs: self.logger.info('Calling: %s', postprocess_func) postprocess_func()