Esercitazione: Inviare processi di ottimizzazione ad Azure Quantum

Nota

Si noti che i risolutori di ottimizzazione Microsoft QIO e 1QBit saranno deprecati e non saranno più disponibili nel servizio Azure Quantum dopo il 30 giugno 2023.

Questa esercitazione illustra come inviare processi di ottimizzazione ad Azure Quantum usando i notebook di portale di Azure, Python o Jupyter.

Ad esempio, questa esercitazione segue un'azienda di spedizione di esempio che presenta un problema aziendale difficile: bilanciamento dei carichi di navi contenitori in porto. Se si è interessati ai dettagli del problema, vedere l'esempio relativo al caricamento delle spedizioni.

Prerequisiti

Creare un nuovo notebook nell'area di lavoro

  1. Accedere alla portale di Azure e selezionare un'area di lavoro.
  2. A sinistra selezionare Notebook.
  3. Fare clic su Notebook personali e quindi su Aggiungi nuovo.
  4. In Kernel Type (Tipo di kernel) selezionare IPython.
  5. Digitare un nome per il file, ad esempio submit-optimization-job.ipynb e fare clic su Crea file.

Nota

È anche possibile caricare un Jupyter Notebook nell'area di lavoro Azure Quantum. Per altre informazioni, vedere Caricare notebook.

Quando viene aperto il nuovo notebook, crea automaticamente il codice per la prima cella, in base alle informazioni sulla sottoscrizione e sull'area di lavoro.

from azure.quantum import Workspace
workspace = Workspace (
    subscription_id = <your subscription ID>, 
    resource_group = <your resource group>,   
    name = <your workspace name>,          
    location = <your location>        
    )

Nota

Se non diversamente specificato, è necessario eseguire ogni cella in ordine durante la creazione per evitare problemi di compilazione.

Fare clic sull'icona triangolare "play" a sinistra della cella per eseguire il codice.

Creazione di un'istanza del problema

Per inviare un problema ad Azure Quantum, è prima di tutto necessario creare un'istanza di Problem. Si tratta di un oggetto Python che archivia tutte le informazioni necessarie, ad esempio i dettagli della funzione di costo e il tipo di problema da modellare.

Definire quindi una funzione che prende una matrice di pesi del contenitore e restituisce un oggetto Problem che rappresenta la funzione di costo. La funzione seguente generalizza la creazione di Term per qualsiasi numero di pesi usando alcuni cicli for. Prende un array di pesi e restituisce un oggetto Problem.

Selezionare + Codice e aggiungere il codice seguente alla cella:

from typing import List
from azure.quantum.optimization import Problem, ProblemType, Term

def create_problem_for_container_weights(container_weights: List[int]) -> Problem:
    terms: List[Term] = []

    # Expand the squared summation
    for i in range(len(container_weights)):
        for j in range(len(container_weights)):
            if i == j:
                # Skip the terms where i == j as they form constant terms in an Ising problem and can be disregarded:
                # w_i∗w_j∗x_i∗x_j = w_i​*w_j∗(x_i)^2 = w_i∗w_j​​
                # for x_i = x_j, x_i ∈ {1, -1}
                continue
            
            terms.append(
                Term(
                    c = container_weights[i] * container_weights[j],
                    indices = [i, j]
                )
            )

    # Return an Ising-type problem
    return Problem(name="Ship Sample Problem", problem_type=ProblemType.ising, terms=terms)

Aggiungere quindi una cella, definire l'elenco di contenitori e i relativi pesi e creare un'istanza di un problema:

# This array contains a list of the weights of the containers
container_weights = [1, 5, 9, 21, 35, 5, 3, 5, 10, 11]

# Create a problem for the list of containers:
problem = create_problem_for_container_weights(container_weights)

Inviare il processo ad Azure Quantum

Inviare ora il problema ad Azure Quantum:

from azure.quantum.optimization import ParallelTempering
import time

# Instantiate a solver to solve the problem. 
solver = ParallelTempering(workspace, timeout=100)

# Optimize the problem
print('Submitting problem...')
start = time.time()
result = solver.optimize(problem)
time_elapsed = time.time() - start
print(f'Result in {time_elapsed} seconds: ', result)

Nota

Questa guida usa il risolutore Parallel Tempering senza parametri con un timeout di 100 secondi come esempio di un risolutore di ottimizzazione quantum-inspired. Per altre informazioni sui risolutori disponibili, è possibile consultare la pagina della documentazione del provider di ottimizzazione quantum-inspired di Microsoft.

Si noti che il risolutore ha restituito i risultati sotto forma di dizionario Python, assieme ad alcuni metadati. Aggiungere una nuova cella con la funzione seguente per stampare un riepilogo più leggibile della soluzione:

def print_result_summary(result):
    # Print a summary of the result
    ship_a_weight = 0
    ship_b_weight = 0
    for container in result['configuration']:
        container_assignment = result['configuration'][container]
        container_weight = container_weights[int(container)]
        ship = ''
        if container_assignment == 1:
            ship = 'A'
            ship_a_weight += container_weight
        else:
            ship = 'B'
            ship_b_weight += container_weight

        print(f'Container {container} with weight {container_weight} was placed on Ship {ship}')

    print(f'\nTotal weights: \n\tShip A: {ship_a_weight} tonnes \n\tShip B: {ship_b_weight} tonnes\n')

print_result_summary(result)
Container 0 with weight 1 was placed on Ship A
Container 1 with weight 5 was placed on Ship B
Container 2 with weight 9 was placed on Ship A
Container 3 with weight 21 was placed on Ship A
Container 4 with weight 35 was placed on Ship B
Container 5 with weight 5 was placed on Ship B
Container 6 with weight 3 was placed on Ship B
Container 7 with weight 5 was placed on Ship B
Container 8 with weight 10 was placed on Ship A
Container 9 with weight 11 was placed on Ship A

Total weights: 
	Ship A: 52 tonnes 
	Ship B: 53 tonnes

Prerequisiti

Configurazione

Prima di tutto, è necessario creare un'istanza di un oggetto Workspace, che consente di connettersi all'area di lavoro distribuita in precedenza in Azure. Assicurarsi di immettere le impostazioni seguenti, che possono essere recuperate dal portale di Azure oppure aprendo un prompt dei comandi ed eseguendo az quantum workspace show tramite l'interfaccia della riga di comando di Azure. Aprire un nuovo file Python ed eseguire le righe seguenti:

from azure.quantum import Workspace

# Copy the following settings for your workspace
workspace = Workspace ( 
	subscription_id = "", # Add your subscription_id 
	resource_group = "", # Add your resource_group 
	name = "", # Add your workspace name 
	location = ""  # Add your workspace location (for example, "westus") 
)

Creazione di un'istanza del problema

Per inviare un problema ad Azure Quantum, è prima di tutto necessario creare un'istanza di Problem. Si tratta di un oggetto Python che archivia tutte le informazioni necessarie, ad esempio i dettagli della funzione di costo e il tipo di problema da modellare.

from typing import List
from azure.quantum.optimization import Problem, ProblemType, Term

def createProblemForContainerWeights(containerWeights: List[int]) -> Problem:
    terms: List[Term] = []

    # Expand the squared summation
    for i in range(len(containerWeights)):
        for j in range(len(containerWeights)):
            if i == j:
                # Skip the terms where i == j as they form constant terms in an Ising problem and can be disregarded.
                continue

            terms.append(
                Term(
                    c = containerWeights[i] * containerWeights[j],
                    indices = [i, j]
                )
            )

    # Return an Ising-type problem
    return Problem(name="Freight Balancing Problem", problem_type=ProblemType.ising, terms=terms)

Prima di inviare il problema ad Azure Quantum, ne viene creata un'istanza definendo un elenco di contenitori tramite i relativi pesi:

# This array contains the weights of all the containers
containerWeights = [1, 5, 9, 21, 35, 5, 3, 5, 10, 11]

# Create a problem for the given list of containers:
problem = createProblemForContainerWeights(containerWeights)

Inviare il processo ad Azure Quantum

Inviare ora il problema ad Azure Quantum:

from azure.quantum.optimization import ParallelTempering
import time

# Instantiate a solver to solve the problem.
solver = ParallelTempering(workspace, timeout=100)

# Optimize the problem
print('Submitting problem...')
start = time.time()
result = solver.optimize(problem)
timeElapsed = time.time() - start
print(f'Result in {timeElapsed} seconds: ', result)

Nota

Questa guida usa il risolutore Parallel Tempering senza parametri con un timeout di 100 secondi come esempio di un risolutore di ottimizzazione quantum-inspired. Per altre informazioni sui risolutori disponibili, è possibile consultare la pagina della documentazione del provider di ottimizzazione quantum-inspired di Microsoft.

Si noti che il risolutore ha restituito i risultati sotto forma di dizionario Python, assieme ad alcuni metadati. È possibile usare la funzione seguente per stampare un riepilogo più leggibile della soluzione:

def printResultSummary(result):
    # Print a summary of the result
    containerAWeight = 0
    containerBWeight = 0
    for chunk in result['configuration']:
        chunkAssignment = result['configuration'][chunk]
        chunkWeight = containerWeights[int(chunk)]
        container = ''
        if chunkAssignment == 1:
            container = 'A'
            containerAWeight += chunkWeight
        else:
            container = 'B'
            containerBWeight += chunkWeight

        print(f'Container {container} with weight {container_weight} was placed on Ship {ship}')

    print(f'\nTotal weights: \n\tShip A: {ship_a_weight} tonnes \n\tShip B: {ship_b_weight} tonnes\n')

print_result_summary(result)
Container 0 with weight 1 was placed on Ship A
Container 1 with weight 5 was placed on Ship B
Container 2 with weight 9 was placed on Ship A
Container 3 with weight 21 was placed on Ship A
Container 4 with weight 35 was placed on Ship B
Container 5 with weight 5 was placed on Ship B
Container 6 with weight 3 was placed on Ship B
Container 7 with weight 5 was placed on Ship B
Container 8 with weight 10 was placed on Ship A
Container 9 with weight 11 was placed on Ship A

