We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
print summary fails for sum kernel

System information:

* Python version: 3.7
* TensorFlow installed from pip tf2 nightly
* TensorFlow version (use command below):'2.0.0-dev20190930'
* GPflow installed from (source or binary): python setup.py develop
* GPflow version: awav/gpflow-2.0



... _Describe the current behavior_
MWE:
```
k = gpflow.kernels.SquaredExponential() + gpflow.kernels.SquaredExponential()
print_summary(k)

Output:
name    class    transform    trainable    shape    dtype    value
------  -------  -----------  -----------  -------  -------  -------
```
... _Describe the expected behavior_
should print the values of the summed kernel's parameters.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gpflow/utilities/utilities.py`
Content:
```
1 import re
2 from functools import lru_cache
3 from typing import Callable, Dict, List, Optional, Union
4 
5 import numpy as np
6 import tensorflow as tf
7 from tabulate import tabulate
8 from tensorflow.python.training.tracking.data_structures import ListWrapper, _DictWrapper
9 
10 from ..base import Parameter
11 from ..config import summary_fmt
12 
13 __all__ = [
14     "set_trainable",
15     "multiple_assign",
16     "training_loop",
17     "print_summary",
18 ]
19 
20 
21 def set_trainable(model: tf.Module, flag: bool = False):
22     """
23     Set trainable flag for all `tf.Variable`s and `gpflow.Parameter`s in a module.
24     """
25     for variable in model.trainable_variables:
26         variable._trainable = flag
27 
28 
29 def multiple_assign(input: tf.Module, vars_dict: Dict[str, tf.Tensor]):
30     """
31     Multiple assign takes a dictionary with new values. Dictionary keys are paths to the
32     `tf.Variable`s or `gpflow.Parameters` of the input module.
33 
34     :param input: `tf.Module`.
35     :param vars_dict: a dictionary with keys of the form "module.path.to.variable" and new value tensors.
36     """
37     reference_var_dict = leaf_components(input)
38     for path, value in vars_dict.items():
39         reference_var_dict[path].assign(value)
40 
41 
42 def training_loop(closure: Callable[..., tf.Tensor],
43                   optimizer: Optional[tf.optimizers.Optimizer] = None,
44                   var_list: List[tf.Variable] = None,
45                   maxiter=1e3,
46                   jit=False):
47     """
48     Simple generic training loop. At each iteration uses a GradientTape to compute
49     the gradients of a loss function with respect to a set of variables.
50 
51     :param closure: Callable that constructs a loss function based on data and model being trained
52     :param optimizer: tf.optimizers or tf.keras.optimizers that updates variables by applying the
53         corresponding loss gradients. Adam is a default optimizer with default settings.
54     :param var_list: List of model variables to be learnt during training
55     :param maxiter: Maximum number of
56     :return:
57     """
58 
59     optimizer = tf.optimizers.Adam() if optimizer is None else optimizer
60 
61     def optimization_step():
62         with tf.GradientTape() as tape:
63             tape.watch(var_list)
64             loss = closure()
65             grads = tape.gradient(loss, var_list)
66         optimizer.apply_gradients(zip(grads, var_list))
67 
68     if jit:
69         optimization_step = tf.function(optimization_step)
70 
71     for _ in range(int(maxiter)):
72         optimization_step()
73 
74 
75 def print_summary(module: tf.Module, fmt: str = None):
76     """
77     Prints a summary of the parameters and variables contained in a tf.Module.
78     """
79 
80     fmt = fmt if fmt is not None else summary_fmt()
81     column_names = ['name', 'class', 'transform', 'trainable', 'shape', 'dtype', 'value']
82 
83     def get_name(v):
84         return v.__class__.__name__
85 
86     def get_transform(v):
87         if hasattr(v, "transform") and v.transform is not None:
88             return v.transform.__class__.__name__
89         return None
90 
91     merged_leaf_components = _merge_leaf_components(leaf_components(module))
92 
93     column_values = [[
94         path,
95         get_name(variable),
96         get_transform(variable),
97         variable.trainable,
98         variable.shape,
99         variable.dtype.name,
100         _str_tensor_value(variable.numpy())
101     ] for path, variable in merged_leaf_components.items()]
102 
103     if fmt == "notebook":
104         from IPython.core.display import display, HTML
105         tab = tabulate(column_values, headers=column_names, tablefmt="html")
106         display(HTML(tab))
107     else:
108         print(tabulate(column_values, headers=column_names, tablefmt=fmt))
109 
110 
111 def leaf_components(input: tf.Module):
112     return _get_leaf_components(input)
113 
114 
115 def _merge_leaf_components(
116         input: Dict[str, Union[tf.Tensor, Parameter]]) -> Dict[str, Union[tf.Tensor, Parameter]]:
117     if len(set(input.values())) == len(input):
118         return input
119     tmp_dict = dict()
120     for key, item in input.items():
121         if item in tmp_dict:
122             tmp_dict[item] = f"{tmp_dict[item]}\n{key}"
123         else:
124             tmp_dict[item] = key
125     return {key: item for item, key in tmp_dict.items()}
126 
127 
128 def _get_leaf_components(input: tf.Module, prefix: Optional[str] = None):
129     """
130     Returns a list of tuples each corresponding to a gpflow.Parameter or tf.Variable in the each
131     submodules of a given tf.Module. Each tuple consists of an specific Parameter (or Variable) and
132     its relative path inside the module, which is constructed recursively by adding a prefix with
133     the path to the current module. Designed to be used as a helper for the method 'print_summary'.
134 
135     :param module: tf.Module including keras.Model, keras.layers.Layer and gpflow.Module.
136     :param prefix: string containing the relative path to module, by default set to None.
137     :return:
138     """
139     if not isinstance(input, tf.Module):
140         raise TypeError("Input object expected to have `tf.Module` type")
141 
142     prefix = input.__class__.__name__ if prefix is None else prefix
143     var_dict = dict()
144 
145     for key, submodule in vars(input).items():
146         if key in tf.Module._TF_MODULE_IGNORED_PROPERTIES:
147             continue
148         elif isinstance(submodule, Parameter) or isinstance(submodule, tf.Variable):
149             var_dict[f"{prefix}.{key}"] = submodule
150         elif isinstance(submodule, tf.Module):
151             submodule_var = _get_leaf_components(submodule, prefix=f"{prefix}.{key}")
152             var_dict.update(submodule_var)
153         elif isinstance(submodule, ListWrapper):
154             submodule_name = input.__class__.__name__
155             for term_idx, subterm in enumerate(submodule):
156                 subterm_key = f"{submodule_name}_{key}[{term_idx}]"
157                 if isinstance(subterm, Parameter):
158                     subterm_var = _get_leaf_components(subterm, prefix=f"{prefix}.{subterm_key}")
159                     var_dict.update(subterm_var)
160         elif isinstance(submodule, _DictWrapper):
161             submodule_name = input.__class__.__name__
162             for term_key, subterm in submodule.items():
163                 subterm_key = f"{submodule_name}_{key}[{term_key}]"
164                 subterm_var = _get_leaf_components(subterm, prefix=f"{prefix}.{subterm_key}")
165                 var_dict.update(subterm_var)
166     return var_dict
167 
168 
169 @lru_cache()
170 def _first_three_elements_regexp():
171     num_re = r"[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?"
172     pat_re = rf"^(?:(\[+)\s*)?({num_re})(?:\s+({num_re})(?:\s+({num_re}))?)?.*?"
173     return re.compile(pat_re)
174 
175 
176 def _str_tensor_value(value: np.ndarray):
177     value_str = str(value)
178     if value.size <= 3:
179         return value_str
180 
181     max_chars = 500
182     value_str = value_str[:max_chars]
183     regexp = _first_three_elements_regexp()
184     match = regexp.match(value_str)
185     assert match is not None
186     brackets, elem1, elem2, elem3 = match.groups()
187 
188     out = f"{elem1}"
189     if elem2 is not None:
190         out = f"{out}{f', {elem2}'}"
191         if elem3 is not None:
192             out = f"{out}{f', {elem3}'}"
193     if brackets is not None:
194         out = f"{brackets}{out}..."
195 
196     return out
197
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gpflow/utilities/utilities.py b/gpflow/utilities/utilities.py
--- a/gpflow/utilities/utilities.py
+++ b/gpflow/utilities/utilities.py
@@ -100,6 +100,7 @@
         _str_tensor_value(variable.numpy())
     ] for path, variable in merged_leaf_components.items()]
 
+
     if fmt == "notebook":
         from IPython.core.display import display, HTML
         tab = tabulate(column_values, headers=column_names, tablefmt="html")
@@ -154,7 +155,7 @@
             submodule_name = input.__class__.__name__
             for term_idx, subterm in enumerate(submodule):
                 subterm_key = f"{submodule_name}_{key}[{term_idx}]"
-                if isinstance(subterm, Parameter):
+                if isinstance(subterm, tf.Module):
                     subterm_var = _get_leaf_components(subterm, prefix=f"{prefix}.{subterm_key}")
                     var_dict.update(subterm_var)
         elif isinstance(submodule, _DictWrapper):

{"golden_diff": "diff --git a/gpflow/utilities/utilities.py b/gpflow/utilities/utilities.py\n--- a/gpflow/utilities/utilities.py\n+++ b/gpflow/utilities/utilities.py\n@@ -100,6 +100,7 @@\n         _str_tensor_value(variable.numpy())\n     ] for path, variable in merged_leaf_components.items()]\n \n+\n     if fmt == \"notebook\":\n         from IPython.core.display import display, HTML\n         tab = tabulate(column_values, headers=column_names, tablefmt=\"html\")\n@@ -154,7 +155,7 @@\n             submodule_name = input.__class__.__name__\n             for term_idx, subterm in enumerate(submodule):\n                 subterm_key = f\"{submodule_name}_{key}[{term_idx}]\"\n-                if isinstance(subterm, Parameter):\n+                if isinstance(subterm, tf.Module):\n                     subterm_var = _get_leaf_components(subterm, prefix=f\"{prefix}.{subterm_key}\")\n                     var_dict.update(subterm_var)\n         elif isinstance(submodule, _DictWrapper):\n", "issue": "print summary fails for sum kernel\n\r\nSystem information:\r\n\r\n* Python version: 3.7\r\n* TensorFlow installed from pip tf2 nightly\r\n* TensorFlow version (use command below):'2.0.0-dev20190930'\r\n* GPflow installed from (source or binary): python setup.py develop\r\n* GPflow version: awav/gpflow-2.0\r\n\r\n\r\n\r\n... _Describe the current behavior_\r\nMWE:\r\n```\r\nk = gpflow.kernels.SquaredExponential() + gpflow.kernels.SquaredExponential()\r\nprint_summary(k)\r\n\r\nOutput:\r\nname    class    transform    trainable    shape    dtype    value\r\n------  -------  -----------  -----------  -------  -------  -------\r\n```\r\n... _Describe the expected behavior_\r\nshould print the values of the summed kernel's parameters.\r\n\n", "before_files": [{"content": "import re\nfrom functools import lru_cache\nfrom typing import Callable, Dict, List, Optional, Union\n\nimport numpy as np\nimport tensorflow as tf\nfrom tabulate import tabulate\nfrom tensorflow.python.training.tracking.data_structures import ListWrapper, _DictWrapper\n\nfrom ..base import Parameter\nfrom ..config import summary_fmt\n\n__all__ = [\n    \"set_trainable\",\n    \"multiple_assign\",\n    \"training_loop\",\n    \"print_summary\",\n]\n\n\ndef set_trainable(model: tf.Module, flag: bool = False):\n    \"\"\"\n    Set trainable flag for all `tf.Variable`s and `gpflow.Parameter`s in a module.\n    \"\"\"\n    for variable in model.trainable_variables:\n        variable._trainable = flag\n\n\ndef multiple_assign(input: tf.Module, vars_dict: Dict[str, tf.Tensor]):\n    \"\"\"\n    Multiple assign takes a dictionary with new values. Dictionary keys are paths to the\n    `tf.Variable`s or `gpflow.Parameters` of the input module.\n\n    :param input: `tf.Module`.\n    :param vars_dict: a dictionary with keys of the form \"module.path.to.variable\" and new value tensors.\n    \"\"\"\n    reference_var_dict = leaf_components(input)\n    for path, value in vars_dict.items():\n        reference_var_dict[path].assign(value)\n\n\ndef training_loop(closure: Callable[..., tf.Tensor],\n                  optimizer: Optional[tf.optimizers.Optimizer] = None,\n                  var_list: List[tf.Variable] = None,\n                  maxiter=1e3,\n                  jit=False):\n    \"\"\"\n    Simple generic training loop. At each iteration uses a GradientTape to compute\n    the gradients of a loss function with respect to a set of variables.\n\n    :param closure: Callable that constructs a loss function based on data and model being trained\n    :param optimizer: tf.optimizers or tf.keras.optimizers that updates variables by applying the\n        corresponding loss gradients. Adam is a default optimizer with default settings.\n    :param var_list: List of model variables to be learnt during training\n    :param maxiter: Maximum number of\n    :return:\n    \"\"\"\n\n    optimizer = tf.optimizers.Adam() if optimizer is None else optimizer\n\n    def optimization_step():\n        with tf.GradientTape() as tape:\n            tape.watch(var_list)\n            loss = closure()\n            grads = tape.gradient(loss, var_list)\n        optimizer.apply_gradients(zip(grads, var_list))\n\n    if jit:\n        optimization_step = tf.function(optimization_step)\n\n    for _ in range(int(maxiter)):\n        optimization_step()\n\n\ndef print_summary(module: tf.Module, fmt: str = None):\n    \"\"\"\n    Prints a summary of the parameters and variables contained in a tf.Module.\n    \"\"\"\n\n    fmt = fmt if fmt is not None else summary_fmt()\n    column_names = ['name', 'class', 'transform', 'trainable', 'shape', 'dtype', 'value']\n\n    def get_name(v):\n        return v.__class__.__name__\n\n    def get_transform(v):\n        if hasattr(v, \"transform\") and v.transform is not None:\n            return v.transform.__class__.__name__\n        return None\n\n    merged_leaf_components = _merge_leaf_components(leaf_components(module))\n\n    column_values = [[\n        path,\n        get_name(variable),\n        get_transform(variable),\n        variable.trainable,\n        variable.shape,\n        variable.dtype.name,\n        _str_tensor_value(variable.numpy())\n    ] for path, variable in merged_leaf_components.items()]\n\n    if fmt == \"notebook\":\n        from IPython.core.display import display, HTML\n        tab = tabulate(column_values, headers=column_names, tablefmt=\"html\")\n        display(HTML(tab))\n    else:\n        print(tabulate(column_values, headers=column_names, tablefmt=fmt))\n\n\ndef leaf_components(input: tf.Module):\n    return _get_leaf_components(input)\n\n\ndef _merge_leaf_components(\n        input: Dict[str, Union[tf.Tensor, Parameter]]) -> Dict[str, Union[tf.Tensor, Parameter]]:\n    if len(set(input.values())) == len(input):\n        return input\n    tmp_dict = dict()\n    for key, item in input.items():\n        if item in tmp_dict:\n            tmp_dict[item] = f\"{tmp_dict[item]}\\n{key}\"\n        else:\n            tmp_dict[item] = key\n    return {key: item for item, key in tmp_dict.items()}\n\n\ndef _get_leaf_components(input: tf.Module, prefix: Optional[str] = None):\n    \"\"\"\n    Returns a list of tuples each corresponding to a gpflow.Parameter or tf.Variable in the each\n    submodules of a given tf.Module. Each tuple consists of an specific Parameter (or Variable) and\n    its relative path inside the module, which is constructed recursively by adding a prefix with\n    the path to the current module. Designed to be used as a helper for the method 'print_summary'.\n\n    :param module: tf.Module including keras.Model, keras.layers.Layer and gpflow.Module.\n    :param prefix: string containing the relative path to module, by default set to None.\n    :return:\n    \"\"\"\n    if not isinstance(input, tf.Module):\n        raise TypeError(\"Input object expected to have `tf.Module` type\")\n\n    prefix = input.__class__.__name__ if prefix is None else prefix\n    var_dict = dict()\n\n    for key, submodule in vars(input).items():\n        if key in tf.Module._TF_MODULE_IGNORED_PROPERTIES:\n            continue\n        elif isinstance(submodule, Parameter) or isinstance(submodule, tf.Variable):\n            var_dict[f\"{prefix}.{key}\"] = submodule\n        elif isinstance(submodule, tf.Module):\n            submodule_var = _get_leaf_components(submodule, prefix=f\"{prefix}.{key}\")\n            var_dict.update(submodule_var)\n        elif isinstance(submodule, ListWrapper):\n            submodule_name = input.__class__.__name__\n            for term_idx, subterm in enumerate(submodule):\n                subterm_key = f\"{submodule_name}_{key}[{term_idx}]\"\n                if isinstance(subterm, Parameter):\n                    subterm_var = _get_leaf_components(subterm, prefix=f\"{prefix}.{subterm_key}\")\n                    var_dict.update(subterm_var)\n        elif isinstance(submodule, _DictWrapper):\n            submodule_name = input.__class__.__name__\n            for term_key, subterm in submodule.items():\n                subterm_key = f\"{submodule_name}_{key}[{term_key}]\"\n                subterm_var = _get_leaf_components(subterm, prefix=f\"{prefix}.{subterm_key}\")\n                var_dict.update(subterm_var)\n    return var_dict\n\n\n@lru_cache()\ndef _first_three_elements_regexp():\n    num_re = r\"[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?\"\n    pat_re = rf\"^(?:(\\[+)\\s*)?({num_re})(?:\\s+({num_re})(?:\\s+({num_re}))?)?.*?\"\n    return re.compile(pat_re)\n\n\ndef _str_tensor_value(value: np.ndarray):\n    value_str = str(value)\n    if value.size <= 3:\n        return value_str\n\n    max_chars = 500\n    value_str = value_str[:max_chars]\n    regexp = _first_three_elements_regexp()\n    match = regexp.match(value_str)\n    assert match is not None\n    brackets, elem1, elem2, elem3 = match.groups()\n\n    out = f\"{elem1}\"\n    if elem2 is not None:\n        out = f\"{out}{f', {elem2}'}\"\n        if elem3 is not None:\n            out = f\"{out}{f', {elem3}'}\"\n    if brackets is not None:\n        out = f\"{brackets}{out}...\"\n\n    return out\n", "path": "gpflow/utilities/utilities.py"}], "after_files": [{"content": "import re\nfrom functools import lru_cache\nfrom typing import Callable, Dict, List, Optional, Union\n\nimport numpy as np\nimport tensorflow as tf\nfrom tabulate import tabulate\nfrom tensorflow.python.training.tracking.data_structures import ListWrapper, _DictWrapper\n\nfrom ..base import Parameter\nfrom ..config import summary_fmt\n\n__all__ = [\n    \"set_trainable\",\n    \"multiple_assign\",\n    \"training_loop\",\n    \"print_summary\",\n]\n\n\ndef set_trainable(model: tf.Module, flag: bool = False):\n    \"\"\"\n    Set trainable flag for all `tf.Variable`s and `gpflow.Parameter`s in a module.\n    \"\"\"\n    for variable in model.trainable_variables:\n        variable._trainable = flag\n\n\ndef multiple_assign(input: tf.Module, vars_dict: Dict[str, tf.Tensor]):\n    \"\"\"\n    Multiple assign takes a dictionary with new values. Dictionary keys are paths to the\n    `tf.Variable`s or `gpflow.Parameters` of the input module.\n\n    :param input: `tf.Module`.\n    :param vars_dict: a dictionary with keys of the form \"module.path.to.variable\" and new value tensors.\n    \"\"\"\n    reference_var_dict = leaf_components(input)\n    for path, value in vars_dict.items():\n        reference_var_dict[path].assign(value)\n\n\ndef training_loop(closure: Callable[..., tf.Tensor],\n                  optimizer: Optional[tf.optimizers.Optimizer] = None,\n                  var_list: List[tf.Variable] = None,\n                  maxiter=1e3,\n                  jit=False):\n    \"\"\"\n    Simple generic training loop. At each iteration uses a GradientTape to compute\n    the gradients of a loss function with respect to a set of variables.\n\n    :param closure: Callable that constructs a loss function based on data and model being trained\n    :param optimizer: tf.optimizers or tf.keras.optimizers that updates variables by applying the\n        corresponding loss gradients. Adam is a default optimizer with default settings.\n    :param var_list: List of model variables to be learnt during training\n    :param maxiter: Maximum number of\n    :return:\n    \"\"\"\n\n    optimizer = tf.optimizers.Adam() if optimizer is None else optimizer\n\n    def optimization_step():\n        with tf.GradientTape() as tape:\n            tape.watch(var_list)\n            loss = closure()\n            grads = tape.gradient(loss, var_list)\n        optimizer.apply_gradients(zip(grads, var_list))\n\n    if jit:\n        optimization_step = tf.function(optimization_step)\n\n    for _ in range(int(maxiter)):\n        optimization_step()\n\n\ndef print_summary(module: tf.Module, fmt: str = None):\n    \"\"\"\n    Prints a summary of the parameters and variables contained in a tf.Module.\n    \"\"\"\n\n    fmt = fmt if fmt is not None else summary_fmt()\n    column_names = ['name', 'class', 'transform', 'trainable', 'shape', 'dtype', 'value']\n\n    def get_name(v):\n        return v.__class__.__name__\n\n    def get_transform(v):\n        if hasattr(v, \"transform\") and v.transform is not None:\n            return v.transform.__class__.__name__\n        return None\n\n    merged_leaf_components = _merge_leaf_components(leaf_components(module))\n\n    column_values = [[\n        path,\n        get_name(variable),\n        get_transform(variable),\n        variable.trainable,\n        variable.shape,\n        variable.dtype.name,\n        _str_tensor_value(variable.numpy())\n    ] for path, variable in merged_leaf_components.items()]\n\n\n    if fmt == \"notebook\":\n        from IPython.core.display import display, HTML\n        tab = tabulate(column_values, headers=column_names, tablefmt=\"html\")\n        display(HTML(tab))\n    else:\n        print(tabulate(column_values, headers=column_names, tablefmt=fmt))\n\n\ndef leaf_components(input: tf.Module):\n    return _get_leaf_components(input)\n\n\ndef _merge_leaf_components(\n        input: Dict[str, Union[tf.Tensor, Parameter]]) -> Dict[str, Union[tf.Tensor, Parameter]]:\n    if len(set(input.values())) == len(input):\n        return input\n    tmp_dict = dict()\n    for key, item in input.items():\n        if item in tmp_dict:\n            tmp_dict[item] = f\"{tmp_dict[item]}\\n{key}\"\n        else:\n            tmp_dict[item] = key\n    return {key: item for item, key in tmp_dict.items()}\n\n\ndef _get_leaf_components(input: tf.Module, prefix: Optional[str] = None):\n    \"\"\"\n    Returns a list of tuples each corresponding to a gpflow.Parameter or tf.Variable in the each\n    submodules of a given tf.Module. Each tuple consists of an specific Parameter (or Variable) and\n    its relative path inside the module, which is constructed recursively by adding a prefix with\n    the path to the current module. Designed to be used as a helper for the method 'print_summary'.\n\n    :param module: tf.Module including keras.Model, keras.layers.Layer and gpflow.Module.\n    :param prefix: string containing the relative path to module, by default set to None.\n    :return:\n    \"\"\"\n    if not isinstance(input, tf.Module):\n        raise TypeError(\"Input object expected to have `tf.Module` type\")\n\n    prefix = input.__class__.__name__ if prefix is None else prefix\n    var_dict = dict()\n\n    for key, submodule in vars(input).items():\n        if key in tf.Module._TF_MODULE_IGNORED_PROPERTIES:\n            continue\n        elif isinstance(submodule, Parameter) or isinstance(submodule, tf.Variable):\n            var_dict[f\"{prefix}.{key}\"] = submodule\n        elif isinstance(submodule, tf.Module):\n            submodule_var = _get_leaf_components(submodule, prefix=f\"{prefix}.{key}\")\n            var_dict.update(submodule_var)\n        elif isinstance(submodule, ListWrapper):\n            submodule_name = input.__class__.__name__\n            for term_idx, subterm in enumerate(submodule):\n                subterm_key = f\"{submodule_name}_{key}[{term_idx}]\"\n                if isinstance(subterm, tf.Module):\n                    subterm_var = _get_leaf_components(subterm, prefix=f\"{prefix}.{subterm_key}\")\n                    var_dict.update(subterm_var)\n        elif isinstance(submodule, _DictWrapper):\n            submodule_name = input.__class__.__name__\n            for term_key, subterm in submodule.items():\n                subterm_key = f\"{submodule_name}_{key}[{term_key}]\"\n                subterm_var = _get_leaf_components(subterm, prefix=f\"{prefix}.{subterm_key}\")\n                var_dict.update(subterm_var)\n    return var_dict\n\n\n@lru_cache()\ndef _first_three_elements_regexp():\n    num_re = r\"[+\\-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?\"\n    pat_re = rf\"^(?:(\\[+)\\s*)?({num_re})(?:\\s+({num_re})(?:\\s+({num_re}))?)?.*?\"\n    return re.compile(pat_re)\n\n\ndef _str_tensor_value(value: np.ndarray):\n    value_str = str(value)\n    if value.size <= 3:\n        return value_str\n\n    max_chars = 500\n    value_str = value_str[:max_chars]\n    regexp = _first_three_elements_regexp()\n    match = regexp.match(value_str)\n    assert match is not None\n    brackets, elem1, elem2, elem3 = match.groups()\n\n    out = f\"{elem1}\"\n    if elem2 is not None:\n        out = f\"{out}{f', {elem2}'}\"\n        if elem3 is not None:\n            out = f\"{out}{f', {elem3}'}\"\n    if brackets is not None:\n        out = f\"{brackets}{out}...\"\n\n    return out\n", "path": "gpflow/utilities/utilities.py"}]}