Skip to content

Commit

Permalink
FEAT: Digital component lattice co-simulation, fix installation requi…
Browse files Browse the repository at this point in the history
…rements (#28)

* FEAT: Upgrading version requirements, pre-upgrade

* FEAT: Automated full testing including examples

* FEAT: Component lattice simulation

* FEAT: Kind of works

* FIX: Power diff energy analog example

* FIX: Dependency installatinos

* FEAT: Updating recursive search algorithm

* FEAT: Working instance indexing

* FEAT: Multi switch lattice simulations

* FEAT: Build docs
  • Loading branch information
daquintero authored Aug 13, 2023
1 parent 86aea72 commit bd441ee
Show file tree
Hide file tree
Showing 30 changed files with 1,154 additions and 83 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 88 additions & 1 deletion docs/autoapi/piel/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Functions
piel.sax_circuit_permanent
piel.unitary_permanent
piel.sax_to_ideal_qutip_unitary
piel.verify_sax_model_is_unitary
piel.fock_transition_probability_amplitude
piel.single_parameter_sweep
piel.multi_parameter_sweep
Expand Down Expand Up @@ -115,6 +116,11 @@ Functions
piel.configure_transient_simulation
piel.run_simulation
piel.convert_numeric_to_prefix
piel.address_value_dictionary_to_function_parameter_dictionary
piel.compose_recursive_instance_location
piel.get_component_instances
piel.get_netlist_instances_by_prefix
piel.get_matched_model_recursive_netlist_instances
piel.get_sdense_ports_index
piel.sax_to_s_parameters_standard_matrix
piel.all_fock_states_from_photon_number
Expand Down Expand Up @@ -451,7 +457,7 @@ Attributes
:rtype: tuple


.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType)
.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType, input_ports_order: tuple | None = None)
This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and
dimensions of the matrix can be observed.
Expand Down Expand Up @@ -484,11 +490,26 @@ Attributes

:param sax_input: A dictionary of S-parameters in the form of a SDict from `sax`.
:type sax_input: sax.SType
:param input_ports_order: The order of the input ports. If None, the default order is used.
:type input_ports_order: tuple | None

:returns: A QuTip QObj representation of the S-parameters in a unitary matrix.
:rtype: qobj_unitary (qutip.Qobj)


.. py:function:: verify_sax_model_is_unitary(model: sax.SType, input_ports_order: tuple | None = None) -> bool
Verify that the model is unitary.

:param model: The model to verify.
:type model: dict
:param input_ports_order: The order of the input ports. If None, the default order is used.
:type input_ports_order: tuple | None

:returns: True if the model is unitary, False otherwise.
:rtype: bool


.. py:function:: fock_transition_probability_amplitude(initial_fock_state: qutip.Qobj, final_fock_state: qutip.Qobj, unitary_matrix: jax.numpy.ndarray)
This function returns the transition probability amplitude between two Fock states when propagating in between
Expand Down Expand Up @@ -1210,6 +1231,72 @@ Attributes
This function converts a numeric value to a number under a SPICE unit closest to the base prefix. This allows us to connect a particular number real output, into a term that can be used in a SPICE netlist.


.. py:function:: address_value_dictionary_to_function_parameter_dictionary(address_value_dictionary: dict, parameter_key: str)
This function converts an address of an instance with particular parameter values in the form:

{('component_lattice_gener_fb8c4da8', 'mzi_1', 'sxt'): 0,
('component_lattice_gener_fb8c4da8', 'mzi_5', 'sxt'): 0}

to

