Esempio n. 1
0
 def translation(self, rel):
     origin_sp1 = self.origin_sp + Vector(rel)
     x_interval = (config["win_width"] / 2 -
                   config["x_max"] * self.unit_screen,
                   config["win_width"] / 2)
     y_interval = (config["win_height"] / 2, config["win_height"] / 2 +
                   config["y_max"] * self.unit_screen)
     x1 = clip(origin_sp1[0], *x_interval)
     y1 = clip(origin_sp1[1], *y_interval)
     self.origin_sp = Vector((x1, y1))
Esempio n. 2
0
 def zoom(self, pos, rate):
     pos = Vector(pos)
     unit_screen1 = clip(self.unit_screen * rate,
                         *config["camera.unit_screen.interval"])
     rate1 = unit_screen1 / self.unit_screen
     self.unit_screen = unit_screen1
     origin_sp1 = pos + (self.origin_sp - pos) * rate1
     x_interval = (config["win_width"] / 2 -
                   config["x_max"] * self.unit_screen,
                   config["win_width"] / 2)
     y_interval = (config["win_height"] / 2, config["win_height"] / 2 +
                   config["y_max"] * self.unit_screen)
     x1 = clip(origin_sp1[0], *x_interval)
     y1 = clip(origin_sp1[1], *y_interval)
     self.origin_sp = Vector((x1, y1))
Esempio n. 3
0
 def add_gen(cls, name: str, deg, deg3d=(0, 0, 0)):
     """Add a new generator and return it."""
     if cls.pred(deg3d):
         index = cls.generators[-1][0] + 1 if cls.generators else 0
         cls.generators.append(Gen(index, name, deg, Vector(deg3d)))
         m = ((index, -1),)
         return cls(m).simplify() if cls.auto_simplify else cls(m)
Esempio n. 4
0
 def basis_mons(cls, pred=None, basis: Dict[Vector, List[tuple]] = None):
     """Return a list of basis (mon, deg)."""
     pred = pred or cls.pred
     # noinspection PyArgumentList
     result = basis or defaultdict(list, {Vector((0, 0, 0)): [()]})
     old_ds = set(result)
     leadings = sorted(cls.rels, key=lambda _m: _m[-1][0])
     leadings = {index: list(g) for index, g in groupby(leadings, key=lambda _m: _m[-1][0])}
     for gen in cls.generators:
         index, deg3d = gen.index, gen.deg3d
         ds = list(result)
         for d in ds:
             if (d_ := d + deg3d) not in old_ds and pred(d_):
                 for m in result[d]:
                     i_m = m[-1][0] if m else -1
                     if index == i_m and d in old_ds:
                         e = 1
                         while pred(d1 := d + deg3d * e):
                             m1 = m[:-1] + ((m[-1][0], m[-1][1] - e),)
                             if index in leadings and any(map(le_dtuple, leadings[index], repeat(m1))):
                                 break
                             result[d1].append(m1)
                             e += 1
                     elif index > i_m:
                         e = 1
                         while pred(d1 := d + deg3d * e):
Esempio n. 5
0
    def basis_mons_h0(cls, pred=None):
        """Return a list of $h_0$-structure lines."""
        pred = pred or cls.pred

        def d3d_h0(d3d):
            return d3d - ((d3d0 := d3d[0]), d3d0, d3d0)

        # noinspection PyArgumentList
        result = defaultdict(list, {Vector((0, 0, 0)): [((0, -_S_MAX),)]})
        old_ds = set(result)
        leadings = sorted(cls.rels, key=lambda _m: _m[-1][0])
        leadings = {index: list(g) for index, g in groupby(leadings, key=lambda _m: _m[-1][0])}
        for gen in cls.generators:
            if gen.index == 0:
                continue
            index, deg3d = gen.index, d3d_h0(gen.deg3d)
            ds = list(result)
            for d in ds:
                if (d_ := d + deg3d) not in old_ds and pred(d_):
                    for m in result[d]:
                        i_m = m[-1][0] if m else -1
                        if index == i_m and d in old_ds:
                            e = 1
                            while pred(d1 := d + deg3d * e):
                                m1 = m[:-1] + ((m[-1][0], m[-1][1] - e),)
                                if index in leadings and any(map(le_dtuple, leadings[index], repeat(m1))):
                                    break
                                result[d1].append(m1)
                                e += 1
                        elif index > i_m:
                            e = 1
                            while pred(d1 := d + deg3d * e):
