-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
131 lines (106 loc) · 4.02 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import numpy as np
import numpy.ctypeslib as ctplib
from ctypes import c_float, c_int, cdll, POINTER
import time
class DA:
'''
Attributes:
qubo : np.ndarray
the qubo matrix in 2D
binary : np.ndarray
the initial spin in 1D
maxStep : int
the maximum steps for the algorithm
dim : int
the dimention of the spin array
time : float
the time spent on the last execution of the algorithm. default value 0 is set
'''
def __init__(
self,
qubo: np.ndarray = np.array([[0, 1], [1, 0]]),
binary: np.ndarray = None,
maxStep: int = 10000,
betaStart: float = 0.01,
betaStop: float = 100,
kernel_dim: tuple = (32*16,)
) -> None:
'''
Parameters:
qubo : np.ndarray
the qubo matrix in 2D. elements will be parsed to np.float32 which is equivalent to "float" in C. default qubo matrix [[0,1],[1,0]] is used.
binary : np.ndarray | None
the initial spin in 1D with values between {-1,1}. elements will be parsed to np.float32 which is equivalent to "float" in C. if none then a random initial spin is generated
maxStep : int
the maximum steps for the algorithm. default value 10,000 is used
betaStart : float
betaStop : float
time
energy
'''
self.qubo = qubo.astype(np.float32)
self.maxStep = maxStep
self.betaStart = betaStart
self.betaStop = betaStop
if np.shape(self.qubo)[0] != np.shape(self.qubo)[1]:
print("qubo is not a square matrix")
exit(-1)
self.dim = np.shape(self.qubo)[0]
if(binary is None):
self.binary = np.zeros(self.dim)
self.binary[-1] = 1
self.binary = self.binary.astype(np.int32)
else:
self.binary = binary.astype(np.int32)
if np.shape(self.qubo)[0] != np.shape(self.binary)[0]:
print("qubo dimention and binary dimention mismatch")
exit(-1)
self.time = 0
self.energy = 0
if len(kernel_dim) == 1:
if kernel_dim[0] == 0:
print(f"grid size cannot be 0. Using default grid size.")
kernel_dim[0] = 32*16
self.blocks = kernel_dim[0]
self.threads = self.dim//self.blocks + 1
print(f"grid size = {self.blocks} assigned.")
elif len(kernel_dim) == 2:
if any(kernel_dim) == 0:
print(f'grid size and block size cannot be 0. Using default grid size.')
kernel_dim[0] = 32*16
kernel_dim[1] = self.dim//kernel_dim[0] + 1
self.blocks = kernel_dim[0]
self.threads = kernel_dim[1]
print(
f"grid size {self.blocks} assigned, block size {self.threads} assigned.")
else:
print('kernel_dim has to be a tuple of length 2. Using default grid size.')
self.blocks = 32*16
self.threads = self.dim//self.blocks + 1
def run(self) -> None:
binary = ctplib.as_ctypes(self.binary)
qubo = ctplib.as_ctypes(self.qubo.flatten())
da = cdll.LoadLibrary("./lib/cudaDA.so")
main = da.digitalAnnealingPy
main.argtypes = [POINTER(c_int), POINTER(
c_float), c_int, c_int, c_float, c_float, c_int, c_int]
start = time.time()
main(binary, qubo, self.dim, self.maxStep, self.betaStart,
self.betaStop, self.blocks, self.threads)
end = time.time()
self.time = end-start
self.binary = ctplib.as_array(binary)
bin = np.expand_dims(self.binary, axis=1)
self.energy = (bin.T @ self.qubo @ bin)[0][0]
if __name__ == '__main__':
np.random.seed(1)
dim = 1
maxStep = 100
qubo = 2 * np.random.rand(dim, dim).astype(np.float32) - 1
qubo = (qubo + qubo.T) / 2
binary = np.ones(dim).astype(np.float32)
da = DA(qubo, maxStep=maxStep)
da.run()
print(da.time)
# print(da.binary)
print(da.energy)