Coverage for src/braket/tasks/annealing_quantum_task_result.py : 100%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Copyright 2019-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"). You
4# may not use this file except in compliance with the License. A copy of
5# the License is located at
6#
7# http://aws.amazon.com/apache2.0/
8#
9# or in the "license" file accompanying this file. This file is
10# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11# ANY KIND, either express or implied. See the License for the specific
12# language governing permissions and limitations under the License.
14from __future__ import annotations
16import json
17from dataclasses import dataclass
18from typing import Any, Dict
20import numpy
23@dataclass
24class AnnealingQuantumTaskResult:
25 """
26 Result of an annealing problem quantum task execution. This class is intended
27 to be initialized by a QuantumTask class.
29 Args:
30 record_array (numpy.recarray): numpy array with keys 'solution' (numpy.ndarray)
31 where row is solution, column is value of the variable, 'solution_count' (numpy.ndarray)
32 the number of times the solutions occurred, and 'value' (numpy.ndarray) the
33 output or energy of the solutions.
34 variable_count (int): the number of variables
35 problem_type (str): the type of problem ('ising' or 'qubo')
36 task_metadata (Dict[str, Any]): Dictionary of task metadata.
37 additional_metadata (Dict[str, Any]): A dictionary of additional device-specific metadata
38 """
40 record_array: numpy.recarray
41 variable_count: int
42 problem_type: str
43 task_metadata: Dict[str, Any]
44 additional_metadata: Dict[str, Any]
46 def data(self, selected_fields=None, sorted_by="value", reverse=False):
47 """
48 Iterate over the data in record_array
50 Args:
51 selected_fields (List[str], optional, default=None): selected fields to return.
52 Options are 'solution', 'value', and 'solution_count'
53 sorted_by (str, optional, default='value'): Sorts the data by this field.
54 Options are 'solution', 'value', and 'solution_count'
55 reverse (bool, optional, default=False): If True, returns the data in reverse order.
57 Yields:
58 tuple: data in record_array
59 """
60 if selected_fields is None:
61 selected_fields = ["solution", "value", "solution_count"]
63 if sorted_by is None:
64 order = numpy.arange(len(self.record_array))
65 else:
66 order = numpy.argsort(self.record_array[sorted_by])
68 if reverse:
69 order = numpy.flip(order)
71 for i in order:
72 yield tuple(self.record_array[field][i] for field in selected_fields)
74 def __eq__(self, other) -> bool:
75 if isinstance(other, AnnealingQuantumTaskResult):
76 # __eq__ on numpy arrays results in an array of booleans and therefore can't use
77 # the default dataclass __eq__ implementation. Override equals to check if all
78 # elements in the array are equal.
79 self_fields = (
80 self.variable_count,
81 self.problem_type,
82 self.task_metadata,
83 self.additional_metadata,
84 )
85 other_fields = (
86 other.variable_count,
87 other.problem_type,
88 other.task_metadata,
89 other.additional_metadata,
90 )
91 return (self.record_array == other.record_array).all() and self_fields == other_fields
92 return NotImplemented
94 @staticmethod
95 def from_dict(result: Dict[str, Any]):
96 """
97 Create AnnealingQuantumTaskResult from dict
99 Args:
100 result (Dict[str, Any]): Results dict with AnnealingQuantumTaskResult attributes as keys
102 Returns:
103 AnnealingQuantumTaskResult: An AnnealingQuantumTaskResult based on the given dict
104 """
105 return AnnealingQuantumTaskResult._from_dict_internal(result)
107 @staticmethod
108 def from_string(result: str) -> AnnealingQuantumTaskResult:
109 """
110 Create AnnealingQuantumTaskResult from string
112 Args:
113 result (str): JSON object string
115 Returns:
116 AnnealingQuantumTaskResult: An AnnealingQuantumTaskResult based on the given string
117 """
118 return AnnealingQuantumTaskResult._from_dict_internal(json.loads(result))
120 @classmethod
121 def _from_dict_internal(cls, result: Dict[str, Any]):
122 solutions = numpy.asarray(result["Solutions"], dtype=int)
123 values = numpy.asarray(result["Values"], dtype=float)
124 if result["SolutionCounts"] is None:
125 solution_counts = numpy.ones(len(solutions), dtype=int)
126 else:
127 solution_counts = numpy.asarray(result["SolutionCounts"], dtype=int)
128 record_array = AnnealingQuantumTaskResult._create_record_array(
129 solutions, solution_counts, values
130 )
131 variable_count = result["VariableCount"]
132 problem_type = result["ProblemType"]
133 task_metadata = result["TaskMetadata"]
134 additional_metadata = {}
135 for key in result.keys():
136 if key.endswith("Metadata") and key != "TaskMetadata":
137 additional_metadata[key] = result[key]
138 return cls(
139 record_array=record_array,
140 variable_count=variable_count,
141 problem_type=problem_type,
142 task_metadata=task_metadata,
143 additional_metadata=additional_metadata,
144 )
146 @staticmethod
147 def _create_record_array(
148 solutions: numpy.ndarray, solution_counts: numpy.ndarray, values: numpy.ndarray
149 ) -> numpy.recarray:
150 """
151 Create a solutions record for AnnealingQuantumTaskResult
153 Args:
154 solutions (numpy.ndarray): row is solution, column is value of the variable
155 solution_counts (numpy.ndarray): list of number of times the solutions occurred
156 values (numpy.ndarray): list of the output or energy of the solutions
157 """
158 num_solutions, variable_count = solutions.shape
159 datatypes = [
160 ("solution", solutions.dtype, (variable_count,)),
161 ("value", values.dtype),
162 ("solution_count", solution_counts.dtype),
163 ]
165 record = numpy.rec.array(numpy.zeros(num_solutions, dtype=datatypes))
166 record["solution"] = solutions
167 record["value"] = values
168 record["solution_count"] = solution_counts
169 return record