From 240c6737620086a9f2ece3dfeb308e47ccef4f22 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Sat, 22 Oct 2022 18:39:01 +0200 Subject: [PATCH] =?UTF-8?q?master=20>=20master:=20notebook=20-=20dynamisch?= =?UTF-8?q?e=20Anpassung=20-=20optionen=20f=C3=BCr=20Fkt-Eigenschaften=20b?= =?UTF-8?q?eschr=C3=A4nkt=20durch=20Kardinalit=C3=A4ten=20der=20Mengen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/widgets/function_diagrams.py | 83 ++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/widgets/function_diagrams.py b/src/widgets/function_diagrams.py index bdbd958..40efa24 100644 --- a/src/widgets/function_diagrams.py +++ b/src/widgets/function_diagrams.py @@ -7,6 +7,7 @@ from __future__ import annotations; +from src.thirdparty.code import *; from src.thirdparty.types import *; from src.thirdparty.plots import *; from src.thirdparty.maths import *; @@ -30,12 +31,12 @@ __all__ = [ class FunctionProperty(Enum): NOTHING = '—'; INJECTIVE = 'injektiv'; - SURJECTIVE = 'surjektiv'; NOT_INJECTIVE = '¬ injektiv'; + SURJECTIVE = 'surjektiv'; NOT_SURJECTIVE = '¬ surjektiv'; + BOTH = 'injektiv + surjektiv'; INJECTIVE_NOT_SURJECTIVE = 'injektiv + ¬ surjektiv'; NOT_INJECTIVE_SURJECTIVE = '¬ injektiv + surjektiv'; - BOTH = 'injektiv + surjektiv'; NEITHER = '¬ injektiv + ¬ surjektiv'; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -49,6 +50,7 @@ class FunctionDiagramWidget(): fnames: list[str]; setnames: list[str]; setsfrom: list[list[Any]]; + card: list[int]; def __init__( self, @@ -76,6 +78,7 @@ class FunctionDiagramWidget(): ]; n = len(setsfrom); self.setsfrom = [ setsfrom[k % n] for k, name in enumerate(setnames) ]; + self.card = [ min(3, len(XX)) for XX in self.setsfrom ]; def run(self): if self.N is None: @@ -87,11 +90,11 @@ class FunctionDiagramWidget(): display(self.state); def handler_plot(self, N: int, show_labels: bool, **kwargs): - cardinalities = [ kwargs[f'card_{k}'] for k in range(N+1)]; + self.card[:(N+1)] = [ kwargs[f'card_{k}'] for k in range(N+1) ]; properties = [ option_to_property(kwargs[f'property_{k}']) for k in range(N)]; injective = list(map(is_injective, properties)); surjective = list(map(is_surjective, properties)); - X = [ XX[:card] for XX, card in zip(self.setsfrom, cardinalities) ]; + X = [ XX[:card] for XX, card in zip(self.setsfrom[:(N+1)], self.card[:(N+1)]) ]; comp = Functions(*[ Function( name = (f'{self.fnames[k]}', f'{self.setnames[k]}', f'{self.setnames[k+1]}'), @@ -102,18 +105,6 @@ class FunctionDiagramWidget(): for k in range(N) ]); fig, axs = comp.draw(show_labels=show_labels); - # # for k in range(N): - # # [m, n] = cardinalities[k:][:2]; - # # inj = injective[k]; - # # surj = surjective[k]; - # # if m < n and surj: - # # print(f'\x1b[1m{self.fnames[k]}\x1b[0m kann nicht surjektiv sein'); - # # if m > n and inj: - # # print(f'\x1b[1m{self.fnames[k]}\x1b[0m kann nicht injektiv sein'); - # # if n == 1 and not surj: - # # print(f'\x1b[1m{self.fnames[k]}\x1b[0m kann nicht nicht-surjektiv sein'); - # # if m == 1 and not inj: - # # print(f'\x1b[1m{self.fnames[k]}\x1b[0m kann nicht nicht-injektiv sein'); return; def handler_wrapper(self, N: int): @@ -129,27 +120,45 @@ class FunctionDiagramWidget(): control_nr = widgets.IntSlider(value=N); controls_card = [ widgets.IntSlider( - # value = None, - value = min(3,len(XX)), + value = card, description = f'|{setname}|', min = 1, max = len(XX), ) - for setname, XX in zip(self.setnames[:(N+1)], self.setsfrom[:(N+1)]) + for setname, XX, card in zip(self.setnames[:(N+1)], self.setsfrom[:(N+1)], self.card[:(N+1)]) ]; + + # controls for properties of functions controls_property = [ widgets.RadioButtons( - options = [e.value for e in FunctionProperty], + options = [ e.value for e in possible_properties(all=True) ], value = FunctionProperty.NOTHING.value, layout = { 'description_width': 'initial', 'width': 'initial', }, - # description = f'Eigenschaften von {self.fnames[k]}', disabled = False, ) for k in range(N) ]; + # NOTE: dynamically change the possible properties based on the cardinalities. + def update_controls_property(change, k: int): + self.card[k] = change['new']; + if k > 0: + m = self.card[k-1]; + n = self.card[k]; + controls_property[k-1].options = [ e.value for e in possible_properties(m, n) ]; + if k < N: + m = self.card[k]; + n = self.card[k+1]; + controls_property[k].options = [ e.value for e in possible_properties(m, n) ]; + + for k, control_card in enumerate(controls_card): + control_card.observe( + partial(update_controls_property, k=k), + names='value', + ); + ui = widgets.VBox( [ button_refresh ] \ + [ button_show_labels ] \ @@ -195,6 +204,38 @@ def option_to_property(option: str) -> Optional[FunctionProperty]: except: return None; +def possible_properties(m: int = 1, n: int = 1, all: bool = False) -> list[FunctionProperty]: + if not all: + if m == 1 and n == 1: + return [ + e for e in FunctionProperty + if (is_injective(e) not in [False]) + and (is_surjective(e) not in [False]) + ]; + elif m == 1 and n > 1: + return [ + e for e in FunctionProperty + if (is_injective(e) not in [False]) + and (is_surjective(e) not in [True]) + ]; + elif n == 1 and m > 1: + return [ + e for e in FunctionProperty + if (is_surjective(e) not in [False]) + and (is_injective(e) not in [True]) + ]; + elif m > n: + return [ + e for e in FunctionProperty + if (is_injective(e) not in [True]) + ]; + elif n > m: + return [ + e for e in FunctionProperty + if (is_surjective(e) not in [True]) + ]; + return [ e for e in FunctionProperty ]; + def is_injective(property: Optional[FunctionProperty]) -> Optional[bool]: match property: case FunctionProperty.INJECTIVE | FunctionProperty.INJECTIVE_NOT_SURJECTIVE | FunctionProperty.BOTH: