示例#1
0
    def __init__(self, file, p, traject, timeframe):
        """Initializes the objects needed for the algorithm"""
        self.trains = copy.deepcopy(traject)
        self.proportion = p
        self.timeframe = timeframe

        # reads connections
        read = Read(file)
        self.stations, self.cdict, self.clist, self.clist2 = read.readConnections(
        )

        # initialise time
        self.time = 0

        # adds time of all trains in planning
        for train in self.trains.values():
            self.time += train.time

        # calculates score from planning
        self.score = formula(p, len(self.trains.keys()), self.time)
示例#2
0
    def rerun_train(self):
        # chooses a random train from the planning
        key = random.choice(list(self.trains.keys()))
        train = self.trains[key]

        # make empty list of connections used
        connections_used = []

        # adds all other trains to connections used
        for traject in self.trains.values():
            if traject is not train:
                for c in traject.connections:
                    if (c.text() not in connections_used and changeDirection(
                            c.text()) not in connections_used):
                        connections_used.append(c.text())

        new_train = Traject()

        # find unused track to start the train on
        while True:
            start = random.choice(self.clist)
            # only stops looking when it finds an unused connection
            if start not in connections_used:
                break

        # add starting connection
        new_train.addConnection(self.cdict[str(start)],
                                self.cdict[str(start)].time, self.timeframe)

        while True:
            # find the current station of the traject
            destination = traject.connections[-1].destination

            # find the previous station of the traject
            origin = traject.connections[-1].origin

            # check whether there is an option to expand the traject further
            if fastestConnection(self.cdict, destination, origin) != None:
                # add the connection with the shortest time to the traject
                new_connection = fastestConnection(self.cdict, destination,
                                                   origin)
                if self.cdict[new_connection] in traject.connections:
                    break
                traject.addConnection(self.cdict[new_connection],
                                      self.cdict[new_connection].time,
                                      self.timeframe)
            # stops the process when done
            else:
                break

        # adds connections in new train to connections used
        for k in new_train.connections:
            if k.text() not in connections_used and changeDirection(
                    k.text()) not in connections_used:
                connections_used.append(k.text)

        # define the alternative plan
        new_plan = copy.deepcopy(self.trains)

        # replace train with the new train
        new_plan[key] = new_train

        # calculates new p
        new_p = 2 * len(connections_used) / len(self.clist)

        new_time = 0
        for train in new_plan.values():
            new_time += train.time

        # calculates new score
        new_score = formula(new_p, len(new_plan.keys()), new_time)

        # changes train to new train if score higher
        if new_score > self.score:
            self.trains = copy.deepcopy(new_plan)
            self.score = new_score
            self.time = new_time

        return new_score
示例#3
0
    def run(self):
        """Returns a solution for the problem by using a greedy algorithm that takes the fastest option."""

        # save traject objects in dictionairy
        trajecten = {}

        # total amount of connections where a to b and b to a are considered the same count of all the elements in list
        total = len(self.connectionslist) / 2

        # a list which will be filled with the connections that are used in all tracks
        connections_used = []

        # total minutes of all the tracks together
        total_minutes = 0

        # create track object
        traject = Traject()

        # create a new track object for the amount of trains allowed
        for i in range(self.trains):

            # create track object
            traject = Traject()

            # initialize starting point, not a used connection
            while True:
                start = random.choice(self.connectionslist)
                if start not in connections_used:
                    break

            # add starting connection to the track
            traject.addConnection(self.connections[str(start)],
                                  self.connections[str(start)].time,
                                  self.timeframe)

            # for loop that adds connections to the track object
            for j in range(0, 20):

                # find the current station of the track
                new_origin = traject.connections[-1].destination

                # find the previous station of the track
                previous_station = traject.connections[-1].origin

                # check whether there is an option to expand the track further
                if fastestConnection(self.connections, new_origin,
                                     previous_station) != None:

                    # add the connection with the shortest time to the track
                    new_connection = fastestConnection(self.connections,
                                                       new_origin,
                                                       previous_station)
                    traject.addConnection(
                        self.connections[new_connection],
                        self.connections[new_connection].time, self.timeframe)

            # save track in the tracks dictionairy
            trajecten[i] = traject
            total_minutes += traject.time

            # update the list of connections used for every new connection that had not been used before
            for k in traject.connections:
                if k.text() not in connections_used and changeDirection(
                        k.text()) not in connections_used:
                    connections_used.append(k.text())

            # calculate p
            p = len(connections_used) / total
            train_used = i + 1
            score = formula(p, self.trains, total_minutes)

        return trajecten, p, total_minutes, score, train_used
示例#4
0
    def run(self):
        """Returns an efficient solution"""
        
        # keep track of how many trains will be used
        trains_used = 0
        
        # total amount of connections 
        total = len(self.clist)

        # save track objects in dictionairy
        trajecten = {}

        # keep track of the connections used in the whole timetable
        connections_used = []

        # keep track of the total time of all the track object
        total_minutes = 0

        # when current score is lower then previous score, it will be 
        # considered a failed attempt
        failed_attemps = 0

        while True:
            # ratio connection used to total in current state
            current_p = (len(connections_used)) / total
            
            # current score
            current_score = formula(current_p, trains_used , total_minutes)

            # how many connections, that are not used before, will the 
            # new track have
            count_new_connections = 0
            
            traject = Traject()
            while True:
                # choose random begin connection
                start = random.choice(self.clist)

                # however, make sure that this connenction is not used before
                if (start not in connections_used and changeDirection(start) 
                    not in connections_used):
                    break

            # add starting connection to the traject
            traject.addConnection(self.connections[start], 
                self.connections[start].time, self.timeframe)

            while True:
                # find the current station of the traject
                new_origin = traject.connections[-1].destination

                # keep track how much time is left within the track
                time_left = self.timeframe - traject.time

                # save the current connections made in a list
                traject_connections = []
                for each in traject.connections:
                    traject_connections.append(each.text())
                    traject_connections.append(changeDirection(each.text()))

                # check which connection is the best to be made
                best_option = bestConnection(new_origin, time_left, 
                                self.connections, connections_used, 
                                traject_connections)

                # if connection is found, add to track
                if best_option != None:
                    traject.addConnection(self.connections[best_option], 
                        self.connections[best_option].time, self.timeframe)
                else:
                    break
            
            # count how many unused connections are found in the new track
            for k in traject.connections:
                if k.text() not in connections_used: 
                    count_new_connections += 1
                    
            # with new connections found, the new p:
            possible_p = ((len(connections_used) + count_new_connections) 
                            / total)
            
            # calculate the possible score
            score = formula(possible_p, trains_used + 1, total_minutes + 
                    traject.time)
            
            # when the score is indeed higher than before, add the track
            if score > current_score and trains_used != self.trains:
                trajecten[trains_used] = traject
                trains_used += 1
                total_minutes += traject.time
                for k in traject.connections:
                    if k.text() not in connections_used:
                        connections_used.append(k.text())
                        connections_used.append(changeDirection(k.text()))

            # otherwise the track won't be added and a the programs tries to 
            # find a better one  
            else:
                failed_attemps +=1
            
            # if, after 10 failed attemps, no track is found that improves 
            # the score we stop
            if failed_attemps == self.failed_attemps:
                break
        
        # final p and score
        p = len(connections_used) / total
        score = formula(p, trains_used, total_minutes)
        return trajecten, p, score, trains_used            
示例#5
0
    def run(self):
        """Returns a random solution for the problem"""

        # how many connections are there in total
        total = len(self.clist) / 2

        while True:
            # a dictionary filled with the tracks that are made
            trajecten = {}

            # a list which will be filled with the connections that are used
            connections_used = []

            # total minutes of all the tracks together
            total_minutes = 0

            # chooses a random amount of trains within the given boundries
            randtrains = random.randrange(self.trains)

            for i in range(0, randtrains):

                traject = Traject()

                # choose a random begin connection
                start = random.choice(self.clist)

                # add the connection to the current track
                traject.addConnection(self.connections[start],
                                      self.connections[start].time,
                                      self.timeframe)

                while True:
                    # new beginning point
                    new_origin = traject.connections[-1].destination

                    time_left = self.timeframe - traject.time

                    # possible connections from the current origin
                    options = optionsTime(new_origin, time_left,
                                          self.connections)

                    # add the possibility of not adding a connection

                    options.append(None)
                    new_connection = random.choice(options)

                    # choos a random connection and add this to the track, if there are any options available
                    if new_connection != None:
                        traject.addConnection(
                            self.connections[new_connection],
                            self.connections[new_connection].time,
                            self.timeframe)
                    else:
                        break

                # save the track
                trajecten[i] = traject

                # add the amount of minutes
                total_minutes += traject.time

                # for each connection used, add to list connection_used, if connection wasn't used before
                for k in traject.connections:
                    if k.text() not in connections_used and changeDirection(
                            k.text()) not in connections_used:
                        connections_used.append(k.text())

            # calculate p
            p = len(connections_used) / total

            # calculate score
            score = formula(p, randtrains, total_minutes)
            return trajecten, p, score, randtrains
