This repository has been archived on 2023-07-05. You can view files and clone it, but cannot push or open issues/pull-requests.
notes/Machine Tips (Quantum)/Resources/Code & Circuit Operations/Languages/Python Libraries/Xanadu/Blackbird.md

142 lines
5.6 KiB
Markdown
Raw Normal View History

2023-07-01 00:31:53 +00:00
[The Blackbird Programming language](https://strawberryfields.ai/photonics/demos/run_blackbird.html#blackbird) is an assembly language invented by Canadian quantum computing company Xanadu for photonic computing. It is a separate language itself but can also exist as a separate python package. Here we will go directly into the main language.For the python implementation visit here.
- [Here](https://pennylane.xanadu.ai/lab) is a helpful python notebook of all the PennyLane & Borealis files.
It is modeled after [ProjectQ](https://projectq.ch/) an open source quantum computing software. A really great tutorial can be found [here.](https://github.com/ProjectQ-Framework/FermiLib/blob/master/examples/fermilib_demo.ipynb)
---
## Working with Blackbird Scripts
When submitting quantum programs to be executed remotely, they are communicated to the cloud platform using Blackbird—a quantum photonic assembly language. Strawberry Fields also supports exporting programs directly as Blackbird scripts (an `xbb` file); Blackbird scripts can then be submitted to be executed via the [Xanadu Cloud Client](https://xanadu-cloud-client.readthedocs.io/).
For example, lets consider a Blackbird script `program.xbb` representing the same quantum program we constructed above:
```
name remote_job1
version 1.0
target X8_01 (shots = 20)
complex array U[4, 4] =
-0.2075958002056761-0.1295303874004949j, 0.4168590195887626+0.585773678107707j, 0.2890475539846776-0.3529463027479843j, 0.213901659507021+0.411521709357663j
-0.2618964139102731+0.4432947111670047j, -0.5184820552871022+0.1650915362584557j, -0.4128306651379415-0.4882838386727423j, -0.0079437590004708+0.172938838723708j
0.1415402337953751+0.5501271526107689j, 0.3692746956219556+0.0108433797647406j, 0.1986531501150634-0.1359201690880894j, -0.6937372152789114-0.0404525424120204j
-0.5917850330700981-0.0462912812620793j, 0.1868543708455093-0.1249918525715507j, -0.322811013686639+0.4699849324731709j, -0.2704622309566428+0.4459455876188795j
# Initial states are two-mode squeezed states
S2gate(1.0, 0.0) | [0, 4]
S2gate(1.0, 0.0) | [1, 5]
S2gate(1.0, 0.0) | [3, 7]
# Apply the unitary matrix above to
# the first pair of modes, as well
# as a beamsplitter
Interferometer(U) | [0, 1, 2, 3]
BSgate(0.543, 0.123) | [2, 0]
Rgate(0.453) | 1
MZgate(0.65, -0.54) | [2, 3]
# Duplicate the above unitary for
# the second pair of modes
Interferometer(U) | [4, 5, 6, 7]
BSgate(0.543, 0.123) | [6, 4]
Rgate(0.453) | 5
MZgate(0.65, -0.54) | [6, 7]
# Perform a PNR measurement in the Fock basis
MeasureFock() | [0, 1, 2, 3, 4, 5, 6, 7]
```
in:
```
$ xcc job submit --name "remote_job1" --target "X8_01" --circuit "$(cat program1.xbb)"
```
out:
```
{
"id": "743bad0a-8a21-4a6b-86de-50f7ff35a9b3",
"name": "remote_job1",
"status": "open",
"target": "X8_01",
"language": "blackbird:1.0",
"created_at": "2021-11-16 21:15:50.257162+00:00",
"finished_at": null,
"running_time": null,
"metadata": {}
}
```
After executing the above command, the result will be accessible via its unique ID:
```
$ xcc job get 743bad0a-8a21-4a6b-86de-50f7ff35a9b3 --result
```
![[Pasted image 20221218205543.png]]
---
#### Shots
The `shots` argument is an integer that defines how many times the circuit should be evaluated (or “sampled”) to estimate statistical quantities. On some supported simulator devices, `shots=None` computes measurement statistics _exactly_.
Note that this argument can be temporarily overwritten when a QNode is called. For example, `my_qnode(shots=3)` will temporarily evaluate `my_qnode` using three shots.
It is sometimes useful to retrieve the result of a computation for different shot numbers without evaluating a QNode several times (“shot batching”). Batches of shots can be specified by passing a list of integers, allowing measurement statistics to be course-grained with a single QNode evaluation.
Consider:
```
>>> shots_list = [5, 10, 1000]
>>> dev = qml.device("default.qubit", wires=2, shots=shots_list)
```
When QNodes are executed on this device, a single execution of 1015 shots will be submitted. However, three sets of measurement statistics will be returned; using the first 5 shots, second set of 10 shots, and final 1000 shots, separately.
For example:
```
@qml.qnode(dev)
def circuit(x):
qml.RX(x, wires=0)
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0) @ qml.PauliX(1)), qml.expval(qml.PauliZ(0))
```
Executing this, we will get an output of size (3, 2):
```
>>> circuit(0.5)
tensor([[ 1. , 1. ],
[ 0.2 , 1. ],
[-0.022, 0.876]], requires_grad=True)
```
---
## Creating and drawing a quantum node
Together, a quantum function and a device are used to create a _quantum node_ or [`QNode`](https://docs.pennylane.ai/en/stable/code/api/pennylane.QNode.html "pennylane.QNode") object, which wraps the quantum function and binds it to the device.
A QNode can be explicitly created as follows:
```
circuit = qml.QNode(my_quantum_function, dev_unique_wires)
```
```
circuit(np.pi/4, 0.7)
tensor(0.764, requires_grad=True)
```
To view the quantum circuit given specific parameter values, we can use the [`draw()`](https://docs.pennylane.ai/en/stable/code/api/pennylane.draw.html "pennylane.draw") transform,
```
print(qml.draw(circuit)(np.pi/4, 0.7))
aux: ───────────╭●─┤
q1: ──RZ(0.79)─╰X─┤
q2: ──RY(0.70)────┤ <Z>
```
or also :
```
import matplotlib.pyplot as plt
qml.drawer.use_style("black_white")
fig, ax = qml.draw_mpl(circuit)(np.pi/4, 0.7)
plt.show()
```
output:
![[Pasted image 20221218210829.png]]