Esempio n. 6
0
 def __init__(self):
     """`origin_sp` is the screen position of world origin.
     `unit_screen` is the screen length of world unit length."""
     self.origin_sp = Vector(
         (config["margin_left"],
          config["win_height"] - config["margin_bottom"]))
     self.unit_screen = config["camera.unit_screen"]
Esempio n. 7
0
 def add_gens(cls, name_deg_deg3d_s):
     """Add generators. name_deg_deg3d_s is a list of tuples (name, deg, deg3d)."""
     index = cls.generators[-1][0] + 1 if cls.generators else 0
     for n, d, d3d in name_deg_deg3d_s:
         if cls.pred(d3d):
             cls.generators.append(Gen(index, n, d, Vector(d3d)))
             index += 1
Esempio n. 8
0
 def render_grid_numbers(self):
     """Draw the grid numbers."""
     n_label_step = math.ceil(config["axis_text_sep_screen"] /
                              self.camera.unit_screen)
     for i in range(0, config["y_max"] + 1, n_label_step):
         left = self.camera.wp2sp((0, i))
         text_pos = left - Vector([config["axis_text_sep_screen"], 0])
         if text_pos[0] < 16:
             text_pos[0] = 16
         self.paint.draw_text(str(i), text_pos,
                              config["axis_numbers_color"])
     for i in range(0, config["x_max"] + 1, n_label_step):
         bottom = self.camera.wp2sp((i, 0))
         text_pos = bottom + Vector([0, config["axis_text_sep_screen"]])
         if text_pos[1] > config["win_height"] - 16:
             text_pos[1] = config["win_height"] - 16
         self.paint.draw_text(str(i), text_pos,
                              config["axis_numbers_color"])
Esempio n. 9
0
 def to_dga(cls, deg_diff: tuple) -> "Type[GbDga]":
     class_name = f"GbDGA_{GbDga._name_index}"
     GbDga._name_index += 1
     # noinspection PyTypeChecker
     dct = {'generators': [DgaGen(*gen, None) for gen in cls.generators], 'rels': copy.deepcopy(cls.rels),
            '_rels_gen_leads': cls._rels_gen_leads.copy(),
            '_rels_cache': copy.deepcopy(cls._rels_cache),
            'key': cls.key, 'pred': cls.pred, 'auto_simplify': cls.auto_simplify,
            'deg_diff': Vector(deg_diff)}
     # noinspection PyTypeChecker
     return type(class_name, (GbDga,), dct)
Esempio n. 10
0
 def draw_arrow(self, start_pos, end_pos):
     """ Draw a classic arrow """
     d = Vector2c(end_pos) - Vector2c(start_pos)
     if abs(d) == 0:
         return
     d = d / abs(d)
     d1, d2 = d * (10+5j), d * (10-5j)
     end_pos = Vector(end_pos)
     self.draw_line(config["pen_color"], start_pos, end_pos)
     self.draw_line(config["pen_color"], end_pos - c2Vector(d1), end_pos)
     self.draw_line(config["pen_color"], end_pos - c2Vector(d2), end_pos)
Esempio n. 11
0
 def exp_collide_point(self, screen_pos, deg=None):
     """Return if `screen_pos` is in an expansion square."""
     for d in (deg, ) if deg else self.expansion:
         center = self.deg2sp(d)
         n = self.deg2num_bullets[d]
         num_edge = math.ceil(math.sqrt(n))
         length_edge = self.get_bullet_sep() * (num_edge + 1)
         size = Vector([length_edge, length_edge])
         rect = Rect(myroundv(center - size / 2), myroundv(size))
         if rect.collidepoint(*screen_pos):
             return d
     return None
Esempio n. 12
0
 def add_gen(cls, name: str, deg, deg3d=(0, 0, 0), diff=None):
     """Add a new generator and return it."""
     index = cls.generators[-1][0] + 1 if cls.generators else 0
     if diff is None:
         diff = set()
     elif type(diff) is not set:
         diff = diff.data
     if diff and cls.deg3d_data(diff) - deg3d != cls.deg_diff:
         raise BA.MyDegreeError("inconsistent differential degree")
     cls.generators.append(DgaGen(index, name, deg, Vector(deg3d), diff))
     m = ((index, -1),)
     return cls(m).simplify() if cls.auto_simplify else cls(m)
