コード例 #1
0
def test_arithmetic():
    a = Varying(base_time=2, slope=3, base=5)
    b = Varying(base_time=7, slope=11, base=13)

    add = a + b
    assert add._base_time == a._base_time
    assert a(20) + b(20) == add(20)
    assert a(30) + b(30) == add(30)

    sub = a - b
    assert add._base_time == a._base_time
    assert a(20) - b(20) == sub(20)
    assert a(30) - b(30) == sub(30)

    neg = -a
    assert neg._base_time == a._base_time
    assert a(20) == -neg(20)
    assert a(30) == -neg(30)

    offset1 = a + 2
    offset2 = 2 + a
    assert add._base_time == a._base_time
    assert a(20) + 2 == offset1(20) == offset2(20)
    assert a(30) + 2 == offset1(30) == offset2(30)

    dif1 = a - 2
    dif2 = 2 - a
    assert add._base_time == a._base_time
    assert a(20) - 2 == dif1(20) == -dif2(20)
    assert a(30) - 2 == dif1(30) == -dif2(30)

    double1 = a * 2
    double2 = 2 * a
    assert double1._base_time == a._base_time
    assert double2._base_time == a._base_time
    assert double1(20) == double2(20) == a(20) * 2
    assert double1(30) == double2(30) == a(30) * 2

    half = a / 2
    assert half._base_time == a._base_time
    assert half(20) == a(20) / 2
    assert half(30) == a(30) / 2

    with pytest.raises(TypeError):
        _ = Varying.T + 'test'
    with pytest.raises(TypeError):
        _ = 'test' + Varying.T
    with pytest.raises(TypeError):
        _ = 'test' - Varying.T
    with pytest.raises(TypeError):
        _ = Varying.T - 'test'
    with pytest.raises(TypeError):
        _ = Varying.T * 'test'
    with pytest.raises(TypeError):
        _ = 'test' * Varying.T
    with pytest.raises(TypeError):
        _ = Varying.T / 'test'
コード例 #2
0
ファイル: circle_flooder.py プロジェクト: Strilanc/slowmatch
 def __init__(
     self,
     *,
     id: int,
     radius: Union[int, float, Varying],
     source: Union[None, int, float, complex] = None,
     blossom_children: Optional[List['CircleFillRegion']] = None,
 ):
     self.id = id
     self.source = None if source is None else complex(source)
     self.radius = Varying(radius)
     self.blossom_children = blossom_children
コード例 #3
0
def test_zero_intercept():
    assert Varying.T.zero_intercept() == 0
    assert (Varying.T + 5).zero_intercept() == -5
    assert (-Varying.T * 2 + 5).zero_intercept() == 2.5
    assert (-Varying.T * 0 + 5).zero_intercept() is None
    assert Varying(base_time=5, base=3, slope=2).zero_intercept() == 3.5
    assert (Varying.T * 0).zero_intercept() is None
コード例 #4
0
ファイル: graph_flooder.py プロジェクト: Strilanc/slowmatch
    def create_blossom(self, contained_region_ids: List[int]) -> int:
        k = self._next_region_id
        self._next_region_id += 1
        blossom_region = GraphFillRegion(id=k)
        blossom_region.radius = Varying(base_time=self.time, slope=1)
        blossom_region.blossom_children = []
        self._region_data_map[k] = blossom_region

        for i in contained_region_ids:
            region = self._region_data_map[i]
            del self._region_data_map[i]
            blossom_region.blossom_children.append(region)
            region.radius = region.radius.then_slope_at(
                time_of_change=self.time, new_slope=0)
            for loc in region.area:
                blossom_region.area.add(loc)
                loc_data = self._loc_data(loc)
                loc_data.mile_markers.append(
                    MileMarker(
                        blossom_region,
                        -loc_data.local_radius()(self.time),
                    ))

        self._reschedule_events_for_region(blossom_region)

        # Rescheduling the blossom region fixed location schedules, but not
        # child region schedules. Fix them now.
        for child in blossom_region.blossom_children:
            for ev in list(child.schedule_map.values()):
                ev.invalidate()

        return k
