Aracılığıyla paylaş


Qiskit ile Azure Quantum'a kuantum devresi göndermek

Microsoft Quantum Development Kit (QDK) ile Qiskit kuantum bağlantı hattı göndermeyi öğrenin. Visual Studio Code'da (VS Code) QDK ve Jupyter Notebook'u kullanarak Qiskit bağlantı hatlarını Azure Quantum'a gönderebilirsiniz. Ayrıca yerel seyrek simülatörü kullanarak devrelerinizi test edebilirsiniz. QDK, Qiskit'in 1. ve 2. sürümlerini destekler.

Daha fazla bilgi için bkz . Kuantum devreleri.

Önkoşullar

Yükleme ayrıntıları için bkz. QDK uzantısını ayarlama.

Yeni bir Jupyter Notebook oluşturma

  1. VS Code'da Görünüm menüsünü açın ve Komut Paleti'ni seçin.
  2. Oluştur: Yeni Jupyter Not Defteri'ni girin ve seçin.
  3. VS Code, defter için seçilen Python sürümünü ve sanal Python ortamını algılar ve görüntüler. Birden çok Python ortamınız varsa, sağ üstteki çekirdek seçiciyi kullanarak bir çekirdek seçmeniz gerekebilir. Ortam algılanmadıysa kurulum bilgileri için VS Code'da Jupyter Not Defterleri bölümüne bakın.

Gerekli içe aktarmaları yükleyin

Not defterinizin ilk hücresinde, gerekli içeri aktarmaları yüklemek için aşağıdaki kodu çalıştırın:

from qdk.azure import Workspace
from qdk.azure.qiskit import AzureQuantumProvider
from qiskit import QuantumCircuit
from qiskit.visualization import plot_histogram

Azure Quantum hizmetine bağlanma

Azure Quantum hizmetine bağlanmak için Azure Quantum çalışma alanınızın kaynak kimliğine ihtiyacınız vardır.

  1. Azure Portal’da oturum açın.
  2. Azure Quantum çalışma alanınızı seçin ve Genel Bakış'a gidin.
  3. Kaynak Kimliği parametresini kopyalayın.

Defterinize yeni bir hücre ekleyin ve Azure Quantum çalışma alanınıza bağlanmak için hesap bilgilerinizi kullanarak Workspace ve AzureQuantumProvider nesneleri oluşturun.

workspace = Workspace(resource_id="") # Add the resource ID of your workspace

provider = AzureQuantumProvider(workspace)

Tüm backendlere ait listeyi göster

Artık çalışma alanınızda kullanılabilen tüm kuantum bilgi işlem arka uçlarını yazdırabilirsiniz:

print("This workspace's targets:")
for backend in provider.backends():
    print("- " + backend.name)
This workspace's targets:
- ionq.simulator
- ionq.qpu.aria-1
- ionq.qpu.forte-1
- ionq.qpu.forte-enterprise-1
- quantinuum.sim.h2-1sc
- quantinuum.sim.h2-2sc
- quantinuum.sim.h2-1e
- quantinuum.sim.h2-2e
- quantinuum.qpu.h2-1
- quantinuum.qpu.h2-2
- rigetti.sim.qvm
- rigetti.qpu.ankaa-3
- rigetti.qpu.cepheus-1-36q

Basit bir devre çalıştır.

Yeni bir hücrede basit bir Qiskit bağlantı hattı oluşturun.

# Create a Quantum Circuit acting on the q register
circuit = QuantumCircuit(3, 3)
circuit.name = "Qiskit Sample - 3-qubit GHZ circuit"
circuit.h(0)
circuit.cx(0, 1)
circuit.cx(1, 2)
circuit.measure([0,1,2], [0, 1, 2])

# Print out the circuit
circuit.draw()
     ┌───┐          ┌─┐      
q_0: ┤ H ├──■───────┤M├──────
     └───┘┌─┴─┐     └╥┘┌─┐   
q_1: ─────┤ X ├──■───╫─┤M├───
          └───┘┌─┴─┐ ║ └╥┘┌─┐
q_2: ──────────┤ X ├─╫──╫─┤M├
               └───┘ ║  ║ └╥┘
c: 3/════════════════╩══╩══╩═
                     0  1  2 

Programınızı çalıştırmak için bir target seçin

IonQ simülatöründe çalıştırma

Devrenizi gerçek donanımda çalıştırmadan önce simülatörde bağlantı hattınızı test edin. get_backend kullanarak IonQ Simulator arka ucuna bağlanmak için bir Backend nesnesi oluşturun.

simulator_backend = provider.get_backend("ionq.simulator")

IonQ altyapısı, donanım üzerinde en iyi şekilde çalışacak şekilde derlenen tanımlı bir gateset'ten geçitleri destekler. Bağlantı hattınız bu listede olmayan geçitler içeriyorsa, Qiskit tarafından sağlanan işlevi kullanarak gateset desteklenene transpile dönüştürmeniz gerekir:

from qiskit import transpile
circuit = transpile(circuit, simulator_backend)

Dönüştürme işlevi, geçitlerin belirtilen arka uçta desteklenen kapılara ayrıştırıldığı yeni bir devre nesnesi döndürür.

Artık programı Azure Quantum hizmeti aracılığıyla çalıştırabilir ve sonucu alabilirsiniz. Aşağıdaki hücre, devreyi 100 atışla çalıştıran bir iş gönderir.

job = simulator_backend.run(circuit, shots=8)
job_id = job.id()
print("Job id", job_id)
Job id 00000000-0000-0000-0000-000000000000

İş tamamlanana kadar beklemek ve sonuçları döndürmek için şunu çalıştırın:

result = job.result()
print(result)
Result(backend_name='ionq.simulator', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=8, success=True, meas_level=2, data=ExperimentResultData(counts={'000': 4, '111': 4}, memory=['000', '000', '000', '000', '111', '111', '111', '111'], probabilities={'000': 0.5, '111': 0.5}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits=3, metadata={}), status=JobStatus.DONE, name='Qiskit Sample - 3-qubit GHZ circuit')], date=None, status=None, header=None, error_data=None)

Sonuç Qiskit paketine özgü bir nesne türü olduğundan, sonuçları görselleştirmek için result.get_counts ve plot_histogram kullanın. Tüm olası bit dizesi etiketlerini temsil etmek için etiketleri counts öğesine ekleyin.

counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
{'000': 4, '001': 0, '010': 0, '011': 0, '100': 0, '101': 0, '110': 0, '111': 4}

IonQ Simülatörü'nde Qiskit devresi sonucu

get_memory fonksiyonunu, iş ile ilişkili tekil çekim verilerini görüntülemek için de kullanabilirsiniz.

result.get_memory(circuit)
['000', '000', '000', '000', '111', '111', '111', '111']

Not

IonQ'da targetstek sayıda çekim içeren bir iş gönderirseniz, atış sayısı en yakın çift sayıya yuvarlanır. Örneğin, 9 çekim belirtirseniz sonuçlar 8 çekim için verileri görüntüler.

İş maliyetini tahmin

QPU'da bir işi çalıştırmadan önce bir işin maliyetini tahmin edin.

En güncel fiyatlandırma ayrıntıları için IonQ Fiyatlandırması'na bakın veya çalışma alanınızı bulun ve fiyatlandırma seçeneklerini çalışma alanınızın Sağlayıcı sekmesinde görüntüleyin: aka.ms/aq/myworkspaces.

IonQ QPU üzerinde çalıştırma

Gerçek donanıma (bir Kuantum İşlemci Birimi (QPU)) bağlanmak için, target"ionq.qpu.aria-1" adını get_backend yöntemine basitçe verin.

qpu_backend = provider.get_backend("ionq.qpu.aria-1")

** Azure Quantum'da çalıştırmak için devreyi gönderin, sonuçları alın ve ardından plot_histogram çalıştırarak sonuçları çizmek için çalıştırın.

Not

QPU'da bir bağlantı hattını çalıştırmak için gereken süre geçerli kuyruk sürelerine bağlıdır.

# Submit the circuit to run on Azure Quantum
job = qpu_backend.run(circuit, shots=100)
job_id = job.id()
print("Job id", job_id)

# Get the job results (this method waits for the Job to complete):
result = job.result()
print(result)
counts = {format(n, "03b"): 0 for n in range(8)}
counts.update(result.get_counts(circuit))
print(counts)
plot_histogram(counts)
Job id 00000000-0000-0000-0000-000000000000
Job Status: job has successfully run
Result(backend_name='ionq.qpu.aria-1', backend_version='1', qobj_id='Qiskit Sample - 3-qubit GHZ circuit', job_id='00000000-0000-0000-0000-000000000000', success=True, results=[ExperimentResult(shots=1024, success=True, meas_level=2, data=ExperimentResultData(counts={'0': 505, '1': 6, '2': 1, '3': 1, '4': 1, '5': 10, '6': 11, '7': 488}, probabilities={'0': 0.4932, '1': 0.0059, '2': 0.001, '3': 0.001, '4': 0.001, '5': 0.0098, '6': 0.0117, '7': 0.4766}), header=QobjExperimentHeader(name='Qiskit Sample - 3-qubit GHZ circuit', num_qubits='3', qiskit='True'))])
{'000': 505, '001': 6, '010': 1, '011': 1, '100': 1, '101': 10, '110': 11, '111': 488}

IonQ QPU üzerinde Qiskit devre sonucu

Önemli

Tek bir işte birden çok devre gönderemezsiniz. Geçici bir çözüm olarak, her devreyi zaman uyumsuz olarak göndermek için backend.run yöntemini çağırabilir ve ardından her işin sonuçlarını almak için sonuçları getirebilirsiniz. Örneğin:

jobs = []
for circuit in circuits:
    jobs.append(backend.run(circuit, shots=N))

results = []
for job in jobs:
    results.append(job.result())

Önkoşullar

Yükleme ayrıntıları için bkz. QDK uzantısını ayarlama.

Temel devre çalıştırma

VS Code'da, Python modülündeki yerleşik seyrek simülatörle temel bir devre oluşturmak ve çalıştırmak için yeni bir qsharp dosyası açın.

# load the required imports 
from qdk import qsharp
from qsharp.interop.qiskit import QSharpBackend
from qiskit.circuit.random import random_circuit

# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)

# run the circuit using the built-in sparse simulator
backend = QSharpBackend()
job = backend.run(circuit)
counts = job.result().get_counts()

print(counts)

Programı çalıştırmak için sağ üstteki Çalıştır simgesini ve ardından Dosyayı çalıştır'ı Python seçin. Çıkış yeni bir terminal penceresinde görüntülenir.

                  ┌─────────────────────────┐┌─┐
q_0: ─■───────────┤0                        ├┤M├───
      │P(0.79983) │  (XX-YY)(1.9337,1.7385) │└╥┘┌─┐
q_1: ─■───────────┤1                        ├─╫─┤M├
                  └─────────────────────────┘ ║ └╥┘
c: 2/═════════════════════════════════════════╩══╩═
                                              0  1
{'11': 680, '00': 344}

Devre için QIR üretme

Aynı bağlantı hattından, kuantum donanımında çalıştırmak için kullanılan QIR'yi oluşturabilirsiniz.

Not

QIR oluşturmak için tüm yazmaçların ölçülmesi gerekir. Kullanılmayan kayıt varsa bir hata oluşur. Ayrıca, bir profille QIR oluşturmayı denediğinizde bir Unrestrictedtarget hata mesajı alırsınız. Unrestricted profili yalnızca simülasyon için geçerlidir. , TargetProfile.Baseveya TargetProfile.Adaptive_RIkullanmanız TargetProfile.Adaptive_RIFgerekir. Profiller arasında geçiş yapmak için target_profile çağrısına backend.qir(...) kodunu geçersiz kılabilirsiniz.

  1. QSharpError ve TargetProfile içeri aktarma

    from qdk.qsharp import QSharpError, TargetProfile
    
  2. QIR oluşturmak için çıkışı değiştirin:

    print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))
    

Kodunuz şimdi şöyle görünmelidir:

# load the required imports 
from qdk import qsharp
from qsharp import QSharpError, TargetProfile
from qsharp.interop.qiskit import QSharpBackend
from qiskit.circuit.random import random_circuit

# define and display the circuit
circuit = random_circuit(2, 2, measure=True)
print(circuit)

# generate QIR for the circuit
print(backend.qir(circuit, target_profile=TargetProfile.Adaptive_RI))

Kodunuzun çıkışı şu şekilde görünmelidir:

     ┌────────────┐             ┌─┐   
q_0: ┤ Rx(2.7195) ├─■───────────┤M├───
     └──┬─────┬───┘ │U1(5.5924) └╥┘┌─┐
q_1: ───┤ Tdg ├─────■────────────╫─┤M├
        └─────┘                  ║ └╥┘
c: 2/════════════════════════════╩══╩═
                                 0  1
%Result = type opaque
%Qubit = type opaque

define void @ENTRYPOINT__main() #0 {
block_0:
  call void @__quantum__qis__rx__body(double 2.7194945105768586, %Qubit* inttoptr (i64 0 to %Qubit*))
  call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 0 to %Qubit*))
  call void @__quantum__qis__t__adj(%Qubit* inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__rz__body(double -2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__rz__body(double 2.796204066686262, %Qubit* inttoptr (i64 1 to %Qubit*))
  call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
  call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 1 to %Result*))
  call void @__quantum__rt__array_record_output(i64 2, i8* null)
  call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
  call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
  ret void
}

declare void @__quantum__qis__rx__body(double, %Qubit*)

declare void @__quantum__qis__rz__body(double, %Qubit*)

declare void @__quantum__qis__t__adj(%Qubit*)

declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)

declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1

declare void @__quantum__rt__array_record_output(i64, i8*)

declare void @__quantum__rt__result_record_output(%Result*, i8*)

attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="2" "required_num_results"="2" }
attributes #1 = { "irreversible" }

; module flags

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10}

!0 = !{i32 1, !"qir_major_version", i32 1}
!1 = !{i32 7, !"qir_minor_version", i32 0}
!2 = !{i32 1, !"dynamic_qubit_management", i1 false}
!3 = !{i32 1, !"dynamic_result_management", i1 false}
!4 = !{i32 1, !"classical_ints", i1 true}
!5 = !{i32 1, !"qubit_resetting", i1 true}
!6 = !{i32 1, !"classical_floats", i1 false}
!7 = !{i32 1, !"backwards_branching", i1 false}
!8 = !{i32 1, !"classical_fixed_points", i1 false}
!9 = !{i32 1, !"user_functions", i1 false}
!10 = !{i32 1, !"multiple_target_branching", i1 false}

Tüm programlar tüm donanımlarda çalıştırılamayabilir. Burada, target profilini Base denemeye çalışırsanız, programın desteklenmeyen bölümleri hakkında ayrıntılı hata mesajları alırsınız.

try:
    backend.qir(qc, target_profile=TargetProfile.Base)
except QSharpError as e:
    print(e)

Sonraki adımlar