Esempio n. 1
0
def add_edge(network):
    """
    Random mutation of adding a single edge between two random chosen nodes.
    :param network: PeepoNetwork to mutate
    :return: mutated PeepoNetwork
    """
    node_pool = network.get_root_nodes()
    if not node_pool:
        logging.debug(
            'Model contains no valid nodes to add edge from... Adding a new node'
        )
        return add_node(network)

    parent_node = random.choice(node_pool)
    child_pool = np.setdiff1d(network.get_leaf_nodes(),
                              network.get_outgoing_edges(parent_node),
                              assume_unique=True)
    if not child_pool.size:
        return remove_edge(network)
    child_node = random.choice(child_pool)
    logging.info('Adding edge from %s to %s', parent_node, child_node)

    network.add_edge((parent_node, child_node))

    parents_card = [
        network.cardinality_map[x]
        for x in network.get_incoming_edges(child_node)
    ]

    network.add_cpd(child_node,
                    ga_child_cpd(parents_card, network.omega_map[child_node]))

    return network
Esempio n. 2
0
def remove_edge(network):
    """
    Random mutation of removing a single edge between two random chosen nodes.
    :param network: PeepoNetwork to mutate
    :return: mutated PeepoNetwork
    """
    node_pool = network.get_root_nodes()
    if not node_pool:
        logging.debug(
            'Model contains no valid nodes to remove an edge from... Adding a new node'
        )
        return add_node(network)

    parent_node = random.choice(node_pool)
    outgoing_edges = network.get_outgoing_edges(parent_node)
    if len(outgoing_edges) <= 1:
        logging.debug(
            'Model contains no valid edges to remove... Adding a new edge instead'
        )
        return add_edge(network)

    child_node = random.choice(outgoing_edges)

    network.remove_edge((parent_node, child_node))
    logging.info('Removed edge (%s, %s)', parent_node, child_node)

    parents_card = [
        network.cardinality_map[x]
        for x in network.get_incoming_edges(child_node)
    ]

    network.add_cpd(child_node,
                    ga_child_cpd(parents_card, network.omega_map[child_node]))

    return network
Esempio n. 3
0
def add_node(network):
    """
    Random mutation of adding a single node and an edge.
    :param network: PeepoNetwork to mutate
    :return: mutated PeepoNetwork
    """
    new_parent_node = str(uuid.uuid4())[:8]
    child_node = random.choice(network.get_leaf_nodes())
    logging.info('Adding new node with edge to: %s to %s', new_parent_node,
                 child_node)

    network.add_belief_node(new_parent_node, 2)
    network.add_edge((new_parent_node, child_node))

    parents_card = [
        network.cardinality_map[x]
        for x in network.get_incoming_edges(child_node)
    ]

    network.add_omega(new_parent_node, np.random.rand(2) * (2 * math.pi))
    network.add_cpd(new_parent_node,
                    ga_parent_cpd(network.omega_map[new_parent_node]))
    network.add_cpd(child_node,
                    ga_child_cpd(parents_card, network.omega_map[child_node]))

    return network
Esempio n. 4
0
 def mutate_cpds(network):
     epsilon = random.uniform(0.05, 0.75)
     for leaf in network.get_leaf_nodes():
         parents_card = [
             network.cardinality_map[x]
             for x in network.get_incoming_edges(leaf)
         ]
         network.omega_map[leaf] += (
             0.5 - np.random.rand(network.cardinality_map[leaf])) * epsilon
         network.add_cpd(
             leaf, ga_child_cpd(parents_card, network.omega_map[leaf]))
     return network
Esempio n. 5
0
    def first_generation(self):
        """
        Generates the 0th generation population.

        :return New population
        """
        peepo_template = read_from_file(self.source)
        population = []

        if not peepo_template.get_root_nodes():
            for _ in range(0, int(len(peepo_template.get_leaf_nodes()) / 3)):
                peepo_template.add_belief_node(str(uuid.uuid4())[:8], 2)

        # TODO: use get_topologies once accepted
        topologies = get_topologies(peepo_template,
                                    simple_first=self.simple_start,
                                    max_topologies=self.n_pop)
        for topology in topologies:
            peepo_template.edges = topology['edges']
            individual = peepo_template.copy()

            for node in individual.get_nodes():
                parent_nodes = individual.get_incoming_edges(node)
                if len(parent_nodes) == 0:
                    omega = []
                    cpd = np.full(individual.cardinality_map[node],
                                  1 / individual.cardinality_map[node])
                else:
                    parents_card = [
                        individual.cardinality_map[p] for p in parent_nodes
                    ]
                    max_omega = 2 * math.pi * np.prod(parents_card)
                    omega = np.random.rand(
                        individual.cardinality_map[node]) * max_omega
                    cpd = ga_child_cpd(parents_card, omega)

                individual.add_cpd(node, cpd)
                individual.add_omega(node, omega)
            individual.assemble()
            population.append(Individual(0.0, individual))

        self.best_chromosome = population[0]
        self.last_generation = (0.0, population)
        return population
Esempio n. 6
0
    def cross_over(self, selected_parents):
        selected_offspring = []
        mating_couples = list(itertools.combinations(selected_parents, 2))

        # To control exponential growth, limit number of combinations
        if len(mating_couples) > self.n_pop:
            random.shuffle(mating_couples)
            mating_couples = mating_couples[0:int(self.n_pop / 2.)]

        for n, chrom in enumerate(mating_couples):
            map_1 = get_adjency_map(chrom[0].network)
            map_2 = get_adjency_map(chrom[1].network)
            diff = np.abs(map_1 - map_2)
            i_sum = np.sum(diff)

            if i_sum == 0 or i_sum > GeneticAlgorithm.THRESHOLD:
                selected_offspring.append(
                    (Individual(0.0, chrom[0].network.copy()), 0, 0))
                selected_offspring.append(
                    (Individual(0.0, chrom[1].network.copy()), 0, 0))
                continue

            indices = np.argwhere(diff == 1)
            combinations = [[1, 0], [0, 1]]
            if len(indices) > 1:
                combinations = np.transpose(
                    get_index_matrix(np.full(len(indices), 2).tolist()))

            for comb in combinations:
                i_map = np.copy(map_1)
                for pos, index in enumerate(indices):
                    i_map[index[0], index[1]] = comb[pos]

                if 0 in np.sum(i_map, axis=1) or np.array_equal(
                        i_map, map_1) or np.array_equal(i_map, map_2):
                    continue

                edges = adjency_to_edges(chrom[0].network, i_map)
                new_peepo = chrom[0].network.copy()
                new_peepo.disassemble()
                new_peepo.edges = edges
                for node in new_peepo.get_nodes():
                    incoming_nodes = new_peepo.get_incoming_edges(node)
                    if len(incoming_nodes) == 0:
                        my_cpd = np.full(new_peepo.cardinality_map[node],
                                         1. / new_peepo.cardinality_map[node])
                        my_omega = []
                    else:
                        my_card_parents = []
                        [
                            my_card_parents.append(
                                new_peepo.cardinality_map[nod])
                            for nod in incoming_nodes
                        ]
                        max_omega = 2 * math.pi * np.prod(my_card_parents)
                        my_omega = np.random.rand(
                            new_peepo.cardinality_map[node]) * max_omega
                        my_cpd = ga_child_cpd(my_card_parents, my_omega)
                    new_peepo.add_cpd(node, my_cpd)
                    new_peepo.add_omega(node, my_omega)
                new_peepo.assemble()

                if np.array_equal(comb[0], comb[1]):
                    selected_offspring.append((Individual(0.0,
                                                          new_peepo), 0, 0))
                else:
                    selected_offspring.append(
                        (Individual(0.0, new_peepo), random.uniform(0, 1),
                         random.uniform(0, 1)))

        # If there's not enough offspring, fill it up with parents
        while True:
            if len(selected_parents) + len(selected_offspring) >= self.n_pop:
                break
            for parent in selected_parents:
                if len(selected_parents) + len(
                        selected_offspring) >= self.n_pop:
                    break
                selected_offspring.append((parent, 0, 0))

        return selected_offspring