# Managing Optimizations and Solutions

Luna simplifies the process of creating, storing, and managing optimizations, allowing you to efficiently solve complex problems. By leveraging Luna's intuitive interface and powerful tools, you can seamlessly define optimization problems, execute them on classical, quantum, or hybrid hardware, and analyze the results. Additionally, Luna provides robust mechanisms for managing solutions, enabling you to store, visualize and refine them to achieve optimal outcomes. This streamlined approach enhances your workflow and ensures that you can focus on finding the best solutions for your problems.

Upon completing this tutorial, you will be able to:

- Define and Configure Optimization Problems in Luna.
- Effortlessly execute and manage solutions using a wide array of algorithms.

## Managing Optimizations

First, you'll need to upload an optimization problem to Luna. In this example, we'll use a simple optimization in the BQM format.

```
from luna_sdk.schemas.optimization_formats.bqm import BQMSchema
# Define your QUBO problem as a BQM
bqm_data = {
"linear": {"0": 4.0, "1": -2.0, "2": 6.0, "3": 2.0, "4": 5.0},
"quadratic": {("3", "2"): -6.0, ("4", "0"): -4.0},
"vartype": "BINARY"
}
bqm = BQMSchema(**bqm_data)
# Upload your BQM to LunaSolve
optimization = ls.optimization.create_from_bqm(name="My BQM", bqm=bqm)
```

Luna makes it easy to manage all your stored optimizations. You can retrieve, edit, and delete them.

```
# Retrieve an optimization
optimization = ls.optimization.get(optimization_id=optimization.id)
print(optimization)
```

Output:

```
quadratic:
('3', '2'): -6.0
('4', '0'): -4.0
linear:
2: 6.0
3: 2.0
0: 4.0
4: 5.0
1: -2.0
vartype: BQMVarType.BINARY
offset: 0.0
id: 664e1452acaf90d0a917a4e3
name: My BQM
created_date: 2024-05-22 17:50:42.070000
created_by: 66291cab401df553a5f5ccd6
modified_date: None
modified_by: None
use_case_name: None
params: None
```

```
# Retrieve all optimization available to you
ls.optimization.get_all()
```

```
from luna_sdk.schemas.enums.timeframe import TimeframeEnum
# If desired, you can specify a timeframe for when the optimizations were created
# Additionally, you can set a limit on the number of optimizations to be returned, which is set to 50 by default
ls.optimization.get_all(timeframe=TimeframeEnum.this_week, limit=10)
```

```
# Rename an optimization
updated_optimization = ls.optimization.rename(optimization_id=optimization.id, name="My Updated BQM")
print(updated_optimization)
```

Output:

```
id: 664e1452acaf90d0a917a4e3
name: My Updated BQM
created_date: 2024-05-22 17:50:42.070000
created_by: 66291cab401df553a5f5ccd6
modified_date: None
modified_by: 66291cab401df553a5f5ccd6
use_case_name: None
params: None
```

```
# Delete an optimization
ls.optimization.delete(optimization_id=optimization.id)
```

## Managing Solutions

First, you'll need to create a solution for an optimization via Luna. We'll use the same BQM from earlier and generate a simple solution using the Simulated Annealing algorithm.

```
# Define your QUBO problem as a BQM
bqm_data = {
"linear": {"0": 4.0, "1": -2.0, "2": 6.0, "3": 2.0, "4": 5.0},
"quadratic": {("3", "2"): -6.0, ("4", "0"): -4.0},
"vartype": "BINARY"
}
bqm = BQMSchema(**bqm_data)
# Upload your BQM to LunaSolve
optimization = ls.optimization.create_from_bqm(name="My BQM", bqm=bqm)
# Create a solution for the BQM using SA
job = ls.solution.create(
optimization_id=optimization.id,
solver_name="SA",
provider="dwave"
)
```

Similar to optimizations, Luna provides the same features for managing solutions. Users can easily print solution details, obtaining all necessary information for their problem. Luna provides two options for solution visualization. Using `print(solution)`

displays all problem solutions, `print(solution.head)`

highlights 5 solutions among all the availabe possibilities. If you only need to verify that the solution process was successful and don't require all solutions to be displayed, you can use `print(solution.head)`

. This will provide the necessary information about the solution object without displaying every single solution.

```
# Retrieve an optimization
solution = ls.solution.get(solution_id=job.id)
print(solution.head)
```

Output:

```
--------------------------------------------------------------------------------
META DATA:
--------------------------------------------------------------------------------
id: 664e1574ca894b28dc87b1e0
name: None
created_date: 2024-05-22 17:55:32.998000
created_by: 66291cab401df553a5f5ccd6
modified_date: 2024-05-22 17:55:33.116000
modified_by: None
error_message: None
params:
num_reads: None
num_sweeps: 1000
beta_range: None
beta_schedule_type: geometric
initial_states_generator: random
num_sweeps_per_beta: 1
seed: None
interrupt_function: None
beta_schedule: None
initial_states: None
randomize_order: False
proposal_acceptance_criteria: Metropolis
runtime:
total: 0.005857708998519229
overhead: None
qpu: None
sense: SenseEnum.MIN
provider: dwave
status: StatusEnum.DONE
optimization:
id: 664e1574ca894b28dc87b1df
name: My BQM
created_date: 2024-05-22 17:55:32.366000
created_by: 66291cab401df553a5f5ccd6
modified_date: None
modified_by: None
use_case_name: None
params: None
representation: None
--------------------------------------------------------------------------------
RESULTS:
--------------------------------------------------------------------------------
1 results found. Displaying first 5 results.
Result 1:
{'sample': {'0': 0.0, '1': 1.0, '2': 0.0, '3': 0.0, '4': 0.0}, 'obj_value': -2.0, 'feasible': True, 'constraints': {}}
--------------------------------------------------------------------------------
DWAVE META DATA:
--------------------------------------------------------------------------------
beta_range: [0.11552453009332421, 4.605170185988092]
beta_schedule_type: geometric
timing:
preprocessing_ns: 5021833
sampling_ns: 638458
postprocessing_ns: 189417
```

```
# Retrieve all solutions available to you
ls.solution.get_all()
```

```
# If desired, you can specify a timeframe for when the solutions were created
# Additionally, you can set a limit on the number of solutions to be returned, which is set to 50 by default
ls.solution.get_all(timeframe=TimeframeEnum.this_week, limit=10)
```

```
# Delete a solution
ls.solution.delete(solution_id=job.id)
```

Because some algorithms return multiple possible solutions, Luna allows you to retrieve only the best result from any created solutions.

```
ls.solution.get_best_result(solution)
```

When you create a solution through our use case library, Luna also offers the option to directly access the best result within the use case representation.

```
import networkx as nx
from luna_sdk.schemas import TravellingSalesmanProblem
# Create an empty graph using networkx
graph = nx.Graph()
# Define the cities we want to visit
cities = ['Berlin', 'Hamburg', 'Munich']
# Add the cities as nodes in our graph
graph.add_nodes_from(cities)
# Define the distances between each city
edges = [('Berlin', 'Hamburg', 289),
('Berlin', 'Munich', 586),
('Hamburg', 'Munich', 796)]
# Add the distances as the edges in our graph
graph.add_weighted_edges_from(edges)
# 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
tsp = TravellingSalesmanProblem(graph=graph_data)
# Create a TSP instance and retrieve the corresponding ID
optimization = ls.optimization.create_from_use_case(name="My TSP", use_case=tsp)
# Create a solution for the TSP using SA
job = ls.solution.create(
optimization_id=optimization.id,
solver_name="SA",
provider="dwave"
)
# Instead of retrieving the raw solution, get it in the format fitting for your problem formulation
use_case_solution = ls.solution.get_use_case_representation(job.id)
# Finally, get the best result directly in the use case representation
result = ls.solution.get_best_use_case_result(use_case_solution)
print(result)
```

Output:

```
representation=[['Hamburg'], ['Munich'], ['Berlin']] obj_value=-3111.0
```