예제 #1
0
 def __init__(self, world = None, logenabled = True, logOutput = True,
                  logMemory = True, metaEnabled = False, phaseManager = None, verbose = 2):
     self.world = world
     self.mem = Memory()
     self.phases = []
     self.metaPhases = []
     self.modules = {}
     self.metaModules = {}
     self.verbose = verbose
     self.initialized = False
     self.phaseNum = 1
     self.metaPhaseNum = 1
     self.logger = logging.Logger()
     self.metaEnabled = metaEnabled
     if metaEnabled:
         if not phaseManager:
             raise Exception("MetaEnabled but phaseManager pointer not given")
         self.mem.enableMeta(trace.CogTrace(), phaseManager) # self is pointer to midca itself
     if not logenabled:
         self.logger.working = False
     else:
         self.logger.start()
         if self.logger.working:
             if logOutput:
                 self.logger.logOutput()
             self.mem.enableLogging(self.logger)
             self.mem.logEachAccess = logMemory
예제 #2
0
 def copy(self):
     '''
     This method does not make a true copy - it will not copy
     the original object's loggers and is not
     intended to be run, only checked to see what MIDCA's state was
     at an earlier time.
     '''
     newCopy = MIDCA(self.world, False, self.verbose)
     newCopy.mem = Memory()
     newCopy.mem.knowledge = self.mem.knowledge.copy()
     newCopy.mem.locks = {name: threading.Lock() for name in self.mem.locks}
     newCopy.phases = list(self.phases)
     newCopy.modules = self.modules.copy()
     newCopy.initialized = self.initialized
     newCopy.phaseNum = self.phaseNum
     return newCopy
예제 #3
0
class MIDCA:
    def __init__(self,
                 world=None,
                 logenabled=True,
                 logOutput=True,
                 logMemory=True,
                 metaEnabled=False,
                 phaseManager=None,
                 verbose=2):
        self.world = world
        self.mem = Memory()
        self.phases = []
        self.metaPhases = []
        self.modules = {}
        self.metaModules = {}
        self.verbose = verbose
        self.initialized = False
        self.phaseNum = 1
        self.metaPhaseNum = 1
        self.logger = logging.Logger(verbose=verbose)
        self.metaEnabled = metaEnabled
        if metaEnabled:
            self.mem.enableTrace()
            if not phaseManager:
                raise Exception(
                    "MetaEnabled but phaseManager pointer not given")

            self.mem.enableMeta(phaseManager)

        if not logenabled:
            self.logger.working = False
        else:
            self.logger.start()
            if self.logger.working:
                if logOutput:
                    self.logger.logOutput()
                self.mem.enableLogging(self.logger)
                self.mem.logEachAccess = logMemory

    def phase_by_name(self, name, meta=False):
        phases = self.phases
        if meta:
            phases = self.metaPhases

        for phase in phases:
            if phase.name == name:
                return phase
        return None

    def insert_phase(self, phase, phaseOrIndex, meta=False):
        phases = self.phases
        modules = self.modules
        if meta:  # switch if inserting a meta phase
            phases = self.metaPhases
            modules = self.metaModules

        if isinstance(phase, str):
            phase = Phase(phase)
        if not isinstance(phase, Phase):
            raise KeyError(str(phase) + " is not a valid phase or phase name.")
        if isinstance(phaseOrIndex, str):
            phaseOrIndex = self.phase_by_name(phaseOrIndex, meta)
        elif isinstance(phaseOrIndex, int):
            phases.insert(phaseOrIndex, phase)
            modules[phase] = []
            return
        if not isinstance(phaseOrIndex, Phase):
            raise KeyError(str(phase) + " is not a valid phase or index.")
        if phaseOrIndex not in self.phases:
            raise KeyError("phase " + str(phaseOrIndex) +
                           " not in phase list.")
        phases.insert(self.phases.index(phaseOrIndex), phase)
        modules[phase] = []

    def append_phase(self, phase, meta=False):
        if meta:
            self.insert_phase(phase, len(self.metaPhases) + 1, meta)
        else:
            self.insert_phase(phase, len(self.phases) + 1, meta)

    def remove_phase(self, phaseOrName):
        if isinstance(phaseOrName, str):
            phase = self.phase_by_name(phaseOrName)
        else:
            phase = phaseOrName
        try:
            self.phases.remove(phase)
            del self.modules[phase]
        except ValueError:
            raise ValueError("Phase " + str(phaseOrName) + " is not a phase.")
        #if there is a KeyError, something has gone very wrong.

    def append_module(self, phase, module, meta=False):
        self.insert_module(phase, module, MAX_MODULES_PER_PHASE, meta)

    def runtime_append_module(self, phase, module):
        self.runtime_insert_module(phase, module, MAX_MODULES_PER_PHASE)

    #note: error handling should be cleaned up - if a phase cannot be found by name, the error will report the phase name as "None" instead of whatever was given. True for removeModule as well.
    def insert_module(self, phase, module, i, meta=False):
        phases = self.phases
        modules = self.modules
        if meta:
            phases = self.metaPhases
            modules = self.metaModules
        if isinstance(phase, str):
            phase = self.phase_by_name(phase, meta)
        if phase not in phases:
            raise KeyError(
                "phase " + str(phase) +
                " not in phase list. Call insert_phase() or append_phase() to add it."
            )
        if not hasattr(module, "run"):
            raise AttributeError("All modules must a 'run' function")
        if len(modules[phase]) == MAX_MODULES_PER_PHASE:
            raise Exception("max module per phase [" +
                            str(MAX_MODULES_PER_PHASE) +
                            "] exceeded for phase" + str(phase) +
                            ". Cannot add another.")
        modules[phase].insert(i, module)

    # just like insert_module but also calls module.init()
    def runtime_insert_module(self, phase, module, i):
        if isinstance(phase, str):
            phase = self.phase_by_name(phase)
        if phase not in self.phases:
            raise KeyError(
                "phase " + str(phase) +
                " not in phase list. Call insert_phase() or append_phase() to add it."
            )
        if not hasattr(module, "run"):
            raise AttributeError("All modules must a 'run' function")
        if len(self.modules[phase]) == MAX_MODULES_PER_PHASE:
            raise Exception("max module per phase [" +
                            str(MAX_MODULES_PER_PHASE) +
                            "] exceeded for phase" + str(phase) +
                            ". Cannot add another.")
        self.modules[phase].insert(i, module)

        try:  # TODO: hacky fix for having modules with two kinds of init functions (one with verbose and one without)
            # some modules use verbose to get the new verbose value
            # and others don't
            module.init(mem=self.mem, world=self.world, verbose=self.verbose)
        except:
            module.init(mem=self.mem, world=self.world)

    def removeModule(self, phase, i):
        if isinstance(phase, str):
            phase = self.phase_by_name(phase)
        if phase not in self.modules:
            raise KeyError(
                "phase " + str(phase) +
                " not in phase list. Call insert_phase() or append_phase() to add it."
            )
        modules = self.modules[phase]
        if i < 0 or i >= len(modules):
            raise IndexError(
                "index " + str(i) +
                " is outside the range of the module list for phase " +
                str(phase))
        else:
            return modules.pop(i)

    def clearPhase(self, phaseOrName):
        if isinstance(phaseOrName, str):
            phase = self.phase_by_name(phaseOrName)
        else:
            phase = phaseOrName
        try:
            self.modules[phase] = []
        except ValueError:
            raise ValueError("Phase " + str(phaseOrName) + " is not a phase.")

    def get_modules(self, phase):
        if isinstance(phase, str):
            phase = self.phase_by_name(phase)
        if phase in self.modules:
            return self.modules[phase]
        else:
            raise ValueError("No such phase as " + str(phase))

    def init(self):
        self.init_cognitive_layer(verbose=self.verbose)
        if self.metaEnabled:
            self.init_metacognitive_layer(verbose=self.verbose)

    def init_cognitive_layer(self, verbose=2):
        for phase in self.phases:
            modules = self.modules[phase]
            i = 0
            for module in modules:
                i += 1
                try:
                    if verbose >= 2:
                        print("[cognitive] Initializing " + phase.name +
                              " module " + str(i) + " " +
                              str(module.__class__.__name__) + "...",
                              end="")
                    module.init(world=self.world, mem=self.mem)
                    if verbose >= 2: print("done.")

                except Exception as e:
                    print(e)
                    if verbose >= 2:
                        print(
                            "\n[cognitive] Phase " + phase.name + " module " +
                            str(i) + " " + str(module.__class__.__name__) +
                            " has no init function or had an error. Skipping init."
                        )

        self.initGoalGraph(overwrite=False)
        self.initialized = True

    def init_metacognitive_layer(self, verbose=2):
        for phase in self.metaPhases:
            modules = self.metaModules[phase]
            i = 0
            for module in modules:
                i += 1
                try:
                    if verbose >= 2:
                        print("[metacognitive] Initializing " + phase.name +
                              " module " + str(i) + " " +
                              str(module.__class__.__name__) + "...",
                              end="")
                    module.init(world=self.world, mem=self.mem)
                    if verbose >= 2: print("done.")

                except Exception as e:
                    print(e)
                    if verbose >= 2:
                        print(
                            "\n[metacognitive] Phase " + phase.name +
                            " module " + str(i) + " " +
                            str(module.__class__.__name__) +
                            "has no init function or had an error. Skipping init."
                        )

        self.initGoalGraph(overwrite=False)
        self.initialized = True

    def initGoalGraph(self, cmpFunc=None, overwrite=True):
        if overwrite or not self.mem.get(self.mem.GOAL_GRAPH):
            self.mem.set(self.mem.GOAL_GRAPH, goals.GoalGraph(cmpFunc))
            if self.verbose > 0: print("Goal Graph initialized.", )
            if cmpFunc:
                if self.verbose > 0: print()
            else:
                if self.verbose > 0:
                    print(
                        "To use goal ordering, call initGoalGraph manually with a custom goal comparator"
                    )

    def next_phase(self, verbose=2, meta=False):
        phaseNum = self.phaseNum
        phases = self.phases
        modules = self.modules
        if meta:  # switch if meta
            phaseNum = self.metaPhaseNum
            phases = self.metaPhases
            modules = self.metaModules

        retVal = ""
        self.phasei = (phaseNum - 1) % len(phases)
        if self.phasei == 0:
            if self.logger.working:
                self.logger.logEvent(
                    logging.CycleStartEvent((phaseNum - 1) / len(phases)))
        if verbose >= 2:
            if meta:
                print("    ***[meta] Starting ",
                      phases[self.phasei].name,
                      "Phase ***\n",
                      file=sys.stderr)
            else:
                print("****** Starting",
                      phases[self.phasei].name,
                      "Phase ******\n",
                      file=sys.stderr)
            if self.logger.working:
                self.logger.logEvent(
                    logging.PhaseStartEvent(phases[self.phasei].name))
        i = 0
        while i < len(modules[phases[self.phasei]]):
            module = modules[phases[self.phasei]][i]
            if self.logger.working:
                self.logger.logEvent(logging.ModuleStartEvent(module))
            try:
                retVal = module.run((phaseNum - 1) / len(phases), verbose)
                i += 1
            except NotImplementedError:
                if verbose >= 1:
                    print("module", module, "does not",
                          "implement the run() method and",
                          "is therefore invalid. It will be",
                          "removed from MIDCA.")
                self.removeModule(phases[self.phasei], i)
            if self.logger.working:
                self.logger.logEvent(logging.ModuleEndEvent(module))

        if self.logger.working:
            self.logger.logEvent(
                logging.PhaseEndEvent(phases[self.phasei].name))

        if not meta:
            self.phaseNum += 1
        else:
            self.metaPhaseNum += 1

        if (phaseNum - 1) % len(phases) == 0:
            if self.logger.working:
                self.logger.logEvent(
                    logging.CycleEndEvent((phaseNum - 1) / len(phases)))

        # record phase and run metareasoner
        #self.mem.set("phase", self.phases[self.phasei].name)
        #metareasoner.MetaReasoner(self.trace, self.mem).run()

        return retVal

    def copy(self):
        '''
        This method does not make a true copy - it will not copy
        the original object's loggers and is not
        intended to be run, only checked to see what MIDCA's state was
        at an earlier time.
        '''
        newCopy = MIDCA(self.world, False, self.verbose)
        newCopy.mem = Memory()
        newCopy.mem.knowledge = self.mem.knowledge.copy()
        newCopy.mem.locks = {name: threading.Lock() for name in self.mem.locks}
        newCopy.phases = list(self.phases)
        newCopy.modules = self.modules.copy()
        newCopy.initialized = self.initialized
        newCopy.phaseNum = self.phaseNum
        return newCopy
