Skip to content

Commit

Permalink
Add a counter for graph atlas.
Browse files Browse the repository at this point in the history
  • Loading branch information
KmolYuan committed Jun 30, 2019
1 parent a82afe1 commit 7acc193
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 60 deletions.
1 change: 1 addition & 0 deletions core/synthesis/structure_synthesis/Ui_structure_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ def retranslateUi(self, Form):
self.number_synthesis_button.setStatusTip(_translate("Form", "Find the possible number of different joints."))
self.number_synthesis_button.setText(_translate("Form", "Number Synthesis"))
self.link_assortment_list.headerItem().setText(0, _translate("Form", "Link Assortment / Contracted Link Assortment"))
self.link_assortment_list.headerItem().setText(1, _translate("Form", "Count"))
self.graph_engine_text.setText(_translate("Form", "Engine: "))
self.graph_engine.setStatusTip(_translate("Form", "Layout engine from NetworkX."))
self.reload_atlas.setToolTip(_translate("Form", "Re-layout"))
Expand Down
96 changes: 48 additions & 48 deletions core/synthesis/structure_synthesis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@

from typing import (
TYPE_CHECKING,
Tuple,
List,
Sequence,
Dict,
Iterable,
Optional,
)
from time import time
Expand All @@ -43,15 +41,20 @@
QScrollBar,
QListWidgetItem,
QTreeWidgetItem,
QHeaderView,
)
from core.libs import (
VJoint,
Graph,
link_assortment as l_a,
contracted_link_assortment as c_l_a,
link_assortment,
contracted_link_assortment,
)
from core.graphics import to_graph, engines
from .thread import LinkSynthesisThread, GraphEnumerateThread
from .thread import (
assortment_eval,
LinkSynthesisThread,
GraphEnumerateThread,
)
from .Ui_structure_widget import Ui_Form

if TYPE_CHECKING:
Expand All @@ -62,20 +65,6 @@
Assortment = Sequence[int]


def _link_assortment(links_expr: str) -> Assortment:
"""Return link assortment from expr."""
return tuple(int(n.split('=')[-1]) for n in links_expr.split(", "))


def compare_assortment(first: Tuple[int, ...], second: Sequence[Tuple[int, ...]]) -> int:
"""Compare assortment."""
my_len = len(first)
for i, job in enumerate(second):
if job == first + (0,) * (len(job) - my_len):
return i
return -1


class SynthesisProgressDialog(QProgressDialog):

