def test_register_by_name(self): i_set = InstructionSet() i_set.register_by_name(".*_mult") print(i_set) assert len(i_set) == 2 assert set([i.name for i in i_set.values()]) == {"int_mult", "float_mult"}
def test_unregister(self, instr_set): i_set = InstructionSet() i_set.register(instr_set["int_add"]) i_set.register(instr_set["int_sub"]) i_set.unregister("int_add") assert len(i_set) == 1 assert list(i_set.values())[0].name == "int_sub"
def test_unregister(self, atoms): i_set = InstructionSet() i_set.register(atoms["add"]) i_set.register(atoms["sub"]) i_set.unregister("int_add") assert len(i_set) == 1 assert list(i_set.values())[0].name == "int_sub"
def test_register_core_by_stack_with_exclude(self, core_type_lib): foo = common.instructions(core_type_lib) print([i for i in foo if i.name == "exec_dup_times"][0].required_stacks()) i_set = InstructionSet(register_core=False) i_set.register_core_by_stack({"int"}, exclude_stacks={"str", "exec", "code"}) for i in i_set.values(): if len(i.required_stacks()) > 0: print(i.name, i.required_stacks()) assert i.name not in { "exec_pop", "exec_dup", "exec_dup_times", "exec_swap", "exec_rot", "exec_flush", "exec_stack_depth", "exec_yank", "exec_yank_dup", "exec_shove", "exec_shove_dup" } assert "int" in i.required_stacks() assert "exec" not in i.required_stacks()
def __init__(self, instruction_set: InstructionSet, literals: Sequence[Union[Literal, Any]], erc_generators: Sequence[Callable], distribution: DiscreteProbDistrib = "proportional"): self.instruction_set = instruction_set self.type_library = instruction_set.type_library self.literals = [lit if isinstance(lit, Literal) else infer_literal(lit, self.type_library) for lit in literals] self.erc_generators = erc_generators if distribution == "proportional": self.distribution = ( DiscreteProbDistrib() .add("instruction", len(instruction_set)) .add("close", sum([i.code_blocks for i in instruction_set.values()])) .add("literal", len(literals)) .add("erc", len(erc_generators)) ) else: self.distribution = distribution
def __init__(self, instruction_set: InstructionSet, literals: Sequence[Union[Literal, Any]], erc_generators: Sequence[Callable], distribution: DiscreteProbDistrib = "proportional"): self.instruction_set = instruction_set self.literals = [ lit if isinstance(lit, Literal) else Literal(lit) for lit in literals ] self.erc_generators = erc_generators if distribution == "proportional": self.distribution = (DiscreteProbDistrib().add( "instruction", len(instruction_set)).add( "close", sum([i.code_blocks for i in instruction_set.values() ])).add("literal", len(literals)).add("erc", len(erc_generators))) else: self.distribution = distribution
def test_register_core(self, all_core_instructions): i_set = InstructionSet().register_core() assert set(i_set.values()) == all_core_instructions
def test_register_core_by_stack(self): i_set = InstructionSet() i_set.register_core_by_stack({"int"}) for i in i_set.values(): if len(i.required_stacks()) > 0: assert "int" in i.required_stacks()
class GeneSpawner: """A factory of random Genes (Atoms) and Genomes. When spawning a random gene, the result can be one of three types of Atoms. An Instruction, a Closer, or a Literal. If the Atom is a Literal, it may be one of the supplied Literals, or it may be the result of running one of the Ephemeral Random Constant generators. Reference for ERCs: "A field guide to genetic programming", Section 3.1 Riccardo Poli and William B. Langdon and Nicholas Freitag McPhee, http://www.gp-field-guide.org.uk/ Attributes ---------- n_input : int Number of input instructions that could appear the genomes. instruction_set : pyshgp.push.instruction_set.InstructionSet InstructionSet containing instructions to use when spawning genes and genomes. literals : Sequence[pyshgp.push.instruction_set.atoms.Literal] A list of Literal objects to pull from when spawning genes and genomes. erc_generator : Sequence[Callable] A list of functions (aka Ephemeral Random Constant generators). When one of these functions is called, the output is placed in a Literal and returned as the spawned gene. distribution : pyshgp.utils.DiscreteProbDistrib A probability distribution describing how frequently to produce Instructions, Closers, Literals, and ERCs. """ def __init__(self, n_inputs: int, instruction_set: Union[InstructionSet, str], literals: Sequence[Any], erc_generators: Sequence[Callable], distribution: DiscreteProbDistrib = "proportional"): self.n_inputs = n_inputs self.erc_generators = erc_generators self.instruction_set = instruction_set if self.instruction_set == "core": self.instruction_set = InstructionSet(register_core=True) self.type_library = self.instruction_set.type_library self.literals = [ lit if isinstance(lit, Literal) else infer_literal( lit, self.type_library) for lit in literals ] if distribution == "proportional": self.distribution = (DiscreteProbDistrib().add( GeneTypes.INPUT, self.n_inputs).add( GeneTypes.INSTRUCTION, len(self.instruction_set)).add( GeneTypes.CLOSE, sum([ i.code_blocks for i in self.instruction_set.values() ])).add(GeneTypes.LITERAL, len(literals)).add(GeneTypes.ERC, len(erc_generators))) else: self.distribution = distribution def random_input(self) -> Input: """Return a random ``Input``. Returns ------- pyshgp.push.atoms.Input """ return Input(input_index=np.random.randint(self.n_inputs)) def random_instruction(self) -> InstructionMeta: """Return a random Instruction from the InstructionSet. Returns ------- pyshgp.push.atoms.InstructionMeta A randomly selected Literal. """ i = np.random.choice(list(self.instruction_set.values())) return InstructionMeta(name=i.name, code_blocks=i.code_blocks) def random_literal(self) -> Literal: """Return a random Literal from the set of Literals. Returns ------- pyshgp.push.atoms.Literal A randomly selected Literal. """ lit = np.random.choice(self.literals) if not isinstance(lit, Literal): lit = infer_literal(lit, self.type_library) return lit def random_erc(self) -> Literal: """Materialize a random ERC generator into a Literal and return it. Returns ------- pyshgp.push.atoms.Literal A Literal whose value comes from running a ERC generator function. """ erc_value = np.random.choice(self.erc_generators)() if not isinstance(erc_value, Literal): erc_value = infer_literal(erc_value, self.type_library) return erc_value def random_gene(self) -> Atom: """Return a random Atom based on the GenomeSpawner's distribution. Returns ------- pyshgp.push.atoms.Atom An random Atom. Either an Instruction, Closer, or Literal. """ atom_type = self.distribution.sample() if atom_type is GeneTypes.INPUT: return self.random_input() elif atom_type is GeneTypes.INSTRUCTION: return self.random_instruction() elif atom_type is GeneTypes.CLOSE: return Closer() elif atom_type is GeneTypes.LITERAL: return self.random_literal() elif atom_type is GeneTypes.ERC: return self.random_erc() else: raise ValueError( "GenomeSpawner distribution bad atom type {t}".format( t=str(atom_type))) def spawn_genome(self, size: Union[int, Sequence[int]]) -> Genome: """Return a random Genome based on the GenomeSpawner's distribution. The genome will contain the specified number of Atoms if size is an integer. If size is a pair of integers, the genome will be of a random size in the range of the two integers. Parameters ---------- size The resulting genome will contain this many Atoms if size is an integer. If size is a pair of integers, the genome will be of a random size in the range of the two integers. Returns ------- pyshgp.gp.genome.Genome A Genome with random contents of a given size. """ if isinstance(size, Sequence): size = np.random.randint(size[0], size[1]) + 1 return Genome([self.random_gene() for _ in range(size)])
def test_register_all(self): i_set = InstructionSet().register_all() # assert len(i_set) == len(_CORE_INSTRUCTIONS) # If fail, likely duplicated instr names. assert set(i_set.values()) == set(_CORE_INSTRUCTIONS)
def test_register_by_type(self): i_set = InstructionSet() i_set.register_by_type(["int"]) for i in i_set.values(): assert "int" in i.relevant_types()
def test_register_core(self, all_core_instrucitons): i_set = InstructionSet().register_core() assert set(i_set.values()) == all_core_instrucitons
def test_register_core_by_name(self, core_type_lib): i_set = InstructionSet() i_set.register_core_by_name(".*_mult") assert len(i_set) == 2 assert set([i.name for i in i_set.values()]) == {"int_mult", "float_mult"}
def test_register_core_by_stack(self, core_type_lib): i_set = InstructionSet() i_set.register_core_by_stack({"int"}) for i in i_set.values(): if len(i.required_stacks()) > 0: assert "int" in i.required_stacks()