Repository: Qiskit/qiskit

Issue:
Document usage of high level synthesis plugins
### What should we add?

The [API documentation for synthesis plugins](https://docs.quantum.ibm.com/api/qiskit/transpiler_synthesis_plugins) does not explain how to use high level synthesis plugins. For example, the [Using plugins](https://docs.quantum.ibm.com/api/qiskit/transpiler_synthesis_plugins#using-plugins) section only discusses unitary synthesis plugins, not high level synthesis plugins.


Discussion:

Resolving patch:
diff --git a/qiskit/transpiler/passes/__init__.py b/qiskit/transpiler/passes/__init__.py
--- a/qiskit/transpiler/passes/__init__.py
+++ b/qiskit/transpiler/passes/__init__.py
@@ -146,6 +146,7 @@
    LinearFunctionsSynthesis
    LinearFunctionsToPermutations
    HighLevelSynthesis
+   HLSConfig
    SolovayKitaev
    SolovayKitaevSynthesis
 
@@ -253,6 +254,7 @@
 from .synthesis import LinearFunctionsSynthesis
 from .synthesis import LinearFunctionsToPermutations
 from .synthesis import HighLevelSynthesis
+from .synthesis import HLSConfig
 from .synthesis import SolovayKitaev
 from .synthesis import SolovayKitaevSynthesis
 
diff --git a/qiskit/transpiler/passes/synthesis/high_level_synthesis.py b/qiskit/transpiler/passes/synthesis/high_level_synthesis.py
--- a/qiskit/transpiler/passes/synthesis/high_level_synthesis.py
+++ b/qiskit/transpiler/passes/synthesis/high_level_synthesis.py
@@ -53,17 +53,23 @@
 class HLSConfig:
     """The high-level-synthesis config allows to specify a list of "methods" used by
     :class:`~.HighLevelSynthesis` transformation pass to synthesize different types
-    of higher-level-objects. A higher-level object is an object of type
-    :class:`~.Operation` (e.g., "clifford", "linear_function", etc.), and the list
-    of applicable synthesis methods is strictly tied to the name of the operation.
-    In the config, each method is specified as a tuple consisting of the name of the
-    synthesis algorithm and of a dictionary providing additional arguments for this
-    algorithm. Additionally, a synthesis method can be specified as a tuple consisting
-    of an instance of :class:`.HighLevelSynthesisPlugin` and additional arguments.
-    Moreover, when there are no additional arguments, a synthesis
-    method can be specified simply by name or by an instance
-    of :class:`.HighLevelSynthesisPlugin`. The following example illustrates different
-    ways how a config file can be created::
+    of higher-level objects.
+
+    A higher-level object is an object of type :class:`~.Operation` (e.g., :class:`.Clifford` or
+    :class:`.LinearFunction`).  Each object is referred to by its :attr:`~.Operation.name` field
+    (e.g., ``"clifford"`` for :class:`.Clifford` objects), and the applicable synthesis methods are
+    tied to this name.
+
+    In the config, each method is specified in one of several ways:
+
+    1. a tuple consisting of the name of a known synthesis plugin and a dictionary providing
+       additional arguments for the algorithm.
+    2. a tuple consisting of an instance of :class:`.HighLevelSynthesisPlugin` and additional
+       arguments for the algorithm.
+    3. a single string of a known synthesis plugin
+    4. a single instance of :class:`.HighLevelSynthesisPlugin`.
+
+    The following example illustrates different ways how a config file can be created::
 
         from qiskit.transpiler.passes.synthesis.high_level_synthesis import HLSConfig
         from qiskit.transpiler.passes.synthesis.high_level_synthesis import ACGSynthesisPermutation
@@ -74,7 +80,7 @@ class HLSConfig:
         hls_config = HLSConfig(permutation=[(ACGSynthesisPermutation(), {})])
         hls_config = HLSConfig(permutation=[ACGSynthesisPermutation()])
 
-    The names of the synthesis algorithms should be declared in ``entry-points`` table for
+    The names of the synthesis plugins should be declared in ``entry-points`` table for
     ``qiskit.synthesis`` in ``pyproject.toml``, in the form
     <higher-level-object-name>.<synthesis-method-name>.
 
@@ -84,8 +90,11 @@ class HLSConfig:
 
     To avoid synthesizing a given higher-level-object, one can give it an empty list of methods.
 
-    For an explicit example of using such config files, refer to the
-    documentation for :class:`~.HighLevelSynthesis`.
+    For an explicit example of using such config files, refer to the documentation for
+    :class:`~.HighLevelSynthesis`.
+
+    For an overview of the complete process of using high-level synthesis, see
+    :ref:`using-high-level-synthesis-plugins`.
     """
 
     def __init__(self, use_default_on_unspecified=True, **kwargs):
diff --git a/qiskit/transpiler/passes/synthesis/plugin.py b/qiskit/transpiler/passes/synthesis/plugin.py
--- a/qiskit/transpiler/passes/synthesis/plugin.py
+++ b/qiskit/transpiler/passes/synthesis/plugin.py
@@ -232,6 +232,9 @@ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **
 Using Plugins
 =============
 
+Unitary Synthesis Plugins
+-------------------------
+
 To use a plugin all you need to do is install the package that includes a
 synthesis plugin. Then Qiskit will automatically discover the installed
 plugins and expose them as valid options for the appropriate
@@ -243,6 +246,44 @@ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **
 :func:`qiskit.transpiler.passes.synthesis.plugin.unitary_synthesis_plugin_names`
 function.
 
+.. _using-high-level-synthesis-plugins:
+
+High-level Synthesis Plugins
+----------------------------
+
+To use a high-level synthesis plugin, you first instantiate an :class:`.HLSConfig` to
+store the names of the plugins to use for various high-level objects.
+For example::
+
+    HLSConfig(permutation=["acg"], clifford=["layers"], linear_function=["pmh"])
+
+creates a high-level synthesis configuration that uses the ``acg`` plugin
+for synthesizing :class:`.PermutationGate` objects, the ``layers`` plugin
+for synthesizing :class:`.Clifford` objects, and the ``pmh`` plugin for synthesizing
+:class:`.LinearFunction` objects.  The keyword arguments are the :attr:`.Operation.name` fields of
+the relevant objects.  For example, all :class:`.Clifford` operations have the
+:attr:`~.Operation.name` ``clifford``, so this is used as the keyword argument.  You can specify
+any keyword argument here that you have installed plugins to handle, including custom user objects
+if you have plugins installed for them.  See :class:`.HLSConfig` for more detail on alternate
+formats for configuring the plugins within each argument.
+
+For each high-level object, the list of given plugins are tried in sequence until one of them
+succeeds (in the example above, each list only contains a single plugin). In addition to specifying
+a plugin by its name, you can instead pass a ``(name, options)`` tuple, where the second element of
+the tuple is a dictionary containing options for the plugin.
+
+Once created you then pass this :class:`.HLSConfig` object into the
+``hls_config`` argument for :func:`.transpile` or :func:`.generate_preset_pass_manager`
+which will use the specified plugins as part of the larger compilation workflow.
+
+To get a list of installed high level synthesis plugins for any given :attr:`.Operation.name`, you
+can use the :func:`.high_level_synthesis_plugin_names` function, passing the desired ``name`` as the
+argument::
+
+    high_level_synthesis_plugin_names("clifford")
+
+will return a list of all the installed Clifford synthesis plugins.
+
 Plugin API
 ==========
 
@@ -264,10 +305,12 @@ def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **
 
    HighLevelSynthesisPlugin
    HighLevelSynthesisPluginManager
+   high_level_synthesis_plugin_names
 
 """
 
 import abc
+from typing import List
 
 import stevedore
 
@@ -595,3 +638,22 @@ def method(self, op_name, method_name):
         """Returns the plugin for ``op_name`` and ``method_name``."""
         plugin_name = op_name + "." + method_name
         return self.plugins[plugin_name].obj
+
+
+def high_level_synthesis_plugin_names(op_name: str) -> List[str]:
+    """Return a list of plugin names installed for a given high level object name
+
+    Args:
+        op_name: The operation name to find the installed plugins for. For example,
+            if you provide ``"clifford"`` as the input it will find all the installed
+            clifford synthesis plugins that can synthesize :class:`.Clifford` objects.
+            The name refers to the :attr:`.Operation.name` attribute of the relevant objects.
+
+    Returns:
+        A list of installed plugin names for the specified high level operation
+
+    """
+    # NOTE: This is not a shared global instance to avoid an import cycle
+    # at load time for the default plugins.
+    plugin_manager = HighLevelSynthesisPluginManager()
+    return plugin_manager.method_names(op_name)


Test patch: