Aracılığıyla paylaş


Belirli biçimlendirilmiş devreleri Azure Quantum'a gönderme

Azure Quantum hizmetine belirli biçimlerde bağlantı hatları göndermek için paketi kullanmayı azure-quantumPython öğrenin. Bu makalede bağlantı hatlarını aşağıdaki biçimlerde gönderme işlemi gösterilmektedir:

Daha fazla bilgi için bkz . Kuantum devreleri.

Not

Microsoft Quantum Geliştirme Seti (Klasik QDK) artık 30 Haziran 2024'e kadar desteklenmeyecektir. Mevcut bir QDK geliştiricisiyseniz kuantum çözümleri geliştirmeye devam etmek için yeni Azure Quantum Geliştirme Seti'ne (Modern QDK) geçmenizi öneririz. Daha fazla bilgi için bkz . Q# kodunuzu Modern QDK'ye geçirme.

Önkoşullar

Bağlantı hatlarınızı Azure portalındaki bir Not Defteri'nde çalıştırmak için şunları yapmanız gerekir:

  • Etkin aboneliği olan bir Azure hesabı. Azure hesabınız yoksa ücretsiz kaydolun ve kullandıkça öde aboneliğine kaydolun.
  • Azure Quantum çalışma alanı. Daha fazla bilgi için bkz . Azure Quantum çalışma alanı oluşturma.

Bağlantı hatlarınızı Visual Studio Code'da geliştirmek ve çalıştırmak için şunları da yapmanız gerekir:

  • Python ve Pip'in yüklü olduğu bir ortamPython.

  • Azure Quantum Geliştirme Seti, Pythonve Jupyter uzantılarının yüklü olduğu VS Code.

  • Azure Quantum qsharp, azure-quantumve ipykernel paketleri.

    python -m pip install --upgrade qsharp azure-quantum ipykernel
    

Yeni bir Jupyter Notebook oluşturma

VS Code'da veya doğrudan Azure Quantum portalında not defteri oluşturabilirsiniz.

  1. Azure portalında oturum açın ve önceki adımda çalışma alanını seçin.
  2. Sol dikey pencerede Not Defterleri'ni seçin.
  3. Not Defterlerim'e ve Yeni Ekle'ye tıklayın.
  4. Çekirdek Türü'nde I'yiPython seçin.
  5. Dosya için bir ad yazın ve Dosya oluştur'a tıklayın.

Yeni Not Defteriniz açıldığında, aboneliğinize ve çalışma alanı bilgilerinize göre ilk hücrenin kodunu otomatik olarak oluşturur.

from azure.quantum import Workspace
workspace = Workspace ( 
    resource_id = "", # Your resource_id 
    location = ""  # Your workspace location (for example, "westus") 
)

QIR biçimli bağlantı hatlarını gönderme