{'mzi_1': {'sxt': {parameter_key: 0}},
('mzi_5', {'sxt': {parameter_key: 0}}}




.. py:function:: compose_recursive_instance_location(recursive_netlist: dict, top_level_instance_name: str, required_models: list, target_component_prefix: str, models: dict)
This function returns the recursive location of any matching ``target_component_prefix`` instances within the ``recursive_netlist``. A function that returns the mapping of the ``matched_component`` in the corresponding netlist at any particular level of recursion. This function iterates over a particular level of recursion of a netlist. It returns a list of the missing required components, and updates a dictionary of models that contains a particular matching component. It returns the corresponding list of instances of a particular component at that level of recursion, so that it can be appended upon in order to construct the location of the corresponding matching elements.
If ``required_models`` is an empty list, it means no recursion is required and the function is complete. If a ``required_model_i`` in ``required_models`` matches ``target_component_prefix``, then no more recursion is required down the component function.
The ``recursive_netlist`` should contain all the missing composed models that are not provided in the main models dictionary. If not, then we need to require the user to input the missing model that cannot be extracted from the composed netlist.
We know when a model is composed, and when it is already provided at every level of recursion based on the ``models`` dictionary that gets updated at each level of recursion with the corresponding models of that level, and the ``required_models`` down itself.

However, a main question appears on how to do the recursion. There needs to be a flag that determines that the recursion is complete. However, this is only valid for every particular component in the ``required_models`` list. Every component might have missing component. This means that this recursion begins component by component, updating the ``required_models`` list until all of them have been composed from the recursion or it is determined that is it missing fully.

It would be ideal to access the particular component that needs to be implemented.

Returns a tuple of ``model_composition_mapping, instance_composition_mapping, target_component_mapping`` in the form of

({'mzi_214beef3': ['straight_heater_metal_s_ad3c1693']},
{'mzi_214beef3': ['mzi_1', 'mzi_5'],
'mzi_d46c281f': ['mzi_2', 'mzi_3', 'mzi_4']})


.. py:function:: get_component_instances(recursive_netlist: dict, top_level_prefix: str, component_name_prefix: str)
Returns a dictionary of all instances of a given component in a recursive netlist.

:param recursive_netlist: The recursive netlist to search.
:param top_level_prefix: The prefix of the top level instance.
:param component_name_prefix: The name of the component to search for.

:returns: A dictionary of all instances of the given component.


.. py:function:: get_netlist_instances_by_prefix(recursive_netlist: dict, instance_prefix: str) -> str
Returns a list of all instances with a given prefix in a recursive netlist.

:param recursive_netlist: The recursive netlist to search.
:param instance_prefix: The prefix to search for.

:returns: A list of all instances with the given prefix.


.. py:function:: get_matched_model_recursive_netlist_instances(recursive_netlist: dict, top_level_instance_prefix: str, target_component_prefix: str, models: Optional[dict] = None) -> list[tuple]
This function returns an active component list with a tuple mapping of the location of the active component within the recursive netlist and corresponding model. It will recursively look within a netlist to locate what models use a particular component model. At each stage of recursion, it will compose a list of the elements that implement this matching model in order to relate the model to the instance, and hence the netlist address of the component that needs to be updated in order to functionally implement the model.

It takes in as a set of parameters the recursive_netlist generated by a ``gdsfactory`` netlist implementation.

Returns a list of tuples, that correspond to the phases applied with the corresponding component paths at multiple levels of recursion.
eg. [("component_lattice_gener_fb8c4da8", "mzi_1", "sxt"), ("component_lattice_gener_fb8c4da8", "mzi_5", "sxt")] and these are our keys to our sax circuit decomposition.


.. py:function:: get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) -> dict
This function returns the ports index of the sax dense S-parameter matrix.
Expand Down
18 changes: 17 additions & 1 deletion docs/autoapi/piel/integration/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Functions
piel.integration.sax_circuit_permanent
piel.integration.unitary_permanent
piel.integration.sax_to_ideal_qutip_unitary
piel.integration.verify_sax_model_is_unitary
piel.integration.fock_transition_probability_amplitude


Expand Down Expand Up @@ -175,7 +176,7 @@ Functions
:rtype: tuple


.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType)
.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType, input_ports_order: tuple | None = None)
This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and
dimensions of the matrix can be observed.
Expand Down Expand Up @@ -208,11 +209,26 @@ Functions

:param sax_input: A dictionary of S-parameters in the form of a SDict from `sax`.
:type sax_input: sax.SType
:param input_ports_order: The order of the input ports. If None, the default order is used.
:type input_ports_order: tuple | None

:returns: A QuTip QObj representation of the S-parameters in a unitary matrix.
:rtype: qobj_unitary (qutip.Qobj)


