text: # Azure Quantum Optimization Sample: Secret Santa
  # 
  # This sample walks through how to solve the Secret Santa problem using Azure Quantum. The scenario is defined as follows:
  # 
  # - Vincent, Tess, and Uma each write their name on a slip of paper and place the paper in a jar.
  # - Everybody then draws a slip of paper from the jar at random.
  # - Each person buys a small gift and writes a poem for the person whose name they have drawn.
  #   - If they draw their own name, they return the slip of paper and re-draw.
  # 
  # Note:
  # The inspiration for this scenario came from Vincent's blog post (found here: https://vincent.frl/quantum-secret-santa/),
  # which demonstrates how to use [Q# and the QDK](https://docs.microsoft.com/azure/quantum/overview-what-is-qsharp-and-qdk) to solve this scenario. In this sample, we will make use of the [Azure Quantum QIO service](https://docs.microsoft.com/azure/quantum/optimization-what-is-quantum-optimization) to solve the same problem.
  
  # Import required modules
  from typing import List
  from azure.quantum import Workspace
  from azure.quantum.optimization import Problem, ProblemType, Term, SimulatedAnnealing 
  
  # Helper function to build terms with indices i, j:
  def build_terms(i: int, j: int):
      """
      Construct Terms for a row or a column (two variables) of the Secret Santa matrix
  
      Arguments:
      i (int): index of first variable
      j (int): index of second variable
  
      """
      
      terms = []                                      # Initialize empty terms list
      terms.append(Term(c = 1.0, indices = [i, i]))   # x(i)^2
      terms.append(Term(c = 1.0, indices = [j, j]))   # x(j)^2
      terms.append(Term(c = 2.0, indices = [i, j]))   # 2x(i)x(j) 
      terms.append(Term(c = -2.0, indices = [i]))     # -2x(i)
      terms.append(Term(c = -2.0, indices = [j]))     # -2x(j)
      terms.append(Term(c = 1.0, indices = []))       # +1
  
      return terms
  
  # Helper function to interpret the answer returned by the service in a human-readable way:
  def print_results(config: dict) :
      """
      print results of run
  
      Arguements:
      config (dictionary): config returned from solver
      """
      result = {
                  '0': 'Vincent buys Tess a gift and writes her a poem.',
                  '1': 'Vincent buys Uma a gift and writes her a poem.',
                  '2': 'Tess buys Vincent a gift and writes him a poem.',
                  '3': 'Tess buys Uma a gift and writes her a poem.',
                  '4': 'Uma buys Vincent a gift and writes him a poem.',
                  '5': 'Uma buys Tess a gift and writes her a poem.'}
  
      for key, val in config.items():
          if val == 1:
              print(result[key])
  
  # Bringing it all together:
  # Sign into your Azure Quantum workspace
  # Copy the settings for your workspace below
  workspace = Workspace(
      subscription_id = "",
      resource_group = "",
      name = "",
      location = ""
  )
  
  """
  build secret santa matrix
  
          Vincent Tess Uma
  Vincent    -    x(0) x(1)
  Tess      x(2)   -   x(3)
  Uma	      x(4)  x(5)  -
  """
  
  #       row 0             + row 1             + row 2                
  terms = build_terms(0, 1) + build_terms(2, 3) + build_terms(4, 5)
  
  #             + col 0             + col 1             + col 2
  terms = terms + build_terms(2, 4) + build_terms(0, 5) + build_terms(1, 3)
  
  print(f'Terms: {terms}\n')
  
  problem = Problem(name = 'secret santa', problem_type = ProblemType.pubo, terms = terms)
  
  solver = SimulatedAnnealing(workspace, timeout = 2)
  
  print('Submitting problem to Azure Quantum')
  result = solver.optimize(problem)
  
  print(f'\n\nResult: {result}\n')
  
  print('Human-readable solution:')
  print_results(result['configuration'])