Binary Ant Colony Optimization


      Binary ACO is a modification of TACO. Touring ant colony optimization was initially desinged for handling continuous varibales in the optimization problems, and was later used for different problems such as digital filter design. In this algorithm, each solution is represented with a string of binary bits. Artificial ants search for the value of each bit in the string. At the decision stage for the value of a bit, ants only use the pheromone information. After all ants in the colony have produced their solutions and pheromone of sub-paths between the bits is updated.This is carried out by evaporating the previous pheromone amounts and depositing the new pheromone amounts on the paths.     
     Here I give the python codes for binary colony based on its general ideas. In the codes, only the global best ant is admissible to deposit pheromone and max-min ant system stragety is utilized for pheromone updating. Here i applied the binary ant colony algorithm for feature selection. The dataset can be dowloaded from the UCI websites. 
    Welcome everyone to give some advice!
Created on Tue Jan 00 00:00:00 2017

@author: Randolph.Lee
"""
from __future__ import division
import numpy as np
import random


class Graph:


    def __init__(self, num_nodes, min_pheromone, max_pheromone, phro, Q):
        self.nodes_number = num_nodes
        self.pheromone_min = min_pheromone
        self.pheromone_max = max_pheromone
        self.Q = Q
        self.phro = phro
        self.pheromone_mat = np.ones((self.nodes_number, 2))
        self.pheromone_deltaMat = np.zeros((self.nodes_number, 2))


    def update_pheromone(self, result_list, fitness):
        # update the pheromone according to the best ant
        # result_list is a tuple
        # max-min ant system
        for (feat_index, bin_code) in result_list:
            self.pheromone_deltaMat[feat_index, bin_code] = self.Q / fitness


        self.pheromone_mat = (1 - self.phro) * self.pheromone_mat + self.pheromone_deltaMat


        for index in range(self.nodes_number):
            for j in [0, 1]:
                if self.pheromone_mat[index, j] > self.pheromone_max:
                    self.pheromone_mat[index, j] = self.pheromone_max
                if self.pheromone_mat[index, j] < self.pheromone_min:
                    self.pheromone_mat[index, j] = self.pheromone_min

class Ant:
    def __init__(self, ID):
        self.ID = ID
        # save the result of binary string including the feature index ant corresponding status
        self.result_list = []
        # the next index to select
        self.next_i = 0
        # the subset selected
        self.subset_list = []
        # calculate the recall and precision for the evaluation criterion
        '''
        Here it's noted that the graph is directed and the ant search the feature nodes by the ordering path
        '''
        self.accuracy = 0.0
        self.current_fitness = 0.0

    def select_bin(self, alpha, beta, pheromone_mat, heuristic_mat):
        # pheromone_mat: num_nodes * 2, heuristic_mat: num_nodes * 2
        temp_prob0 = np.power(pheromone_mat[self.next_i, 0], alpha) * np.power(heuristic_mat[self.next_i, 0], beta)
        temp_prob1 = np.power(pheromone_mat[self.next_i, 1], alpha) * np.power(heuristic_mat[self.next_i, 1], beta)
        transfer_to1 = temp_prob1 / (temp_prob0 + temp_prob1)
        #  Roulette
        if random.random() <= transfer_to1:
            res = (self.next_i, 1)
        else:
            res = (self.next_i, 0)
        return res

    def add_bin(self, bin_tuple):
        self.result_list.append(bin_tuple)
        self.next_i += 1

    def decode_bin(self, feature_num):
        temp_result = filter(lambda x: x[1] == 1, self.result_list)
        if len(temp_result) == 0:
            self.subset_list = [random.randint(0, feature_num - 1)]  # modify
        else:
            self.subset_list = map(lambda x: x[0], temp_result)

    def evaluate_subset(self, origin_featMat, label_arr, centers=None):
        # calculate the three indicators
        if centers is not None:
            selected_feat = self.subset_list.extend(centers)
        else:
            selected_feat = self.subset_list

        feat_mat = origin_featMat[:, selected_feat]
        self.accuracy = cal_indicator(feat_mat, label_arr)
        '''
        Here we encode the features except the most representative features due to that the most representative features
        must be added into the subsets, which can decrease the search time of each ant
        '''
        self.current_fitness = cal_fitness1(len(self.subset_list), self.accuracy)

    def clear_subset(self):
        self.subset_list = []
        self.result_list = []

class AntSearch:
    def __init__(self, constructed_graph, ant_num, alpha_para, beta_para, iteration_max):
        self.graph = constructed_graph
        self.num_ant = ant_num
        self.alpha = alpha_para
        self.beta = beta_para
        self.iter_max = iteration_max
        self.best_subset = []
        self.best_result = []
        self.best_fit = 0.0
        self.best_accuracy = 0.0
        self.res = []

    def create_ant(self):
        ant_list = []
        for j in range(self.num_ant):
            ant_list.append(Ant(j))
        return ant_list

    def iter_search(self, origin_featMat, label_arr, heuristic_mat, centers=None):
        for i in range(self.iter_max):
            ant_list = self.create_ant()
            for ant in ant_list:
                # remember that the graph is directed so the search is an ordering path
                while ant.next_i < self.graph.nodes_number:
                    next_bin = ant.select_bin(self.alpha, self.beta, self.graph.pheromone_mat, heuristic_mat)
                    ant.add_bin(next_bin)
                ant.decode_bin(origin_featMat.shape[1])
                # i, origin_featMat, label_arr, most_repList=None, params=None, property_dict=None
                ant.evaluate_subset(origin_featMat, label_arr, centers)

            # record the local best subset
            local_fit = ant_list[0].current_fitness
            local_subset = ant_list[0].subset_list
            local_result = ant_list[0].result_list
            local_accuracy = ant_list[0].accuracy

            for ant in ant_list[1:]:
                if ant.current_fitness > local_fit:
                    local_fit = ant.current_fitness
                    local_subset = ant.subset_list
                    local_result = ant.result_list
                    local_accuracy = ant.accuracy
            # record the global best subset
            if local_fit > self.best_fit:
                self.best_fit = local_fit
                self.best_subset = local_subset
                self.best_result = local_result
                self.best_accuracy = local_accuracy
            '''
            Here we employ the max-min ant system, and only the global ant can update the pheromone
            '''
            self.graph.update_pheromone(self.best_result, self.best_fit)
            # clear up the datasets
            for ant in ant_list:
                ant.clear_subset()
        self.res.append([self.best_fit, self.best_accuracy, self.best_subset, len(self.best_subset) / origin_featMat.shape[1]])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值