Total weights: 
	Ship A: 52 tonnes 
	Ship B: 53 tonnes

Prerequisiti

Configurazione

  1. Eseguire jupyter notebook dal terminale scelto. Verrà avviato il server del notebook e verrà aperto Jupyter in un browser. Nella visualizzazione del browser selezionare il pulsante a discesa nell'angolo superiore destro e selezionare Python 3 dall'elenco per creare un nuovo notebook.
  2. Creare un'istanza di un oggetto Workspace, che consente di connettersi all'area di lavoro distribuita in precedenza in Azure. Assicurarsi di immettere le impostazioni seguenti, reperibili eseguendo az quantum workspace show.
# This allows you to connect to the Workspace you've previously deployed in Azure. 
from  azure.quantum  import  Workspace  

# Copy the settings for your workspace below  
workspace = Workspace ( 
	subscription_id = "", # Add your subscription_id 
	resource_group = "", # Add your resource_group 
	name = "", # Add your workspace name 
	location = ""  # Add your workspace location (for example, "westus") )

Creazione di un'istanza del problema

Per inviare un problema ad Azure Quantum, è prima di tutto necessario creare un'istanza di Problem. Si tratta di un oggetto Python che archivia tutte le informazioni necessarie, ad esempio i dettagli della funzione di costo e il tipo di problema da modellare.

Definire quindi una funzione che prende una matrice di pesi del contenitore e restituisce un oggetto Problem che rappresenta la funzione di costo. La funzione seguente generalizza la creazione di Term per qualsiasi numero di pesi usando alcuni cicli for. Prende un array di pesi e restituisce un oggetto Problem.

from typing import List
from azure.quantum.optimization import Problem, ProblemType, Term

def create_problem_for_container_weights(container_weights: List[int]) -> Problem:
    terms: List[Term] = []

    # Expand the squared summation
    for i in range(len(container_weights)):
        for j in range(len(container_weights)):
            if i == j:
                # Skip the terms where i == j as they form constant terms in an Ising problem and can be disregarded:
                # w_i∗w_j∗x_i∗x_j = w_i​*w_j∗(x_i)^2 = w_i∗w_j​​
                # for x_i = x_j, x_i ∈ {1, -1}
                continue
            
            terms.append(
                Term(
                    c = container_weights[i] * container_weights[j],
                    indices = [i, j]
                )
            )

    # Return an Ising-type problem
    return Problem(name="Ship Sample Problem", problem_type=ProblemType.ising, terms=terms)

Definire quindi l'elenco di contenitori e i relativi pesi e creare un'istanza di un problema:

# This array contains a list of the weights of the containers
container_weights = [1, 5, 9, 21, 35, 5, 3, 5, 10, 11]

# Create a problem for the list of containers:
problem = create_problem_for_container_weights(container_weights)

Inviare il processo ad Azure Quantum

Inviare ora il problema ad Azure Quantum:

from azure.quantum.optimization import ParallelTempering
import time

# Instantiate a solver to solve the problem. 
solver = ParallelTempering(workspace, timeout=100)

# Optimize the problem
print('Submitting problem...')
start = time.time()
result = solver.optimize(problem)
time_elapsed = time.time() - start
print(f'Result in {time_elapsed} seconds: ', result)

Nota

Questa guida usa il risolutore Parallel Tempering senza parametri con un timeout di 100 secondi come esempio di un risolutore di ottimizzazione quantum-inspired. Per altre informazioni sui risolutori disponibili, è possibile consultare la pagina della documentazione del provider di ottimizzazione quantum-inspired di Microsoft.

Si noti che il risolutore ha restituito i risultati sotto forma di dizionario Python, assieme ad alcuni metadati. È possibile usare la funzione seguente per stampare un riepilogo più leggibile della soluzione:

def print_result_summary(result):
    # Print a summary of the result
    ship_a_weight = 0
    ship_b_weight = 0
    for container in result['configuration']:
        container_assignment = result['configuration'][container]
        container_weight = container_weights[int(container)]
        ship = ''
        if container_assignment == 1:
            ship = 'A'
            ship_a_weight += container_weight
        else:
            ship = 'B'
            ship_b_weight += container_weight

        print(f'Container {container} with weight {container_weight} was placed on Ship {ship}')

    print(f'\nTotal weights: \n\tShip A: {ship_a_weight} tonnes \n\tShip B: {ship_b_weight} tonnes\n')

print_result_summary(result)
Container 0 with weight 1 was placed on Ship A
Container 1 with weight 5 was placed on Ship B
Container 2 with weight 9 was placed on Ship A
Container 3 with weight 21 was placed on Ship A
Container 4 with weight 35 was placed on Ship B
Container 5 with weight 5 was placed on Ship B
Container 6 with weight 3 was placed on Ship B
Container 7 with weight 5 was placed on Ship B
Container 8 with weight 10 was placed on Ship A
Container 9 with weight 11 was placed on Ship A

Total weights: 
	Ship A: 52 tonnes 
	Ship B: 53 tonnes

Passaggi successivi

Ora che si è in grado di inviare processi di Azure Quantum, continuare a esplorare l'ottimizzazione con gli articoli seguenti: