Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 39 additions & 42 deletions sphinx/language_guide/comptime.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,44 @@ ladder.compile_function();
As we can see, the ``print`` statement is executed at compile-time.
We get 9 printed lines, highlighting that the ``for`` loop is compile-time evaluated as well.

With Guppy v1.0 and above, we can use generic variables in the type signatures of generic functions. Let's generalize the `ladder` function defined above to apply a chain of `cx` gates to a qubit array of variable size.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to specifically call out v1 changes in regular docs sections?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its fine to call out version numbers for major features.


```{code-cell} ipython3
@guppy.comptime
def generic_ladder[k: nat](qs: array[qubit, k]) -> None:
for q1, q2 in zip(qs[1:], qs[:-1]):
print("Applying CX")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why include the print here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess its helpful for building intuition on comptime. When compiling the function for k=7 we see k-1=7 prints.

cx(q1, q2)
```

The input to the `ladder` function is of type `array[qubit, k]` so this comptime function is generic over the number of qubits.

Note that we cannot compile the `generic_ladder` function directly as the value of `k` is unknown at compile time.

```{code-cell} ipython3
---
tags: [raises-exception]
---
generic_ladder.compile_function()
```

However we can call `generic_ladder` inside another function with a concrete `k` value.


```{code-cell} ipython3
from guppylang.std.quantum import discard_array

@guppy
def main() -> None:
qs = array(qubit() for _ in range(7))
# Invoke generic_ladder on an array of seven qubits (k=7).
generic_ladder(qs)
discard_array(qs)

main.compile();
```


### What can and cannot happen at comptime

Note that not *everything* inside ``comptime`` functions can happen at compile-time.
Expand Down Expand Up @@ -281,48 +319,7 @@ dynamic_branch.compile_function(); # Compilation fails

This kind of dynamic branching is only possible in regular Guppy functions, not in a ``comptime`` context.

### Generalizing comptime functions

Note that Guppy comptime functions cannot yet be used in conjunction with [generic type variables](static.md#generics). Consider the following generic version of the `ladder` comptime function above.


```{code-cell} ipython3
---
tags: [raises-exception]
---

N_QB = guppy.nat_var("n_qb")

@guppy.comptime
def generic_ladder(qs: array[qubit, N_QB]) -> None:
for q1, q2 in zip(qs[1:], qs[:-1]):
print("Applying CX")
cx(q1, q2)
return ladder

generic_ladder.compile_function(); # Compilation fails
```

There is however a workaround for this particular issue. If we want to generalize this comptime `ladder` function with a variable number of qubits we can do this we can do this with metaprogramming. We can define a Python function which takes an integer argument and returns a instance of the comptime function for that integer.

```{code-cell} ipython3
from guppylang.defs import GuppyFunctionDefinition

def get_comptime_ladder_function(n_qubits: int) -> GuppyFunctionDefinition:
@guppy.comptime
def ladder(qs: array[qubit, comptime(n_qubits)]) -> None:
for q1, q2 in zip(qs[1:], qs[:-1]):
print("Applying CX")
cx(q1, q2)
return ladder

four_qubit_ladder = get_comptime_ladder_function(n_qubits=4)
four_qubit_ladder.compile_function();
```

Note how the input to the `ladder` function is of type `array[qubit, comptime(n_qubits)]` so we can create this function for any integer number of qubits.



### Arrays and lists

Arrays and regular Python lists can be used interchangeably inside ``comptime`` functions since the size of ``comptime`` lists is statically known.
Expand Down
Loading