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');
|
||||
T2 = TypeVar('T2');
|
||||
|
||||
SCALE = (1., 4.);
|
||||
SCALE = (1., 1.5);
|
||||
OFFSET = (3., 0.);
|
||||
HMARGIN = 0.1;
|
||||
VMARGIN = 0.2;
|
||||
@ -119,15 +119,15 @@ class Functions:
|
||||
for k, f in enumerate(self.fcts):
|
||||
if k == 0:
|
||||
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:
|
||||
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:
|
||||
comp_range_next = [y for x, y in f.fct if x in comp_range];
|
||||
|
||||
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:
|
||||
for i, p in enumerate(p_domain):
|
||||
x_name = f.domain[i];
|
||||
@ -136,7 +136,7 @@ class Functions:
|
||||
for j, p in enumerate(p_codomain):
|
||||
y = f.codomain[j];
|
||||
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];
|
||||
if show_labels:
|
||||
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];
|
||||
x = f.domain[i];
|
||||
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:
|
||||
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:
|
||||
comp_range = comp_range_next;
|
||||
axs.set_aspect('equal')
|
||||
return fig, axs;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -188,7 +189,7 @@ def random_points(
|
||||
scale: tuple[float, float] = (1., 1.),
|
||||
centre: tuple[float, float] = (0., 0.),
|
||||
force: bool = False,
|
||||
tol: float = 0.2,
|
||||
tol: float = 0.1,
|
||||
) -> NDArray[Shape['*, 2'], Float]:
|
||||
theta = np.linspace(start=0, stop=2*np.pi, num=nr_points, endpoint=False);
|
||||
r_min = 0.25;
|
||||
|
@ -12,8 +12,8 @@ from src.maths.sets.random import *;
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'Letters',
|
||||
'random_function',
|
||||
'randomset_alphabet',
|
||||
'randomset_greek',
|
||||
'randomset_integers',
|
||||
];
|
||||
|
@ -15,9 +15,9 @@ from src.thirdparty.maths import *;
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
__all__ = [
|
||||
'Letters',
|
||||
'randomset_integers',
|
||||
'randomset_alphabet',
|
||||
'randomset_greek',
|
||||
'random_function',
|
||||
];
|
||||
|
||||
@ -25,29 +25,68 @@ __all__ = [
|
||||
# CONSTANTS / VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
ALPHA = 'abcdefghijklmnopqrstuvwxyz';
|
||||
GREEK = 'αβγδεζηθικλμνξοπρςτυφχψω';
|
||||
# local usage only
|
||||
T1 = TypeVar('T1');
|
||||
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
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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:
|
||||
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]:
|
||||
if N == -1:
|
||||
def randomset_alphabet(
|
||||
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);
|
||||
return list([a for k, a in enumerate(ALPHA) if k < N]);
|
||||
|
||||
def randomset_greek(N: int = -1, low: int = 1, high: int = 1) -> list[int]:
|
||||
if N == -1:
|
||||
N = random.randint(low, high);
|
||||
return list([a for k, a in enumerate(GREEK) if k < N]);
|
||||
if shuffle:
|
||||
return sample(letters, size=N, replace=False);
|
||||
return letters[:N];
|
||||
|
||||
def random_function(
|
||||
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 numpy as np;
|
||||
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
|
||||
@ -19,4 +42,5 @@ __all__ = [
|
||||
'math',
|
||||
'np',
|
||||
'random',
|
||||
'sample',
|
||||
];
|
||||
|
@ -9,6 +9,7 @@ from __future__ import annotations;
|
||||
|
||||
from src.thirdparty.types import *;
|
||||
from src.thirdparty.plots import *;
|
||||
from src.thirdparty.maths import *;
|
||||
from src.thirdparty.render import *;
|
||||
|
||||
from src.maths.diagrams import *;
|
||||
@ -32,11 +33,13 @@ class FunctionDiagramWidget():
|
||||
N_max: int;
|
||||
fnames: list[str];
|
||||
setnames: list[str];
|
||||
setsfrom: list[list[Any]];
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
fnames: list[str],
|
||||
setnames: list[str],
|
||||
setsfrom: dict[str, list[Any]] | list[list[Any]] = [],
|
||||
N: Optional[int] = 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}.';
|
||||
self.fnames = fnames;
|
||||
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):
|
||||
if self.N is None:
|
||||
@ -59,7 +75,7 @@ class FunctionDiagramWidget():
|
||||
cardinalities = [ kwargs[f'card_{k}'] for k in range(N+1)];
|
||||
injective = [ kwargs[f'injective_{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(*[
|
||||
Function(
|
||||
name = (f'{self.fnames[k]}', f'{self.setnames[k]}', f'{self.setnames[k+1]}'),
|
||||
@ -85,38 +101,47 @@ class FunctionDiagramWidget():
|
||||
return;
|
||||
|
||||
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);
|
||||
controls_card = [
|
||||
widgets.IntSlider(
|
||||
value = None,
|
||||
description = f'|{self.setnames[k]}|',
|
||||
# value = None,
|
||||
value = min(3,len(XX)),
|
||||
description = f'|{setname}|',
|
||||
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 = [
|
||||
widgets.Checkbox(
|
||||
value = None,
|
||||
description = f'{self.fnames[k]} injektiv?',
|
||||
value = False,
|
||||
description = f'{fname} injektiv?',
|
||||
style = {
|
||||
'description_width': 'initial',
|
||||
},
|
||||
visible = True,
|
||||
)
|
||||
for k in range(N)
|
||||
for fname in self.fnames[:N]
|
||||
];
|
||||
controls_surjective = [
|
||||
widgets.Checkbox(
|
||||
value = None,
|
||||
description = f'{self.fnames[k]} surjectiv?',
|
||||
value = False,
|
||||
description = f'{fname} surjectiv?',
|
||||
style = {
|
||||
'description_width': 'initial',
|
||||
},
|
||||
visible = True,
|
||||
)
|
||||
for k in range(N)
|
||||
for fname in self.fnames[:N]
|
||||
];
|
||||
# controls_func = [None for _ in range(2*N)];
|
||||
# controls_func[::2] = controls_injective;
|
||||
@ -136,19 +161,33 @@ class FunctionDiagramWidget():
|
||||
# for k in range(N)
|
||||
# ];
|
||||
ui = widgets.VBox(
|
||||
[show_labels] \
|
||||
[ button_refresh ] \
|
||||
+ [ button_show_labels ] \
|
||||
+ controls_card \
|
||||
+ [
|
||||
widgets.HBox([control_injective, control_surjective])
|
||||
for control_injective, control_surjective in zip(controls_injective, controls_surjective)
|
||||
]
|
||||
widgets.HBox(
|
||||
[
|
||||
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(widgets.interactive_output(
|
||||
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'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;
|
||||
|
Loading…
Reference in New Issue
Block a user