Spaces:
Sleeping
Sleeping
| # Quantum Agent-Task Optimization (QATO) Simulation | |
| # This script simulates how a quantum annealer would solve the optimal task | |
| # assignment problem for the "Society of Minds" architecture. | |
| # We use D-Wave's 'dimod' library, which provides tools for working with | |
| # QUBO (Quadratic Unconstrained Binary Optimization) models, the native | |
| # input format for quantum annealers. | |
| # You can install it via pip: pip install dimod numpy | |
| import numpy as np | |
| import dimod | |
| import time | |
| def create_society_of_minds(): | |
| """Defines the agents and their specialized roles for Phase I: The Town.""" | |
| # As per the spec, we create 30 agents with specialized roles. | |
| # To make it interesting, we'll create a few of each type. | |
| roles = { | |
| "Data_Analyst": 5, | |
| "Creative_Writer": 3, | |
| "Debugger": 4, | |
| "Network_Security_Specialist": 5, | |
| "System_Administrator": 4, | |
| "UX_Designer": 3, | |
| "Project_Manager": 2, | |
| "Hardware_Technician": 4 | |
| } | |
| agents = [] | |
| for role, count in roles.items(): | |
| for i in range(1, count + 1): | |
| agents.append(f"{role}_{i}") | |
| return agents | |
| def create_job_board(): | |
| """Defines the tasks and their required skills for the Task Marketplace.""" | |
| # Tasks are designed to map to the agent specializations. | |
| tasks = { | |
| "Analyze_Q3_Login_Anomalies": "Data_Analyst", | |
| "Draft_Internal_Security_Bulletin": "Creative_Writer", | |
| "Patch_Kernel_Vulnerability_CVE-2024-XXXX": "Debugger", | |
| "Configure_New_Firewall_Rules": "Network_Security_Specialist", | |
| "Migrate_Database_Server": "System_Administrator", | |
| "Design_New_Dashboard_Mockup": "UX_Designer", | |
| "Coordinate_Software_Release_v2.1": "Project_Manager", | |
| "Replace_Failing_RAID_Controller": "Hardware_Technician", | |
| "Identify_Phishing_Campaign_Patterns": "Data_Analyst", | |
| "Review_Code_For_Buffer_Overflows": "Debugger", | |
| "Audit_VPN_Access_Logs": "Network_Security_Specialist", | |
| "Write_User_Documentation_For_New_App": "Creative_Writer", | |
| } | |
| return tasks | |
| def calculate_suitability(agents, tasks): | |
| """ | |
| Creates a suitability matrix (S). | |
| S[i, j] is a score representing how suitable agent i is for task j. | |
| A higher score is better. | |
| """ | |
| num_agents = len(agents) | |
| num_task_keys = len(tasks.keys()) | |
| task_list = list(tasks.keys()) | |
| # Initialize a matrix of zeros | |
| suitability_matrix = np.zeros((num_agents, num_task_keys)) | |
| for i, agent_name in enumerate(agents): | |
| agent_role = agent_name.split('_')[0] | |
| for j, task_name in enumerate(task_list): | |
| required_role = tasks[task_name] | |
| if agent_role == required_role: | |
| # High suitability if the role matches perfectly | |
| suitability_matrix[i, j] = 10 | |
| else: | |
| # Low suitability otherwise | |
| suitability_matrix[i, j] = 1 | |
| return suitability_matrix | |
| def build_qubo(suitability_matrix): | |
| """ | |
| Constructs the QUBO model from the suitability matrix. | |
| The goal is to MAXIMIZE the total suitability score. Quantum annealers | |
| MINIMIZE, so we formulate the problem as minimizing the NEGATIVE of the score. | |
| """ | |
| num_agents, num_tasks = suitability_matrix.shape | |
| # Initialize the QUBO dictionary | |
| Q = {} | |
| # --- Objective Function --- | |
| # We want to maximize sum(S_ij * x_ij), where x_ij is a binary variable | |
| # that is 1 if agent i is assigned task j. | |
| # This is equivalent to minimizing sum(-S_ij * x_ij). | |
| # In QUBO, linear terms go on the diagonal. | |
| for i in range(num_agents): | |
| for j in range(num_tasks): | |
| # The variable is x_ij, which we can represent as a tuple (i, j) | |
| variable = (i, j) | |
| Q[(variable, variable)] = -suitability_matrix[i, j] | |
| # --- Constraints --- | |
| # We need to add penalties to ensure the solution is valid. | |
| # A large penalty term (gamma) ensures constraints are met. | |
| gamma = 20 # This value should be larger than any possible suitability score | |
| # Constraint 1: Each task must be assigned to exactly one agent. | |
| # For each task j, sum(x_ij for i in agents) == 1 | |
| # The penalty term for this is gamma * (sum(x_ij) - 1)^2 | |
| for j in range(num_tasks): | |
| for i in range(num_agents): | |
| # Linear part of the squared term | |
| var1 = (i, j) | |
| if (var1, var1) in Q: | |
| Q[(var1, var1)] += gamma * -2 | |
| else: | |
| Q[(var1, var1)] = gamma * -2 | |
| # Quadratic part of the squared term | |
| for k in range(i + 1, num_agents): | |
| var2 = (k, j) | |
| if (var1, var2) in Q: | |
| Q[(var1, var2)] += gamma * 2 | |
| else: | |
| Q[(var1, var2)] = gamma * 2 | |
| # Constraint 2: Each agent can be assigned at most one task. | |
| # For each agent i, sum(x_ij for j in tasks) <= 1 | |
| # The penalty term for this is gamma * (sum(x_ij) * (sum(x_ij) - 1)) | |
| # which simplifies to gamma * sum(x_ij * x_ik for j < k) | |
| for i in range(num_agents): | |
| for j in range(num_tasks): | |
| for k in range(j + 1, num_tasks): | |
| var1 = (i, j) | |
| var2 = (i, k) | |
| if (var1, var2) in Q: | |
| Q[(var1, var2)] += gamma * 2 | |
| else: | |
| Q[(var1, var2)] = gamma * 2 | |
| return Q | |
| def solve_and_interpret(qubo, agents, tasks, S): | |
| """Solves the QUBO using a simulated annealer and interprets the result.""" | |
| task_list = list(tasks.keys()) | |
| num_agents = len(agents) | |
| num_tasks = len(task_list) | |
| # Use dimod's classical solver that simulates the behavior of a quantum annealer | |
| sampler = dimod.SimulatedAnnealingSampler() | |
| # num_reads is like running the experiment multiple times to find the best result. | |
| # We've reduced this from 100 to 10 to significantly speed up the simulation. | |
| num_reads = 10 | |
| print(f"** Solving with {num_reads} reads... (this may take a moment) **") | |
| start_time = time.time() | |
| response = sampler.sample_qubo(qubo, num_reads=num_reads) | |
| end_time = time.time() | |
| print(f"** Solving complete in {end_time - start_time:.2f} seconds. **\n") | |
| # The best solution is the one with the lowest energy | |
| best_solution = response.first.sample | |
| print("--- Optimal Task Assignment Found ---") | |
| total_suitability = 0 | |
| assignments_found = 0 | |
| for i in range(num_agents): | |
| for j in range(num_tasks): | |
| if best_solution.get((i, j), 0) == 1: | |
| agent_name = agents[i] | |
| task_name = task_list[j] | |
| suitability_score = S[i, j] | |
| total_suitability += suitability_score | |
| print(f"Assign -> Agent: {agent_name:<30} | Task: {task_name:<40} | Suitability: {suitability_score:.0f}") | |
| assignments_found += 1 | |
| if assignments_found == 0: | |
| print("\n!! No valid assignments were found. The model may be too constrained or the penalty 'gamma' may need adjustment.") | |
| print("\n--- Total Suitability Score ---") | |
| print(f"The total score for this assignment is: {total_suitability:.0f}") | |
| # --- Main Execution --- | |
| if __name__ == "__main__": | |
| print("Initializing Project Chimera: Phase I (The Town)...") | |
| # 1. Create the agents and tasks | |
| agents = create_society_of_minds() | |
| tasks = create_job_board() | |
| print(f"Created {len(agents)} agents and {len(tasks)} tasks.\n") | |
| # 2. Define the problem by calculating suitability | |
| print("Calculating suitability matrix...") | |
| S = calculate_suitability(agents, tasks) | |
| # 3. Formulate the problem for the quantum computer (build the QUBO) | |
| print("Building QUBO model for quantum annealer...") | |
| qubo_model = build_qubo(S) | |
| # 4. Solve on the simulated quantum annealer and interpret the results | |
| print("Sending to simulated quantum annealer to find optimal assignment...\n") | |
| solve_and_interpret(qubo_model, agents, tasks, S) | |