예제 #4
0
파일: base.py 프로젝트: dtdannen/MIDCA
class MIDCA:

    def __init__(self, world = None, logenabled = True, logOutput = True,
                     logMemory = True, metaEnabled = False, phaseManager = None, verbose = 2):
        self.world = world
        self.mem = Memory()
        self.phases = []
        self.metaPhases = []
        self.modules = {}
        self.metaModules = {}
        self.verbose = verbose
        self.initialized = False
        self.phaseNum = 1
        self.metaPhaseNum = 1
        self.logger = logging.Logger()
        self.metaEnabled = metaEnabled
        if metaEnabled:
            if not phaseManager:
                raise Exception("MetaEnabled but phaseManager pointer not given")
            self.mem.enableMeta(trace.CogTrace(), phaseManager) # self is pointer to midca itself
        if not logenabled:
            self.logger.working = False
        else:
            self.logger.start()
            if self.logger.working:
                if logOutput:
                    self.logger.logOutput()
                self.mem.enableLogging(self.logger)
                self.mem.logEachAccess = logMemory

    def phase_by_name(self, name, meta = False):
        phases = self.phases
        if meta:
            phases = self.metaPhases

        for phase in phases:
            if phase.name == name:
                return phase
        return None

    def insert_phase(self, phase, phaseOrIndex, meta = False):
        phases = self.phases
        modules = self.modules
        if meta: # switch if inserting a meta phase
            phases = self.metaPhases
            modules = self.metaModules

        if isinstance(phase, str):
            phase = Phase(phase)
        if not isinstance(phase, Phase):
            raise KeyError(str(phase) + " is not a valid phase or phase name.")
        if isinstance(phaseOrIndex, str):
            phaseOrIndex = self.phase_by_name(phaseOrIndex, meta)
        elif isinstance(phaseOrIndex, int):
            phases.insert(phaseOrIndex, phase)
            modules[phase] = []
            return
        if not isinstance(phaseOrIndex, Phase):
            raise KeyError(str(phase) + " is not a valid phase or index.")
        if phaseOrIndex not in self.phases:
            raise KeyError("phase " + str(phaseOrIndex) + " not in phase list.")
        phases.insert(self.phases.index(phaseOrIndex), phase)
        modules[phase] = []

    def append_phase(self, phase, meta=False):
        if meta:
            self.insert_phase(phase, len(self.metaPhases) + 1, meta)
        else:
            self.insert_phase(phase, len(self.phases) + 1, meta)

    def remove_phase(self, phaseOrName):
        if isinstance(phaseOrName, str):
            phase = self.phase_by_name(phaseOrName)
        else:
            phase = phaseOrName
        try:
            self.phases.remove(phase)
            del self.modules[phase]
        except ValueError:
            raise ValueError("Phase " + str(phaseOrName) + " is not a phase.")
        #if there is a KeyError, something has gone very wrong.

    def append_module(self, phase, module, meta=False):
        self.insert_module(phase, module, MAX_MODULES_PER_PHASE, meta)

    def runtime_append_module(self, phase, module):
        self.runtime_insert_module(phase, module, MAX_MODULES_PER_PHASE)

    #note: error handling should be cleaned up - if a phase cannot be found by name, the error will report the phase name as "None" instead of whatever was given. True for removeModule as well.
    def insert_module(self, phase, module, i, meta=False):
        phases = self.phases
        modules = self.modules
        if meta:
            phases = self.metaPhases
            modules = self.metaModules
        if isinstance(phase, str):
            phase = self.phase_by_name(phase, meta)
        if phase not in phases:
            raise KeyError("phase " + str(phase) + " not in phase list. Call insert_phase() or append_phase() to add it.")
        if not hasattr(module, "run"):
            raise AttributeError("All modules must a 'run' function")
        if len(modules[phase]) == MAX_MODULES_PER_PHASE:
            raise Exception("max module per phase [" + str(MAX_MODULES_PER_PHASE) + "] exceeded for phase" + str(phase) + ". Cannot add another.")
        modules[phase].insert(i, module)

    # just like insert_module but also calls module.init()
    def runtime_insert_module(self, phase, module, i):
        if isinstance(phase, str):
            phase = self.phase_by_name(phase)
        if phase not in self.phases:
            raise KeyError("phase " + str(phase) + " not in phase list. Call insert_phase() or append_phase() to add it.")
        if not hasattr(module, "run"):
            raise AttributeError("All modules must a 'run' function")
        if len(self.modules[phase]) == MAX_MODULES_PER_PHASE:
            raise Exception("max module per phase [" + str(MAX_MODULES_PER_PHASE) + "] exceeded for phase" + str(phase) + ". Cannot add another.")
        self.modules[phase].insert(i, module)
        module.init(mem=self.mem, world=self.world)

    def removeModule(self, phase, i):
        if isinstance(phase, str):
            phase = self.phase_by_name(phase)
        if phase not in self.modules:
            raise KeyError("phase " + str(phase) + " not in phase list. Call insert_phase() or append_phase() to add it.")
        modules = self.modules[phase]
        if i < 0 or i >= len(modules):
            raise IndexError("index " + str(i) + " is outside the range of the module list for phase " + str(phase))
        else:
            modules.pop(i)

    def clearPhase(self, phaseOrName):
        if isinstance(phaseOrName, str):
            phase = self.phase_by_name(phaseOrName)
        else:
            phase = phaseOrName
        try:
            self.modules[phase] = []
        except ValueError:
            raise ValueError("Phase " + str(phaseOrName) + " is not a phase.")

    def get_modules(self, phase):
        if isinstance(phase, str):
            phase = self.phase_by_name(phase)
        if phase in self.modules:
            return self.modules[phase]
        else:
            raise ValueError("No such phase as " + str(phase))

    def init(self, verbose = 2):
        self.init_cognitive_layer(verbose)
        if self.metaEnabled:
            self.init_metacognitive_layer(verbose)

    def init_cognitive_layer(self, verbose = 2):
        for phase in self.phases:
            modules = self.modules[phase]
            i = 0
            for module in modules:
                i += 1
                try:
                    if verbose >= 2:
                        print("[cognitive] Initializing " + phase.name + " module " + str(i) + "...",end="")
                    module.init(world = self.world,
                                mem = self.mem)
                    print("done.")

                except Exception as e:
                    print(e)
                    if verbose >= 2:
                        print("\n[cognitive] Phase " + phase.name + " module " + str(i) +  " has no init function or had an error. Skipping init.")

        self.initGoalGraph(overwrite = False)
        self.initialized = True

    def init_metacognitive_layer(self, verbose = 2):
        for phase in self.metaPhases:
            modules = self.metaModules[phase]
            i = 0
            for module in modules:
                i += 1
                try:
                    if verbose >= 2:
                        print("[metacognitive] Initializing " + phase.name + " module " + str(i) + "...",end="")
                    module.init(world = self.world,
                                mem = self.mem)
                    print("done.")

                except Exception as e:
                    print(e)
                    if verbose >= 2:
                        print("\n[metacognitive] Phase " + phase.name + " module " + str(i) +  "has no init function or had an error. Skipping init.")

        self.initGoalGraph(overwrite = False)
        self.initialized = True

    def initGoalGraph(self, cmpFunc = None, overwrite = True):
        if overwrite or not self.mem.get(self.mem.GOAL_GRAPH):
            self.mem.set(self.mem.GOAL_GRAPH, goals.GoalGraph(cmpFunc))
            print("Goal Graph initialized.",)
            if cmpFunc:
                print()
            else:
                print("To use goal ordering, call initGoalGraph manually with a custom goal comparator")

    def next_phase(self, verbose = 2, meta = False):
        phaseNum = self.phaseNum
        phases = self.phases
        modules = self.modules
        if meta: # switch if meta
            phaseNum = self.metaPhaseNum
            phases = self.metaPhases
            modules = self.metaModules

        retVal = ""
        self.phasei = (phaseNum - 1) % len(phases)
        if self.phasei == 0:
            self.logger.logEvent(logging.CycleStartEvent((phaseNum - 1) / len(phases)))
        if verbose >= 2:
            if meta:
                print("    ***[meta] Starting ", phases[self.phasei].name, "Phase ***\n", file = sys.stderr)
            else:
                print("****** Starting", phases[self.phasei].name, "Phase ******\n", file = sys.stderr)
            self.logger.logEvent(logging.PhaseStartEvent(phases[self.phasei].name))
        i = 0
        while i < len(modules[phases[self.phasei]]):
            module = modules[phases[self.phasei]][i]
            self.logger.logEvent(logging.ModuleStartEvent(module))
            try:
                retVal = module.run((phaseNum - 1) / len(phases), verbose)
                i += 1
            except NotImplementedError:
                if verbose >= 1:
                    print("module", module, "does not",
                          "implement the run() method and",
                          "is therefore invalid. It will be",
                          "removed from MIDCA.")
                self.removeModule(phases[self.phasei], i)
            self.logger.logEvent(logging.ModuleEndEvent(module))

        self.logger.logEvent(logging.PhaseEndEvent(phases[self.phasei].name))

        if not meta:
            self.phaseNum += 1
        else:
            self.metaPhaseNum += 1

        if (phaseNum - 1) % len(phases) == 0:
            self.logger.logEvent(logging.CycleEndEvent((phaseNum - 1) / len(phases)))

        # record phase and run metareasoner
        #self.mem.set("phase", self.phases[self.phasei].name)
        #metareasoner.MetaReasoner(self.trace, self.mem).run()

        return retVal

    def copy(self):
        '''
        This method does not make a true copy - it will not copy
        the original object's loggers and is not
        intended to be run, only checked to see what MIDCA's state was
        at an earlier time.
        '''
        newCopy = MIDCA(self.world, False, self.verbose)
        newCopy.mem = Memory()
        newCopy.mem.knowledge = self.mem.knowledge.copy()
        newCopy.mem.locks = {name: threading.Lock() for name in self.mem.locks}
        newCopy.phases = list(self.phases)
        newCopy.modules = self.modules.copy()
        newCopy.initialized = self.initialized
        newCopy.phaseNum = self.phaseNum
        return newCopy