master > master: notebook - dynamische Anpassung

- optionen für Fkt-Eigenschaften beschränkt durch Kardinalitäten der Mengen
This commit is contained in:
RD 2022-10-22 18:39:01 +02:00
parent 011fe1d9d9
commit 240c673762

View File

@ -7,6 +7,7 @@
from __future__ import annotations; from __future__ import annotations;
from src.thirdparty.code import *;
from src.thirdparty.types import *; from src.thirdparty.types import *;
from src.thirdparty.plots import *; from src.thirdparty.plots import *;
from src.thirdparty.maths import *; from src.thirdparty.maths import *;
@ -30,12 +31,12 @@ __all__ = [
class FunctionProperty(Enum): class FunctionProperty(Enum):
NOTHING = ''; NOTHING = '';
INJECTIVE = 'injektiv'; INJECTIVE = 'injektiv';
SURJECTIVE = 'surjektiv';
NOT_INJECTIVE = '¬ injektiv'; NOT_INJECTIVE = '¬ injektiv';
SURJECTIVE = 'surjektiv';
NOT_SURJECTIVE = '¬ surjektiv'; NOT_SURJECTIVE = '¬ surjektiv';
BOTH = 'injektiv + surjektiv';
INJECTIVE_NOT_SURJECTIVE = 'injektiv + ¬ surjektiv'; INJECTIVE_NOT_SURJECTIVE = 'injektiv + ¬ surjektiv';
NOT_INJECTIVE_SURJECTIVE = '¬ injektiv + surjektiv'; NOT_INJECTIVE_SURJECTIVE = '¬ injektiv + surjektiv';
BOTH = 'injektiv + surjektiv';
NEITHER = '¬ injektiv + ¬ surjektiv'; NEITHER = '¬ injektiv + ¬ surjektiv';
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -49,6 +50,7 @@ class FunctionDiagramWidget():
fnames: list[str]; fnames: list[str];
setnames: list[str]; setnames: list[str];
setsfrom: list[list[Any]]; setsfrom: list[list[Any]];
card: list[int];
def __init__( def __init__(
self, self,
@ -76,6 +78,7 @@ class FunctionDiagramWidget():
]; ];
n = len(setsfrom); n = len(setsfrom);
self.setsfrom = [ setsfrom[k % n] for k, name in enumerate(setnames) ]; 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): def run(self):
if self.N is None: if self.N is None:
@ -87,11 +90,11 @@ class FunctionDiagramWidget():
display(self.state); display(self.state);
def handler_plot(self, N: int, show_labels: bool, **kwargs): 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)]; properties = [ option_to_property(kwargs[f'property_{k}']) for k in range(N)];
injective = list(map(is_injective, properties)); injective = list(map(is_injective, properties));
surjective = list(map(is_surjective, 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(*[ comp = Functions(*[
Function( Function(
name = (f'{self.fnames[k]}', f'{self.setnames[k]}', f'{self.setnames[k+1]}'), 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) for k in range(N)
]); ]);
fig, axs = comp.draw(show_labels=show_labels); 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; return;
def handler_wrapper(self, N: int): def handler_wrapper(self, N: int):
@ -129,27 +120,45 @@ class FunctionDiagramWidget():
control_nr = widgets.IntSlider(value=N); control_nr = widgets.IntSlider(value=N);
controls_card = [ controls_card = [
widgets.IntSlider( widgets.IntSlider(
# value = None, value = card,
value = min(3,len(XX)),
description = f'|{setname}|', description = f'|{setname}|',
min = 1, min = 1,
max = len(XX), 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 = [ controls_property = [
widgets.RadioButtons( widgets.RadioButtons(
options = [e.value for e in FunctionProperty], options = [ e.value for e in possible_properties(all=True) ],
value = FunctionProperty.NOTHING.value, value = FunctionProperty.NOTHING.value,
layout = { layout = {
'description_width': 'initial', 'description_width': 'initial',
'width': 'initial', 'width': 'initial',
}, },
# description = f'Eigenschaften von {self.fnames[k]}',
disabled = False, disabled = False,
) )
for k in range(N) 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( ui = widgets.VBox(
[ button_refresh ] \ [ button_refresh ] \
+ [ button_show_labels ] \ + [ button_show_labels ] \
@ -195,6 +204,38 @@ def option_to_property(option: str) -> Optional[FunctionProperty]:
except: except:
return None; 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]: def is_injective(property: Optional[FunctionProperty]) -> Optional[bool]:
match property: match property:
case FunctionProperty.INJECTIVE | FunctionProperty.INJECTIVE_NOT_SURJECTIVE | FunctionProperty.BOTH: case FunctionProperty.INJECTIVE | FunctionProperty.INJECTIVE_NOT_SURJECTIVE | FunctionProperty.BOTH: