Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fancier teleportation code #50

Open
rgobbel opened this issue Nov 23, 2022 · 0 comments
Open

Fancier teleportation code #50

rgobbel opened this issue Nov 23, 2022 · 0 comments

Comments

@rgobbel
Copy link

rgobbel commented Nov 23, 2022

This code is a bit messy, and I don't have time to do a proper cleanup on it, so I'm submitting it here in the hopes that someone can get some use out of it. I found the results of the sample code for Example 1-4 confusing, so I added some more code to make the output easier to understand. The Javascript version uses functions that might not be available in the context of a real quantum computer, so beware.

First the Javascript:

// Programming Quantum Computers
//   by Eric Johnston, Nic Harrigan and Mercedes Gimeno-Segovia
//   O'Reilly Media

// To run this online, go to http://oreilly-qc.github.io?p=4-1

// This sample demonstrates basic teleportation.

qc.reset(5);
qc.clearOutput();

function random_bit() {
    if (Math.random() < 0.5)
        return 0;
    else
        return 1;
}

var inPhase = 45

function random_phase() {
    if (Math.random() < 0.5)
        return inPhase;
    else
        return -inPhase;
}

function gen_payload()
{
    qc.label('gen payload');
    result = random_bit();
    qc.label('');
    qc.nop();
    return result;
}

var check = qint.new(1, 'check');
var signal = qint.new(1, 'signal');
var alice = qint.new(1, 'alice');
var ep    = qint.new(1, 'ep');
var bob   = qint.new(1, 'bob');
//var alice_out = 0;
//var ep_out = 0;
var b_in = 0;
var rphase = random_phase();

var payload = gen_payload();
signal.write(payload);
qc.print('payload='+payload+'\n');

// This will work with entangle() and alice_prep() in either order.
// Try swapping them to verify this.
entangle();
alice_prep(payload);
var [alice_out, ep_out] = alice_send();
//alice_out = outs[0];
//ep_out = outs[1];
qc.print('after send, a='+alice_out+', e='+ep_out+'\n');
bob_receive(alice_out, ep_out);
bob_verify(payload);

function entangle()
{
    // First, create an entangled pair
    qc.label('entangle');
    qc.write(0, ep.bits()|bob.bits());
    ep.had();
    bob.cnot(ep);
    qc.label('');
    qc.nop();
}


function alice_prep(pl)
{
    // Alice prepares her payload to teleport
    qc.label('prep payload');
    alice.write(pl);
    alice.had();
    qc.print('rphase='+rphase+'\n');
    alice.phase(rphase);
    alice.had();
    qc.print('ppa:'+alice.peekProbability().toFixed(2)+'\n');
    qc.label('');
    qc.nop();
}

function alice_send()
{
    // Alice sends the payload (and destroys it in the process)
    qc.label('send');
    ep.cnot(alice);
    alice.had();
    a_out = alice.read();
    e_out = ep.read();
    qc.print('in send, a='+a_out+', e='+e_out+'\n');
    qc.label('');
    qc.nop();
    return [a_out, e_out];
}

function bob_receive(a_val, ep_val)
{
    // Bob receives the payload, using the two bits Alice sent
    qc.label('receive');
    var bob_is_asleep = false;
    var use_conditonal_gates = true;

    // Option 1: Bob is asleep (can't respond to Alice's data), so he just does whatever.
    if (bob_is_asleep)
    {
        bob.not();
        bob.phase(180);
    }
    // // Option 2: Bob is responsive, and we use conditional-ops for visual clarity
    else if (use_conditonal_gates)
    {
        // Here, we use conditional gates, just for visual clarity.
        // The "conditions" are on qubits which have already been read and
        // turned into classical bits.
        bob.cnot(ep);
        bob.cz(alice);
    }
    // Option 3: Bob is responsive, and we use straightforward "if" in the code.
    else
    {
        if (ep_val)
            bob.not();
        if (a_val)
            bob.phase(180);
    }
    qc.print('ppb:'+bob.peekProbability().toFixed(2)+'\n');
    qc.label('');
    qc.nop();
}

function bob_verify(payload)
{
    // Verify that the teleportation worked
    qc.label('verify');
    bob.had();
    bob.phase(-rphase);
    bob.had();
    check.write(0);
    check.had();
    bob.exchange(signal, 0x1, check.bits());
    // bob.exchange(signal, 0x1);
    check.had();
    check.not();
    check_ok = check.read();
    //result = bob.read();
    // if (result == payload)
    if (check_ok == 1)
        qc.print('MATCH: ');
    else
        qc.print('MISMATCH: ');
    // qc.print('payload = '+payload+', result = '+result+', a_out = '+a_out+', e_out = '+e_out+' -> ('+check_ok+''+e_out+''+a_out+''+result+')\n');
    qc.print('a_out = '+a_out+', e_out = '+e_out+' -> ('+check_ok+''+e_out+''+a_out+')\n');
    qc.label('');
    qc.nop();
}

then the OpenQASM:

// Programming Quantum Computers
//   by Eric Johnston, Nic Harrigan and Mercedes Gimeno-Segovia
//   O'Reilly Media

// To run this on an actual quantum computer,
//    1. go to https://quantum-computing.ibm.com
//    2. Click "Switch to Qasm Editor" and paste in the code sample.

// To run the JS version in a browser, go to http://oreilly-qc.github.io?p=4-1

// This sample demonstrates basic teleportation (postselected).

include "qelib1.inc";
qreg check[1];
qreg signal[1]; // for checking: this register must match alice
qreg alice[1];
qreg ep[1];
qreg bob[1];
creg read_send[4];
creg results[1];

// Step 1: Create an entangled pair
h ep[0];
reset check[0];
cx ep[0], bob[0];
barrier check[0], signal[0], alice[0], ep[0], bob[0];

// Step 2: Prepare a payload
reset alice[0];
reset signal[0];
x alice[0];
x signal[0];
h alice[0];
t alice[0];
h alice[0];
barrier check[0], signal[0], alice[0], ep[0], bob[0];

// Step 3: Send
cx alice[0], ep[0];
h alice[0];
measure ep[0] -> read_send[1];
measure alice[0] -> read_send[0];
barrier alice[0], ep[0], bob[0];

// Step 4: Receive
cx ep[0], bob[0];
cz alice[0], bob[0];
barrier alice[0], ep[0], bob[0];

// Step 5: Verify
// correct results will have a 1 in the top bit,
// with the next two bits having the same value
h bob[0];
tdg bob[0];
h bob[0];
barrier check[0], signal[0], bob[0];
h check[0];
cswap check[0], signal[0], bob[0];
h check[0];
x check[0];
measure check[0] -> results[0];
barrier check[0], signal[0], bob[0];

// these two are optional, just for information, could be omitted
measure signal[0] -> read_send[2];
measure bob[0] -> read_send[3];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant