Module loda.mine.miner

Miner class for finding integer sequence programs.

Classes

class Miner (sequences: list,
interpreter: Interpreter,
generator)
Expand source code
class Miner:

    def __init__(self, sequences: list, interpreter: Interpreter, generator):
        self.__sequences = sequences
        self.__index = PrefixIndex(sequences)
        self.__interpreter = interpreter
        self.__generator = generator
        self.__basic_timeout = 60
        self.__extended_timeout = 600
        self.__back_off_after = 3
        self.__failed_matches = {}

    def __call__(self):
        program = self.__generator()
        evaluator = Evaluator(program, self.__interpreter)
        match = self.__index.global_match()
        refine = True
        start_time = time.time()
        try:
            while refine:
                term = evaluator()
                refine = self.__index.refine_match(match, term)
                if (time.time() - start_time) > self.__basic_timeout:
                    print("Timeout")
                    return
        except Exception as e:
            print("Evaluation error: {}".format(e))
            return
        ids = self.__index.get_match_ids(match)
        for id in ids:
            seq = self.__index.get(id)
            if self.__check_match(program, id):
                print("Found match for {}".format(seq))
                p = "~/loda/programs/local/{}.asm".format(seq.id_str())
                with open(os.path.expanduser(p), "w") as asm_file:
                    asm_file.write("; {}\n".format(seq))
                    asm_file.write(str(program))
            elif self.__back_off_after > 0:
                if id not in self.__failed_matches:
                    self.__failed_matches[id] = 1
                else:
                    self.__failed_matches[id] += 1
                if self.__failed_matches[id] >= self.__back_off_after:
                    print("Back off matching {}".format(seq))
                    self.__sequences = list(
                        filter(lambda s: s.id != id, self.__sequences))
                    self.__index = PrefixIndex(self.__sequences)

    def __check_match(self, program: Program, id: int):
        seq = self.__index.get(id)
        terms = seq.load_b_file(os.path.expanduser("~/loda/oeis"))
        if terms is None or len(terms) == len(seq.terms):
            print("Skipping check for {}".format(seq))
            return False
        print("Checking match for {}".format(seq))
        start_time = time.time()
        if len(terms) > 1000:
            terms = terms[0:1000]
        evaluator = Evaluator(program, self.__interpreter)
        for t in terms:
            n = evaluator()
            if n != t:
                return False
            if (time.time() - start_time) > self.__extended_timeout:
                print("Timeout")
                return False
        return True