Mathematical Girls / Gödel's incompleteness theorems

数学ガール/ゲーデルの不完全性定理 (数学ガールシリーズ 3)

数学ガール/ゲーデルの不完全性定理 (数学ガールシリーズ 3)

「数学って、不完全だったの?」

D

 「そうか……」僕は、ひとりごとのように言う。「対角線論法のような有名な論法でも、きちんと理解しているかどうかを確かめるのは大切なことなんだな。《名前を聞いたことがある》や《本で読んだことがある》というレベルと、《きちんと理解している》というレベルの間には、すごく大きなギャップがありそうだ」
7.1.4 挑戦:有理数対角線論法 p208

ああぁっ。この本に書かれていることで《きちんと理解している》に至っているのは『9.1 0/3πラジアン』あたりくらいしかないいぃっ。それにしたところで、

(Python 2.5.4 & Pygame 1.9.1)

from __future__ import division
import pygame
from pygame.locals import *
import math
import random

################ 設定 #####################
FPS = 30  # 秒間描画枚数
WIDTH, HEIGHT = 640, 480  # 表示する画面のサイズ
BG_COLOR = 0, 0, 50  # 背景色
DOWN_SPEED = 4  # 雪が落下する速度
###########################################


class Cells(object):

    def __init__(self, size):
        self.size = size
        n = (size + 1) * 2 - 1
        self.cells = [[False] * (n + 4) for x in range(n + 4)]
        self.sin60 = math.sin(math.pi / 3)

    def set(self, x, y, value):
        self.cells[x + 2][y + 2] = value

    def get(self, x, y):
        return self.cells[x + 2][y + 2]

    def get_width(self):
        return (self.size + 1) * 2 - 1

    def get_center(self):
        return self.size

    def coordinate(self, x, y):
        c = self.size
        return (((x - c) * 2 - (c + y) % 2) / 2,
                (y - c) * self.sin60)
        
    def neighbors(self, x, y):
        c = self.cells
        x += 2
        y += 2
        if (self.size + y) % 2:
            # oox
            # oio
            # oox
            return sum((
                c[x-1][y-1], c[x][y-1],
                c[x-1][y],              c[x+1][y],
                c[x-1][y+1], c[x][y+1]))
        else:
            # xoo
            # oio
            # xoo
            return sum((
                            c[x][y-1],  c[x+1][y-1],
                c[x-1][y],              c[x+1][y],
                            c[x][y+1],  c[x+1][y+1]))

    def neighbors2(self, x, y):
        c = self.cells
        x += 2
        y += 2
        if (self.size + y) % 2:
            # xooox
            # oxxox
            # oxixo
            # oxxox
            # xooox
            return sum((
                c[x-1][y-2], c[x][y-2], c[x+1][y-2],
    c[x-2][y-1],                        c[x+1][y-1],
    c[x-2][y],                                      c[x+2][y],
    c[x-2][y+1],                        c[x+1][y+1],
                c[x-1][y+2], c[x][y+2], c[x+1][y+2]))
        else:
            # xooox
            # xoxxo
            # oxixo
            # xoxxo
            # xooox
            return sum((
                c[x-1][y-2], c[x][y-2], c[x+1][y-2],
                c[x-1][y-1],                        c[x+2][y-1],
    c[x-2][y],                                      c[x+2][y],
                c[x-1][y+1],                        c[x+2][y+1],
                c[x-1][y+2], c[x][y+2], c[x+1][y+2]))
    

