diff --git a/TP_2_3/exo_1_2.py b/TP_2_3/exo_1_2.py new file mode 100644 index 0000000000000000000000000000000000000000..899cea1dd47051d4e49f5bed69f055e96fd44076 --- /dev/null +++ b/TP_2_3/exo_1_2.py @@ -0,0 +1,193 @@ +import random +import itertools + +class Robot: + def __init__(self, id, capacity): + self.id = id + self.capacity = capacity + + def __repr__(self): + return f"Robot({self.id})" + + +class Zone: + def __init__(self, id, dirt): + self.id = id + self.dirt = dirt + + def __repr__(self): + return f"Zone({self.id})" + +class TaskAllocation: + def __init__(self, robotliste, zoneliste): + self.robotliste = robotliste + self.zoneliste = zoneliste + # Création d'un dictionnaire d'utilités aléatoires pour chaque paire (robot, zone) + self.dictio = {(robot, zone): random.randint(1, 10) for robot, zone in itertools.product(robotliste, zoneliste)} + + def allocation(self, cuf): + # On garde votre structure mais on corrige le problème d'assignation + best_allocation = None + best_utility = float('-inf') # On commence avec une utilité très basse + + # On utilise une approche simplifiée pour générer des allocations + # On distribue les zones de manière cyclique avec différents points de départ + for start in range(len(self.robotliste)): + current_allocation = {robot: [] for robot in self.robotliste} + for i, zone in enumerate(self.zoneliste): + robot_index = (start + i) % len(self.robotliste) + current_allocation[self.robotliste[robot_index]].append(zone) + + utility = cuf.utility(current_allocation) + if best_allocation is None or utility > best_utility: + best_utility = utility + best_allocation = current_allocation + + return best_allocation + + def dummy_allocation(self, robotliste, zoneliste): + # On garde votre fonction exactement comme elle était + i = 0 + dico = {robot: [] for robot in robotliste} + for zone in zoneliste: + robot = robotliste[i % len(robotliste)] + dico[robot].append(zone) + i += 1 + return dico + + def calculate_cleaning_time(self, allocation): + # Nouvelle fonction pour calculer le temps de nettoyage + robot_times = [] + + for robot, zones in allocation.items(): + total_dirt = sum(zone.dirt for zone in zones) + cleaning_time = total_dirt / robot.capacity + robot_times.append(cleaning_time) + + # Le temps total est le maximum des temps individuels + return max(robot_times) if robot_times else 0 + + def getdictio(self): + return self.dictio + + +class CollectiveUtilityFunction: + def __init__(self, dico, utility): + # On garde votre nom de paramètre "utility" au lieu de "utility_type" + self.utility = getattr(self, utility) + self.dico = dico + + def utilitariste(self, allocation): + total_uti = 0 + for robot, zones in allocation.items(): + for zone in zones: + total_uti += self.dico[(robot, zone)] + return total_uti + + def egalitariste(self, allocation): + uti_par_robot = {} + for robot, zones in allocation.items(): + robot_utility = 0 + for zone in zones: + robot_utility += self.dico[(robot, zone)] + uti_par_robot[robot] = robot_utility + + # Si aucun robot n'a d'utilité, retourner 0 + if not uti_par_robot: + return 0 + + return min(uti_par_robot.values()) + + def elitiste(self, allocation): + uti_par_robot = {} + for robot, zones in allocation.items(): + robot_utility = 0 + for zone in zones: + robot_utility += self.dico[(robot, zone)] + uti_par_robot[robot] = robot_utility + + # Si aucun robot n'a d'utilité, retourner 0 + if not uti_par_robot: + return 0 + + return max(uti_par_robot.values()) + + def nash(self, allocation): + produit_uti = 1 + for robot, zones in allocation.items(): + robot_uti = 0 + for zone in zones: + robot_uti += self.dico[(robot, zone)] + + # Pour éviter de multiplier par 0 + if robot_uti > 0: + produit_uti *= robot_uti + + return produit_uti + + +# Test avec 3 robots et 6 zones +if __name__ == "__main__": + # Création des robots + robot1 = Robot("robot1", 10) + robot2 = Robot("robot2", 6) + robot3 = Robot("robot3", 4) + + # Création des zones + zone1 = Zone("zone1", 4) + zone2 = Zone("zone2", 6) + zone3 = Zone("zone3", 1) + zone4 = Zone("zone4", 5) + zone5 = Zone("zone5", 3) + zone6 = Zone("zone6", 2) + + robotliste = [robot1, robot2, robot3] + zoneliste = [zone1, zone2, zone3, zone4, zone5, zone6] + + # Création de l'allocation de tâches + task_allocation = TaskAllocation(robotliste, zoneliste) + + # Affichage du dictionnaire d'utilités + print("Dictionnaire d'utilités:") + for (robot, zone), utility in task_allocation.getdictio().items(): + print(f"{robot} - {zone}: {utility}") + + print("\n--- Allocation naïve (dummy) ---") + dummy_alloc = task_allocation.dummy_allocation(robotliste, zoneliste) + for robot, zones in dummy_alloc.items(): + print(f"{robot}: {zones}") + + print(f"Temps de nettoyage avec allocation naïve: {task_allocation.calculate_cleaning_time(dummy_alloc):.2f} heures") + + # Test des différentes fonctions d'utilité collective + print("\n--- Allocation avec fonction d'utilité utilitariste ---") + cuf_utilitariste = CollectiveUtilityFunction(task_allocation.getdictio(), "utilitariste") + alloc_utilitariste = task_allocation.allocation(cuf_utilitariste) + for robot, zones in alloc_utilitariste.items(): + print(f"{robot}: {zones}") + print(f"Utilité utilitariste: {cuf_utilitariste.utility(alloc_utilitariste)}") + print(f"Temps de nettoyage: {task_allocation.calculate_cleaning_time(alloc_utilitariste):.2f} heures") + + print("\n--- Allocation avec fonction d'utilité égalitariste ---") + cuf_egalitariste = CollectiveUtilityFunction(task_allocation.getdictio(), "egalitariste") + alloc_egalitariste = task_allocation.allocation(cuf_egalitariste) + for robot, zones in alloc_egalitariste.items(): + print(f"{robot}: {zones}") + print(f"Utilité égalitariste: {cuf_egalitariste.utility(alloc_egalitariste)}") + print(f"Temps de nettoyage: {task_allocation.calculate_cleaning_time(alloc_egalitariste):.2f} heures") + + print("\n--- Allocation avec fonction d'utilité élitiste ---") + cuf_elitiste = CollectiveUtilityFunction(task_allocation.getdictio(), "elitiste") + alloc_elitiste = task_allocation.allocation(cuf_elitiste) + for robot, zones in alloc_elitiste.items(): + print(f"{robot}: {zones}") + print(f"Utilité élitiste: {cuf_elitiste.utility(alloc_elitiste)}") + print(f"Temps de nettoyage: {task_allocation.calculate_cleaning_time(alloc_elitiste):.2f} heures") + + print("\n--- Allocation avec fonction d'utilité de Nash ---") + cuf_nash = CollectiveUtilityFunction(task_allocation.getdictio(), "nash") + alloc_nash = task_allocation.allocation(cuf_nash) + for robot, zones in alloc_nash.items(): + print(f"{robot}: {zones}") + print(f"Utilité de Nash: {cuf_nash.utility(alloc_nash)}") + print(f"Temps de nettoyage: {task_allocation.calculate_cleaning_time(alloc_nash):.2f} heures") \ No newline at end of file