Esempio n. 13
0
 def addr2sp(self, addr):
     deg, index = addr
     if index is None:
         return self.deg2sp(deg)
     n = self.deg2num_bullets[deg]
     if n <= 9:
         offset = config["bullet.patterns"][
             n - 1][index] * self.get_bullet_sep() // 2
         return self.deg2sp(deg) + offset
     else:
         if deg in self.expansion or deg in self.spread:
             center = self.deg2sp(deg)
             n = self.deg2num_bullets[deg]
             num_edge = math.ceil(math.sqrt(n))
             length_edge = self.get_bullet_sep() * (num_edge + 1)
             size = Vector([length_edge, length_edge])
             y, x = divmod(index, num_edge)
             pos_bullet = (center - size / 2) + Vector(
                 [x + 1, y + 1]) * self.get_bullet_sep()
             return pos_bullet
         else:
             return self.deg2sp(deg)
Esempio n. 14
0
 def new_alg(*, key=None, pred=None, deg_diff=None) -> "Type[GbDga]":
     """Return a dynamically created subclass of GbDga."""
     cls = GbDga
     class_name = f"GbAlgMod2_{cls._name_index}"
     cls._name_index += 1
     if deg_diff is not None:
         deg_diff = Vector(deg_diff)
     else:
         raise BA.MyDegreeError("degree of differential not supplied")
     dct = {'generators': [], 'rels': {}, '_rels_gen_leads': set(), '_rels_cache': [],
            'key': key, 'pred': pred or GbAlgMod2.pred_default, 'auto_simplify': True, 'deg_diff': deg_diff}
     # noinspection PyTypeChecker
     return type(class_name, (cls,), dct)
Esempio n. 15
0
 def sp2addr(self, screen_pos):
     """* Return None if not on any bullet
     * Return (deg, None) if on folded bullet
     * Return (deg, index) if on some bullet"""
     deg = self.sp2deg(screen_pos)
     deg_expand = self.exp_collide_point(screen_pos) or (
         deg if deg in self.spread else None)
     if deg_expand:
         center = self.deg2sp(deg_expand)
         n = self.deg2num_bullets[deg_expand]
         num_edge = math.ceil(math.sqrt(n))
         length_edge = self.get_bullet_sep() * (num_edge + 1)
         size = Vector([length_edge, length_edge])
         offset = Vector(screen_pos) - (center - size / 2)
         x, y = myroundv(offset / self.get_bullet_sep())
         if 0 < x <= num_edge and 0 < y <= num_edge:
             index = x - 1 + num_edge * (y - 1)
             if index < n:
                 return deg_expand, index
         return None
     if deg in self.deg2num_bullets:
         n = self.deg2num_bullets[deg]
         if 0 < n <= 9:
             offset = Vector(screen_pos) - Vector(self.deg2sp(deg))
             index = self.offset_to_bullet(offset, n)
             if index is not None:
                 return deg, index
             else:
                 return None
         elif n > 9:
             if math.dist(screen_pos,
                          self.deg2sp(deg)) < 2 * self.get_bullet_radius():
                 return deg, None
             else:
                 return None
     else:
         return None
Esempio n. 16
0
    def construct_alg(pred, basis, cls_basis, fn: Callable[[Any], set], naming: Callable):
        """Construct an algebra from basis."""
        R = GbAlgMod2.new_alg(pred=pred)
        # noinspection PyArgumentList
        R_basis_mons = defaultdict(list, {Vector((0, 0, 0)): [()]})
        map_alg = linalg.GradedLinearMapKMod2()
        image_gens = {}
        basis_V = basis
        if basis:
            d = get_one_element(basis)
            if type(basis[d]) is not linalg.VectorSpaceMod2:
                basis_V = {d: linalg.VectorSpaceMod2({m} for m in basis[d]) for d in basis}

        ds = sorted(d for d in basis if pred(d))
        for d in ds:
            if d == (0, 0, 0):
                continue
            BA.Monitor.print(f"{d=}")
            for x in (basis_V[d] / map_alg.image(d)).simplify().basis(cls_basis):
                BA.Monitor.print(f"{x=}", 1)
                gen_name = naming(x, d)
                R.add_gen(gen_name, d[1], d)
                index = R.generators[-1][0]
                image_gens[gen_name] = x

                ds_R_basis_mons = {d: len(R_basis_mons[d]) for d in R_basis_mons}
                leadings = []
                for d1 in ds_R_basis_mons:
                    if pred(d1 + d):
                        for i in range(ds_R_basis_mons[d1]):
                            m1 = R_basis_mons[d1][i]
                            e = 1
                            while pred(d2 := d1 + d * e):
                                m2 = m1 + ((index, -e),)  # type: tuple
                                if any(map(le_dtuple, leadings, repeat(m2))):
                                    break
                                R_basis_mons[d2].append(m2)
                                r2 = R(m2)
                                fr2 = fn(r2.evaluation(image_gens))
                                map_alg.add_maps_set([(r2.data, fr2)], d2)
                                if map_alg.kernel(d2):
                                    R.add_rels_data(map_alg.kernel(d2).basis(set))
                                    map_alg.kernel(d2).clear()
                                    leadings = [m for m in R.rels if m[-1][0] == index]
                                    break
                                e += 1