コード例 #5
0
def test_scalar():
    with pytest.raises(TypeError):
        _ = int(Varying(slope=1))
    with pytest.raises(TypeError):
        _ = float(Varying(slope=1))
    with pytest.raises(TypeError):
        _ = complex(Varying(slope=1))
    assert float(Varying(2)) == 2
    assert int(Varying(2)) == 2
    assert complex(Varying(2)) == 2
    assert isinstance(float(Varying(2)), float)
    assert isinstance(int(Varying(2)), int)
    assert isinstance(complex(Varying(2)), complex)
コード例 #6
0
ファイル: circle_flooder.py プロジェクト: Strilanc/slowmatch
 def create_region(self, location: complex) -> int:
     k = self._next_region_id
     self._next_region_id += 1
     self.regions[k] = CircleFillRegion(source=complex(location),
                                        id=k,
                                        radius=Varying(base_time=self.time,
                                                       slope=1))
     return k
コード例 #7
0
def test_init():
    z = Varying()
    assert z._base_time == 0
    assert z._base == 0
    assert z.slope == 0
    assert z(0) == 0
    assert z(1) == 0

    z = Varying(base=2, base_time=3, slope=5)
    assert z._base_time == 3
    assert z._base == 2
    assert z.slope == 5
    assert z(0) == -13
    assert z(1) == -8

    z = Varying(z)
    assert z._base_time == 3
    assert z._base == 2
    assert z.slope == 5
    assert z(0) == -13
    assert z(1) == -8
コード例 #8
0
ファイル: graph_flooder.py プロジェクト: Strilanc/slowmatch
 def __init__(
     self,
     *,
     id: int,
     source: Optional[TLocation] = None,
     radius: Union[int, float, Varying] = Varying.T,
     blossom_children: Optional[Iterable['GraphFillRegion']] = None,
 ):
     self.id = id
     self.source = source
     self.area: Set[TLocation] = set()
     self.radius = Varying(radius)
     self.blossom_children: Optional[List['GraphFillRegion', ...]] = (
         None if blossom_children is None else list(blossom_children))
     self.schedule_map: Dict[int, TentativeEvent] = {}
コード例 #9
0
ファイル: circle_flooder.py プロジェクト: Strilanc/slowmatch
    def create_blossom(self, contained_region_ids: List[int]) -> int:
        regions = []
        for i in contained_region_ids:
            regions.append(self.regions[i])
            del self.regions[i]

        for r in regions:
            r.radius = r.radius.then_slope_at(time_of_change=self.time,
                                              new_slope=0)

        k = self._next_region_id
        self._next_region_id += 1
        self.regions[k] = CircleFillRegion(id=k,
                                           blossom_children=regions,
                                           radius=Varying(base_time=self.time,
                                                          slope=1))

        return k
コード例 #10
0
ファイル: graph_flooder.py プロジェクト: Strilanc/slowmatch
 def local_radius(self) -> Varying:
     if self.mile_markers:
         marker = self.mile_markers[-1]
         return marker.region.radius - marker.distance_from_region_center
     return Varying(0)
コード例 #11
0
ファイル: circle_flooder.py プロジェクト: Strilanc/slowmatch
class CircleFillRegion:
    def __init__(
        self,
        *,
        id: int,
        radius: Union[int, float, Varying],
        source: Union[None, int, float, complex] = None,
        blossom_children: Optional[List['CircleFillRegion']] = None,
    ):
        self.id = id
        self.source = None if source is None else complex(source)
        self.radius = Varying(radius)
        self.blossom_children = blossom_children

    def _value_equality_values_(self):
        return self.id, self.source, self.radius, self.blossom_children

    def iter_all_circles(self) -> Iterator['CircleFillRegion']:
        if self.blossom_children is not None:
            for child in self.blossom_children:
                yield from (child + self.radius).iter_all_circles()
        if self.source is not None:
            yield self

    def __add__(self, other: Varying) -> 'CircleFillRegion':
        return CircleFillRegion(
            source=self.source,
            blossom_children=self.blossom_children,
            id=self.id,
            radius=self.radius + other,
        )

    def implosion_time(self) -> Optional[float]:
        if self.radius.slope >= 0:
            return None
        return self.radius.zero_intercept()

    def distance_from_at(self, other: 'CircleFillRegion',
                         time: float) -> float:
        if self.source is None or other.source is None:
            return min(
                a.distance_from_at(b, time) for a in self.iter_all_circles()
                for b in other.iter_all_circles())
        assert isinstance(time, (int, float))
        r0 = self.radius(time)
        r1 = other.radius(time)
        return abs(self.source - other.source) - r1 - r0

    def collision_time(self, other: 'CircleFillRegion') -> Optional[float]:
        if self.source is None or other.source is None:
            times = [
                a.collision_time(b) for a in self.iter_all_circles()
                for b in other.iter_all_circles()
            ]
            return min([t for t in times if t is not None], default=None)

        approach_speed = self.radius.slope + other.radius.slope
        if approach_speed <= 0:
            return None
        base_time = self.radius._base_time
        distance = self.distance_from_at(other, base_time)
        return base_time + distance / approach_speed

    def draw(self,
             *,
             time: float,
             screen,
             color: Optional[Tuple[int, int, int]] = None,
             scale: float = 1):
        # coverage: ignore
        import pygame

        if color is None:
            if self.radius.slope == 0:
                color = (0, 255, 0)
            elif self.radius.slope > 0:
                color = (255, 0, 0)
            else:
                color = (255, 255, 0)

        if self.source is not None:
            x = self.source.real * scale
            y = self.source.imag * scale
            r = self.radius(time) * scale
            pygame.draw.circle(screen, color, (int(x), int(y)),
                               int(math.ceil(r)))
        else:
            for child in self.iter_all_circles():
                child.draw(time=time, screen=screen, color=color, scale=scale)

            # Child regions darker.
            r, g, b = color
            darken = 0.75
            color = int(r * darken), int(g * darken), int(b * darken)
            for child in self.blossom_children:
                child.draw(time=time, screen=screen, color=color, scale=scale)

    def __repr__(self):
        return f'VaryingCircle(id={self.id!r}, center={self.source!r}, radius={self.radius!r})'
コード例 #12
0
def test_normal_progression():
    def assert_process_event(*expected_commands: Any):
        event = fill.next_event()
        mwpm.process_event(event)
        assert fill.recorded_commands == list(expected_commands)
        fill.recorded_commands.clear()

    fill = RecordingFlooder(CircleFlooder())
    mwpm = Mwpm(flooder=fill)
    mwpm.add_region(fill.create_region(100))
    mwpm.add_region(fill.create_region(101))
    mwpm.add_region(fill.create_region(200))
    mwpm.add_region(fill.create_region(202))
    mwpm.add_region(fill.create_region(300))
    fill.recorded_commands.clear()

    # Pair ups.
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=0, region2=1, time=0.5)),
        ('set_region_growth', 0, 0),
        ('set_region_growth', 1, 0),
    )
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=2, region2=3, time=1)),
        ('set_region_growth', 2, 0),
        ('set_region_growth', 3, 0),
    )
    # Alternating tree starts.
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=3, region2=4, time=97)),
        ('set_region_growth', 3, -1),
        ('set_region_growth', 2, +1),
    )
    # Alternating tree turns into a blossom.
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=2, region2=4, time=98)),
        ('create_blossom', (2, 3, 4), 5),
    )
    assert fill.sub_flooder.regions == {
        0:
        CircleFillRegion(id=0, source=100, radius=0.5),
        1:
        CircleFillRegion(id=1, source=101, radius=0.5),
        5:
        CircleFillRegion(
            id=5,
            radius=Varying(base_time=98, slope=1),
            blossom_children=[
                CircleFillRegion(id=2, source=200, radius=2),
                CircleFillRegion(id=3, source=202, radius=0),
                CircleFillRegion(id=4, source=300, radius=98),
            ],
        ),
    }
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=1, region2=5, time=194.5)),
        ('set_region_growth', 1, -1),
        ('set_region_growth', 0, +1),
    )
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=0, region2=5, time=195)),
        ('create_blossom', (0, 1, 5), 6),
    )
    assert fill.next_event() is None