示例#6
0
    def run(self):
        """Returns the tracks that are covered, p, score and amount of trais used"""

        # a list which will be filled with the connections that are used
        connections_used = []

        # a dictionary, with the key being the station and the value is the 
        # amount of connections of this station
        stationsvalues = {}

        # a dictionary filled with the tracks that are made
        trajecten = {}

        # total minutes of all the tracks together
        total_minutes = 0

        # amount of connections possible, used for calculating p
        total_connections = len(self.connections)/2
        
        # fills the stationsvalues dictionary
        for station in self.stations:
            con_values = len(self.stations[station])
            if station not in stationsvalues:
                stationsvalues[station] = []
            stationsvalues[station].append(con_values)     
        
        # sorts the stationvalues dictionary in ascending order
        sort_con = sorted(stationsvalues.items(), key=lambda kv: (kv[1], kv[0]))

        scorelist = {}
        
        for i in range(1, self.trains):
            traject = Traject()

            # searches for a station with the least connections and not used yet
            while True:
                try:
                    check = f"{sort_con[0][0]}-{self.stations[sort_con[0][0]][0][0]}"
                except:
                    check = 'not valid'
                    break
                # if the connection is used, drop this connection from the dictionary
                if check in connections_used or changeDirection(check) in connections_used:
                    sort_con.pop(0)

                # otherwise use this connection
                else:
                    break
            if check == 'not valid':
                break
            # add the connection to the track
            origin = sort_con[0][0]
            destination = self.stations[origin][0][0]
            traject.addConnection(self.connections[f"{origin}-{destination}"], self.stations[origin][0][1], self.timeframe)
            
            # append track of the used connections, so it won't be used a second time
            connections_used.append(f"{origin}-{destination}")

            # delete the connection from the sorted dictionary, so it wont be used a second time as a start connection
            sort_con.pop(0)  
        
            # after the first connection is found, finish the track
            while True:   
                # we pick the fastest connection
                new_connection = fastestConnection(self.connections, destination, origin)
                if new_connection != None:

                    # if the connection is already in the current track, stop the train
                    if self.connections[new_connection] in traject.connections:
                        break   

                    # otherwise add the connection to the current track      
                    traject.addConnection(self.connections[new_connection], self.connections[new_connection].time, self.timeframe)    
                    if new_connection not in connections_used:
                        connections_used.append(new_connection)

                # if there is no new connection stop the current track
                else: 
                    break
                
                # extracts destination and origin from the connection object
                destination = traject.connections[-1].destination
                origin = traject.connections[-1].origin

                # if the total time of the track is bigger than the allowed timeframe, stop the current track  
                if traject.time + self.connections[new_connection].time >= self.timeframe:
                    break 

            # update the total minutes
            total_minutes += traject.time

            # save track
            trajecten[i -1] = traject

            # save amount of trains used
            train_used = i + 1

            # calculate p
            p = (len(connections_used)-i)/total_connections

            # score after track is added
            score_i = formula(p, train_used, total_minutes)
            if i not in scorelist:
                scorelist[i] = []
            scorelist[i].append(score_i)

        train_used= max(scorelist.items(), key=operator.itemgetter(1))[0]
        score = max(scorelist.values())[0]
        return trajecten, p, score, train_used
示例#7
0
    def run(self):
        """Returns the tracks, p, score and trains that are used, found with the help of Kruskal"""

        # dictionary that will be filled with the tracks that are made
        trajecten = {}

        # total minutes of all the tracks together
        total_minutes = 0

        # amount of connections available
        total_connections = len(self.clist) / 2

        # a list which will be filled with the connections that are used in all tracks
        connections_used = []

        # the connection list sorted by time in ascending order
        graph = sorted(self.clist2, key=lambda item: item[2])

        for i in range(0, self.trains):
            # origin, destination, time
            u, v, w = graph[0]

            # create track object
            traject = Traject()

            # add first, with the least time, connection
            traject.addConnection(self.connections[f"{u}-{v}"], w,
                                  self.timeframe)

            connections_used.append(self.connections[f"{u}-{v}"])

            # remove from graph so it won't be used again
            graph.remove([u, v, w])
            graph.remove([v, u, w])

            while True:
                # build the track from first given connection
                new_origin = traject.connections[-1].destination
                previous_station = traject.connections[-1].origin

                # find options that are allowed to use
                options = findConnections(new_origin, previous_station,
                                          self.connections)
                useful_options = usefulConnections(new_origin, options,
                                                   connections_used,
                                                   traject.time,
                                                   self.timeframe,
                                                   self.connections)

                # with the found options, find shortest option
                new_connection = self.shortest(useful_options,
                                               self.connections)
                try:
                    time_new_connection = self.connections[new_connection].time
                except:
                    pass

                if new_connection != None:
                    # add connection to the current track
                    traject.addConnection(self.connections[new_connection],
                                          time_new_connection, self.timeframe)

                    # update the list of connections used for every new
                    # connection that had not been used before
                    if (new_connection not in connections_used
                            and changeDirection(new_connection)
                            not in connections_used):
                        connections_used.append(new_connection)

                    try:
                        # if newconnection is still in graph, remove this from
                        # graph
                        graph.remove([
                            new_origin, traject.connections[-1].destination,
                            int(time_new_connection)
                        ])
                        graph.remove([
                            traject.connections[-1].destination, new_origin,
                            int(time_new_connection)
                        ])
                    except:
                        pass
                else:
                    break

                # keep adding connections untill track is at the maximum of timeframe
                if traject.time + time_new_connection > self.timeframe:
                    break

            # update the situation
            graph = sorted(graph, key=lambda item: item[2])
            trajecten[i] = traject
            total_minutes += traject.time
            trains_used = i

        # calculate the score in the final situation
        p = (len(connections_used) - trains_used) / total_connections
        score = formula(p, self.trains, total_minutes)
        return trajecten, p, score, trains_used