Esempio n. 17
0
def myroundv(t) -> Vector:
    return Vector(map(round, t))
Esempio n. 18
0
"""pygame wrapper"""
import os
import json
import pygame
import pygame.gfxdraw
from algebras.mymath import Vector


with open(f"{os.path.dirname(__file__)}\\pen_ss.json", "r") as file:
    config = json.load(file)
    config["bullet.patterns.offset"] = [{tuple(pos): i for i, pos in enumerate(pattern)}
                                        for pattern in config["bullet.patterns"]]
    config["bullet.patterns"] = [[Vector(pos) for pos in pattern] for pattern in config["bullet.patterns"]]


def myroundv(t) -> Vector:
    return Vector(map(round, t))


def c2Vector(z: complex):
    return Vector((z.real, z.imag))


def Vector2c(a):
    return complex(a[0], a[1])


class Paint:
    def __init__(self, surface):
        self.surface = surface
        self.font = pygame.font.SysFont("Arial", 20)
Esempio n. 19
0
 def sp2wp(self, pos):
     """Convert screen position to world position."""
     return self.flip((Vector(pos) - self.origin_sp) / self.unit_screen)
Esempio n. 20
0
    def render(self):
        """Draw on the screen."""
        if not self.wait_for_update:
            return
        else:
            self.wait_for_update = False

        bullet_radius = self.get_bullet_radius()

        # draw background
        self.render_grid_lines()

        # draw expansions
        for deg in self.expansion:
            if deg not in self.spread:
                n = self.deg2num_bullets[deg]
                num_edge = math.ceil(math.sqrt(n))
                length_edge = self.get_bullet_sep() * (num_edge + 1)
                center = self.deg2sp(deg)
                size = Vector([length_edge, length_edge])
                rect = Rect(myroundv(center - size / 2), myroundv(size))
                self.paint.draw_rect(config["pen_color"], rect, 1)

        # draw lines
        lines = sorted(
            ((addr1 := self.id2addr[line.src_id], addr2 :=
              self.id2addr[line.tgt_id], math.dist(
                  addr1[0], addr2[0]), line.color) for line in self.ss.lines),
            key=lambda _l: _l[2])
        for addr1, addr2, dist, color in reversed(lines):
            if dist < 3:
                line_color = color
            else:
                line_color = interpolation(3 / dist, color, config['bg_color'])
            self.paint.draw_line(line_color, self.addr2sp(addr1),
                                 self.addr2sp(addr2))

        # draw arrows
        for arrow in self.ss.arrows:
            addr1, addr2 = self.id2addr[arrow.src_id], self.id2addr[
                arrow.tgt_id]
            self.paint.draw_arrow(self.addr2sp(addr1), self.addr2sp(addr2))
        if self.status == "on_bullet":
            if self.addr_mouse_down is not None and self.addr_mouse_down[
                    1] is not None:
                self.paint.draw_arrow(self.addr2sp(self.addr_mouse_down),
                                      self.pos_current)

        # draw bullets
        for deg in self.camera.degs_in_screen():
            if deg in self.deg2num_bullets:
                n = self.deg2num_bullets[deg]
                if n <= 9:
                    for i in range(n):
                        offset = config["bullet.patterns"][
                            n - 1][i] * self.get_bullet_sep() / 2
                        self.paint.draw_circle(
                            self.addr2color((deg, i)),
                            Vector(self.deg2sp(deg)) + offset, bullet_radius)
                else:
                    num_edge = math.ceil(math.sqrt(n))
                    length_edge = self.get_bullet_sep() * (num_edge + 1)
                    center = self.deg2sp(deg)
                    size = Vector([length_edge, length_edge])
                    rect = Rect(myroundv(center - size / 2), myroundv(size))
                    if deg in self.spread:
                        for i in range(n):
                            y, x = divmod(i, num_edge)
                            pos_bullet = Vector(rect.topleft) + Vector(
                                (x + 1, y + 1)) * self.get_bullet_sep()
                            self.paint.draw_circle(self.addr2color((deg, i)),
                                                   pos_bullet, bullet_radius)
                    elif deg not in self.expansion:
                        self.paint.draw_circle(config["pen_color"],
                                               self.deg2sp(deg), bullet_radius)
                        self.paint.draw_circle(config["pen_color"],
                                               self.deg2sp(deg),
                                               bullet_radius * 2, False)

        # draw bullets in expansions
        for deg in self.expansion:
            if deg not in self.spread:
                n = self.deg2num_bullets[deg]
                num_edge = math.ceil(math.sqrt(n))
                length_edge = self.get_bullet_sep() * (num_edge + 1)
                center = self.deg2sp(deg)
                size = Vector([length_edge, length_edge])
                top_left = myroundv(center - size / 2)
                for i in range(n):
                    y, x = divmod(i, num_edge)
                    pos_bullet = Vector(top_left) + Vector(
                        (x + 1, y + 1)) * self.get_bullet_sep()
                    self.paint.draw_circle(self.addr2color((deg, i)),
                                           pos_bullet, bullet_radius)

        # enlarge hovered-on bullet
        if self.id_hover_on is not None:
            addr = self.id2addr[self.id_hover_on]
            sp = self.addr2sp(addr)
            color = self.ss.get_bullet_by_id(self.id_hover_on).color
            self.paint.draw_circle(color, sp, bullet_radius * 1.5)

        # draw texts
        for text_p in self.ss.texts:
            if self.camera.is_in_screen(text_p.deg):
                s = text_p.text
                pos = self.camera.wp2sp(Vector(text_p.deg) + text_p.offset)
                self.paint.draw_text(s, pos, text_p.color)

        # draw label
        if self.id_hover_on is not None:
            addr = self.id2addr[self.id_hover_on]
            sp = self.addr2sp(addr)
            s = self.ss.get_bullet_by_id(self.id_hover_on).label
            self.paint.draw_text(s, sp + Vector((0, -20)))

        # draw grid numbers
        self.render_grid_numbers()
