Еквівалент "Hello World" у світі D-Wave - приклад 2D-шашки. У цьому прикладі вам надається наступний квадратний графік з 4 вузлами:
Давайте визначимо, що ми забарвлюємо вершину чорну, якщо σ i = - 1, а білу, якщо σ i = + 1 . Мета - створити шаблон шашки з чотирма вершинами на графіку. Існують різні способи визначення
h та J для досягнення цього результату. Перш за все, є два можливі рішення цієї проблеми:σiσi= - 1σi= + 1годJ
Квантовий відпалювач D-Wave мінімізує гамільтоніан Ізінга, який ми визначаємо, і важливо зрозуміти вплив різних параметрів з'єднувача. Розглянемо для прикладу з'єднувач :J0 , 1
Якщо встановити його на , гамільтоніан мінімізується, якщо обидва кубіти приймають однакове значення. Ми кажемо, що негативні сполучники співвідносяться . Якщо, якщо ми встановимо його J 0 , 1 = + 1 , гамільтоніан мінімізується, якщо два кубіти приймають протилежні значення. Таким чином, позитивні муфти антикорелюють .J0 , 1= - 1J0 , 1= + 1
У прикладі шашки ми хочемо антикорелювати кожну пару сусідніх кубітів, що породжує наступні гамільтоніани:
Н= σ0σ1+ σ0σ2+ σ1σ3+ σ2σ3
0σ0= - 1год0= 1
Н= σ0+ σ0σ1+ σ0σ2+ σ1σ3+ σ2σ3
Тож давайте зашифруємо це!
ПРИМІТКА. Вам потрібен доступ до хмарного сервісу D-Wave для роботи.
Перш за все, переконайтеся, що встановлено пакет dwave_sapi2
( https://cloud.dwavesys.com/qubist/downloads/ ) Python. Все буде Python 2.7, оскільки D-Wave на даний момент не підтримує жодної вищої версії Python. Як сказано, давайте імпортувати найголовніше:
from dwave_sapi2.core import solve_ising
from dwave_sapi2.embedding import find_embedding, embed_problem, unembed_answer
from dwave_sapi2.util import get_hardware_adjacency
from dwave_sapi2.remote import RemoteConnection
Для підключення до API D-Wave Solver вам знадобиться дійсний маркер API для їх розв'язувача SAPI, URL-адреса SAPI, і вам потрібно визначити, який квантовий процесор ви хочете використовувати:
DWAVE_SAPI_URL = 'https://cloud.dwavesys.com/sapi'
DWAVE_TOKEN = [your D-Wave API token]
DWAVE_SOLVER = 'DW_2000Q_VFYC_1'
Я рекомендую використовувати D-Wave 2000Q Virtual Full-Yield Chimera (VFYC), який є повністю функціональним чіпом без жодних мертвих кубітів! Ось макет чіпа Chimera:
У цей момент я розбиваю підручник на дві чіткі частини. У першому розділі ми вручаємо проблему вручну на графіку апаратних засобів Chimera, а у другому розділі ми використовуємо евристику вбудовування D-Wave для пошуку апаратного вбудовування.
Ручне вбудовування
Одинична комірка у верхньому лівому куті на макеті мікросхеми D-Wave 2000Q вище виглядає так:
010 → 01 → 42 → 73 → 3годJ
J = {(0,4): 1, (4,3): 1, (3,7): 1, (7,0): 1}
h = [-1,0,0,0,0,0,0,0,0]
год
connection = RemoteConnection(DWAVE_SAPI_URL, DWAVE_TOKEN)
solver = connection.get_solver(DWAVE_SOLVER)
Тепер ми можемо визначити кількість показань та вибрати answer_mode
«гістограму», яка вже сортує результати за кількістю подій для нас. Зараз ми готові вирішити екземпляр Ізінга за допомогою квантового відпалу D-Wave:
params = {"answer_mode": 'histogram', "num_reads": 10000}
results = solve_ising(solver, h, J, **params)
print results
Ви повинні отримати такий результат:
{
'timing': {
'total_real_time': 1655206,
'anneal_time_per_run': 20,
'post_processing_overhead_time': 13588,
'qpu_sampling_time': 1640000,
'readout_time_per_run': 123,
'qpu_delay_time_per_sample': 21,
'qpu_anneal_time_per_sample': 20,
'total_post_processing_time': 97081,
'qpu_programming_time': 8748,
'run_time_chip': 1640000,
'qpu_access_time': 1655206,
'qpu_readout_time_per_sample': 123
},
'energies': [-5.0],
'num_occurrences': [10000],
'solutions': [
[1, 3, 3, 1, -1, 3, 3, -1, {
lots of 3 's that I am omitting}]]}
energies
- 5,030 → 04 → 17 → 23 → 3[1,−1,−1,1]
Евристичне вбудовування
Jh
J = {(0,1): 1, (0,2): 1, (1,3): 1, (2,3): 1}
h = [-1,0,0,0]
Ми знову встановлюємо віддалене з'єднання і отримуємо розв'язувальний екземпляр D-Wave 2000Q VFYC:
connection = RemoteConnection(DWAVE_SAPI_URL, DWAVE_TOKEN)
solver = connection.get_solver(DWAVE_SOLVER)
Для того, щоб знайти вбудовування нашої проблеми, нам потрібно спочатку отримати матрицю суміжності поточного графіка обладнання:
adjacency = get_hardware_adjacency(solver)
Тепер спробуємо знайти вкладення нашої проблеми:
embedding = find_embedding(J.keys(), adjacency)
Якщо ви маєте справу з великими екземплярами Ising, ви, можливо, захочете шукати вбудовування в декількох потоках (паралельно на декількох процесорах), а потім виберіть вбудовування з найменшою довжиною ланцюга! Ланцюг , коли кілька кубітів змушені діяти як єдиний кубіт з метою підвищення ступеня зв'язності. Однак чим довше ланцюг, тим більше шансів на те, що він розірветься. А зламані ланцюги дають погані результати!
Зараз ми готові вкласти нашу проблему на графік:
[h, j0, jc, embeddings] = embed_problem(h, J, embedding, adjacency)
j0
jc
J
J = j0.copy()
J.update(jc)
Тепер ми готові вирішити вбудовану проблему:
params = {"answer_mode": 'histogram', "num_reads": 10000}
raw_results = solve_ising(solver, h, J, **params)
print 'Lowest energy found: {}'.format(raw_results['energies'])
print 'Number of occurences: {}'.format(raw_results['num_occurrences'])
raw_results
Чи не буде мати сенс для нас , якщо ми не unembed проблеми. У разі, якщо деякі ланцюги зламалися, ми фіксуємо їх більшістю голосів, як визначено необов'язковим аргументом broken_chains
:
unembedded_results = unembed_answer(raw_results['solutions'],
embedding, broken_chains='vote')
print 'Solution string: {}'.format(unembedded_results)
Якщо це запустити, ви повинні отримати правильний результат у всіх показаннях:
Lowest energy found: [-5.0]
Number of occurences: [10000]
Solution string: [[1, -1, -1, 1]]
Я сподіваюся, що це відповіло на ваше запитання, і я настійно рекомендую перевірити всі додаткові параметри, які ви можете передати solve_ising
функції, щоб поліпшити якість ваших рішень, таких як num_spin_reversal_transforms
або postprocess
.