class Snowflake(object):

    def __init__(self, surface, limit, pos=(0, 0), color=(255, 255, 255),
                 revolving_speed=1):
        self.sf = surface
        self.color = color
        self.revolve = revolving_speed
        x, y = [i // 2 for i in surface.get_size()]
        self.center = x + pos[0], y - pos[1]
        self.limit = limit
        self.size = s = 1
        self.cell = Cells(s)
        c = self.cell.get_center()
        self.cell.set(c, c, True)
        self.generation = 1
        self.ended = False
        self.fall = 0

    def update(self):
        if self.ended:
            return
        if self.generation > self.limit:
            self.fall = (self.generation - self.limit) * DOWN_SPEED
            self.generation += 1
            if self.fall >= 256:
                self.ended = True
            return
        next_cell = Cells(self.size + 1)
        r = (0, 1, 3, random.choice((5, 6, 7, 8, 9, 10)))
        w = self.cell.get_width()
        for x in range(w):
            for y in range(w):
                if self.cell.get(x, y):
                    next_cell.set(x + 1, y + 1, True)
                elif (self.cell.neighbors(x, y) == 1 and
                      self.cell.neighbors2(x, y) in r):
                    next_cell.set(x + 1, y + 1, True)
        self.cell = next_cell
        self.size += 1
        self.generation += 1


    def draw(self, rotate=0):
        rad = math.radians(rotate * self.revolve)
        sina = math.sin(rad)
        cosa = math.cos(rad)
        c = self.cell
        w = c.get_width()
        scx, scy = self.center
        scy += self.fall
        sf = pygame.Surface(self.sf.get_size())
        sf.set_colorkey((0, 0, 0))
        sf.set_alpha(255 - self.fall)
        for x in range(w):
            for y in range(w):
                if c.get(x, y):
                    xp, yp = c.coordinate(x, y)
                    xp *= 4
                    yp *= 4
                    pygame.draw.circle(
                        sf, self.color,
                        (scx + cosa * xp - sina * yp,
                         scy + sina * xp + cosa * yp),
                         3)
        l = self.size * 4
        self.sf.blit(sf, (0, 0))
                
def main():
    screen = pygame.display.set_mode((WIDTH, HEIGHT), 0)

    ## ここで描画する部品を登録する
    snow = Snowflake(screen, 30)
    drawlist = [snow]
    timer = pygame.time.Clock()
    while True:
        start_time = pygame.time.get_ticks()
        old_time = start_time
        timer.tick()
        now = 0
        savecount = 0
        while True:
            t = timer.tick(FPS)
            screen.fill(BG_COLOR)
            now = (pygame.time.get_ticks() - start_time) / 1000
            rotate = (now * 360 / 6)
            if snow.fall:
                snow = Snowflake(
                    screen, random.randint(10, 50),
                    (random.randint(- WIDTH // 2, WIDTH // 2),
                     random.randint(- HEIGHT // 2, HEIGHT // 2)),
                    revolving_speed=random.uniform(-2, 2))
                drawlist.append(snow)
            newlist = []
            for i in drawlist:
                i.update()
                i.draw(rotate)
                if not i.ended:
                    newlist.append(i)
            drawlist = newlist
            now_time = pygame.time.get_ticks()
            old_time = now_time
            pygame.display.flip()
            cap = '%5.2f fps, %03d generation, deg=%06.2f' % (
                timer.get_fps(), snow.generation, rotate)
            pygame.display.set_caption(cap)
            if pygame.event.get((QUIT, KEYDOWN, MOUSEBUTTONDOWN)):
                return


if __name__=='__main__':
    pygame.init()
    try:
        main()
    finally:
        pygame.quit()

# Public domain. 好きに流用してください。

みたくプログラム作るのに使ったことがあるから、というだけだし。(BNF*1とか読んだ経験あるから後半のそれも部分単位でならば《書かれていること》は分かるけれども……)

ちゃんと

プログラマの数学

プログラマの数学

あたり読んで基礎固めしてから読み返そう。

ポニテ*2キャラのユーリに男の影が……で『僕』が動揺したりミルカさんが……とかラブコメ展開にも進展あるけども。前巻
数学ガール/フェルマーの最終定理 (数学ガールシリーズ 2)

数学ガール/フェルマーの最終定理 (数学ガールシリーズ 2)

数学ガール 下 (MFコミックス フラッパーシリーズ)
数学ガール 上 (MFコミックス フラッパーシリーズ)
同様に後半のミルカさん独演会がどうにもならない(どちらもそれなしでは意味がない話だし)から、残念だけどマンガ化は難しいかな。まあ文章で読んでもライトノベルとして充分におもしろいからいいんですけども。

 「ゲーデル不完全性定理」とミルカさんは言った。
 「へえ!――ちょうど、この間、ユーリがその定理の話をしていたよ。ええっと、《理性の限界》を証明した定理だとか」
 「ユーリがそんなことを?」彼女は顔を上げた。険しい表情。
 「……うん」
 「理性の限界……その理解はまずい」とミルカさん。「で、きみは?」
第5章 ライプニッツの夢
5.3 ミルカさんならばミルカさんである
5.3.1 教室 p127

量子力学の解釈問題―実験が示唆する「多世界」の実在 (ブルーバックス)
論理哲学論考 (岩波文庫)
この巻の裏のテーマとしてこの問題あるよね。特定領域での限界(というより性質の話)が一般の倫理や哲学にまで援用されてしまう、という疑似科学的態度。この不完全性定理もそうだけれども、量子力学での不確定性原理とか、あるいは哲学での論理哲学論考とかがよく、そういう扱いを受けてますが。あるいはこの本の意義はそこらへんをきちんと説明して否定しているところにあるかも。

 「だから、私の考えはこうだ。不完全性定理の結果を使って数学的な話をしたいなら、対象を数学にしぽって話そう。そうでなく、不完全性定理の結果からインスピレーションをもらって数学的な話をしたいなら、そのつもりで話そう。忘れてはならないのは、数学的な話は《数学的に証明された》わけではないということ」
10.10.4 数学の限界? p368

*1:バッカス・ナウア記法

*2:いとこだけど