Ejemplo n.º 1
0
    def expandBusMatrix(self):
        """
        """
        # Do a matrix the size of the train info matrix full of zeros
        matrix_parser = AdjacencyMatrixParser()
        matrix_parser.loadFile(MA_PATH)
        matrix_parser.parse()
        train_costs = matrix_parser.values
        matrix_parser.closeFile()
        zero_list = []
        for element in train_costs:
            sub_list = []
            for element2 in element:
                sub_list.append(0)
            zero_list.append(sub_list)

        # Load info of the trolleybus costs
        matrix_parser.loadFile(TROLEI_BUS_MA_PATH)
        matrix_parser.parse()
        bus_costs = matrix_parser.values
        matrix_parser.closeFile()

        # Load the information of the trolleybus
        bus_parser = CityInfoParser()
        bus_parser.loadFile(TROLEI_BUS_INFO_PATH)
        bus_parser.parse()
        bus_info = bus_parser.info

        # Iterate twice over the bus_info dictionary and move the values in it's
        # adjacency matrix to the zero_list
        i = 0
        bus_info_keys = bus_info.keys()
        bus_info_keys.sort()
        for id in bus_info_keys:
            j = 0
            bus_info_keys_2 = bus_info.keys()
            bus_info_keys_2.sort()
            for id2 in bus_info_keys_2:
                m, n = ((id2, id) if id < id2 else (id, id2))
                x, y = ((j, i) if i < j else (i, j))
                zero_list[m-1][n-1] = bus_costs[x][y] 
                j += 1
            i += 1
        return zero_list
Ejemplo n.º 2
0
def main():
    """
    Method used for testing the performance and the correctness of the implemented
    A* and BFS algorithms along with the parsers.
    Comment / Uncomment code to test different features of the software.
    """

    # Load the information of the city
    train_parser = CityInfoParser()
    train_parser.loadFile(CITY_INFO_PATH)
    train_parser.parse()
    train_parser.setDistances()
    train_info = train_parser.info
    distances = train_parser.distances

    # Load the information of the troleibus (distances are the same as the train)
    bus_parser = CityInfoParser()
    bus_parser.loadFile(TROLEI_BUS_INFO_PATH)
    bus_parser.parse()
    bus_info = bus_parser.info

    # Load the information of the train costs
    matrix_parser = AdjacencyMatrixParser()
    matrix_parser.loadFile(MA_PATH)
    matrix_parser.parse()
    train_costs = matrix_parser.values
    matrix_parser.closeFile()

    # Load info of the troleibus costs
    matrix_parser.loadFile(TROLEI_BUS_MA_PATH)
    matrix_parser.parse()
    bus_costs = matrix_parser.values
    matrix_parser.closeFile()

    
    # Open an instance of cost manager to provide custom results
    # in some cases.
    costs_manager = CostsManager()
    
    
    ########################################
    # Add both the bus and the train info on the same matrix
    # costs_aux = copy.deepcopy(train_costs)
    # for x in enumerate(costs_aux):
    #     print(x)
    costs = costs_manager.combineCosts(train_info, bus_info, train_costs, bus_costs)
    # print(pprint.pformat(enumerate(costs)))
    # for x in enumerate(costs):
    #     print(x)
    # print(costs == costs_aux)

    # # Count differences (debug)
    # count = 0
    # for i in range(len(costs)):
    #     for j in range(len(costs[i])):
    #         if (costs[i][j] != costs_aux[i][j]):
    #             count += 1
    # print("Count: ", count) 
    # return
    # Set transfer costs really high so they are ignored
    # costs_manager.setTransferCost(info_parser.info, costs, 999)
    #########################################

    # Walking costs
    costs = costs_manager.setWalkingCostsWithDistances(
                                               costs,
                                               distances,
                                               multiplier = WALK_MULTIPLIER
                                          )


    # Set up the A* algorithm
    search = SearchStrategies()
    search.setCosts(costs)
    search.setHeuristic(distances)
    search.setIgnore(0)

    # Run the algorithm
    # way = search.aStar(1, 24, start_at=1)
    way = search.BFS(1, 24, start_at=1)
    print 'Result:', way
