Transformation

How to create optimization problem instances

To start solving an optimization problem, the first step is to define which problem you want to solve in the first place. You have two different approaches how to formulate the problem: You can either choose an optimization problem from our library of Use Cases or directly provide your use case in a mathematical modeling format. At the moment, we only support QUBOs as predefined modeling formats, but other modeling languages will be included in future versions.

Access our use case library

We provide users with a built-in library of (currently) more than 40 different optimization problems which can be configured using human-readable data formats such as graphs or lists. These are then automatically transformed into appropriate mathematical representations for optimization algorithms and quantum hardware.

The list of currently available optimizations can be retrieved from our library of Use Cases. Here, you can also find detailed information on how to specify each problem formulation, i.e. which parameters you need to provide for each optimization problem and which format they should be in.

As an example, let's say you want to solve a Traveling Salesman Problem (TSP). From our use case library, you can find all information about the use case, including a description, a link to a detailed description of the mathematical model, and any parameters necessary to create a problem instance. Here, you will see that to create an instance of TSP, the only data you need to provide is a graph. This graph can either be a nested dictionary or can be created from networkx. We recommend the latter approach.

import networkx as nx

# Create an empty graph using networkx
graph = nx.Graph()

# Define the nodes of our TSP instance
nodes = ['A', 'B', 'C', 'D']

# Add the nodes to our graph
graph.add_nodes_from(nodes)

# Define the distances between each node
edges = [('A', 'B', 10),
         ('A', 'C', 9),
         ('A', 'D', 13),
         ('B', 'C', 6),
         ('B', 'D', 21),
         ('C', 'D', 15)]

# Add the distances as the edges in our graph
graph.add_weighted_edges_from(edges)

With this, we have defined our graph and provided all the necessary specifications. Now, let's send our graph to Luna and generate the TSP instance.

from luna_sdk.schemas import TravellingSalesmanProblem, UseCase
from luna_sdk.schemas.optimization import Optimization

# Convert the networkx graph to a digestible format for Luna
graph_data = nx.to_dict_of_dicts(graph)

# Define that we want to create a TSP with the corresponding graph data
use_case: UseCase = TravellingSalesmanProblem(graph=graph_data)

# Create a TSP instance and retrieve the corresponding ID
created_optimization: Optimization = luna.optimization.create_from_use_case(
  name="a name",
  use_case=use_case,
)

When creating an instance of an optimization problem, Luna will store this problem in your account's database. This way, you can access the instance for further calculations or revisit it at a later time.

Uploading custom optimization problems

We also offer the ability to solve instances of problem classes that are not included in our use case library. To achieve this, you can send the mathematical model of your optimization problem to Luna. Currently, only QUBOs are supported, but we plan to include other mathematical formats in future versions. QUBOs can be provided as nested lists of floats, and they have access to the same functionalities as optimization problems.

from luna_sdk.schemas.qubo import QUBO

qubo_matrix = [
    [4, 0, 0, 0, -2],
    [0, -2, 0, 0, 0],
    [0, 0, 6, -3, 0],
    [0, 0, -3, 2, 0],
    [-2, 0, 0, 0, 5]
]

# Create an Optimization from a QUBO Matrix
optimization = luna.optimization.create_from_qubo(
    name="a name to recognize the optimization", matrix=qubo_matrix
)

In a similar fashion to when creating an instance of an optimization problem, Luna will store this problem in your account's database. You can access the QUBO for further computations just as you would with instances created through the use case library.

Managing and accessing your optimization problems and solutions

All optimization problems created through Luna or uploaded to it will be stored in your account. You can always access a list of all IDs of the optimization problems you have created.

from luna_sdk.schemas.optimization import Optimization
from typing import List

# Maximum number of optimization problems to be returned
show_limit = 10

# Retrieve a list of your created optimization problem instances
all_optimization = luna.optimization.list(
    timeframe=TimeframeEnum.this_week,
    limit=10,
)

You can use this functionality for repeated access at a later point, allowing you to create multiple solutions and perform various operations. Additionally, you have the ability to access individual instances to retrieve more detailed information, such as the name of the instance, its creation timestamp, or the specific QUBO formulation.

from luna_sdk.schemas.optimization import Optimization

# Select an instance you want more details about
optimization_id = 'SOMEID'

# Get more information about the specific instance
optimization: Optimization = luna.optimization.get(optimization_id=optimization_id)

Furthermore, you have the option to rename the optimizations you have created:

# Rename a specific instance
renamed_optimization = luna.optimization.rename(
    optimization_id=optimization.id,
    name='New instance name'
)

You can always retrieve all existing solutions for any optimization:

from luna_sdk.schemas.solution import SolutionOut

# Retrieve all solutions for a specific instance
all_solutions = luna.optimization.get_solutions(
    optimization_id=optimization_id
)

Or, retrieve any specific solution for your optimization problems:

# Specify a solution ID to retrieve
solution_id = "SomeSolutionID"

# Retrieve one solutions for a specific instance
solution = luna.solution.get(
    solution_id=solution_id
)

Your solver's solution may contain multiple results, e.g., if you created the solution with one of DWave's annealing algoritms. If you're only interested in the best result, you can easily retrieve it with our pre-defined function:

from luna_sdk.schemas import Result

best_result: Result = luna.solution.retrieve_best_result(solution)

Finally, if you no longer need a specific optimization, you can delete it from your account.

Note: Deleting an optimization will also delete all solutions corresponding to that optimization.

# Delete a specific instance. Use with caution!
luna.optimization.delete(id=optimization_id)

Was this page helpful?