Renmusxd / RustQIP

Quantum computing using rust. Efficient and a borrow-checked no cloning theorem!
https://docs.rs/qip/
MIT License
223 stars 18 forks source link

Examples PR 1: dense_coding, bell_inequalities, cswap #41

Open kris524 opened 2 years ago

kris524 commented 2 years ago

This is the first example with CSWAP. The new documentation was used (internally generated using cargo doc --open) and the layout of the old examples as well

Ive started working on the dense_coding as well. However, I am faced with difficulty in using the x, y, z methods inside the match statements. For example I get this in the last three statements:

mismatched types
      expected struct `Qudit`
found associated type `<CB as qip::builder_traits::CircuitBuilder>::Register
Renmusxd commented 2 years ago

The type error you are describing is because your signature looks like:

fn run_alice<P: Precision, CB: CircuitBuilder>(b: &mut LocalBuilder<P>, epr_alice: CB::Register, bit_a: bool, bit_b: bool) -> CB::Register {
    match (bit_a, bit_b) {
        (false, false) => epr_alice,
        (false, true) => b.x(epr_alice),
        (true, false) => b.z(epr_alice),
        (true, true) => b.y(epr_alice),
    }
}

So while it's taking a CB::Register for epr_alice, it's taking a LocalBuilder for the builder, it should look like:

fn run_alice<P: Precision, CB: CliffordTBuilder<P>>(b: &mut CB, epr_alice: CB::Register, bit_a: bool, bit_b: bool) -> CB::Register {
    match (bit_a, bit_b) {
        (false, false) => epr_alice,
        (false, true) => b.x(epr_alice),
        (true, false) => b.z(epr_alice),
        (true, true) => b.y(epr_alice),
    }
}
Renmusxd commented 2 years ago

Or of course you could lean into the LocalBuilder and ignore the generics:

fn run_alice<P: Precision>(b: &mut LocalBuilder<P>, epr_alice: Qudit, bit_a: bool, bit_b: bool) -> Qudit {
    match (bit_a, bit_b) {
        (false, false) => epr_alice,
        (false, true) => b.x(epr_alice),
        (true, false) => b.z(epr_alice),
        (true, true) => b.y(epr_alice),
    }
}
kris524 commented 2 years ago

Quick question, what would we use instead of the program! macro? It seems like it has been removed in the new version.

Renmusxd commented 2 years ago

program! should work - it lives in qip-macro now since it's a procedural macro rather than a macro_rules! one.

kris524 commented 2 years ago

OK, got it. Will take a closer look tonight

kris524 commented 2 years ago

Feel free to share any thoughts or feedback you have so far. I wanted to ask how does this program! macro work? Initially, I got my functions undetected, and when I clicked the empty main function to run, they got detected? I generally follow a pattern as the code is a bit difficult and want to get this done quickly, why do we use #[cfg(feature = "macros")] on each import and function?

Renmusxd commented 2 years ago

program! Is a procedural macro, which means it is a bit of code that gets compiled before the rest then included into the compiler itself. Basically it lets the programmer make something like a custom interpreter which translates plain text into rust before everything is fed into the normal compiler.

Documentation here

Renmusxd commented 2 years ago

That cfg thing you pointed out is a conditional compilation - basically it says "only try to compile this if the feature called 'macros' is enabled".

Documentation here

Renmusxd commented 2 years ago

I tried to run these examples and there are a large number of compiler errors:

cargo run --example bell_inequalities --all-features

Also to ensure people know to run with the macro feature, we should probably add a note to the main function for when its disabled: see inline comment

Renmusxd commented 1 year ago

While you are still working on these I'm going to convert them to drafts, let me know once they are ready for review.

kris524 commented 1 year ago

Hi, @Renmusxd could you have a look at my circuit3 (latest commit) and confirm if it has the right logic? I am not sure what I should return from those circuits functions.

Also, how can I get rid of this error help: a local variable with a similar name exists: 'r' ?

Renmusxd commented 1 year ago

I believe the circuit3 is doing the correct thing - the reason you're getting that error for circuit1 is because you are passing r to program! but there's no variable called r. There is however one called ra so you may have meant that.

kris524 commented 1 year ago

So I think I fixed some stuff, if you want run the example, but now I have a consistent error across all three circuits: ^ cannot use the ? operator in a function that returns &[f64] at the end of program! and help: a local variable with a similar name exists: r2 again inside program!

If you have any tips I can quickly fix this let me know, otherwise later I will dive deeper in the docs

Renmusxd commented 1 year ago

Pulling your most recent commits I am not seeing the errors you are mentioning, that being said those are certainly rust related and not RustQIP related, so RustQIP docs will not be helpful.

If you're not familiar with the ? operator I'd recommend reading the book: See the whole page but also specifically this section.

The second error you mentioned is just an undefined variable. I can improve the docs for program! to clarify things but it goes like this:

let res = program!(builder; r1, r2, r3, ...; exprs)

Where builder is an expression that evaluates to a mutable circuit builder (I will be more specific with type requirements in docs. And r1 through rN are expressions of type Builder::Register, they must pass ownership.

The error you are describing is likely because you wrote r when r was not defined up to that point, so r didn't have the correct type (or any type).