Esempio n. 21
0
 def deg3d_mon(cls, mon: tuple):
     return sum((cls.get_gen(i).deg3d * -e for i, e in mon), Vector((0, 0, 0)))
Esempio n. 22
0
                                for (S4, T4), (S5, T5) in product(
                                        Hp(ap, a1), Hp(b2, bp)):
                                    for S3, T3 in Hp(a1, a2):
                                        yield sum(
                                            (h(S6, T6) *
                                             h_wrap(S4 | S5 | S7, T4 | T5 | T7)
                                             for (S6,
                                                  T6), (S7, T7) in relation6BA(
                                                      S1, T1, S2, T2, S3, T3)),
                                            A.zero())
                                    for S3, T3 in Hp(b1, b2):
                                        yield sum(
                                            (h(S6, T6) *
                                             h_wrap(S4 | S5 | S7, T4 | T5 | T7)
                                             for (S6,
                                                  T6), (S7, T7) in relation6BB(
                                                      S1, T1, S2, T2, S3, T3)),
                                            A.zero())


def pred_E2(d3d):
    return d3d[1] <= 500


save_dir = "C:\\Users\\lwnpk\\Documents\\MyProgramData\\Math_AlgTop\\"
with open(save_dir + "E2_9_generators.json", "r") as fp:
    generators = json.load(fp)
A = GbAlgMod2.new_alg(pred=pred_E2)
for name, *d3d in generators:
    A.add_gen(name, d3d[1], Vector(d3d))
Esempio n. 23
0
 def deg_mon(mon: tuple):
     return Vector(
         (len(mon), sum(DualSteenrodDense.deg_mon(m) for m in mon)))
Esempio n. 24
0
def c2Vector(z: complex):
    return Vector((z.real, z.imag))
Esempio n. 25
0
 def flip(world_pos):
     return Vector((world_pos[0], -world_pos[1]))
Esempio n. 26
0
 def deg_mon(mon: tuple):
     return Vector((len(mon), sum(SteenrodMilnor.deg_mon(m) for m in mon)))
Esempio n. 27
0
class RelCache(NamedTuple):
    deg: int
    is_rel_gen: bool
    rel: set
    deg3d: Vector = Vector((0, 0, 0))