From e9d6f98ca12f59f312475d37908a2b33ef9fdc9c Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Wed, 15 Feb 2023 21:55:10 +0100
Subject: [PATCH] Add interleaver generators

---
 b_asic/gui_utils/__init__.py   |   0
 b_asic/research/__init__.py    |   0
 b_asic/research/interleaver.py | 112 +++++++++++++++++++++++++++++++++
 docs_sphinx/Makefile           |   2 +-
 docs_sphinx/gui_utils.rst      |   9 +++
 docs_sphinx/index.rst          |   2 +
 docs_sphinx/research.rst       |   9 +++
 7 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 b_asic/gui_utils/__init__.py
 create mode 100644 b_asic/research/__init__.py
 create mode 100644 b_asic/research/interleaver.py
 create mode 100644 docs_sphinx/gui_utils.rst
 create mode 100644 docs_sphinx/research.rst

diff --git a/b_asic/gui_utils/__init__.py b/b_asic/gui_utils/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/b_asic/research/__init__.py b/b_asic/research/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/b_asic/research/interleaver.py b/b_asic/research/interleaver.py
new file mode 100644
index 00000000..83eb4b3b
--- /dev/null
+++ b/b_asic/research/interleaver.py
@@ -0,0 +1,112 @@
+"""
+Functions to generate memory-variable test data that are used for research.
+"""
+
+import random
+from typing import Optional, Set
+
+from b_asic.process import PlainMemoryVariable
+
+
+def _insert_delays(inputorder, outputorder, min_lifetime, cyclic):
+    size = len(inputorder)
+    maxdiff = min(outputorder[i] - inputorder[i] for i in range(size))
+    outputorder = [o - maxdiff + min_lifetime for o in outputorder]
+    maxdelay = max(outputorder[i] - inputorder[i] for i in range(size))
+    if cyclic:
+        if maxdelay < size:
+            outputorder = [o % size for o in outputorder]
+        else:
+            inputorder = inputorder + [i + size for i in inputorder]
+            outputorder = outputorder + [o + size for o in outputorder]
+    return inputorder, outputorder
+
+
+def generate_random_interleaver(
+    size: int, min_lifetime: int = 0, cyclic: bool = True
+) -> Set[PlainMemoryVariable]:
+    """
+    Generate a ProcessCollection with memory variable corresponding to a random
+    interleaver with length *size*.
+
+    Parameters
+    ----------
+    size : int
+        The size of the random interleaver sequence.
+    min_lifetime : int, default: 0
+        The minimum lifetime for a memory variable. Default is 0 meaning that at least
+        one variable is passed from the input to the output directly,
+    cyclic : bool, default: True
+        If the interleaver should operate continuously in a cyclic manner. That is,
+        start a new interleaving operation directly after the previous.
+
+    Returns
+    -------
+        ProcessCollection
+
+    """
+    inputorder = list(range(size))
+    outputorder = inputorder[:]
+    random.shuffle(outputorder)
+    print(inputorder, outputorder)
+    inputorder, outputorder = _insert_delays(
+        inputorder, outputorder, min_lifetime, cyclic
+    )
+    print(inputorder, outputorder)
+    return {
+        PlainMemoryVariable(inputorder[i], 0, {0: outputorder[i]})
+        for i in range(size)
+    }
+
+
+def generate_matrix_transposer(
+    height: int,
+    width: Optional[int] = None,
+    min_lifetime: int = 0,
+    cyclic: bool = True,
+) -> Set[PlainMemoryVariable]:
+    r"""
+    Generate a ProcessCollection with memory variable corresponding to transposing a
+    matrix of size *height* :math:`\times` *width*. If *width* is not provided, a
+    square matrix of size *height* :math:`\times` *height* is used.
+
+    Parameters
+    ----------
+    height : int
+        Matrix height.
+    width : int, optional
+        Matrix width. If not provided assumed to be equal to height, i.e., a square
+        matrix.
+    min_lifetime : int, default: 0
+        The minimum lifetime for a memory variable. Default is 0 meaning that at
+        least one variable is passed from the input to the output directly,
+    cyclic : bool, default: True
+        If the interleaver should operate continuously in a cyclic manner. That is,
+        start a new interleaving operation directly after the previous.
+
+    Returns
+    -------
+        ProcessCollection
+    """
+    if width is None:
+        width = height
+
+    inputorder = []
+    for row in range(height):
+        for col in range(width):
+            inputorder.append(col + width * row)
+
+    outputorder = []
+    for row in range(width):
+        for col in range(height):
+            outputorder.append(col * width + row)
+
+    print(inputorder, outputorder)
+    inputorder, outputorder = _insert_delays(
+        inputorder, outputorder, min_lifetime, cyclic
+    )
+    print(inputorder, outputorder)
+    return {
+        PlainMemoryVariable(inputorder[i], 0, {0: outputorder[i]})
+        for i in range(width * height)
+    }
diff --git a/docs_sphinx/Makefile b/docs_sphinx/Makefile
index a5036b7a..1bede10d 100644
--- a/docs_sphinx/Makefile
+++ b/docs_sphinx/Makefile
@@ -20,7 +20,7 @@ clean:
 	rm -rf "$(SOURCEDIR)/examples"
 
 show:
-	@python -c "import webbrowser; webbrowser.open_new_tab('file://$(shell pwd)/build/html/index.html')"
+	@python -c "import webbrowser; webbrowser.open_new_tab('file://$(shell pwd)/_build/html/index.html')"
 
 # Catch-all target: route all unknown targets to Sphinx using the new
 # "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
diff --git a/docs_sphinx/gui_utils.rst b/docs_sphinx/gui_utils.rst
new file mode 100644
index 00000000..2396b29c
--- /dev/null
+++ b/docs_sphinx/gui_utils.rst
@@ -0,0 +1,9 @@
+gui\_utils package
+==================
+
+gui\_utils.about\_window module
+-------------------------------
+
+.. automodule:: b_asic.gui_utils.about_window
+   :members:
+   :undoc-members:
diff --git a/docs_sphinx/index.rst b/docs_sphinx/index.rst
index 9ebbd2b4..3242ce54 100644
--- a/docs_sphinx/index.rst
+++ b/docs_sphinx/index.rst
@@ -28,4 +28,6 @@ Table of Contents
    api/index
    GUI
    scheduler_gui
+   gui_utils
    examples/index
+   research
diff --git a/docs_sphinx/research.rst b/docs_sphinx/research.rst
new file mode 100644
index 00000000..e64712df
--- /dev/null
+++ b/docs_sphinx/research.rst
@@ -0,0 +1,9 @@
+Research functions
+==================
+
+research.interleaver module
+---------------------------
+
+.. automodule:: b_asic.research.interleaver
+   :members:
+   :undoc-members:
-- 
GitLab