Ejemplo n.º 3
0
    def run(self):
        """
        Takes the options (input from the user) and processes it in order to
        give a customizable output, which is later on moved to a textctrl
        widget.
        """
        # Get the state of the check boxes
        walking_selected = self.walking_cb.GetValue()
        subway_selected = self.subway_cb.GetValue()
        trolleybus_selected = self.trolleybus_cb.GetValue()

        # Get the state of the radio boxes
        minimize_stations = self.stations_rb.GetValue()
        minimize_transfers = self.transfers_rb.GetValue()        
        minimize_cost = self.costs_rb.GetValue()

        # Get the origin selected - if no origin selected -> error
        selected = self.choice_origin.GetCurrentSelection()
        if selected == -1:
            return self.error("No origin selected.")
        origin = self.list_origin[selected]
        origin_id = self.stationStringToId(origin)

        # Get the destiny selected - if no destination is selected -> error
        selected = self.choice_destiny.GetCurrentSelection()
        if selected == -1:
            return self.error("No destiny selected.")
        destiny = self.list_destiny[selected]
        destiny_id = self.stationStringToId(destiny)

        #### Use the logic obtained to run the algorithm
        ## Error checking
        # Check if the user selected at least one of the check boxes
        if not (walking_selected or subway_selected or trolleybus_selected):
            return self.error("Please select some vehicle.")

        # If we selected trolleybus, check for a valid destiny and origin
        if trolleybus_selected and not subway_selected and not walking_selected:
            trolleybus_ids = self.gettrolleybusIdList()
            found = False
            for id in origin_id:
                if id in trolleybus_ids:
                    found = True
            if not found:
                return self.error("This origin isn't possible when we use trolleybus.")
            found = False
            for id in destiny_id:
                if id in trolleybus_ids:
                    found = True
            if not found:
                return self.error("Unreachable destiny via trolleybus.")

        # Check if the user selected the same origin and destiny
        if origin_id == destiny_id:
            return self.output_text.ChangeValue("You are already there.")
        ## /Error checking

        ## Use selected options to manage the data to run the algorithm
        # Load the information of the city
        train_parser = CityInfoParser()
        train_parser.loadFile(CITY_INFO_PATH)
        train_parser.parse() 
        train_parser.setDistances()
        train_info = train_parser.info
        distances = train_parser.distances

        # Load the information of the trolleybus (distances are the same as the train)
        bus_parser = CityInfoParser()
        bus_parser.loadFile(TROLEI_BUS_INFO_PATH)
        bus_parser.parse()
        bus_info = bus_parser.info

        # Load the information of the train costs
        matrix_parser = AdjacencyMatrixParser()
        matrix_parser.loadFile(MA_PATH)
        matrix_parser.parse()
        train_costs = matrix_parser.values
        matrix_parser.closeFile()

        # Load info of the trolleybus costs
        matrix_parser.loadFile(TROLEI_BUS_MA_PATH)
        matrix_parser.parse()
        bus_costs = matrix_parser.values
        matrix_parser.closeFile()

        # Open an instance of cost manager to provide custom results
        # in some cases.
        costs_manager = CostsManager()

        if subway_selected and trolleybus_selected:
            costs = costs_manager.combineCosts(train_info, bus_info, train_costs, bus_costs)
        elif subway_selected:
            costs = train_costs
        elif walking_selected and not subway_selected and not trolleybus_selected:
            costs = self.makeWalkingMatrix(distances)
        elif walking_selected and trolleybus_selected:
            costs = self.expandBusMatrix()
        else:
            costs = bus_costs

        if walking_selected and (subway_selected or trolleybus_selected):
            costs = costs_manager.setWalkingCostsWithDistances(
                                               costs,
                                               distances,
                                               multiplier = WALK_MULTIPLIER
                                          )

        if minimize_transfers:
            if subway_selected:
                costs_manager.setTransferCost(train_parser.info, costs, 999)
            elif trolleybus_selected:
                costs_manager.setTransferCost(bus_parser.info, costs, 999)


        # Set up the algorithm
        search = SearchStrategies()
        search.setCosts(costs)
        search.setHeuristic(distances)
        search.setIgnore(0)

        # Run the algorithm
        # If we only selected walking option, let the user go directly to their destination
        if walking_selected and not trolleybus_selected and not subway_selected:
            result = [destiny_id[0] - 1, origin_id[0] - 1] # substract -1 to normalize, enumeration starts with n=1
        # Select the optimum way in case we have stations with same name (multiple IDs station)
        elif minimize_stations:
            result_list = []
            for id in origin_id:
                for id2 in destiny_id:
                    result_list.append(search.BFS(id, id2, start_at = 1))
            bird = len
            result_list.sort(key=bird) # The key is the bird
            result = result_list[0]
        else:
            result_list = []
            for id in origin_id:
                for id2 in destiny_id:
                    print(id, id2)
                    result_list.append(search.aStar(id, id2, start_at = 1))
            bird = len
            result_list.sort(key=bird)
            result = result_list[0]
        
        # We process the result in order to display a nice output to the user
        # We do that because the algorithms return a boring list of numbers.
        self.output_text.Clear()
        walking_costs = self.makeWalkingMatrix(distances)

        # Helper method to calculate the optimum way of traversing from two
        # stations id given the actual options.
        def wayCheck(id1, id2):
            """
            Helper function.
            Returns 1, 2 or 3 depending on whether the optimum way of going from
            id1 to id2 is by train (subway), bus or walking.
            @id1 (int): station_id1
            @id2 (int): station_id2
            """
            # id1, id2 = id1-1, id2-1
            patata = False
            if id2>id1:
                id1,id2=id2,id1            
            if walking_selected:
                costCaminant = walking_costs[id1-1][id2-1]
            if trolleybus_selected:
                ola=False
                busList = self.gettrolleybusIdList()
                if id2==18:
                    ola=True
                    id2,id1=id1,38
                print busList
                print id1 , id2 ,id1 in busList and id2 in busList
                if id1 in busList and id2 in busList:
                    patata = True
                    sorted_dict_keys = bus_parser.info.keys()
                    sorted_dict_keys.sort()
                    for n, i in enumerate(sorted_dict_keys):
                        if id1 == i:
                            break
                    for n2, j in enumerate(sorted_dict_keys):
                        if id2 == j:
                            break
                    if n2>n:
                        n2,n = n,n2
                    costBus = bus_costs[n][n2]
                if ola:
                    id1,id2=id2,18
            if subway_selected:
                if id1==38:
                    xx,yy=17,id2-1
                    if xx<yy:
                        xx,yy=yy,xx
                    if train_costs[xx][yy]!=0 and train_costs[37][id2-1]==0:
                        id1=18
                if id1<id2:
                    id2,id1=id1,id2
                costsubway = train_costs[id1-1][id2-1]
            if subway_selected and not trolleybus_selected and not walking_selected:
                #100
                return 1
            elif not subway_selected and trolleybus_selected and not walking_selected:
                #010
                return 2
            elif not subway_selected and not trolleybus_selected and walking_selected:
                #001
                return 3
            elif subway_selected and not trolleybus_selected and walking_selected:
                #101
                if costsubway==0:
                    return 3
                x = min(costsubway,costCaminant)
                if x==costsubway:
                    return 1
                elif x==costCaminant:
                    return 3
                else:
                    raise ValueError()
            elif subway_selected and trolleybus_selected and not walking_selected and patata:
                #110
                if costsubway==0:
                    return 2
                elif costBus==0:
                    return 1
                else:
                    x = min(costsubway,costBus)
                    if x==costsubway:
                        return 1
                    elif x==costBus:
                        return 2
                    else:
                        raise ValueError()
            elif subway_selected and trolleybus_selected and not walking_selected and not patata:
                return 1
            elif not subway_selected and trolleybus_selected and walking_selected and patata:
                #011
                if costBus==0:
                    return 3
                x = min(costBus,costCaminant)
                if x==costBus:
                    return 2
                elif x==costCaminant:
                    return 3
                else:
                    raise ValueError()
            elif not subway_selected and trolleybus_selected and walking_selected and not patata:
                return 3
            elif subway_selected and trolleybus_selected and walking_selected and patata:
                #111
                if costsubway==0 and costBus==0:
                    return 3
                elif costsubway==0:
                    x = min(costBus,costCaminant)
                    if x==costBus:
                        return 2
                    elif x==costCaminant:
                        return 3
                    else:
                        raise ValueError()
                elif costBus==0:
                    x = min(costsubway,costCaminant)
                    if x==costsubway:
                        return 1
                    elif x==costCaminant:
                        return 3
                    else:
                        raise ValueError()
                else:
                    x = min(costsubway,costCaminant,costBus)
                    if x==costsubway:
                        return 1
                    elif x==costCaminant:
                        return 3
                    elif x==costBus:
                        return 2
                    else:
                        raise ValueError()
            elif subway_selected and trolleybus_selected and walking_selected and not patata:
                if costsubway==0:
                    return 3
                x = min(costsubway,costCaminant)
                if x==costsubway:
                    return 1
                elif x==costCaminant:
                    return 3
                else:
                    raise ValueError()
            else:
                raise ValueError()
        result.reverse()

        ###### Parse 2 per arreglar error
        matrix_parser = AdjacencyMatrixParser()
        matrix_parser.loadFile(MA_PATH)
        matrix_parser.parse()
        train_costs = matrix_parser.values
        matrix_parser.closeFile()

        print "result", result
        result = map(lambda num: num+1, result) # Increment each result by one
        print "result",result
        station_id1=result[0]       
        for n, station_id2 in enumerate(result[1:], start=1):
            number = wayCheck(station_id1,station_id2)
            print "station ids: ", station_id1, station_id2

            origen_station = self.stationIdToString(station_id1)
            destiny_station = self.stationIdToString(station_id2)

            station_id1=station_id2
            
            self.output_text.AppendText(str(n) + ") " + origen_station + " -> " + destiny_station +": ")            
            if number == 1:
                self.output_text.AppendText("Subway")
            elif number == 2:
                self.output_text.AppendText("Trolleybus")
            elif number == 3:
                self.output_text.AppendText("Walking")
            else:
                raise ValueError()

            if origen_station == destiny_station:
                self.output_text.AppendText(" (transfer)")
            self.output_text.AppendText("\n")

        # Move selection of text ctrl to topleft    
        self.output_text.ShowPosition(0)