Kuantum Ara Gösterimi (QIR), kuantum programlama dilleri/çerçeveleri ile targeted kuantum hesaplama platformları arasında ortak bir arabirim görevi üstlenen bir ara temsildir. Daha fazla bilgi için bkz . Kuantum Ara Gösterimi.

  1. QIR bağlantı hattını oluşturun. Örneğin, aşağıdaki kod basit bir dolanıklık devresi oluşturur.

    QIR_routine = """%Result = type opaque
    %Qubit = type opaque
    
    define void @ENTRYPOINT__main() #0 {
      call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 0 to %Qubit*))
      call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
      call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
      call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
      call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 2 to %Qubit*))
      call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*))
      call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
      call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 3 to %Qubit*))
      call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 2 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
      call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 3 to %Qubit*), %Result* inttoptr (i64 1 to %Result*)) #1
      call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
      call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
      call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 1 to %Result*), i8* null)
      ret void
    }
    
    declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
    declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
    declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
    declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
    declare void @__quantum__qis__rx__body(double, %Qubit*)
    declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
    declare void @__quantum__qis__ry__body(double, %Qubit*)
    declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
    declare void @__quantum__qis__rz__body(double, %Qubit*)
    declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
    declare void @__quantum__qis__h__body(%Qubit*)
    declare void @__quantum__qis__s__body(%Qubit*)
    declare void @__quantum__qis__s__adj(%Qubit*)
    declare void @__quantum__qis__t__body(%Qubit*)
    declare void @__quantum__qis__t__adj(%Qubit*)
    declare void @__quantum__qis__x__body(%Qubit*)
    declare void @__quantum__qis__y__body(%Qubit*)
    declare void @__quantum__qis__z__body(%Qubit*)
    declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
    declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
    declare void @__quantum__rt__result_record_output(%Result*, i8*)
    declare void @__quantum__rt__array_record_output(i64, i8*)
    declare void @__quantum__rt__tuple_record_output(i64, i8*)
    
    attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="4" "required_num_results"="2" }
    attributes #1 = { "irreversible" }
    
    ; module flags
    
    !llvm.module.flags = !{!0, !1, !2, !3}
    
    !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}
    """
    
  2. QIR bağlantı hattını bir öğesine göndermek için bir submit_qir_jobtargetyardımcı işlevi oluşturun. Giriş ve çıkış veri biçimlerinin sırasıyla ve microsoft.quantum-results.v1olarak qir.v1 belirtildiğini unutmayın.

    # Submit the job with proper input and output data formats
    def submit_qir_job(target, input, name, count=100):
        job = target.submit(
            input_data=input, 
            input_data_format="qir.v1",
            output_data_format="microsoft.quantum-results.v1",
            name=name,
            input_params = {
                "entryPoint": "ENTRYPOINT__main",
                "arguments": [],
                "count": count
                }
        )
    
        print(f"Queued job: {job.id}")
        job.wait_until_completed()
        print(f"Job completed with state: {job.details.status}")
        #if job.details.status == "Succeeded":
        result = job.get_results()
    
        return result
    
  3. Bir target seçin ve QIR bağlantı hattını Azure Quantum'a gönderin. Örneğin, QIR bağlantı hattını IonQ simülatörüne targetgöndermek için:

    target = workspace.get_targets(name="ionq.simulator") 
    result = submit_qir_job(target, QIR_routine, "QIR routine")
    result
    
    {'Histogram': ['(0, 0)', 0.5, '(1, 1)', 0.5]}
    

Azure Quantum'a sağlayıcıya özgü biçime sahip bir bağlantı hattı gönderme

Q# veya Qiskit gibi QIR dillerinin yanı sıra, kuantum devrelerini sağlayıcıya özgü biçimlerde Azure Quantum'a gönderebilirsiniz. Her sağlayıcının kuantum devrelerini temsil etmek için kendi biçimi vardır.

JSON biçimini kullanarak IonQ'ya bağlantı hattı gönderme

  1. IonQ API belgelerinde açıklandığı gibi, IonQtargets tarafından desteklenen dilden bağımsız JSON biçimini kullanarak bir kuantum devresi oluşturun. Örneğin, aşağıdaki örnek üç kubit arasında bir süper konum oluşturur:

    circuit = {
        "qubits": 3,
        "circuit": [
            {
            "gate": "h",
            "target": 0
            },
            {
            "gate": "cnot",
            "control": 0,
            "target": 1
            },
            {
            "gate": "cnot",
            "control": 0,
            "target": 2
            },
        ]
    }
    
  2. Bağlantı hattını IonQ'ya targetgönderin. Aşağıdaki örnek, bir Job nesne döndüren IonQ simülatörünü kullanır.

    target = workspace.get_targets(name="ionq.simulator")
    job = target.submit(circuit)
    
  3. İş tamamlanana kadar bekleyin ve sonuçları getirin.

    results = job.get_results()
    print(results)
    
    .....
    {'duration': 8240356, 'histogram': {'0': 0.5, '7': 0.5}}
    
  4. Ardından Matplotlib kullanarak sonuçları görselleştirebilirsiniz.

    import pylab as pl
    pl.rcParams["font.size"] = 16
    hist = {format(n, "03b"): 0 for n in range(8)}
    hist.update({format(int(k), "03b"): v for k, v in results["histogram"].items()})
    pl.bar(hist.keys(), hist.values())
    pl.ylabel("Probabilities")
    

    IonQ iş çıkışı

  5. QPU'da bir işi çalıştırmadan önce çalıştırmanın maliyetini tahmin edebilirsiniz. QPU'da bir işi çalıştırmanın maliyetini tahmin etmek için yöntemini kullanabilirsiniz estimate_cost :

    target = workspace.get_targets(name="ionq.qpu")
    cost = target.estimate_cost(circuit, shots=500)
    
    print(f"Estimated cost: {cost.estimated_total}")
    

    Bu, tahmini maliyeti ABD doları cinsinden yazdırır.

    Not

    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.

Pulser SDK'sını kullanarak PASQAL'a bağlantı hattı gönderme

PASQAL'a bir bağlantı hattı göndermek için Pulser SDK'sını kullanarak darbe dizileri oluşturabilir ve bunları PASQAL target'e gönderebilirsiniz.

Pulser SDK'sını yükleme

Pulser , nötr atom kuantum cihazları için darbe dizilerini oluşturma, simülasyon ve yürütmeye yönelik bir çerçevedir. PASQAL tarafından kuantum işlemcilerine kuantum denemeleri göndermek için geçiş olarak tasarlanmıştır. Daha fazla bilgi için Pulser belgelerine bakın.

Darbe dizilerini göndermek için önce Pulser SDK paketlerini yükleyin:

try:
    import pulser
except ImportError:
    !pip -q install pulser
    !pip -q install pulser-core

Kuantum yazmaç oluşturma

  1. İlk olarak, gerekli içeri aktarmaları yükleyin:

    import numpy as np
    import pulser
    from pprint import pprint
    from pulser import Pulse, Sequence, Register
    
  2. PASQAL'in QPU's QPU bir kafeste iyi tanımlanmış konumlarda kapana kısılmış nötr atomlardan oluşur. Kuantum kayıtlarınızı tanımlamak için bir kafeste bir kubit dizisi oluşturursunuz. Örneğin, aşağıdaki kod kubitlerin 4x4 karelik bir kafesini oluşturur:

    L = 4
    square = np.array([[i, j] for i in range(L) for j in range(L)], dtype=float)
    square -= np.mean(square, axis=0)
    square *= 5
    
    qubits = dict(enumerate(square))
    reg = Register(qubits)
    reg.draw()
    

    16 kubitli 4x4 kare kafes çizimi.

Darbe dizisi yazma

Nötr atomlar lazer darbeleri ile kontrol edilir. Pulser SDK'sı, kuantum yazmacına uygulanacak darbe dizileri oluşturmanıza olanak tanır.

  1. İlk olarak, bir darbe dizisi ayarlamanız ve atomları denetlemek için kullanılacak kanalları bildirmeniz gerekir. Örneğin, aşağıdaki kod iki kanal bildirir: ch0 ve ch1.

    from pulser.devices import Chadoq2
    
    seq = Sequence(reg, Chadoq2)
    
    seq.declare_channel("ch0", "raman_local")
    print("Available channels after declaring 'ch0':")
    pprint(seq.available_channels)
    
    seq.declare_channel("ch1", "rydberg_local", initial_target=4)
    print("\nAvailable channels after declaring 'ch1':")
    pprint(seq.available_channels)
    

    Dikkate alınması gereken birkaç şey:

    • Pulser'da a Sequence , kuantum yazmacında yürütülecek bir dizi işlemdir.
    • Kod, bir AnalogDevice cihazda yürütülecek bir işlem dizisi ayarlar. AnalogDevice , Pulser'da Fresnel1 ile eşdeğer kuantum bilgisayarı temsil eden önceden tanımlanmış bir cihazdır.
  2. Bir darbe dizisi oluşturun. Bunu yapmak için, bildirdiğiniz kanallarda darbeler oluşturup eklersiniz. Örneğin, aşağıdaki kod basit bir darbe oluşturur ve bunu kanala ch0ekler ve ardından karmaşık bir darbe oluşturup kanala ch1ekler.

    seq.target(1, "ch0") # Target qubit 1 with channel "ch0"
    simple_pulse = Pulse.ConstantPulse(200, 2, -10, 0)
    seq.add(simple_pulse, "ch0") # Add the pulse to channel "ch0"
    seq.delay(100, "ch1")
    from pulser.waveforms import RampWaveform, BlackmanWaveform
    
    duration = 1000
    # Create a Blackman waveform with a duration of 1000 ns and an area of pi/2 rad
    amp_wf = BlackmanWaveform(duration, np.pi / 2)  
    # Create a ramp waveform with a duration of 1000 ns and a linear sweep from -20 to 20 rad/µs
    detuning_wf = RampWaveform(duration, -20, 20) 
    
    # Create a pulse with the amplitude waveform amp_wf, the detuning waveform detuning_wf, and a phase of 0 rad.
    complex_pulse = Pulse(amp_wf, detuning_wf, phase=0) 
    complex_pulse.draw()
    seq.add(complex_pulse, "ch1") # Add the pulse to channel "ch1"
    

Resimde basit ve karmaşık darbe gösterilmektedir.

Basit ve karmaşık darbenin çizimi.

Sırayı JSON dizesine dönüştürme

Darbe dizilerini göndermek için Pulser nesnelerini giriş verileri olarak kullanılabilecek bir JSON dizesine dönüştürmeniz gerekir.

import json

# Convert the sequence to a JSON string
def prepare_input_data(seq):
    input_data = {}
    input_data["sequence_builder"] = json.loads(seq.to_abstract_repr())
    to_send = json.dumps(input_data)
    #print(json.dumps(input_data, indent=4, sort_keys=True))
    return to_send

Darbe sırasını PASQAL'a gönderin target

  1. İlk olarak, uygun giriş ve çıkış veri biçimlerini ayarlamanız gerekir. Örneğin, aşağıdaki kod giriş veri biçimini olarak pasqal.pulser.v1 , çıkış veri biçimini ise olarak pasqal.pulser-results.v1ayarlar.

    # Submit the job with proper input and output data formats
    def submit_job(target, seq):
        job = target.submit(
            input_data=prepare_input_data(seq), # Take the JSON string previously defined as input data
            input_data_format="pasqal.pulser.v1", 
            output_data_format="pasqal.pulser-results.v1",
            name="PASQAL sequence",
            shots=100 # Number of shots
        )
    
        print(f"Queued job: {job.id}")
        job.wait_until_completed()
        print(f"Job completed with state: {job.details.status}")
        result = job.get_results()
    
        return result
    

    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. Çalışma alanınızın Sağlayıcılar dikey penceresini seçerek için target ortalama kuyruk süresini görüntüleyebilirsiniz.

  2. Programı PASQAL'a gönderin. Örneğin, programı PASQAL Emu-TN targetadresine gönderebilirsiniz.

    target = workspace.get_targets(name="pasqal.sim.emu-tn")
    submit_job(target, seq)
    
    {'0000000000000000': 59,
     '0000100000000000': 39,
     '0100000000000000': 1,
     '0100100000000000': 1}
    

OpenQASM kullanarak Quantinuum'a bağlantı hattı gönderme

  1. OpenQASM gösteriminde bir kuantum devresi oluşturun. Örneğin, aşağıdaki örnek bir ışınlama bağlantı hattı oluşturur:

    circuit = """OPENQASM 2.0;
    include "qelib1.inc";
    qreg q[3];
    creg c0[3];
    h q[0];
    cx q[0], q[1];
    cx q[1], q[2];
    measure q[0] -> c0[0];
    measure q[1] -> c0[1];
    measure q[2] -> c0[2];
    """
    

    İsteğe bağlı olarak, bağlantı hattını bir dosyadan yükleyebilirsiniz:

    with open("my_teleport.qasm", "r") as f:
        circuit = f.read()
    
  2. Bağlantı hattını Quantinuum'a targetgönderin. Aşağıdaki örnek, bir Job nesne döndüren Quantinuum API doğrulayıcısını kullanır.

    target = workspace.get_targets(name="quantinuum.sim.h1-1sc")
    job = target.submit(circuit, shots=500)
    
  3. İş tamamlanana kadar bekleyin ve sonuçları getirin.

    results = job.get_results()
    print(results)
    
    ........
    {'c0': ['000',
    '000',
    '000',
    '000',
    '000',
    '000',
    '000',
    ...
    ]}
    
  4. Ardından Matplotlib kullanarak sonuçları görselleştirebilirsiniz.

    import pylab as pl
    pl.hist(results["c0"])
    pl.ylabel("Counts")
    pl.xlabel("Bitstring")
    

    Quantinuum iş çıkışı

    Histograma baktığınızda, rastgele sayı oluşturucunun her seferinde 0 döndürdüğünü ve bunun çok rastgele olmadığını fark edebilirsiniz. Bunun nedeni, API Doğrulayıcı kodunuzun Quantinuum donanımında başarıyla çalışmasını sağlarken, her kuantum ölçümü için 0 değerini de döndürmesidir. Gerçek bir rastgele sayı oluşturucu için bağlantı hattınızı kuantum donanımında çalıştırmanız gerekir.

  5. QPU'da bir işi çalıştırmadan önce çalıştırmanın maliyetini tahmin edebilirsiniz. QPU'da bir işi çalıştırmanın maliyetini tahmin etmek için yöntemini kullanabilirsiniz estimate_cost .

    target = workspace.get_targets(name="quantinuum.qpu.h1-1")
    cost = target.estimate_cost(circuit, shots=500)
    
    print(f"Estimated cost: {cost.estimated_total}")
    

    Bu, H-System Quantum Kredilerinde (HQC) tahmini maliyeti yazdırır.

    Not

    Bir Quantinuum targetile maliyet tahmini çalıştırmak için önce [qiskit] parametresiyle azure-quantumPython paketini yeniden yüklemeniz ve Qiskit'in en son sürümüne sahip olduğunuzdan emin olmanız gerekir. Daha fazla bilgi için bkz . Azure-quantum Python paketini güncelleştirme.

    Not

    En güncel fiyatlandırma ayrıntıları için bkz . Azure Quantum fiyatlandırması veya çalışma alanınızı bulma ve fiyatlandırma seçeneklerini çalışma alanınızın "Sağlayıcı" sekmesinde görüntüleme yoluyla: aka.ms/aq/myworkspaces.

Quil kullanarak Rigetti'ye bağlantı hattı gönderme

Quil işlerini göndermenin en kolay yolu pyquil-for-azure-quantum paketini kullanmaktır. Bu paket pyQuil kitaplığının araçlarını ve belgelerini kullanmanıza olanak tanır. Bu paket olmadan pyQuil, Quil programları oluşturmak için kullanılabilir ancak bunları Azure Quantum'a göndermek için kullanılamaz.

Quil programlarını el ile de oluşturabilir ve doğrudan paketi kullanarak azure-quantum gönderebilirsiniz.

  1. İlk olarak, gerekli içeri aktarmaları yükleyin.

    from pyquil.gates import CNOT, MEASURE, H
    from pyquil.quil import Program
    from pyquil.quilbase import Declare
    from pyquil_for_azure_quantum import get_qpu, get_qvm
    
  2. get_qvm QVM veya QPU'ya bağlantı almak için or get_qpu işlevini kullanın.

    qc = get_qvm()  # For simulation
    # qc = get_qpu("Ankaa-2") for submitting to a QPU
    
  3. Quil programı oluşturun. Geçerli herhangi bir Quil programı kabul edilir, ancak okuma olarak adlandırılmalıdırro.

    program = Program(
        Declare("ro", "BIT", 2),
        H(0),
        CNOT(0, 1),
        MEASURE(0, ("ro", 0)),
        MEASURE(1, ("ro", 1)),
    ).wrap_in_numshots_loop(5)
    
    # Optionally pass to_native_gates=False to .compile() to skip the compilation stage
    
    result = qc.run(qc.compile(program))
    data_per_shot = result.readout_data["ro"]
    
  4. Burada, data_per_shot yöntemleri kullanabileceğiniz numpy bir numpy dizidir.

    assert data_per_shot.shape == (5, 2)
    ro_data_first_shot = data_per_shot[0]
    assert ro_data_first_shot[0] == 1 or ro_data_first_shot[0] == 0
    
  5. Tüm verileri yazdırın.

    print("Data from 'ro' register:")
    for i, shot in enumerate(data_per_shot):
        print(f"Shot {i}: {shot}")
    

Önemli

Tek bir işte birden çok bağlantı hattının gönderilmesi şu anda desteklenmemektedir. Geçici bir çözüm olarak, her bağlantı hattını zaman uyumsuz olarak göndermek için yöntemini çağırabilir backend.run ve ardından her işin sonuçlarını getirebilirsiniz. Örneğin:

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

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