예제 #1
0
class Ant():

    ant_id = 0
    print_id = -1

    def __init__(self, wrapper, portfolio):
        self.solution = Solution()
        self.solution.ant = self
        self.curr_node = None
        self.ant_id = Ant.ant_id
        Ant.ant_id += 1

        self.portfolio = portfolio
        self.wrapper = wrapper
        

        self.graph = wrapper.get_graph()

        self.LEN = self.portfolio.model.duration

        self.unavailable = Set([])
        self.total_weight = 0
       

        self.capital = self.portfolio.model.budget


        self.generated = [0]* self.LEN
        self.substracted = [0] * self.LEN

        self.merged_glob = [self.capital] * self.LEN
        self.extra = []
        self.last_year = 0

        self.not_active = []
        self.drugs_so_far = {}
        self.position_to_year = [1]


        self.populate_inactive()
        self.move_next(wrapper.nest, {"complete": {}, "incomplete": []})
        
    
    def populate_inactive(self):
        for x in self.graph.nodes():
            node = self.graph.node[x]

            if node["active"] != True:
                self.not_active.append(x)


    def move_next(self, node, complete):
        self.unavailable.add(self.curr_node)
        self.update_curr_node(node)
        self.update_time(complete['complete'])


    def update_curr_node(self, node):
        self.curr_node = node
        self.solution.update_path(node)
        self.total_weight += self.graph.node[self.curr_node]['cost']
        self.enable_next_node(self.curr_node)

    def enable_next_node(self,node):
        if node is not "food" and node is not "nest":
            i = int(node[1:]) + 1
            next_node = str(node[0]) + str(i)

            if next_node in self.not_active:
                self.not_active.remove(next_node)

         

    def update_time(self, complete):
        
        #empty arrays for capital generated each year and spend each year
        generated_per_year = [0] * self.LEN
        spent_per_year = [0] * self.LEN

        #array for mapping the investment year with each stage
        diff = len(self.solution.path) - len(self.position_to_year)

        while(diff != 0):
            self.position_to_year.append(1)
            diff -= 1

        # based on completed drugs - calculate how much each generated per year and when
        for d, d_val in complete.iteritems():
            total_duration = 0
            for s, s_val in d_val.iteritems():
                total_duration += s_val["duration"]

            while total_duration < self.LEN:
                #print self.wrapper.profit_year
                generated_per_year[total_duration] += self.wrapper.profit_year[str(d)]
                total_duration += 1


        # eg. {u'B': 2, u'L': 4} and then {u'B': 5, u'L': 4}
        # keeps track on how much time passed since a drug started accounting for any gaps/break/wait in between too
        drugs_so_far = self.drugs_so_far

        # only for the last added stage to the solution as everything else is computed already
        last_added_stage = self.solution.path[-1]

        if last_added_stage is not "nest" and last_added_stage is not "food":
            drug = last_added_stage[:-1]

            if drug not in drugs_so_far.keys():
                drugs_so_far[drug] = 0

                      
            if drugs_so_far[drug] > self.last_year:
                wait = drugs_so_far[drug]
            else:
                wait = self.last_year


            # if total time exceeds portfolio time remove this from the solution path 
            # - to do : remove all last_added_stages related to this drug as drug not possible 
            if wait + self.graph.node[last_added_stage]["duration"] < self.LEN:
                self.position_to_year[-1] =  wait
                drugs_so_far[drug] = self.position_to_year[-1] + self.graph.node[last_added_stage]["duration"]
            else:
                self.solution.path.remove(last_added_stage)
                self.unavailable.add(last_added_stage)
                self.position_to_year.pop()

        
        #update the amount of money spend in each year
        for i in range(1, len(self.position_to_year)):
            stage = self.solution.path[i]
            position = self.position_to_year[i] - 1

            spent_per_year[position] -=  self.graph.node[stage]["cost"]



        merged = [0] * self.LEN
        self.substracted = [0] * self.LEN

        running_total = self.capital
        i = 0
        for x in range(0,self.LEN):
            merged[i] = running_total + spent_per_year[i] + generated_per_year[i]
            running_total = merged[i]

            self.substracted[i] = generated_per_year[i] + spent_per_year[i]
            i +=1

        self.merged_glob = merged
        self.generated = generated_per_year

            
        self.drugs_so_far = drugs_so_far


    def get_weight(self):
        return self.total_weight

    def get_neighbours(self):
        neigh = self.graph.neighbors(self.curr_node)
        sanitized = []

        next = True
        i = 1
        while next and i <= self.LEN:
            sanitized = []

            for x in neigh:
                if x not in self.solution.path and x not in self.unavailable and x not in self.not_active:
                    #TEST FOR EMPTY NODE{X} => node[x] = {}
                    cost = self.graph.node[x]["cost"]
                        
                    #check if current cost exceeds the available capital.
                    tmp_merged = self.merged_glob[i-1:]
                    tmp_merged = [a - cost for a in tmp_merged]
                    negative = sum(1 for n in tmp_merged if n < 0)
                    
                    if negative == 0 :
                        sanitized.append(x)

            # means for this year (year i) no stage was respecting the above constraint 
            # so we go to the next year where extra generated capital might be available
            if (len(sanitized) == 1 and "food" in sanitized):
                i+=1
            else:
                self.last_year = i
                self.extra = sanitized
                next = False

        return sanitized