master > master: src - clean up
- enums für Alphabete - button layout - refresh Knopf - aspect ratio
This commit is contained in:
parent
56744bd389
commit
1d627623c7
@ -28,7 +28,7 @@ __all__ = [
|
|||||||
T1 = TypeVar('T1');
|
T1 = TypeVar('T1');
|
||||||
T2 = TypeVar('T2');
|
T2 = TypeVar('T2');
|
||||||
|
|
||||||
SCALE = (1., 4.);
|
SCALE = (1., 1.5);
|
||||||
OFFSET = (3., 0.);
|
OFFSET = (3., 0.);
|
||||||
HMARGIN = 0.1;
|
HMARGIN = 0.1;
|
||||||
VMARGIN = 0.2;
|
VMARGIN = 0.2;
|
||||||
@ -119,15 +119,15 @@ class Functions:
|
|||||||
for k, f in enumerate(self.fcts):
|
for k, f in enumerate(self.fcts):
|
||||||
if k == 0:
|
if k == 0:
|
||||||
comp_range = f.domain;
|
comp_range = f.domain;
|
||||||
p_domain = random_points(nr_points=len(f.domain), scale=SCALE, centre=origin + k*offset);
|
p_domain = random_points(nr_points=len(f.domain), scale=SCALE, centre=origin + k*offset, tol=0.5);
|
||||||
else:
|
else:
|
||||||
p_domain = p_codomain;
|
p_domain = p_codomain;
|
||||||
p_codomain = random_points(nr_points=len(f.codomain), scale=SCALE, centre=origin + (k+1)*offset);
|
p_codomain = random_points(nr_points=len(f.codomain), scale=SCALE, centre=origin + (k+1)*offset, tol=0.5);
|
||||||
# range of composition so far:
|
# range of composition so far:
|
||||||
comp_range_next = [y for x, y in f.fct if x in comp_range];
|
comp_range_next = [y for x, y in f.fct if x in comp_range];
|
||||||
|
|
||||||
if k == 0:
|
if k == 0:
|
||||||
axs.scatter(p_domain[:, 0], p_domain[:, 1], label='', color='black', marker='o');
|
axs.scatter(p_domain[:, 0], p_domain[:, 1], label='', color='blue', marker='o');
|
||||||
if show_labels:
|
if show_labels:
|
||||||
for i, p in enumerate(p_domain):
|
for i, p in enumerate(p_domain):
|
||||||
x_name = f.domain[i];
|
x_name = f.domain[i];
|
||||||
@ -136,7 +136,7 @@ class Functions:
|
|||||||
for j, p in enumerate(p_codomain):
|
for j, p in enumerate(p_codomain):
|
||||||
y = f.codomain[j];
|
y = f.codomain[j];
|
||||||
marker = 'o' if (y in comp_range_next) else '.';
|
marker = 'o' if (y in comp_range_next) else '.';
|
||||||
axs.scatter([p[0]], [p[1]], label='', color='black', marker=marker);
|
axs.scatter([p[0]], [p[1]], label='', color='blue', marker=marker);
|
||||||
y_name = f.codomain[j];
|
y_name = f.codomain[j];
|
||||||
if show_labels:
|
if show_labels:
|
||||||
axs.annotate(text=f'{y_name}', xy=p, textcoords='offset points', xytext=ANNOTATE_OFFSET, ha='center', size=FONTSIZE_PTS);
|
axs.annotate(text=f'{y_name}', xy=p, textcoords='offset points', xytext=ANNOTATE_OFFSET, ha='center', size=FONTSIZE_PTS);
|
||||||
@ -146,7 +146,7 @@ class Functions:
|
|||||||
q = p_codomain[j];
|
q = p_codomain[j];
|
||||||
x = f.domain[i];
|
x = f.domain[i];
|
||||||
if k == 0 or (x in comp_range):
|
if k == 0 or (x in comp_range):
|
||||||
axs.plot([p[0], q[0]], [p[1], q[1]], label='', color='black', linewidth=1);
|
axs.plot([p[0], q[0]], [p[1], q[1]], label='', color='blue', linewidth=1);
|
||||||
else:
|
else:
|
||||||
axs.plot([p[0], q[0]], [p[1], q[1]], label='', color='red', linestyle='--', linewidth=1);
|
axs.plot([p[0], q[0]], [p[1], q[1]], label='', color='red', linestyle='--', linewidth=1);
|
||||||
|
|
||||||
@ -165,6 +165,7 @@ class Functions:
|
|||||||
|
|
||||||
# update range of composition:
|
# update range of composition:
|
||||||
comp_range = comp_range_next;
|
comp_range = comp_range_next;
|
||||||
|
axs.set_aspect('equal')
|
||||||
return fig, axs;
|
return fig, axs;
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -188,7 +189,7 @@ def random_points(
|
|||||||
scale: tuple[float, float] = (1., 1.),
|
scale: tuple[float, float] = (1., 1.),
|
||||||
centre: tuple[float, float] = (0., 0.),
|
centre: tuple[float, float] = (0., 0.),
|
||||||
force: bool = False,
|
force: bool = False,
|
||||||
tol: float = 0.2,
|
tol: float = 0.1,
|
||||||
) -> NDArray[Shape['*, 2'], Float]:
|
) -> NDArray[Shape['*, 2'], Float]:
|
||||||
theta = np.linspace(start=0, stop=2*np.pi, num=nr_points, endpoint=False);
|
theta = np.linspace(start=0, stop=2*np.pi, num=nr_points, endpoint=False);
|
||||||
r_min = 0.25;
|
r_min = 0.25;
|
||||||
|
@ -12,8 +12,8 @@ from src.maths.sets.random import *;
|
|||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'Letters',
|
||||||
'random_function',
|
'random_function',
|
||||||
'randomset_alphabet',
|
'randomset_alphabet',
|
||||||
'randomset_greek',
|
|
||||||
'randomset_integers',
|
'randomset_integers',
|
||||||
];
|
];
|
||||||
|
@ -15,9 +15,9 @@ from src.thirdparty.maths import *;
|
|||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
'Letters',
|
||||||
'randomset_integers',
|
'randomset_integers',
|
||||||
'randomset_alphabet',
|
'randomset_alphabet',
|
||||||
'randomset_greek',
|
|
||||||
'random_function',
|
'random_function',
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -25,29 +25,68 @@ __all__ = [
|
|||||||
# CONSTANTS / VARIABLES
|
# CONSTANTS / VARIABLES
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
ALPHA = 'abcdefghijklmnopqrstuvwxyz';
|
# local usage only
|
||||||
GREEK = 'αβγδεζηθικλμνξοπρςτυφχψω';
|
|
||||||
T1 = TypeVar('T1');
|
T1 = TypeVar('T1');
|
||||||
T2 = TypeVar('T2');
|
T2 = TypeVar('T2');
|
||||||
|
|
||||||
|
class Letters(Enum):
|
||||||
|
# 'abcdefghijklmnopqrstuvwxyz'
|
||||||
|
ROMAN = [chr(97 + n) for n in range(26)];
|
||||||
|
# 'αβγδεζηθικλμνξοπρςτυφχψω'
|
||||||
|
GREEK = [chr(945 + n) for n in range(25)]
|
||||||
|
# 'אבגדהוזחטיךכלםמןנסעףפץצקרשת' (but <—)
|
||||||
|
HEBREW = [chr(1488 + n) for n in range(27)];
|
||||||
|
SYMBOLS = [
|
||||||
|
r'$|0\rangle$',
|
||||||
|
r'$|\uparrow\rangle$',
|
||||||
|
r'$|\downarrow\rangle$',
|
||||||
|
r'$\sqrt{2}$',
|
||||||
|
r'$\pi$',
|
||||||
|
r'$e$',
|
||||||
|
r'$\frac{1}{137}$',
|
||||||
|
r'$\infty$',
|
||||||
|
# r'$-\infty$',
|
||||||
|
r'$\clubsuit$',
|
||||||
|
# r'$\diamondsuit$',
|
||||||
|
r'$\heartsuit$',
|
||||||
|
# r'$\spadesuit$',
|
||||||
|
r'$\hbar$',
|
||||||
|
];
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# METHODS
|
# METHODS
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
def randomset_integers(N: int = -1, low: int = 1, high: int = 1) -> list[int]:
|
def randomset_integers(
|
||||||
|
N: int = -1,
|
||||||
|
low: int = 1,
|
||||||
|
high: int = 1,
|
||||||
|
shuffle: bool = False,
|
||||||
|
) -> list[int]:
|
||||||
if N == -1:
|
if N == -1:
|
||||||
N = random.randint(low, high);
|
N = random.randint(low, high);
|
||||||
return list(range(1, N+1));
|
values = list(range(1, N+1));
|
||||||
|
if shuffle:
|
||||||
|
return sample(values, size=N, replace=False);
|
||||||
|
return values;
|
||||||
|
|
||||||
def randomset_alphabet(N: int = -1, low: int = 1, high: int = 1) -> list[int]:
|
def randomset_alphabet(
|
||||||
if N == -1:
|
mode: Letters,
|
||||||
|
N: int = -1,
|
||||||
|
low: int = 1,
|
||||||
|
high: int = 1,
|
||||||
|
shuffle: bool = False,
|
||||||
|
full: bool = False,
|
||||||
|
) -> list[str]:
|
||||||
|
letters: list[str] = mode.value;
|
||||||
|
if full:
|
||||||
|
N = len(letters);
|
||||||
|
elif N == -1:
|
||||||
|
high = min(low+1, high)
|
||||||
N = random.randint(low, high);
|
N = random.randint(low, high);
|
||||||
return list([a for k, a in enumerate(ALPHA) if k < N]);
|
if shuffle:
|
||||||
|
return sample(letters, size=N, replace=False);
|
||||||
def randomset_greek(N: int = -1, low: int = 1, high: int = 1) -> list[int]:
|
return letters[:N];
|
||||||
if N == -1:
|
|
||||||
N = random.randint(low, high);
|
|
||||||
return list([a for k, a in enumerate(GREEK) if k < N]);
|
|
||||||
|
|
||||||
def random_function(
|
def random_function(
|
||||||
X: list[T1],
|
X: list[T1],
|
||||||
|
24
src/thirdparty/maths.py
vendored
24
src/thirdparty/maths.py
vendored
@ -9,6 +9,29 @@ from fractions import Fraction;
|
|||||||
import math;
|
import math;
|
||||||
import numpy as np;
|
import numpy as np;
|
||||||
import random;
|
import random;
|
||||||
|
from typing import TypeVar;
|
||||||
|
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
# MODIFICATIONS
|
||||||
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
# local usage only
|
||||||
|
T = TypeVar('T');
|
||||||
|
|
||||||
|
def sample(
|
||||||
|
X: list[T],
|
||||||
|
size: int = 1,
|
||||||
|
replace: bool = True,
|
||||||
|
) -> list[T]:
|
||||||
|
'''
|
||||||
|
@inputs
|
||||||
|
- `X` - a list
|
||||||
|
- `size` <int> - desired sample size
|
||||||
|
- `replace` <bool> - optional replacement
|
||||||
|
|
||||||
|
@returns a sample from an uniformly distributed set.
|
||||||
|
'''
|
||||||
|
return np.random.choice(X, size=size, replace=replace).tolist();
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
# EXPORTS
|
# EXPORTS
|
||||||
@ -19,4 +42,5 @@ __all__ = [
|
|||||||
'math',
|
'math',
|
||||||
'np',
|
'np',
|
||||||
'random',
|
'random',
|
||||||
|
'sample',
|
||||||
];
|
];
|
||||||
|
@ -9,6 +9,7 @@ from __future__ import annotations;
|
|||||||
|
|
||||||
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.render import *;
|
from src.thirdparty.render import *;
|
||||||
|
|
||||||
from src.maths.diagrams import *;
|
from src.maths.diagrams import *;
|
||||||
@ -32,11 +33,13 @@ class FunctionDiagramWidget():
|
|||||||
N_max: int;
|
N_max: int;
|
||||||
fnames: list[str];
|
fnames: list[str];
|
||||||
setnames: list[str];
|
setnames: list[str];
|
||||||
|
setsfrom: list[list[Any]];
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
fnames: list[str],
|
fnames: list[str],
|
||||||
setnames: list[str],
|
setnames: list[str],
|
||||||
|
setsfrom: dict[str, list[Any]] | list[list[Any]] = [],
|
||||||
N: Optional[int] = None,
|
N: Optional[int] = None,
|
||||||
):
|
):
|
||||||
self.state = None;
|
self.state = None;
|
||||||
@ -45,6 +48,19 @@ class FunctionDiagramWidget():
|
|||||||
assert len(setnames) == len(fnames) + 1, f'The number of sets must be {self.N_max+1}.';
|
assert len(setnames) == len(fnames) + 1, f'The number of sets must be {self.N_max+1}.';
|
||||||
self.fnames = fnames;
|
self.fnames = fnames;
|
||||||
self.setnames = setnames;
|
self.setnames = setnames;
|
||||||
|
# fix set contents:
|
||||||
|
if isinstance(setsfrom, dict):
|
||||||
|
default = randomset_alphabet(mode=Letters.ROMAN, shuffle=True, full=True);
|
||||||
|
setsfrom = [ setsfrom.get(name, default) for name in setnames ];
|
||||||
|
if len(setsfrom) == 0:
|
||||||
|
setsfrom = [
|
||||||
|
randomset_alphabet(mode=Letters.SYMBOLS, shuffle=True, full=True),
|
||||||
|
randomset_alphabet(mode=Letters.ROMAN, shuffle=True, full=True),
|
||||||
|
randomset_alphabet(mode=Letters.HEBREW, shuffle=True, full=True),
|
||||||
|
randomset_alphabet(mode=Letters.GREEK, shuffle=True, full=True),
|
||||||
|
];
|
||||||
|
n = len(setsfrom);
|
||||||
|
self.setsfrom = [ setsfrom[k % n] for k, name in enumerate(setnames) ];
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if self.N is None:
|
if self.N is None:
|
||||||
@ -59,7 +75,7 @@ class FunctionDiagramWidget():
|
|||||||
cardinalities = [ kwargs[f'card_{k}'] for k in range(N+1)];
|
cardinalities = [ kwargs[f'card_{k}'] for k in range(N+1)];
|
||||||
injective = [ kwargs[f'injective_{k}'] for k in range(N)];
|
injective = [ kwargs[f'injective_{k}'] for k in range(N)];
|
||||||
surjective = [ kwargs[f'surjective_{k}'] for k in range(N)];
|
surjective = [ kwargs[f'surjective_{k}'] for k in range(N)];
|
||||||
X = [ randomset_alphabet(N=card) for card in cardinalities ];
|
X = [ XX[:card] for XX, card in zip(self.setsfrom, cardinalities) ];
|
||||||
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]}'),
|
||||||
@ -85,38 +101,47 @@ class FunctionDiagramWidget():
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
def handler_wrapper(self, N: int):
|
def handler_wrapper(self, N: int):
|
||||||
show_labels = widgets.Checkbox(description='Labels anzeigen?', style={'description_width': 'initial'}, visible=True);
|
button_refresh = widgets.ToggleButton(description='Neu laden');
|
||||||
|
button_show_labels = widgets.Checkbox(
|
||||||
|
description = 'Labels anzeigen?',
|
||||||
|
value = True,
|
||||||
|
style = {
|
||||||
|
'description_width': 'initial',
|
||||||
|
},
|
||||||
|
visible = True
|
||||||
|
);
|
||||||
control_nr = widgets.IntSlider(value=N);
|
control_nr = widgets.IntSlider(value=N);
|
||||||
controls_card = [
|
controls_card = [
|
||||||
widgets.IntSlider(
|
widgets.IntSlider(
|
||||||
value = None,
|
# value = None,
|
||||||
description = f'|{self.setnames[k]}|',
|
value = min(3,len(XX)),
|
||||||
|
description = f'|{setname}|',
|
||||||
min = 1,
|
min = 1,
|
||||||
max = 24,
|
max = len(XX),
|
||||||
)
|
)
|
||||||
for k in range(N+1)
|
for setname, XX in zip(self.setnames[:(N+1)], self.setsfrom[:(N+1)])
|
||||||
];
|
];
|
||||||
controls_injective = [
|
controls_injective = [
|
||||||
widgets.Checkbox(
|
widgets.Checkbox(
|
||||||
value = None,
|
value = False,
|
||||||
description = f'{self.fnames[k]} injektiv?',
|
description = f'{fname} injektiv?',
|
||||||
style = {
|
style = {
|
||||||
'description_width': 'initial',
|
'description_width': 'initial',
|
||||||
},
|
},
|
||||||
visible = True,
|
visible = True,
|
||||||
)
|
)
|
||||||
for k in range(N)
|
for fname in self.fnames[:N]
|
||||||
];
|
];
|
||||||
controls_surjective = [
|
controls_surjective = [
|
||||||
widgets.Checkbox(
|
widgets.Checkbox(
|
||||||
value = None,
|
value = False,
|
||||||
description = f'{self.fnames[k]} surjectiv?',
|
description = f'{fname} surjectiv?',
|
||||||
style = {
|
style = {
|
||||||
'description_width': 'initial',
|
'description_width': 'initial',
|
||||||
},
|
},
|
||||||
visible = True,
|
visible = True,
|
||||||
)
|
)
|
||||||
for k in range(N)
|
for fname in self.fnames[:N]
|
||||||
];
|
];
|
||||||
# controls_func = [None for _ in range(2*N)];
|
# controls_func = [None for _ in range(2*N)];
|
||||||
# controls_func[::2] = controls_injective;
|
# controls_func[::2] = controls_injective;
|
||||||
@ -136,19 +161,33 @@ class FunctionDiagramWidget():
|
|||||||
# for k in range(N)
|
# for k in range(N)
|
||||||
# ];
|
# ];
|
||||||
ui = widgets.VBox(
|
ui = widgets.VBox(
|
||||||
[show_labels] \
|
[ button_refresh ] \
|
||||||
|
+ [ button_show_labels ] \
|
||||||
+ controls_card \
|
+ controls_card \
|
||||||
+ [
|
+ [
|
||||||
widgets.HBox([control_injective, control_surjective])
|
widgets.HBox(
|
||||||
for control_injective, control_surjective in zip(controls_injective, controls_surjective)
|
[
|
||||||
]
|
widgets.VBox(
|
||||||
|
[control_injective, control_surjective],
|
||||||
|
layout = {
|
||||||
|
'display': 'flex',
|
||||||
|
'align_items': 'stretch',
|
||||||
|
'width': '100%',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
for control_injective, control_surjective in zip(controls_injective, controls_surjective)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
);
|
);
|
||||||
display(ui);
|
display(ui);
|
||||||
display(widgets.interactive_output(
|
display(widgets.interactive_output(
|
||||||
f = self.handler_plot,
|
f = self.handler_plot,
|
||||||
controls = { 'N': control_nr, 'show_labels': show_labels } \
|
controls = { 'N': control_nr, 'show_labels': button_show_labels } \
|
||||||
| { f'card_{k}': controls_card[k] for k in range(N+1) } \
|
| { f'card_{k}': controls_card[k] for k in range(N+1) } \
|
||||||
| { f'injective_{k}': controls_injective[k] for k in range(N) } \
|
| { f'injective_{k}': controls_injective[k] for k in range(N) } \
|
||||||
| { f'surjective_{k}': controls_surjective[k] for k in range(N) }
|
| { f'surjective_{k}': controls_surjective[k] for k in range(N) } \
|
||||||
|
| { 'refresh': button_refresh }
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user