{% import 'circuit_css.html' as style %} {% macro getNumberSize(loopLength) %} {{ "large-number" if loopLength > 16 else ("mid-number" if loopLength > 8) }} {% endmacro %} {% macro display_matrix(data, display_title=True) %}
{% if display_title %}

Matrix

{% endif %} {% for (ket, row) in data.chart %} {% for (bra, entry) in row %} {% endfor %} {% endfor %}
{{ entry }}
{% endmacro %} {% macro display_list(data) %}
{% if data.headings %}
{{ data.headings[0] }}
{% endif %}
{% for entry in data.chart %}
{{ entry }}
{% endfor %}
{% endmacro %} {# ------------------------------------------- #} {# - CIRCUIT RENDERING - #} {# ------------------------------------------- #} {# Enclose the circuit rendering components into one big macro so we can share circuit depth indices #} {% macro circuit_render_engine(circuit, options={}, nested=false) %} {% set c = namespace(depth=0, max_depth=-1) %} {# - SUB-MACROS - #} {# to help render circuit blocks #} {# Gap #} {% macro gap(link_vertical=false) -%}
{% if link_vertical %} {% endif %}
{%- endmacro %} {# Plain wire #} {% macro wire(type=1, link_vertical=false) -%}
{% if link_vertical %} {% endif %}
{%- endmacro %} {# Generic single qubit gate #} {% macro gate1(name, wire_type=1, link_vertical=false, box_details=None) -%}
{{ wire(type=wire_type) }}
{# Render special gates with their own images #} {% if name == "Reset" %}
0
{% else %}
{{ name }}
{% endif %} {% if link_vertical %} {% endif %}
{{ wire(type=wire_type) }}
{% if name not in ["X", "Reset"] %} {{ gate_info(box_details) }} {% endif %} {%- endmacro %} {# Generic multi qubit gate #} {% macro gateN(wire_type=1, pos=-1, name='', display_name=false, link=0, link_vertical=false, box_details=None) -%}
{% if link_vertical %} {% endif %}
{{ gate_info(box_details) if pos == 0 }} {%- endmacro %} {# Controlled gate #} {% macro c_gate( params, type, box, wire_type=1, pos=-1, top=false, bottom=false, args=[], options={}, parent_gate=None ) -%} {# Render the involved registers #} {% if pos > -1 %} {# If this is a gate, render it using the usual macro #} {% if wire_type < 2 %} {% set new_options = { "recursive": False, "condensed": options.condensed } %} {{ render_gate({ "op": { "type": type, "raw": box }, "pos": -1 if top else (0 if bottom else 1), "params": box|get_op_params|format_op_params if box else params, "args": [(wire_type, pos)], "t_args": args|length, "n_args": - (args|get_target_args|length) }, link_vertical=not top, options=new_options) }} {% else %} {# Otherwise, it's a control bit #}
{{ wire(type=wire_type-2) }} {% if parent_gate and parent_gate.type == "ConditionalGate" %}
{{ pos }}
{% endif %}
{% if not top %} {% endif %}
{{ gate_info(parent_gate) if pos == 0 }} {% endif %} {# Registers that aren't involed are just vertical links #} {% else %}
{{ wire(type=wire_type) if pos != 1}}
{% if not top %} {% endif %}
{% endif %} {%- endmacro %} {# SWAP #} {% macro swap_gate(pos=-1, link_vertical=false, is_bottom=False) -%}
{% if not is_bottom %} {% endif %} {% if link_vertical %} {% endif %} {{ wire() }}
{%- endmacro %} {# Measurement #} {% macro measure_gate(pos=0, wire_type=1, link_vertical=false) -%}
{% if pos > -1 %} {% endif %} {% if link_vertical %} {% endif %} {{ wire(type=wire_type) }}
{% if pos == 1 %}
z
{% endif %}
{%- endmacro %} {# Render non circuit-shaped gate defining information #} {% macro gate_info(op, is_nested_circuit=False) -%} {% if op.type|has_gate_info %} {% set box = op.raw.box if op.raw.box else op.raw %}
{{ op.type }}
{% if box|get_box_matrix() is not none %} {{ display_matrix(box.get_matrix()|format_raw_matrix) }} {% elif op.type == "ExpBox" %} {% set info = box|get_expbox_details %} {{ display_matrix(info.matrix|format_raw_matrix) }}

Phase

{{ info.phase }} {% elif op.type == "PauliExpBox" %}
Phase Paulis
{{ box.get_phase() }} {{ display_list({ "chart":box.get_paulis() }) }}
{% elif op.type == "PhasePolyBox" %}
Encapsulating {{ box.n_qubits }} gates

Qubit Mapping

{{ display_list({ "chart": box.qubit_indices|format_mapping(coerce_from="register") }) }}

Phase Polynomial

{{ display_list({ "chart": box.phase_polynomial|format_mapping(coerce_from="bool") }) }}

Linear Transformation

{{ display_matrix(box.linear_transformation|format_bool_matrix, display_title=False) }} {% elif op.type == "Custom" %} {% for param in box.params %} {% endfor %}
Parameter Value
{{ box.gate.args[loop.index0] }} {{ param }}
{% elif op.type == "ConditionalGate" %}
Condition value {{ op.raw.value }}
{% elif op.type == "QControlBox" and box.get_op().type.name|has_sub_circuit %} {# If there is a nested circuit display it #} {% set sub_circuit = box.get_op()|get_sub_circuit %} {% if sub_circuit is not none %}

Controlled Circuit

{{ render_circuit( sub_circuit|parse_circuit, options={"condensed": True, "recursive": False }, nested=True ) }}
{% endif %} {% elif op.type == "ClassicalExpBox" %}

Expression

{{ box.get_exp().op|format_logic_exp }}
Input bits {{ box.get_n_i() }}
Input/Output bits {{ box.get_n_io() }}
Output bits {{ box.get_n_o() }}
{% elif op.type|is_classical_gate %} {% if box.get_name() %} {% endif %} {% if box.n_inputs %} {% endif %} {% if box.n_input_outputs %} {% endif %} {% if box.n_outputs %} {% endif %} {% if box.values %} {% endif %} {% if box.upper %} {% endif %} {% if box.lower %} {% endif %}
Operation {{ box.get_name() }}
Input bits {{ box.n_inputs }}
Input/Output bits {{ box.n_input_outputs }}
Output bits {{ box.n_outputs }}
Values {{ display_list({ "chart":box.values }) }}
Upper {{ box.upper }}
Lower {{ box.lower }}
{% endif %} {% if op.type|has_sub_circuit and not is_nested_circuit %} {% set sub_circuit = op.raw|get_sub_circuit %} {% if sub_circuit is not none %}

Gate as Circuit

{{ render_circuit( sub_circuit|parse_circuit, options={"condensed": True, "recursive": False }, nested=True ) }}
{% endif %} {% endif %}
{% endif %} {%- endmacro %} {# List out the qubits #} {% macro register_list(qubits, bits) -%}
{% for qubit in qubits %}
{{ qubit.reg_name ~ qubit.index }}
{% endfor %} {% for bit in bits %}
{{ bit.reg_name ~ bit.index }}
{% endfor %}
{%- endmacro %} {% macro render_circuit(circuit, options={}, nested=false) -%} {% set c.depth = c.depth + 1 %} {% if c.depth > c.max_depth %} {% set c.max_depth = c.depth %} {% endif %} {% if not nested %}
{% endif %} {% if options.condensed %} {# Pad the side of the circuit to fix the display height #}
{% for qubit in circuit.qubits + circuit.bits %}
{% endfor %}
{% endif %}
{{ register_list(circuit.qubits, circuit.bits) }} {% for layer in circuit.layers %}
{% for gate in layer %} {# Controlled gates get special treatment #} {% if gate.op.type|is_control_gate %} {% for (arg_type, pos) in gate.args %} {{ c_gate( gate.params, *gate.op.type|get_op_name(gate.op.raw), wire_type=arg_type, pos=pos, top=loop.first, bottom=loop.last, args=gate.args, options=options, parent_gate=gate.op ) }} {% endfor %} {% else %} {{ render_gate(gate, options=options) }} {% endif %} {% endfor %}
{% endfor %} {{ register_list(circuit.qubits, circuit.bits) }}
{% if options.condensed %}
{% endif %} {% if not nested %}
{% endif %} {% set c.depth = c.depth - 1 %} {%- endmacro %} {% macro render_gate(gate, options={}, link_vertical=false) %} {# Decide what to render by case, in 2 steps: first, type of operation, second no. of qbits involved #} {% if gate.op.type == 'ID' %} {% for (arg_type, pos) in gate.args %} {{ wire(type=arg_type, link_vertical=link_vertical) }} {% endfor %} {# SWAP #} {% elif gate.op.type == 'SWAP' %} {% for arg_type, pos in gate.args %} {{ swap_gate(pos=pos, link_vertical=link_vertical, is_bottom=loop.index == loop.length) }} {% endfor %} {# Measurements #} {% elif gate.op.type == "Measure" %} {{ measure_gate(pos=1, wire_type=gate.args[0][0], link_vertical=link_vertical) }} {% for arg_type, pos in gate.args[1:-1] %} {{ measure_gate(wire_type=arg_type) }} {% endfor %} {{ measure_gate(pos=-1, wire_type=gate.args[-1][0], link_vertical=link_vertical) }} {# Nested circuit #} {% elif gate.op.type|has_sub_circuit and options.recursive %}
{% for (arg_type, link) in gate.args %} {% if link > -1 %} {{ wire(type=arg_type) }} {% else %} {{ gap() }} {% endif %} {% endfor %}
{% for (arg_type, link) in gate.args %}
{{ link if link > -1 }}
{% endfor %}
{% set sub_circuit = gate.op.raw|get_sub_circuit %} {% if sub_circuit is not none %} {{ render_circuit( sub_circuit|parse_circuit, options={"condensed": True, "recursive": options.recursive}, nested=true ) }} {% endif %}
{% for (arg_type, link) in gate.args %}
{{ link if link > -1 }}
{% endfor %}
{% for (arg_type, link) in gate.args %} {% if link > -1 %} {{ wire(type=arg_type) }} {% else %} {{ gap() }} {% endif %} {% endfor %}
{# Add parameters as gate info if necessary #} {{ gate_info(gate.op, is_nested_circuit=True) }}
{# Generic gate #} {% else %} {% if gate.n_args > 1 %} {{ gateN(wire_type=gate.args[0][0], link=gate.args[0][1], link_vertical=link_vertical) }} {% for (arg_type,link) in gate.args[1:] %} {{ gateN( wire_type=arg_type, pos=gate.n_args - loop.index - 1, name=gate.op.type|get_op_display_name(gate.op.raw, gate.params), display_name=loop.index * 2 == gate.n_args - 1 or loop.index * 2 == gate.n_args, link=link, link_vertical=link_vertical, box_details = gate.op ) }} {% endfor %} {% elif gate.n_args < -1 %} {# We are rendering an n-gate incrementally #} {{ gateN( wire_type=gate.args[0][0], pos=gate.pos, name=gate.op.type|get_op_display_name(gate.op.raw, gate.params), display_name=True, link=gate.args[0][1], link_vertical=link_vertical, box_details = gate.op ) }} {% else %} {{ gate1( gate.op.type|get_op_display_name(gate.op.raw, gate.params), wire_type=gate.args[0][0], link_vertical=link_vertical, box_details = gate.op ) }} {% endif %} {% endif %} {% endmacro %} {# - END SUB-MACROS - #} {# The main render function just calls render circuit and recurses from there #} {{ render_circuit(circuit, options, nested) }} {% endmacro %} {# Render the circuit as a standalone page #} {# ------------------------------------------- #} {{ style.get_css() }}
{{ circuit_render_engine(circuit|parse_circuit, options=display_options) }}