HitachiĀ¶
Hitachi Annealing Cloud WebĀ¶
The CMOS annealing machine provided by Hitachi.
- ć½ć«ćć¼ä»ę§:
Client class
API method
REST API (JSON)
API Reference
Binary variable
Ising variable
Integer variable
Real variable
Objective function
-
2nd
-
-
Equality constraint
-
-
-
-
Inequality constraint
-
-
-
-
Note
There are three types of machines that can be used, specified by
type
. (Defaultļ¼type
= 4)type
= 3: GPU 32bit (int)Can process 256k spins (equivalent to 512x512 Kingās graph) using GPGPU.
type
= 4: GPU 32bit (float)Can process 256k spins (equivalent to 512x512 Kingās graph) using GPGPU.
type
= 5: ASIC 4bitCan process 147,456 spins (equivalent to a 384x384 Kingās graph) in a single annealing.
Machines of
type
= 3, 5 can only handle models with integer coefficients. Refer to API Reference for the range of integer values for each type. Even if the objective function has only integer coefficients, the model submitted to the solver may contain real values because the Amplify SDK performs model conversion and graph embedding within theamplify.solve()
function. In such cases, Amplify SDK internally converts them to integers by rounding away from zero, which may result in a discrepancy from the intended formulation. When utilizing these machines, it is recommended to useamplify.HitachiClient.solve()
method directly. (See here).- Configuration example:
from amplify import HitachiClient client = HitachiClient() # Set API token client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # Set Number of annealing runs to 3 client.parameters.num_executions = 3 # Output average value per site of spin client.parameters.outputs.averaged_spins = True # Output the average value of energy client.parameters.outputs.averaged_energy = True
- Execution example:
from amplify import VariableGenerator, Model, solve # Create decision variables and the objective function g = VariableGenerator() s = g.array("Ising", 2) f = s[0] * s[1] + s[0] - s[1] + 1 # Create a model model = Model(f) # Run the solver result = solve(model, client)
Obtain the solver version:
>>> client.version 'v2'
Obtain detailed solution:
>>> result.client_result.result HitachiClient.Result.Result({ "execution_time": 185832138, "energies": [ -3.0, -3.0, -3.0 ], "spins": [ [[0, 0, -1], [1, 0, 1]], [[0, 0, -1], [1, 0, 1]], ... ], "averaged_energy": -3.0, "averaged_spins": [ [1, 0, 1], [0, 0, -1] ] })
Execute with client interfaceĀ¶
amplify.HitachiClient.solve()
method submits the problem directly to the solver using the solverās API and retrieves the results. This method is useful for problems that are optimized for the topology of the Hitachi CMOS Annealing Machine chip or for problems that are already embedded in the graphs.
The CMOS Annealing Machine API defines the Ising variables with coordinates \((x, y)\) on the Kingās graph. On the other hand, the Amplify SDK manages variables by ID (id
). Thus, in the amplify.HitachiClient
class, the mapping to the coordinates on Kingās graph is defined as id = x + y * graph_size
.
Using the graph_size
corresponding to the type
of the CMOS Annealing Machine, the variables satisfying this relationship can be output as follows.
from amplify import VariableGenerator, HitachiClient
client = HitachiClient()
client.parameters.type = 3
client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
graph_size = client.graph.shape[0] # Size of a side of the graph
g = VariableGenerator()
# Generate Ising variables on the King's graph of graph_size x graph_size
s = g.array("Ising", (graph_size, graph_size))
The array indices of the generated Ising variable array s
correspond to the coordinates on Kingās graph. For example, s[x, y]
represents the Ising variable at \((x, y)\) on the Kingās graph.
Then, an objective function Poly
must satisfy the following conditions.
Consists only of Ising variables of degree two or less.
Constraints are included in the objective function in advance as a penalty function.
The range of coefficient values is restricted depending on the machine type (see API Reference)
The indices of a quadratic term are adjacent to the two-dimensional array vertically, horizontally, or diagonally (adjacent on the Kingās graph).
The following is an example of an objective function that satisfies the above conditions.
f = s[0, 0] * s[0, 1] + 2 * s[0, 0] * s[1, 0] - s[0, 1] * s[1, 0] - s[1, 0] * s[1, 1] + 1
The solver response is returned when the created objective function is submitted with the amplify.HitachiClient.solve()
method.
>>> res = client.solve(f)
>>> res.result.energies
array([-5.])
>>> res.result.spins
[[(0, 0, 1), (1, 0, -1), (0, 1, -1), (1, 1, -1)]]
The solution \(s'\) for each Ising variable returned by the solver is stored in spins
in the form [[(x, y, s'), ...], ...]
, where s'
represents the value of the Ising variable at the coordinates \((x, y)\) on the Kingās graph. Note that no values are returned for variables that are not used in the objective function. Since multiple solutions may be returned, variable values are stored as a list of lists of tuples.
To obtain the solution of the Ising variable on the Kingās graph in the same array shape as the variable array s
, you can do the following.
import numpy as np
# Generate a zero array of graph_size x graph_size
spin_values = np.zeros((graph_size, graph_size))
# Enumerate and assign solutions with index 0
# (If multiple solutions are returned, an appropriate index should be specified)
for x, y, s in res.result.spins[0]:
spin_values[x, y] = s