コード例 #13
0
def test_blossom_implosion():
    def assert_process_event(*expected_commands: Any):
        event = fill.next_event()
        mwpm.process_event(event)
        assert fill.recorded_commands == list(expected_commands)
        fill.recorded_commands.clear()

    fill = RecordingFlooder(CircleFlooder())
    mwpm = Mwpm(flooder=fill)
    mwpm.add_region(fill.create_region(0))
    mwpm.add_region(fill.create_region(1))
    mwpm.add_region(fill.create_region(3))
    mwpm.add_region(fill.create_region(-10))
    mwpm.add_region(fill.create_region(+10))
    fill.recorded_commands.clear()

    # Blossom created in center.
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=0, region2=1, time=0.5)),
        ('set_region_growth', 0, 0),
        ('set_region_growth', 1, 0),
    )
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=1, region2=2, time=1.5)),
        ('set_region_growth', 1, -1),
        ('set_region_growth', 0, +1),
    )
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=0, region2=2, time=2)),
        ('create_blossom', (0, 1, 2), 5),
    )
    assert fill.sub_flooder.regions == {
        3:
        CircleFillRegion(id=3, source=-10, radius=Varying.T),
        4:
        CircleFillRegion(id=4, source=+10, radius=Varying.T),
        5:
        CircleFillRegion(
            id=5,
            radius=Varying(base_time=2, slope=1),
            blossom_children=[
                CircleFillRegion(id=0, source=0, radius=1),
                CircleFillRegion(id=1, source=1, radius=0),
                CircleFillRegion(id=2, source=3, radius=2),
            ],
        ),
    }

    # Blossom becomes an inner node.
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=4, region2=5, time=3.5)),
        ('set_region_growth', 4, 0),
        ('set_region_growth', 5, 0),
    )
    assert_process_event(
        ('next_event', RegionHitRegionEvent(region1=3, region2=5, time=7.5)),
        ('set_region_growth', 5, -1),
        ('set_region_growth', 4, +1),
    )

    # Blossom implodes.
    assert_process_event(
        (
            'next_event',
            BlossomImplodeEvent(blossom_region_id=5,
                                time=9,
                                in_out_touch_pairs=[
                                    (0, 3),
                                    (2, 4),
                                ]),
        ),
        ('set_region_growth', 0, -1),
        ('set_region_growth', 1, +1),
        ('set_region_growth', 2, -1),
    )
コード例 #14
0
def test_repr():
    cirq.testing.assert_equivalent_repr(
        Varying(base_time=2, slope=3, base=5), global_vals={'Varying': Varying}
    )
コード例 #15
0
def test_then_slope_at():
    a = Varying(base_time=2, slope=3, base=5)
    b = a.then_slope_at(time_of_change=7, new_slope=11)
    assert b._base_time == 7
    assert b(7) == a(7)
    assert b.slope == 11
コード例 #16
0
def test_equality():
    eq = cirq.testing.EqualsTester()
    eq.add_equality_group(
        Varying(base_time=0, slope=1, base=0),
        Varying(base_time=1, slope=1, base=1),
        Varying(Varying(base_time=0, slope=1, base=0)),
    )
    eq.add_equality_group(
        Varying(base_time=0, slope=-1, base=0), Varying(base_time=1, slope=-1, base=-1), -Varying.T,
    )
    eq.add_equality_group(
        Varying(base_time=0, slope=1, base=1), Varying(base_time=1, slope=1, base=2),
    )
    eq.add_equality_group(
        Varying(base_time=0, slope=0, base=50),
        Varying(base_time=10000, slope=0, base=50),
        50,
        50.0,
        50.0 + 0j,
    )
    eq.add_equality_group(
        Varying(base_time=0, slope=0, base=60), Varying(base_time=10000, slope=0, base=60), 60,
    )
コード例 #17
0
def test_approximate_equality():
    assert cirq.approx_eq(Varying(5), Varying(5.01), atol=0.1)
    assert not cirq.approx_eq(Varying(5), Varying(5.01), atol=0.001)
    assert cirq.approx_eq(Varying(5, slope=4), Varying(5, slope=4.01), atol=0.1)
    assert not cirq.approx_eq(Varying(5, slope=4), Varying(5, slope=4.01), atol=0.001)
    assert not cirq.approx_eq(Varying.T, 'test', atol=0.1)
    assert cirq.approx_eq(Varying(5), 5.001, atol=0.01)
    assert cirq.approx_eq(5.001, Varying(5), atol=0.01)
    assert not cirq.approx_eq(Varying(5), 5.001, atol=0.0001)
    assert not cirq.approx_eq(5.001, Varying(5), atol=0.0001)