"""Progress dialog for structure synthesis."""
Expand Down Expand Up @@ -118,6 +107,7 @@ def __init__(self, parent: MainWindowBase):
"""
super(StructureSynthesis, self).__init__(parent)
self.setupUi(self)
self.link_assortment_list.header().setSectionResizeMode(QHeaderView.ResizeToContents)

# Function references
self.output_to = parent.output_to
Expand Down Expand Up @@ -286,11 +276,11 @@ def update_result(assortment: Dict[Assortment, List[Assortment]]):
for la, cla_list in assortment.items():
la_item = QTreeWidgetItem([", ".join(
f"NL{i + 2} = {a}" for i, a in enumerate(la)
)])
), "N/A"])
for cla in cla_list:
la_item.addChild(QTreeWidgetItem([", ".join(
f"NC{i + 1} = {a}" for i, a in enumerate(cla)
)]))
), "N/A"]))
self.link_assortment_list.addTopLevelItem(la_item)
first_item = self.link_assortment_list.topLevelItem(0)
self.link_assortment_list.setCurrentItem(first_item)
Expand Down Expand Up @@ -323,54 +313,64 @@ def __structure_synthesis(self):
root = item.parent()
if root is None:
# Find by link assortment
_l_a = _link_assortment(item.text(0))
self.__structural_combine(
((_l_a, _c_l_a) for _c_l_a in self.assortment[_l_a]),
len(self.assortment[_l_a])
)
else:
# Find by contracted link assortment
try:
_l_a = _link_assortment(root.text(0))
_c_l_a = _link_assortment(item.text(0))
# Test
assortment_eval(item.text(0))
except ValueError:
return
self.__structural_combine(((_l_a, _c_l_a),), 1)
jobs = [item.child(i) for i in range(item.childCount())]
self.__structural_combine(jobs)
else:
# Find by contracted link assortment
jobs = [item]
self.__structural_combine(jobs)

@Slot(name='on_structure_synthesis_all_button_clicked')
def __structure_synthesis_all(self):
"""Structural synthesis - find all."""
self.__clear_structure_list()

def iterator():
for k, v in self.assortment.items():
for s in v:
yield (k, s)

self.__structural_combine(iterator(), sum(len(l) for l in self.assortment.values()))

def __structural_combine(
self,
jobs: Iterable[Tuple[Assortment, Assortment]],
count: int
):
jobs = []
for i in range(self.link_assortment_list.topLevelItemCount()):
root: QTreeWidgetItem = self.link_assortment_list.topLevelItem(i)
for j in range(root.childCount()):
jobs.append(root.child(j))
self.__structural_combine(jobs)

def __structural_combine(self, jobs: Sequence[QTreeWidgetItem]):
"""Structural combine by iterator."""
t0 = time()
dlg = SynthesisProgressDialog(
"Structural Synthesis",
f"Number of cases: {count}",
count,
f"Number of cases: {len(jobs)}",
len(jobs),
self
)

@Slot(QTreeWidgetItem, int)
def update_count(item: QTreeWidgetItem, count: int):
"""Update the number of graphs."""
item.setText(1, f"{count}")

@Slot(list)
def update_result(answer: List[Graph]):
"""Update the result of atlas."""
self.answer = answer
dlg.deleteLater()
for i in range(self.link_assortment_list.topLevelItemCount()):
root: QTreeWidgetItem = self.link_assortment_list.topLevelItem(i)
count = 0
for j in range(root.childCount()):
item = root.child(j)
try:
count += int(item.text(1))
except ValueError:
pass
root.setText(1, f"{count}")
self.__set_time_count(time() - t0, len(self.answer))
self.__reload_atlas()

work = GraphEnumerateThread(jobs, self.graph_degenerate.currentIndex(), dlg)
work.count_update.connect(update_count)
work.progress_update.connect(dlg.setValue)
work.result.connect(update_result)
dlg.show()
Expand Down Expand Up @@ -425,8 +425,8 @@ def __draw_atlas(self, i: int, g: Graph) -> bool:
))
item.setToolTip(
f"Edge Set: {list(g.edges)}\n"
f"Link assortment: {l_a(g)}\n"
f"Contracted Link assortment: {c_l_a(g)}"
f"Link assortment: {link_assortment(g)}\n"
f"Contracted Link assortment: {contracted_link_assortment(g)}"
)
self.structure_list.addItem(item)
return True
Expand Down
5 changes: 5 additions & 0 deletions core/synthesis/structure_synthesis/structure_widget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@
<string>Link Assortment / Contracted Link Assortment</string>
</property>
</column>
<column>
<property name="text">
<string>Count</string>
</property>
</column>
</widget>
</item>
</layout>
Expand Down
29 changes: 17 additions & 12 deletions core/synthesis/structure_synthesis/thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
__license__ = "AGPL"
__email__ = "[email protected]"

from typing import Tuple, Sequence, Iterable
from typing import Sequence
from core.synthesis.thread import BaseThread
from core.QtModules import Signal, QWidget
from core.QtModules import Signal, QWidget, QTreeWidgetItem
from core.libs import (
link_synthesis,
contracted_link_synthesis,
Expand All @@ -20,6 +20,11 @@
Assortment = Sequence[int]


def assortment_eval(links_expr: str) -> Assortment:
"""Return link assortment from expr."""
return tuple(int(n.split('=')[-1]) for n in links_expr.split(", "))


class LinkSynthesisThread(BaseThread):

"""Link assortment synthesis thread."""
Expand Down Expand Up @@ -59,14 +64,10 @@ class GraphEnumerateThread(BaseThread):
"""Graphs enumeration thread."""

progress_update = Signal(int)
count_update = Signal(QTreeWidgetItem, int)
result = Signal(list)

def __init__(
self,
jobs: Iterable[Tuple[Assortment, Assortment]],
degenerate: int,
parent: QWidget
):
def __init__(self, jobs: Sequence[QTreeWidgetItem], degenerate: int, parent: QWidget):
super(GraphEnumerateThread, self).__init__(parent)
self.jobs = jobs
self.degenerate = degenerate
Expand All @@ -75,20 +76,24 @@ def run(self):
"""Run and return conventional graph."""
cg_list = {}
answers = []
for i, (la, cla) in enumerate(self.jobs):
for i, item in enumerate(self.jobs):
if self.is_stop:
break

root = item.parent()
la = assortment_eval(root.text(0))
cla = assortment_eval(item.text(0))
if la not in cg_list:
cg_list[la] = contracted_graph(la, lambda: self.is_stop)

answers.extend(conventional_graph(
answer = conventional_graph(
cg_list[la],
cla,
self.degenerate,
lambda: self.is_stop
))

)
self.count_update.emit(item, len(answer))
answers.extend(answer)
self.progress_update.emit(1 + i)

self.result.emit(answers)
Expand Down

0 comments on commit 7acc193

Please sign in to comment.