def test_unequal_rules_crossover(self):
        self.configurations['RULE_SET_CROSSOVER_METHOD'] = 'pivot'
        self.initialise_segment_table("plural_english_segment_table.txt")

        r1 = Rule([{"velar": "+"}], [{"velar": "-"}], [{"cons": "+"}], [{"cons": "+"}], obligatory=True)
        r2 = Rule([{"voice": "+"}], [{"voice": "-"}], [{"velar": "+"}], [{"cons": "+"}], obligatory=True)
        r3 = Rule([{"voice": "-"}], [{"cons": "-"}], [{"cons": "+"}], [{"voice": "+"}], obligatory=False)

        rule_1 = RuleSet([r1])
        rule_2 = RuleSet([r2, r3])

        self._seed_me_multiple(
            methods=[random.randrange] + [random.randint for _ in range(5)],
            argss=[[1]] + [[0, 1] for _ in range(5)],
            expecteds=[0, 0, 0, 0, 1, 0])

        offspring_1, offspring_2 = RuleSet.crossover(rule_1, rule_2)
        self.assertEqual(str(offspring_1), str(RuleSet([r1, r3])))
        self.assertEqual(str(offspring_2), str(RuleSet([r2])))
        log_rule_set(rule_1)
        print()
        log_rule_set(rule_2)
        print()
        log_rule_set(offspring_1)
        print()
        log_rule_set(offspring_2)
 def test_crossover(self):
     self.initialise_segment_table("plural_english_segment_table.txt")
     rule_1 = RuleSet([
         Rule([{
             "voice": "+"
         }], [{
             "voice": "-"
         }], [{
             "velar": "+"
         }], [{
             "cons": "+"
         }],
              obligatory=True)
     ])
     rule_2 = RuleSet([
         Rule([{
             "low": "-"
         }], [{
             "low": "+"
         }], [{
             "cont": "+"
         }], [{
             "voice": "-"
         }],
              obligatory=True)
     ])
     offspring_1, offspring_2 = RuleSet.crossover(rule_1, rule_2)
     log_rule_set(rule_1)
     print()
     log_rule_set(rule_2)
     print()
     log_rule_set(offspring_1)
     print()
     log_rule_set(offspring_2)
    def crossover(self, h1, h2):
        if GeneticAlgorithm._is_incest(h1, h2):
            return h1, h2,

        crossover_rules = False
        crossover_hmm = False
        if ga_config.CROSSOVER_BOTH_HMM_AND_RULES:
            if configurations["EVOLVE_RULES"]:
                crossover_rules = True
            if configurations["EVOLVE_HMM"]:
                crossover_hmm = True

        else:
            loci = []
            if configurations["EVOLVE_RULES"]:
                loci.append('rules')
            if configurations["EVOLVE_HMM"]:
                loci.append('hmm')
            locus = random.choice(loci)

            if locus == 'rules':
                crossover_rules = True
            elif locus == 'hmm':
                crossover_hmm = True

        offspring_1 = deepcopy(h1)
        offspring_2 = deepcopy(h2)

        if crossover_rules:
            offspring_1_rule_set, offspring_2_rule_set = RuleSet.crossover(
                offspring_1.grammar.rule_set, offspring_2.grammar.rule_set)
        else:
            offspring_1_rule_set, offspring_2_rule_set = offspring_1.grammar.rule_set, offspring_2.grammar.rule_set

        if crossover_hmm:
            offspring_1_hmm, offspring_2_hmm = HMM.crossover(
                offspring_1.grammar.hmm, offspring_2.grammar.hmm)
        else:
            offspring_1_hmm, offspring_2_hmm = offspring_1.grammar.hmm, offspring_2.grammar.hmm

        offspring_1.grammar = Grammar(offspring_1_hmm, offspring_1_rule_set)
        offspring_2.grammar = Grammar(offspring_2_hmm, offspring_2_rule_set)

        # Invalidate mutated offspring fitness value (i.e. mark for re-evaluation)
        offspring_1.invalidate_fitness()
        offspring_1.invalidate_energy()
        offspring_2.invalidate_fitness()
        offspring_2.invalidate_energy()

        return offspring_1, offspring_2,
    def test_crossover(self):
        self.configurations['RULE_SET_CROSSOVER_METHOD'] = 'pivot'
        self.initialise_segment_table("plural_english_segment_table.txt")
        rule1_target, rule2_target = [{"voice": "+"}],  [{"low": "-"}]
        rule1_change, rule2_change = [{"voice": "-"}], [{"low": "+"}]
        rule1_lcontext, rule2_lcontext = [{"velar": "+"}], [{"cont": "+"}]
        rule1_rcontext, rule2_rcontext = [{"cons": "+"}], [{"voice": "-"}]
        rule1 = Rule(rule1_target, rule1_change, rule1_lcontext, rule1_rcontext, obligatory=True)
        rule2 = Rule(rule2_target, rule2_change, rule2_lcontext, rule2_rcontext, obligatory=True)
        self._seed_me_multiple(methods=[random.randrange] + [random.randint for _ in range(5)],
                               argss=[[1]] + [[0, 1] for _ in range(5)],
                               expecteds=[ANY, 1, 0, 1, 0, 1])

        offspring_1, offspring_2 = RuleSet.crossover(RuleSet([rule1]), RuleSet([rule2]))

        self.assertEqual(str(offspring_1), str(RuleSet([Rule(target=rule2_target, change=rule1_change, left_context=rule2_lcontext, right_context=rule1_rcontext, obligatory=True)])))
        self.assertEqual(str(offspring_2), str(RuleSet([Rule(target=rule1_target, change=rule2_change, left_context=rule1_lcontext, right_context=rule2_rcontext, obligatory=True)])))