.. py:function:: verify_sax_model_is_unitary(model: sax.SType, input_ports_order: tuple | None = None) -> bool
Verify that the model is unitary.

:param model: The model to verify.
:type model: dict
:param input_ports_order: The order of the input ports. If None, the default order is used.
:type input_ports_order: tuple | None

:returns: True if the model is unitary, False otherwise.
:rtype: bool


.. py:function:: fock_transition_probability_amplitude(initial_fock_state: qutip.Qobj, final_fock_state: qutip.Qobj, unitary_matrix: jax.numpy.ndarray)
This function returns the transition probability amplitude between two Fock states when propagating in between
Expand Down
18 changes: 17 additions & 1 deletion docs/autoapi/piel/integration/sax_qutip/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ Functions
.. autoapisummary::

piel.integration.sax_qutip.sax_to_ideal_qutip_unitary
piel.integration.sax_qutip.verify_sax_model_is_unitary



.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType)
.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType, input_ports_order: tuple | None = None)
This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and
dimensions of the matrix can be observed.
Expand Down Expand Up @@ -50,6 +51,21 @@ Functions

:param sax_input: A dictionary of S-parameters in the form of a SDict from `sax`.
:type sax_input: sax.SType
:param input_ports_order: The order of the input ports. If None, the default order is used.
:type input_ports_order: tuple | None

:returns: A QuTip QObj representation of the S-parameters in a unitary matrix.
:rtype: qobj_unitary (qutip.Qobj)


.. py:function:: verify_sax_model_is_unitary(model: sax.SType, input_ports_order: tuple | None = None) -> bool
Verify that the model is unitary.

:param model: The model to verify.
:type model: dict
:param input_ports_order: The order of the input ports. If None, the default order is used.
:type input_ports_order: tuple | None

:returns: True if the model is unitary, False otherwise.
:rtype: bool
2 changes: 1 addition & 1 deletion docs/autoapi/piel/models/frequency/defaults/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Functions



.. py:function:: get_default_models(custom_defaults: dict | None = None, type: Literal[default, quantum] = 'default') -> dict
.. py:function:: get_default_models(custom_defaults: dict | None = None, type: Literal[classical, quantum] = 'classical') -> dict
Returns the default models dictionary.

Expand Down
2 changes: 1 addition & 1 deletion docs/autoapi/piel/models/frequency/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Functions
:rtype: dict


.. py:function:: get_default_models(custom_defaults: dict | None = None, type: Literal[default, quantum] = 'default') -> dict
.. py:function:: get_default_models(custom_defaults: dict | None = None, type: Literal[classical, quantum] = 'classical') -> dict
Returns the default models dictionary.

Expand Down
71 changes: 71 additions & 0 deletions docs/autoapi/piel/tools/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,11 @@ Functions
piel.tools.configure_transient_simulation
piel.tools.run_simulation
piel.tools.convert_numeric_to_prefix
piel.tools.address_value_dictionary_to_function_parameter_dictionary
piel.tools.compose_recursive_instance_location
piel.tools.get_component_instances
piel.tools.get_netlist_instances_by_prefix
piel.tools.get_matched_model_recursive_netlist_instances
piel.tools.get_sdense_ports_index
piel.tools.sax_to_s_parameters_standard_matrix
piel.tools.all_fock_states_from_photon_number
Expand Down Expand Up @@ -734,6 +739,72 @@ Attributes
This function converts a numeric value to a number under a SPICE unit closest to the base prefix. This allows us to connect a particular number real output, into a term that can be used in a SPICE netlist.


.. py:function:: address_value_dictionary_to_function_parameter_dictionary(address_value_dictionary: dict, parameter_key: str)
This function converts an address of an instance with particular parameter values in the form:

{('component_lattice_gener_fb8c4da8', 'mzi_1', 'sxt'): 0,
('component_lattice_gener_fb8c4da8', 'mzi_5', 'sxt'): 0}

to

