Transpilation
Contains functions that operate on blocks and circuits to transpile them to new blocks/circuits.
            transpile(*fs)
    AbstractBlock or QuantumCircuit transpilation.
Compose functions that accept a circuit/block and returns a circuit/block.
| PARAMETER | DESCRIPTION | 
|---|---|
*fs | 
            
               composable functions that either map blocks to blocks
( 
                  
                    TYPE:
                        | 
          
| RETURNS | DESCRIPTION | 
|---|---|
                
                    Callable
                
             | 
            
               Composed function.  | 
          
Examples:
Flatten a block of nested chains and krons:
from qadence import *
from qadence.transpile import transpile, flatten, scale_primitive_blocks_only
b = chain(2 * chain(chain(X(0), Y(0))), kron(kron(X(0), X(1))))
print(b)
# both flatten and scale_primitive_blocks_only are functions that accept and
# return a block
t = transpile(flatten, scale_primitive_blocks_only)(b)
print(t)
We also proved a decorator to easily turn a function Callable[[AbstractBlock], AbstractBlock]
into a Callable[[QuantumCircuit], QuantumCircuit] to be used in circuit transpilation.
from qadence import *
from qadence.transpile import transpile, blockfn_to_circfn, flatten
# We want to pass this circuit to `transpile` instead of a block,
# so we need functions that map from a circuit to a circuit.
circ = QuantumCircuit(2, chain(chain(X(0), chain(X(1)))))
@blockfn_to_circfn
def fn(block):
    # un-decorated function accepts a block and returns a block
    return block * block
transp = transpile(
    # the decorated function accepts a circuit and returns a circuit
    fn,
    # already existing functions can also be decorated
    blockfn_to_circfn(flatten)
)
print(transp(circ))
Source code in qadence/transpile/transpile.py
              
            chain_single_qubit_ops(block)
    Transpile a chain of krons into a kron of chains of single qubit operations.
Examples:
from qadence import hea
from qadence.transpile.block import chain_single_qubit_ops
# Consider a single HEA layer
block = hea(2,1)
print(block)
# After applying chain_single_qubit_ops, we get:
print(chain_single_qubit_ops(block))
ChainBlock(0,1) [tag: HEA]
├── ChainBlock(0,1)
│   ├── KronBlock(0,1)
│   │   ├── RX(0) [params: ['theta_0']]
│   │   └── RX(1) [params: ['theta_1']]
│   ├── KronBlock(0,1)
│   │   ├── RY(0) [params: ['theta_2']]
│   │   └── RY(1) [params: ['theta_3']]
│   └── KronBlock(0,1)
│       ├── RX(0) [params: ['theta_4']]
│       └── RX(1) [params: ['theta_5']]
└── ChainBlock(0,1)
    └── KronBlock(0,1)
        └── CNOT(0, 1)
ChainBlock(0,1)
├── KronBlock(0,1)
│   ├── ChainBlock(0)
│   │   ├── RX(0) [params: ['theta_0']]
│   │   ├── RY(0) [params: ['theta_2']]
│   │   └── RX(0) [params: ['theta_4']]
│   └── ChainBlock(1)
│       ├── RX(1) [params: ['theta_1']]
│       ├── RY(1) [params: ['theta_3']]
│       └── RX(1) [params: ['theta_5']]
└── ChainBlock(0,1)
    └── KronBlock(0,1)
        └── CNOT(0, 1)
Source code in qadence/transpile/block.py
              
            scale_primitive_blocks_only(block, scale=None)
    Push the scale all the way down into the leaves of the block tree.
When given a scaled CompositeBlock consisting of several PrimitiveBlocks.
| PARAMETER | DESCRIPTION | 
|---|---|
block | 
            
               The block to be transpiled. 
                  
                    TYPE:
                        | 
          
scale | 
            
               An optional scale parameter. Only to be used for recursive calls internally. 
                  
                    TYPE:
                        | 
          
| RETURNS | DESCRIPTION | 
|---|---|
                AbstractBlock
             | 
            
               A block of the same type where the scales have been moved into the subblocks. 
                  
                    TYPE:
                        | 
          
Examples:
There are two different cases:
ChainBlocks/KronBlocks: Only the first subblock needs to be scaled because chains/krons
represent multiplications.
from qadence import chain, X, RX
from qadence.transpile import scale_primitive_blocks_only
b = 2 * chain(X(0), RX(0, "theta"))
print(b)
# After applying scale_primitive_blocks_only
print(scale_primitive_blocks_only(b))
[mul: 2] 
└── ChainBlock(0)
    ├── X(0)
    └── RX(0) [params: ['theta']]
ChainBlock(0)
├── [mul: 2.000] 
│   └── X(0)
└── RX(0) [params: ['theta']]
AddBlocks: Consider 2 * add(X(0), RX(0, "theta")).  The scale needs to be added to all
subblocks.  We get add(2 * X(0), 2 * RX(0, "theta")).
from qadence import add, X, RX
from qadence.transpile import scale_primitive_blocks_only
b = 2 * add(X(0), RX(0, "theta"))
print(b)
# After applying scale_primitive_blocks_only
print(scale_primitive_blocks_only(b))
[mul: 2] 
└── AddBlock(0)
    ├── X(0)
    └── RX(0) [params: ['theta']]
AddBlock(0)
├── [mul: 2.000] 
│   └── X(0)
└── [mul: 2.000] 
    └── RX(0) [params: ['theta']]
Source code in qadence/transpile/block.py
              
            set_trainable(blocks, value=True, inplace=True)
    Set the trainability of all parameters in a block to a given value.
| PARAMETER | DESCRIPTION | 
|---|---|
blocks | 
            
               Block or list of blocks for which to set the trainable attribute 
                  
                    TYPE:
                        | 
          
value | 
            
               The value of the trainable attribute to assign to the input blocks 
                  
                    TYPE:
                        | 
          
inplace | 
            
               Whether to modify the block(s) in place or not. Currently, only 
                  
                    TYPE:
                        | 
          
| RAISES | DESCRIPTION | 
|---|---|
              
                  NotImplementedError
              
             | 
            
               if the   | 
          
| RETURNS | DESCRIPTION | 
|---|---|
                
                    AbstractBlock | list[AbstractBlock]
                
             | 
            
               AbstractBlock | list[AbstractBlock]: the input block or list of blocks with the trainable attribute set to the given value  | 
          
Source code in qadence/transpile/block.py
              
            validate(block)
    Moves a block from global to local qubit numbers by adding PutBlocks.
Reassigns qubit locations appropriately.
Example
from qadence.blocks import chain
from qadence.operations import X
from qadence.transpile import validate
x = chain(chain(X(0)), chain(X(1)))
print(x)
print(validate(x))
ChainBlock(0,1)
├── ChainBlock(0)
│   └── X(0)
└── ChainBlock(1)
    └── X(1)
ChainBlock(0,1)
├── put on (0)
│   └── ChainBlock(0)
│       └── put on (0)
│           └── X(0)
└── put on (1)
    └── ChainBlock(0)
        └── put on (0)
            └── X(0)