{'mzi_1': {'sxt': {parameter_key: 0}},
('mzi_5', {'sxt': {parameter_key: 0}}}




.. py:function:: compose_recursive_instance_location(recursive_netlist: dict, top_level_instance_name: str, required_models: list, target_component_prefix: str, models: dict)
This function returns the recursive location of any matching ``target_component_prefix`` instances within the ``recursive_netlist``. A function that returns the mapping of the ``matched_component`` in the corresponding netlist at any particular level of recursion. This function iterates over a particular level of recursion of a netlist. It returns a list of the missing required components, and updates a dictionary of models that contains a particular matching component. It returns the corresponding list of instances of a particular component at that level of recursion, so that it can be appended upon in order to construct the location of the corresponding matching elements.
If ``required_models`` is an empty list, it means no recursion is required and the function is complete. If a ``required_model_i`` in ``required_models`` matches ``target_component_prefix``, then no more recursion is required down the component function.
The ``recursive_netlist`` should contain all the missing composed models that are not provided in the main models dictionary. If not, then we need to require the user to input the missing model that cannot be extracted from the composed netlist.
We know when a model is composed, and when it is already provided at every level of recursion based on the ``models`` dictionary that gets updated at each level of recursion with the corresponding models of that level, and the ``required_models`` down itself.

However, a main question appears on how to do the recursion. There needs to be a flag that determines that the recursion is complete. However, this is only valid for every particular component in the ``required_models`` list. Every component might have missing component. This means that this recursion begins component by component, updating the ``required_models`` list until all of them have been composed from the recursion or it is determined that is it missing fully.

It would be ideal to access the particular component that needs to be implemented.

Returns a tuple of ``model_composition_mapping, instance_composition_mapping, target_component_mapping`` in the form of

({'mzi_214beef3': ['straight_heater_metal_s_ad3c1693']},
{'mzi_214beef3': ['mzi_1', 'mzi_5'],
'mzi_d46c281f': ['mzi_2', 'mzi_3', 'mzi_4']})


.. py:function:: get_component_instances(recursive_netlist: dict, top_level_prefix: str, component_name_prefix: str)
Returns a dictionary of all instances of a given component in a recursive netlist.

:param recursive_netlist: The recursive netlist to search.
:param top_level_prefix: The prefix of the top level instance.
:param component_name_prefix: The name of the component to search for.

:returns: A dictionary of all instances of the given component.


.. py:function:: get_netlist_instances_by_prefix(recursive_netlist: dict, instance_prefix: str) -> str
Returns a list of all instances with a given prefix in a recursive netlist.

:param recursive_netlist: The recursive netlist to search.
:param instance_prefix: The prefix to search for.

:returns: A list of all instances with the given prefix.


.. py:function:: get_matched_model_recursive_netlist_instances(recursive_netlist: dict, top_level_instance_prefix: str, target_component_prefix: str, models: Optional[dict] = None) -> list[tuple]
This function returns an active component list with a tuple mapping of the location of the active component within the recursive netlist and corresponding model. It will recursively look within a netlist to locate what models use a particular component model. At each stage of recursion, it will compose a list of the elements that implement this matching model in order to relate the model to the instance, and hence the netlist address of the component that needs to be updated in order to functionally implement the model.

It takes in as a set of parameters the recursive_netlist generated by a ``gdsfactory`` netlist implementation.

Returns a list of tuples, that correspond to the phases applied with the corresponding component paths at multiple levels of recursion.
eg. [("component_lattice_gener_fb8c4da8", "mzi_1", "sxt"), ("component_lattice_gener_fb8c4da8", "mzi_5", "sxt")] and these are our keys to our sax circuit decomposition.


.. py:function:: get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) -> dict
This function returns the ports index of the sax dense S-parameter matrix.
Expand Down
4 changes: 4 additions & 0 deletions docs/autoapi/piel/tools/qutip/config/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:py:mod:`piel.tools.qutip.config`
=================================

.. py:module:: piel.tools.qutip.config
1 change: 1 addition & 0 deletions docs/autoapi/piel/tools/qutip/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Submodules
:titlesonly:
:maxdepth: 1

config/index.rst
fock/index.rst
unitary/index.rst

Expand Down
Loading

0 comments on commit bd441ee

Please sign in to comment.