Exemplo n.º 1
0
    def __init__(self, Lx=60, Ly=60, plot=True, frames=1000,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 pre_function=None,
                 post_function=None):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)), boundary=boundary)

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)

        center_x, center_y = Lx / 4, Ly / 2
        self.points = [(center_x, center_y)]
        self.occupied[center_x, center_y] = True
        self.neighbors = list(map(
            tuple, np.array(self.lattice.neighbor_of(center_x, center_y)).T
        ))

        self.plot = plot
        self.interval = 1
        self.frames = frames

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []
Exemplo n.º 2
0
    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], plot=True,
                 beta=4.):
        self.plot = plot
        self.beta = beta
        self.interval = 1
        self.frames = 20000

        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10.,
                          boundary={'h': 'periodic', 'v': 'periodic'}
                          )
        randomize(self.lattice)
        self.triang_standard = tri.Triangulation(self.lattice.coordinates_x,
                                                 self.lattice.coordinates_y)
        self.triang_random = tri.Triangulation(
            self.lattice.coordinates_x,
            self.lattice.coordinates_y,
            triangles=self.triang_standard.triangles)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size)

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)
Exemplo n.º 3
0
    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], interval=1000):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10., boundary={'h': 'periodic', 'v': 'periodic'})

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size) * Ly

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = True
        self.interval = interval
Exemplo n.º 4
0
    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], interval=1000):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10., boundary='periodic')

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size) * Ly

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = True
        self.interval = interval
Exemplo n.º 5
0
    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], interval=50,
                 plot=True):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary={'h': 'periodic', 'v': 'periodic'})

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = plot
        self.interval = interval
Exemplo n.º 6
0
    def __init__(self,
                 Lx=60,
                 Ly=60,
                 plot=True,
                 frames=1000,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 pre_function=None,
                 post_function=None):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)

        center_x, center_y = Lx / 4, Ly / 2
        self.points = [(center_x, center_y)]
        self.occupied[center_x, center_y] = True
        self.neighbors = list(
            map(tuple,
                np.array(self.lattice.neighbor_of(center_x, center_y)).T))

        self.plot = plot
        self.interval = 1
        self.frames = frames

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []
Exemplo n.º 7
0
class SAW(base):
    """2次元三角格子上の自己回避ランダムウォーク"""
    def __init__(self,
                 Lx=40,
                 Ly=40,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta=2.,
                 interval=1,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):
        """Init function of Main class.

        Lx (int (even)): 格子のx方向(グラフではy軸)の格子点数
        Ly (int (even)): 格子のy方向(グラフではx軸)の格子点数
        """
        # Create triangular lattice with given parameters
        # self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
        #                   scale=float(max(Lx, Ly)), boundary=boundary)
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)
        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            if string.loop:
                raise AttributeError("string can't be loop.")
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError(
                    "`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(s=self.strings[key],
                                           index_start=0,
                                           index_stop=len(
                                               self.strings[key].pos))

            # TODO: 隣接点がないとき,全体のシミュレーションを終了する
            # if len(value) == 0:
            #     return False

            self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs)
        # print(self.strings[0].pos)
        # pp.pprint(self.bonding_pairs[0])

        # pp.pprint(self.bonding_pairs)
        # return None

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
            # print("Image file is successfully saved at '%s'." % filename_image)

    def __update_dict(self, dict, key, value):
        if dict.has_key(key):
            dict[key].append(value)
        else:
            dict[key] = [value]

    def dot(self, v, w):
        """0〜5で表された6つのベクトルの内積を計算する。

        v, w (int): ベクトル(0〜5の整数で表す)"""
        if (w + 6 - v) % 6 == 0:
            return 1
        elif (w + 6 - v) % 6 == 1 or (w + 6 - v) % 6 == 5:
            return 0.5
        elif (w + 6 - v) % 6 == 2 or (w + 6 - v) % 6 == 4:
            return -0.5
        elif (w + 6 - v) % 6 == 3:
            return -1.

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(self.lattice_X) - 0.1, max(self.lattice_X) + 0.1
        Y_min, Y_max = min(self.lattice_Y) - 0.1, max(self.lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            triang = tri.Triangulation(self.lattice_X, self.lattice_Y)
            self.ax.triplot(triang, color='#d5d5d5', lw=0.5)

        self.lines = [
            self.ax.plot([], [],
                         linestyle='-',
                         color='black',
                         markerfacecolor='black',
                         markeredgecolor='black')[0]
            for i in range(self.number_of_lines)
        ]
        if self.plot_surface:
            self.lines.append(self.ax.plot([], [], '.', color='#ff0000')[0])

        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.plot_string()

    def start_animation(self, filename=""):
        if self.__dict__.has_key('frames'):
            frames = self.frames
        else:
            frames = 1000

        def init_func(*arg):
            return self.lines

        ani = animation.FuncAnimation(self.fig,
                                      self.update,
                                      frames=frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True,
                                      repeat=False)
        if filename != "":
            try:
                ani.save(filename, codec="libx264", bitrate=-1, fps=30)
            except:
                print("Can't saved.")
            else:
                print("Animation is successfully saved at '%s'." % filename)
        else:
            plt.show()

    def plot_string(self):
        """self.strings内に格納されているStringを参照し,グラフ上に図示する
        """
        # print self.string.pos, self.string.vec
        i = 0  # to count how many line2D object
        for s in self.strings:
            start = 0
            for j, pos1, pos2 in zip(range(len(s.pos) - 1), s.pos[:-1],
                                     s.pos[1:]):
                dist_x = abs(self.lattice_X[pos1[0], pos1[1]] -
                             self.lattice_X[pos2[0], pos2[1]])
                dist_y = abs(self.lattice_Y[pos1[0], pos1[1]] -
                             self.lattice_Y[pos2[0], pos2[1]])
                # print j, pos1, pos2
                # print dist_x, dist_y
                if dist_x > 1.5 * self.lattice.dx or dist_y > 1.5 * self.lattice.dy:
                    x = s.pos_x[start:j + 1]
                    y = s.pos_y[start:j + 1]
                    X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                    Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                    self.lines[i].set_data(X, Y)
                    start = j + 1
                    i += 1
            else:
                x = s.pos_x[start:]
                y = s.pos_y[start:]
                X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                self.lines[i].set_data(X, Y)
                i += 1

        if self.plot_surface:
            neighbors = []
            weights = []
            for bonding_pairs in self.bonding_pairs.values():
                # print(bonding_pairs)
                for pos in bonding_pairs.keys():
                    neighbors.append(pos)
                for weight in bonding_pairs.values():
                    weights.append(weight[0][1])
            neighbors = list(np.array(neighbors).T)
            weights = np.array(weights)
            weights = weights / np.sum(weights)
            # print(neighbors)
            X, Y = self.lattice_X[neighbors], self.lattice_Y[neighbors]
            # print(X, Y)
            self.lines[-1].set_data(X, Y)

        # 最終的に,iの数だけ線を引けばよくなる
        # それ以上のオブジェクトはリセット
        if self.plot_surface:
            max_obj = len(self.lines) - 1
        else:
            max_obj = len(self.lines)
        for j in range(i, max_obj):
            self.lines[j].set_data([], [])

        return self.lines

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """

        # update each string
        for i, s in enumerate(self.strings):
            if self.pre_function is not None:
                self.pre_func_res.append(self.pre_function(self, i, s))
            ret = self.update_each_string(i)
            if self.post_function is not None:
                self.post_func_res.append(self.post_function(self, i, s))

        if self.plot or self.save_video:
            ret = self.plot_string()
            return ret

    def update_each_string(self, key):
        X = self.get_neighbor_xy(key)
        if not X:
            raise StopIteration

        # print(X)
        s = self.strings[key]
        # update positions
        if len(X) == 4:
            i, r_rev, nx, ny = X
            s.x, s.y = nx, ny
            s.insert(0, r_rev)
            x, y = s.pos_x[0], s.pos_y[0]
        elif len(X) == 2:
            i, r = X
            s.insert(i + 1, r)
            x, y = s.pos_x[-1], s.pos_y[-1]
        else:
            raise RuntimeError(
                "Something wrong. There should be no intersection part.")

        self.occupied[x, y] = True

        # print("== start == (%d, %d)" % (x, y))

        # pp.pprint(self.bonding_pairs[key])

        for k, bonding_pairs in self.bonding_pairs.items():
            if bonding_pairs.has_key((x, y)):
                del self.bonding_pairs[k][(x, y)]
                # print("del self.bonding_pairs[%d][(%d, %d)]" % (k, x, y))

        # pp.pprint(self.bonding_pairs[key])

        index_start = i
        index_stop = len(s.pos)

        self.cleanup_bonding_pairs(key=key,
                                   index_start=index_start,
                                   index_stop=index_stop)

        value = self.get_bonding_pairs(s=self.strings[key],
                                       index_start=index_start,
                                       index_stop=index_stop)

        # pp.pprint(value)
        # pp.pprint(self.bonding_pairs[key])

        for k, v in value.items():
            if self.bonding_pairs[key].has_key(k):
                self.bonding_pairs[key][k] += v
            else:
                self.bonding_pairs[key][k] = v
            # self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs[key])

        # print("== end ==")

        # pp.pprint(self.strings[key].pos)
        # pp.pprint(self.bonding_pairs[key].keys())

    def cleanup_bonding_pairs(self, key, index_start, index_stop):
        rang = range(index_start, index_stop)
        for (x, y), l in self.bonding_pairs[key].items():
            tmp = []
            for i, (bonding_pair, w) in enumerate(l):
                if not bonding_pair[0] in rang:
                    tmp.append(l[i])
            if len(tmp) == 0:
                del self.bonding_pairs[key][(x, y)]
            else:
                self.bonding_pairs[key][(x, y)] = tmp

    def get_neighbor_xy(self, key):
        """Stringクラスのインスタンスsの隣接する非占有格子点の座標を取得する

        s (String): 対象とするStringクラスのインスタンス
        """
        if len(self.bonding_pairs[key]) == 0:
            return False

        # bonding_pairsの選ばれやすさを適切に重みを付けて評価
        weights = []
        bonding_pairs = []
        b = reduce(operator.add, self.bonding_pairs[key].values())
        # print(b)
        for (pair, w) in b:
            bonding_pairs.append(pair)
            weights.append(w)

        weights = np.array(weights)
        weights = weights / np.sum(weights)
        # print(weights)

        choiced_index = np.random.choice(range(len(weights)), p=weights)
        # print(bonding_pairs[choiced_index])
        return bonding_pairs[choiced_index]

    def get_bonding_pairs(self, s, index_start, index_stop):
        bonding_pairs = {}
        neighbors_dict = {}
        rang = range(index_start, index_stop)
        for i in rang:
            x, y = s.pos[i]
            nnx, nny = self.lattice.neighbor_of(x, y)

            for r in [0, 1, 2, 3, 4, 5]:
                nx, ny = nnx[r], nny[r]
                if self.occupied[nx, ny] or nx == -1 or ny == -1:
                    continue

                r_rev = (r + 3) % 6

                if i == 0:
                    w = self.dot(r_rev, s.vec[0])
                    W = np.exp(self.beta * w)
                    self.__update_dict(bonding_pairs, (nx, ny),
                                       [[0, r_rev, nx, ny], W])
                elif i == len(s.pos) - 1:
                    w = self.dot(s.vec[i - 1], r)
                    W = np.exp(self.beta * w)
                    self.__update_dict(bonding_pairs, (nx, ny), [[i, r], W])
        return bonding_pairs
Exemplo n.º 8
0
    def __init__(self,
                 Lx=40,
                 Ly=40,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta=2.,
                 interval=1,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):
        """Init function of Main class.

        Lx (int (even)): 格子のx方向(グラフではy軸)の格子点数
        Ly (int (even)): 格子のy方向(グラフではx軸)の格子点数
        """
        # Create triangular lattice with given parameters
        # self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
        #                   scale=float(max(Lx, Ly)), boundary=boundary)
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)
        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            if string.loop:
                raise AttributeError("string can't be loop.")
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError(
                    "`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(s=self.strings[key],
                                           index_start=0,
                                           index_stop=len(
                                               self.strings[key].pos))

            # TODO: 隣接点がないとき,全体のシミュレーションを終了する
            # if len(value) == 0:
            #     return False

            self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs)
        # print(self.strings[0].pos)
        # pp.pprint(self.bonding_pairs[0])

        # pp.pprint(self.bonding_pairs)
        # return None

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
Exemplo n.º 9
0
    def __init__(self, Lx=40, Ly=40,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta = 2.,
                 interval=1,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):
        """Init function of Main class.

        Lx (int (even)): 格子のx方向(グラフではy軸)の格子点数
        Ly (int (even)): 格子のy方向(グラフではx軸)の格子点数
        """
        # Create triangular lattice with given parameters
        # self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
        #                   scale=float(max(Lx, Ly)), boundary=boundary)
        self.lattice = LT(
            np.zeros((Lx, Ly), dtype=np.int),
            scale=float(max(Lx, Ly)),
            boundary=boundary
        )
        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            if string.loop:
                raise AttributeError("string can't be loop.")
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError("`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                index_start=0,
                index_stop=len(self.strings[key].pos)
            )

            # TODO: 隣接点がないとき,全体のシミュレーションを終了する
            # if len(value) == 0:
            #     return False

            self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs)
        # print(self.strings[0].pos)
        # pp.pprint(self.bonding_pairs[0])


        # pp.pprint(self.bonding_pairs)
        # return None

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
Exemplo n.º 10
0
class Main(base):
    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], plot=True):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10.,
                          boundary={
                              'h': 'periodic',
                              'v': 'periodic'
                          })

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size)

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = plot
        self.interval = 100

    def update(self, num=0):
        # move head part of each strings (if possible)
        for s in self.strings:
            X = self.get_next_xy(s.x, s.y, s.vec[0])
            if not X:
                raise StopIteration

            # update starting position
            x, y, vec = X
            rmx, rmy = s.follow((x, y, (vec + 3) % 6))
            self.occupied[x, y] = True
            self.occupied[rmx, rmy] = False

        ret = self.plot_string()

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_next_xy(self, x, y, vec):
        # 曲げ弾性の効果を再現するために,位置関係によって次の点の
        # 選ばれやすさが異なるようにする
        nnx, nny = self.lattice.neighbor_of(x, y)
        vectors = [i for i in range(6) if not self.occupied[nnx[i], nny[i]]]
        if len(vectors) == 0:
            print_debug("no neighbors")
            return False

        # 確率的に方向を決定
        # 先頭ベクトルを0とした時の相対ベクトルごとの選ばれやすさを設定
        # weights = [0., 1., 2., 3., 2., 1.]
        weights = [0., 0., 1., 4., 1., 0.]
        # weights = [0., 0., 2., 1., 2., 0.]
        # weights = [0., 0., 0., 1., 0., 0.]
        # 有効なものだけ取り出す
        weights = np.array([weights[(i + 6 - vec) % 6] for i in vectors])
        # 規格化
        weights = weights / np.sum(weights)
        # vectorsから一つ選択
        vector = np.random.choice(vectors, p=weights)
        # 点の格子座標を返す
        x, y = nnx[vector], nny[vector]
        return x, y, vector

    def create_random_strings(self, N=3, size=[10, 5, 3]):
        """Create N strings of each size is specified with 'size'.

        This process is equivalent to self-avoiding walk on triangular lattice.
        """
        strings = []

        n = 0
        while n < N:
            # set starting point
            x = random.randint(0, self.lattice.Lx - 1)
            y = random.randint(0, self.lattice.Ly - 1)
            if self.occupied[x, y]:  # reset
                print_debug("(%d, %d) is occupied already. continue." % (x, y))
                continue
            self.occupied[x, y] = True

            S = size[n]
            pos = [(x, y, np.random.choice(6))]
            trial, nmax = 0, 10
            double = 0
            while len(pos) < S:
                if trial > nmax:
                    for _x, _y, vec in pos:
                        self.occupied[_x, _y] = False
                    print_debug("All reset")
                    break
                X = self.get_next_xy(x, y, pos[-1][2])
                if not X:
                    if len(pos) == 1:
                        print_debug("len(pos) == 1")
                        double = 0
                        trial += 1
                        break
                    else:
                        print_debug("back one step")
                        print_debug(pos)
                        if double == 1:
                            print_debug("two time. back two step")
                            print_debug(pos)
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            x, y, vector = pos[-1]
                            trial += 1
                            print_debug(pos)
                            break
                        oldx, oldy, oldvec = pos[-1]
                        del pos[-1]
                        self.occupied[oldx, oldy] = False
                        x, y, vector = pos[-1]
                        trial += 1
                        print_debug(pos)
                        continue
                else:
                    double = 0
                    x, y, vector = X
                    self.occupied[x, y] = True
                    pos.append((x, y, vector))
                    print_debug("add step normally")
                    print_debug(pos)
            else:
                print_debug("Done. Add string")
                vec = [v[2] for v in pos][1:]
                strings.append(
                    String(self.lattice, n, pos[0][0], pos[0][1], vec=vec))
                n += 1

        return strings
Exemplo n.º 11
0
    def __init__(self, Lx=40, Ly=40,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta = 2.,
                 interval=0,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):

        self.lattice = LT(
            np.zeros((Lx, Ly), dtype=np.int),
            scale=float(max(Lx, Ly)),
            boundary=boundary
        )

        ## randomize
        randomize(self.lattice)

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            self.triang_standard = tri.Triangulation(self.lattice.coordinates_x,
                                                     self.lattice.coordinates_y)
            self.triang_random = tri.Triangulation(
                self.lattice.coordinates_x,
                self.lattice.coordinates_y,
                triangles=self.triang_standard.triangles)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            self.occupied[string.pos_x, string.pos_y] = True


        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError("`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video


        self.interval = interval
        self.frames = frames

        # 逆温度
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                # indexes=[[0, len(self.strings[key].pos)]]
                index_start=0,
                index_stop=len(self.strings[key].pos)
            )

            self.bonding_pairs[key] = value

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
Exemplo n.º 12
0
class SAW(base):
    """2次元三角格子上の自己回避ランダムウォーク"""

    def __init__(self, Lx=40, Ly=40,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta = 2.,
                 interval=1,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):
        """Init function of Main class.

        Lx (int (even)): 格子のx方向(グラフではy軸)の格子点数
        Ly (int (even)): 格子のy方向(グラフではx軸)の格子点数
        """
        # Create triangular lattice with given parameters
        # self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
        #                   scale=float(max(Lx, Ly)), boundary=boundary)
        self.lattice = LT(
            np.zeros((Lx, Ly), dtype=np.int),
            scale=float(max(Lx, Ly)),
            boundary=boundary
        )
        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            if string.loop:
                raise AttributeError("string can't be loop.")
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError("`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                index_start=0,
                index_stop=len(self.strings[key].pos)
            )

            # TODO: 隣接点がないとき,全体のシミュレーションを終了する
            # if len(value) == 0:
            #     return False

            self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs)
        # print(self.strings[0].pos)
        # pp.pprint(self.bonding_pairs[0])


        # pp.pprint(self.bonding_pairs)
        # return None

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
            # print("Image file is successfully saved at '%s'." % filename_image)

    def __update_dict(self, dict, key, value):
        if dict.has_key(key):
            dict[key].append(value)
        else:
            dict[key] = [value]

    def dot(self, v, w):
        """0〜5で表された6つのベクトルの内積を計算する。

        v, w (int): ベクトル(0〜5の整数で表す)"""
        if (w + 6 - v) % 6 == 0:
            return 1
        elif (w + 6 - v) % 6 == 1 or (w + 6 - v) % 6 == 5:
            return 0.5
        elif (w + 6 - v) % 6 == 2 or (w + 6 - v) % 6 == 4:
            return -0.5
        elif (w + 6 - v) % 6 == 3:
            return -1.

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(self.lattice_X) - 0.1, max(self.lattice_X) + 0.1
        Y_min, Y_max = min(self.lattice_Y) - 0.1, max(self.lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            triang = tri.Triangulation(self.lattice_X, self.lattice_Y)
            self.ax.triplot(triang, color='#d5d5d5', lw=0.5)

        self.lines = [self.ax.plot([], [], linestyle='-',
                                   color='black',
                                   markerfacecolor='black',
                                   markeredgecolor='black')[0]
                      for i in range(self.number_of_lines)]
        if self.plot_surface:
            self.lines.append(self.ax.plot([], [], '.', color='#ff0000')[0])

        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.plot_string()

    def start_animation(self, filename=""):
        if self.__dict__.has_key('frames'):
            frames = self.frames
        else:
            frames = 1000

        def init_func(*arg):
            return self.lines

        ani = animation.FuncAnimation(self.fig, self.update, frames=frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True, repeat=False)
        if filename != "":
            try:
                ani.save(filename, codec="libx264", bitrate=-1, fps=30)
            except:
                print("Can't saved.")
            else:
                print("Animation is successfully saved at '%s'." % filename)
        else:
            plt.show()

    def plot_string(self):
        """self.strings内に格納されているStringを参照し,グラフ上に図示する
        """
        # print self.string.pos, self.string.vec
        i = 0  # to count how many line2D object
        for s in self.strings:
            start = 0
            for j, pos1, pos2 in zip(range(len(s.pos) - 1), s.pos[:-1], s.pos[1:]):
                dist_x = abs(self.lattice_X[pos1[0], pos1[1]] -
                            self.lattice_X[pos2[0], pos2[1]])
                dist_y = abs(self.lattice_Y[pos1[0], pos1[1]] -
                            self.lattice_Y[pos2[0], pos2[1]])
                # print j, pos1, pos2
                # print dist_x, dist_y
                if dist_x > 1.5 * self.lattice.dx or dist_y > 1.5 * self.lattice.dy:
                    x = s.pos_x[start:j + 1]
                    y = s.pos_y[start:j + 1]
                    X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                    Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                    self.lines[i].set_data(X, Y)
                    start = j + 1
                    i += 1
            else:
                x = s.pos_x[start:]
                y = s.pos_y[start:]
                X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                self.lines[i].set_data(X, Y)
                i += 1

        if self.plot_surface:
            neighbors = []
            weights = []
            for bonding_pairs in self.bonding_pairs.values():
                # print(bonding_pairs)
                for pos in bonding_pairs.keys():
                    neighbors.append(pos)
                for weight in bonding_pairs.values():
                    weights.append(weight[0][1])
            neighbors = list(np.array(neighbors).T)
            weights = np.array(weights)
            weights = weights / np.sum(weights)
            # print(neighbors)
            X, Y = self.lattice_X[neighbors], self.lattice_Y[neighbors]
            # print(X, Y)
            self.lines[-1].set_data(X, Y)

        # 最終的に,iの数だけ線を引けばよくなる
        # それ以上のオブジェクトはリセット
        if self.plot_surface:
            max_obj = len(self.lines) - 1
        else:
            max_obj = len(self.lines)
        for j in range(i, max_obj):
            self.lines[j].set_data([], [])

        return self.lines

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """

        # update each string
        for i, s in enumerate(self.strings): 
            if self.pre_function is not None:
                self.pre_func_res.append(self.pre_function(self, i, s))
            ret = self.update_each_string(i)
            if self.post_function is not None:
                self.post_func_res.append(self.post_function(self, i, s))

        if self.plot or self.save_video:
            ret = self.plot_string()
            return ret

    def update_each_string(self, key):
        X = self.get_neighbor_xy(key)
        if not X:
            raise StopIteration

        # print(X)
        s = self.strings[key]
        # update positions
        if len(X) == 4:
            i, r_rev, nx, ny = X
            s.x, s.y = nx, ny
            s.insert(0, r_rev)
            x, y = s.pos_x[0], s.pos_y[0]
        elif len(X) == 2:
            i, r = X
            s.insert(i + 1, r)
            x, y = s.pos_x[-1], s.pos_y[-1]
        else:
            raise RuntimeError("Something wrong. There should be no intersection part.")

        self.occupied[x, y] = True

        # print("== start == (%d, %d)" % (x, y))

        # pp.pprint(self.bonding_pairs[key])

        for k, bonding_pairs in self.bonding_pairs.items():
            if bonding_pairs.has_key((x, y)):
                del self.bonding_pairs[k][(x, y)]
                # print("del self.bonding_pairs[%d][(%d, %d)]" % (k, x, y))

        # pp.pprint(self.bonding_pairs[key])

        index_start = i
        index_stop = len(s.pos)

        self.cleanup_bonding_pairs(
            key=key,
            index_start=index_start,
            index_stop=index_stop
        )

        value = self.get_bonding_pairs(
            s=self.strings[key],
            index_start=index_start,
            index_stop=index_stop
        )


        # pp.pprint(value)
        # pp.pprint(self.bonding_pairs[key])

        for k, v in value.items():
            if self.bonding_pairs[key].has_key(k):
                self.bonding_pairs[key][k] += v
            else:
                self.bonding_pairs[key][k] = v
            # self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs[key])

        # print("== end ==")

        # pp.pprint(self.strings[key].pos)
        # pp.pprint(self.bonding_pairs[key].keys())


    def cleanup_bonding_pairs(self, key, index_start, index_stop):
        rang = range(index_start, index_stop)
        for (x, y), l in self.bonding_pairs[key].items():
            tmp = []
            for i, (bonding_pair, w) in enumerate(l):
                if not bonding_pair[0] in rang:
                    tmp.append(l[i])
            if len(tmp) == 0:
                del self.bonding_pairs[key][(x, y)]
            else:
                self.bonding_pairs[key][(x, y)] = tmp

    def get_neighbor_xy(self, key):
        """Stringクラスのインスタンスsの隣接する非占有格子点の座標を取得する

        s (String): 対象とするStringクラスのインスタンス
        """
        if len(self.bonding_pairs[key]) == 0:
            return False

        # bonding_pairsの選ばれやすさを適切に重みを付けて評価
        weights = []
        bonding_pairs = []
        b = reduce(operator.add, self.bonding_pairs[key].values())
        # print(b)
        for (pair, w) in b:
            bonding_pairs.append(pair)
            weights.append(w)

        weights = np.array(weights)
        weights = weights / np.sum(weights)
        # print(weights)

        choiced_index = np.random.choice(range(len(weights)), p=weights)
        # print(bonding_pairs[choiced_index])
        return bonding_pairs[choiced_index]

    def get_bonding_pairs(self, s, index_start, index_stop):
        bonding_pairs = {}
        neighbors_dict = {}
        rang = range(index_start, index_stop)
        for i in rang:
            x, y = s.pos[i]
            nnx, nny = self.lattice.neighbor_of(x, y)

            for r in [0, 1, 2, 3, 4, 5]:
                nx, ny = nnx[r], nny[r]
                if self.occupied[nx, ny] or nx == -1 or ny == -1:
                    continue

                r_rev = (r + 3) % 6

                if i == 0:
                    w = self.dot(r_rev, s.vec[0])
                    W = np.exp(self.beta * w)
                    self.__update_dict(bonding_pairs,
                                       (nx, ny),
                                       [[0, r_rev, nx, ny], W])
                elif i == len(s.pos) - 1:
                    w = self.dot(s.vec[i - 1], r)
                    W = np.exp(self.beta * w)
                    self.__update_dict(bonding_pairs,
                                       (nx, ny),
                                       [[i, r], W])
        return bonding_pairs
Exemplo n.º 13
0
class Main(base):

    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], interval=1000):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10., boundary='periodic')

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size) * Ly

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = True
        self.interval = interval

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """
        # move head part of each strings (if possible)
        # TODO: Fix bug
        for s in self.strings:
            print "=== Start ==="
            print s.vec
            X = self.get_neighbor_xy(s)
            if not X:
                raise StopIteration

            # update starting position
            i, r, r_rev = X
            print i, r, r_rev
            s.vec[i] = r
            self.occupied[s.pos_x[-1], s.pos_y[-1]] = False
            if i == len(s.vec) - 1:
                s.vec = s.vec[:i] + [r_rev]
            else:
                s.vec = s.vec[:i + 1] + [r_rev] + s.vec[i + 1:-1]
            print s.vec
            print "=== Updated ==="
            s.update_pos()
            self.occupied[s.pos_x[i + 1], s.pos_y[i + 1]] = True

        ret = self.plot_string()

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_neighbor_xy(self, s):
        """Stringクラスのインスタンスsの隣接する非占有格子点の座標を取得する

        s (String): 対象とするStringクラスのインスタンス
        """
        neighbors_set = {}
        bonding_pairs = []
        # sのx, y座標に関して
        for i, (x, y) in enumerate(s.pos):
            # それぞれの近傍点を取得
            nnx, nny = self.lattice.neighbor_of(x, y)
            # 6方向全てに関して
            for r in range(6):
                nx, ny = nnx[r], nny[r]
                # 反射境界条件のとき除外される点の場合,次の近接点に
                if nx == -1 or ny == -1:
                    continue
                # 既に占有されているとき,次の近接点に
                elif self.occupied[nx, ny]:
                    continue
                # それ以外(近傍点のうち占有されていない点であるとき)
                # 既にstringの近傍として登録されている場合
                elif neighbors_set.has_key((nx, ny)):
                    # 一つ前に登録された点が現在の評価点の近傍点である場合
                    if neighbors_set[(nx, ny)][-1][0] == i - 1:
                        # r_rev: 現在の点から近接点へのベクトル
                        r_rev = (r + 3) % 6
                        # [i-1, r_{i}, r_{rev}]
                        bonding_pairs.append([i - 1,
                                              neighbors_set[(nx, ny)][-1][1],
                                               r_rev])
                    neighbors_set[(nx, ny)].append((i, r))
                # stringの近傍として登録されていない場合
                # -> 新たに登録
                else:
                    if i == 0:
                        # r_rev: 現在の点から近接点へのベクトル
                        r_rev = (r + 3) % 6
                        bonding_pairs.append([- 1,
                                              neighbors_set[(nx, ny)][-1][1],
                                               r_rev])
                    neighbors_set[(nx, ny)] = [(i, r), ]

        # bonding_pairsの選ばれやすさを適切に重みを付けて評価
        weights = []
        for i, r, r_rev in bonding_pairs:
            if i == 0 or i == len(s.vec) - 1:
                # 端の場合,定数
                weight = 3
            else:
                # 重みは内積の和で表現
                weight = dot(s.vec[i - 1], r) + dot(r_rev, s.vec[i + 1]) + 1
            weights.append(weight)
        weights = np.array(weights)
        weights = weights / np.sum(weights)

        choiced_index = np.random.choice(range(len(weights)), p=weights)
        i, r, r_rev = bonding_pairs[choiced_index]

        return i, r, r_rev
Exemplo n.º 14
0
class Eden():

    def __init__(self, Lx=60, Ly=60, plot=True, frames=1000,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 pre_function=None,
                 post_function=None):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)), boundary=boundary)

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)

        center_x, center_y = Lx / 4, Ly / 2
        self.points = [(center_x, center_y)]
        self.occupied[center_x, center_y] = True
        self.neighbors = list(map(
            tuple, np.array(self.lattice.neighbor_of(center_x, center_y)).T
        ))

        self.plot = plot
        self.interval = 1
        self.frames = frames

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

    def execute(self):
        if self.plot:
            self.plot_all()
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

    def plot_all(self):
        """軸の設定,三角格子の描画

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """

        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(self.lattice_X) - 0.1, max(self.lattice_X) + 0.1
        Y_min, Y_max = min(self.lattice_Y) - 0.1, max(self.lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            triang = tri.Triangulation(self.lattice_X, self.lattice_Y)
            self.ax.triplot(triang, color='#d5d5d5', lw=0.5)
        self.scatter = [
            self.ax.plot([], [], 'k.')[0],
            self.ax.plot([], [], 'r.')[0]
        ]

        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)

        def init_func(*arg):
            return self.scatter

        ani = animation.FuncAnimation(self.fig, self.update, frames=self.frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True, repeat=False)
        plt.show()

    def plot_points(self):
        """self.pointsに格納されている格子座標を元にプロット
        """
        ## self.points: [(x1, y1), (x2, y2), (x3, y3), ...]
        index = list(np.array(self.points).T)
        X = self.lattice_X[index]
        Y = self.lattice_Y[index]
        self.scatter[0].set_data(X, Y)

        index = list(np.array(self.neighbors).T)
        nx = self.lattice_X[index]
        ny = self.lattice_Y[index]
        self.scatter[1].set_data(nx, ny)
        return self.scatter

    def update(self, num=0):
        """funcanimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """

        if len(self.neighbors) == 0:
            print_debug("no neighbors")
            return False

        if self.pre_function is not None:
            self.pre_func_res.append(self.pre_function(self))

        x, y = self.neighbors.pop(random.randint(0, len(self.neighbors) - 1))
        self.occupied[x, y] = True
        self.points.append((x, y))

        new_n = set(((nx, ny) for nx, ny in np.array(self.lattice.neighbor_of(x, y)).T
                    if nx != -1 and ny != -1))
        updated_n = set(tuple(map(tuple, self.neighbors))) | new_n
        self.neighbors = [pos for pos in updated_n if not self.occupied[pos]]

        if self.post_function is not None:
            self.post_func_res.append(self.post_function(self))

        if self.plot:
            return self.plot_points() 
Exemplo n.º 15
0
class Main(base):

    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], interval=1000):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10., boundary={'h': 'periodic', 'v': 'periodic'})

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size) * Ly

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = True
        self.interval = interval

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """
        # move head part of each strings (if possible)
        # TODO: Fix bug
        for s in self.strings:
            print s.vec
            X = self.get_neighbor_xy(s)
            if not X:
                raise StopIteration

            # update starting position
            i, r, r_rev = X
            print i, r, r_rev
            s.vec[i] = r
            self.occupied[s.pos_x[-1], s.pos_y[-1]] = False
            if i == len(s.vec) - 1:
                s.vec = s.vec[:i] + [r_rev]
            else:
                s.vec = s.vec[:i + 1] + [r_rev] + s.vec[i + 1:-1]
            print len(s.vec)
            s.update_pos()
            self.occupied[s.pos_x[i + 1], s.pos_y[i + 1]] = True

        ret = self.plot_string()
        print self.occupied

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_neighbor_xy(self, s):
        """Stringクラスのインスタンスsの隣接する非占有格子点の座標を取得する

        s (String): 対象とするStringクラスのインスタンス
        """
        neighbors_set = {}
        bonding_pairs = []
        # sのx, y座標に関して
        for i, (x, y) in enumerate(s.pos):
            # それぞれの近傍点を取得
            nnx, nny = self.lattice.neighbor_of(x, y)
            # 6方向全てに関して
            for r in range(6):
                nx, ny = nnx[r], nny[r]
                # 反射境界条件のとき除外される点の場合,次の近接点に
                if nx == -1 or ny == -1:
                    continue
                # 既に占有されているとき,次の近接点に
                elif self.occupied[nx, ny]:
                    continue
                # それ以外(近傍点のうち占有されていない点であるとき)
                # 既にstringの近傍として登録されている場合
                elif neighbors_set.has_key((nx, ny)):
                    # 一つ前に登録された点が現在の評価点の近傍点である場合
                    if neighbors_set[(nx, ny)][-1][0] == i - 1:
                        # r_rev: 現在の点から近接点へのベクトル
                        r_rev = (r + 3) % 6
                        # [i-1, r_{i}, r_{rev}]
                        bonding_pairs.append([i - 1,
                                              neighbors_set[(nx, ny)][-1][1],
                                               r_rev])
                    neighbors_set[(nx, ny)].append((i, r))
                # stringの近傍として登録されていない場合
                # -> 新たに登録
                else:
                    neighbors_set[(nx, ny)] = [(i, r), ]

        # bonding_pairsの選ばれやすさを適切に重みを付けて評価
        weights = []
        for i, r, r_rev in bonding_pairs:
            if i == 0 or i == len(s.vec) - 1:
                # 端の場合,定数
                weight = 3
            else:
                # 重みは内積の和で表現
                weight = dot(s.vec[i - 1], r) + dot(r_rev, s.vec[i + 1]) + 1
            weights.append(weight)
        weights = np.array(weights)
        weights = weights / np.sum(weights)

        choiced_index = np.random.choice(range(len(weights)), p=weights)
        i, r, r_rev = bonding_pairs[choiced_index]

        return i, r, r_rev
Exemplo n.º 16
0
class Eden():
    def __init__(self,
                 Lx=60,
                 Ly=60,
                 plot=True,
                 frames=1000,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 pre_function=None,
                 post_function=None):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)

        center_x, center_y = Lx / 4, Ly / 2
        self.points = [(center_x, center_y)]
        self.occupied[center_x, center_y] = True
        self.neighbors = list(
            map(tuple,
                np.array(self.lattice.neighbor_of(center_x, center_y)).T))

        self.plot = plot
        self.interval = 1
        self.frames = frames

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

    def execute(self):
        if self.plot:
            self.plot_all()
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

    def plot_all(self):
        """軸の設定,三角格子の描画

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """

        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        self.lattice_X = self.lattice.coordinates_x
        self.lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(self.lattice_X) - 0.1, max(self.lattice_X) + 0.1
        Y_min, Y_max = min(self.lattice_Y) - 0.1, max(self.lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            triang = tri.Triangulation(self.lattice_X, self.lattice_Y)
            self.ax.triplot(triang, color='#d5d5d5', lw=0.5)
        self.scatter = [
            self.ax.plot([], [], 'k.')[0],
            self.ax.plot([], [], 'r.')[0]
        ]

        self.lattice_X = self.lattice_X.reshape(self.lattice.Lx,
                                                self.lattice.Ly)
        self.lattice_Y = self.lattice_Y.reshape(self.lattice.Lx,
                                                self.lattice.Ly)

        def init_func(*arg):
            return self.scatter

        ani = animation.FuncAnimation(self.fig,
                                      self.update,
                                      frames=self.frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True,
                                      repeat=False)
        plt.show()

    def plot_points(self):
        """self.pointsに格納されている格子座標を元にプロット
        """
        ## self.points: [(x1, y1), (x2, y2), (x3, y3), ...]
        index = list(np.array(self.points).T)
        X = self.lattice_X[index]
        Y = self.lattice_Y[index]
        self.scatter[0].set_data(X, Y)

        index = list(np.array(self.neighbors).T)
        nx = self.lattice_X[index]
        ny = self.lattice_Y[index]
        self.scatter[1].set_data(nx, ny)
        return self.scatter

    def update(self, num=0):
        """funcanimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """

        if len(self.neighbors) == 0:
            print_debug("no neighbors")
            return False

        if self.pre_function is not None:
            self.pre_func_res.append(self.pre_function(self))

        x, y = self.neighbors.pop(random.randint(0, len(self.neighbors) - 1))
        self.occupied[x, y] = True
        self.points.append((x, y))

        new_n = set(((nx, ny)
                     for nx, ny in np.array(self.lattice.neighbor_of(x, y)).T
                     if nx != -1 and ny != -1))
        updated_n = set(tuple(map(tuple, self.neighbors))) | new_n
        self.neighbors = [pos for pos in updated_n if not self.occupied[pos]]

        if self.post_function is not None:
            self.post_func_res.append(self.post_function(self))

        if self.plot:
            return self.plot_points()
Exemplo n.º 17
0
class Main(base):
    """任意に設定したstringの近傍点に点を追加し成長させるモデル

    グラフ上で左端と右端に固定されたstringの近傍点を探索,ランダム(後には曲げ
    弾性による重み付けの効果を追加)に選択し,stringを成長させていくモデル
    """
    def __init__(self,
                 Lx=40,
                 Ly=40,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta=2.,
                 interval=1,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):
        """Init function of Main class.

        Lx (int (even)): 格子のx方向(グラフではy軸)の格子点数
        Ly (int (even)): 格子のy方向(グラフではx軸)の格子点数
        """
        # Create triangular lattice with given parameters
        # self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
        #                   scale=float(max(Lx, Ly)), boundary=boundary)
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError(
                    "`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames

        # 逆温度
        self.beta = beta
        # self.beta = 100. # まっすぐ(≒低温極限)
        # self.beta = 10. # まっすぐ
        # self.beta = 0. # 高温極限
        # self.beta = 5. # 中間的
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                # indexes=[[0, len(self.strings[key].pos)]]
                index_start=0,
                index_stop=len(self.strings[key].pos))

            # TODO: 隣接点がないとき,全体のシミュレーションを終了する
            # if len(value) == 0:
            #     return False

            self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs)
        # print(self.strings[0].pos)
        # pp.pprint(self.bonding_pairs[0])

        # pp.pprint(self.bonding_pairs)
        # return None

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
            # print("Image file is successfully saved at '%s'." % filename_image)

    def _update_dict(self, dict, key, value):
        if dict.has_key(key):
            dict[key].append(value)
        else:
            dict[key] = [value]

    def dot(self, v, w):
        """0〜5で表された6つのベクトルの内積を計算する。

        v, w (int): ベクトル(0〜5の整数で表す)"""
        if (w + 6 - v) % 6 == 0:
            return 1.
        elif (w + 6 - v) % 6 == 1 or (w + 6 - v) % 6 == 5:
            return 0.5
        elif (w + 6 - v) % 6 == 2 or (w + 6 - v) % 6 == 4:
            return -0.5
        elif (w + 6 - v) % 6 == 3:
            return -1.

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        lattice_X = self.lattice.coordinates_x
        lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(lattice_X) - 0.1, max(lattice_X) + 0.1
        Y_min, Y_max = min(lattice_Y) - 0.1, max(lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            triang = tri.Triangulation(lattice_X, lattice_Y)
            self.ax.triplot(triang, color='#d5d5d5', lw=0.5)

        self.lines = [
            self.ax.plot([], [],
                         linestyle='-',
                         color='black',
                         markerfacecolor='black',
                         markeredgecolor='black')[0]
            for i in range(self.number_of_lines)
        ]
        if self.plot_surface:
            # self._num_surface = 1
            # self.lines.append(self.ax.plot([], [], '.', color='#ff0000')[0])
            self._num_surface = 9
            self.lines += [
                self.ax.plot(
                    [],
                    [],
                    '.',
                )[0] for i in range(self._num_surface)
            ]

        self.plot_string()

    def start_animation(self, filename=""):
        if self.__dict__.has_key('frames'):
            frames = self.frames
        else:
            frames = 1000

        def init_func(*arg):
            return self.lines

        ani = animation.FuncAnimation(self.fig,
                                      self.update,
                                      frames=frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True,
                                      repeat=False)
        if filename != "":
            try:
                ani.save(filename, codec="libx264", bitrate=-1, fps=30)
            except:
                print("Can't saved.")
            else:
                print("Animation is successfully saved at '%s'." % filename)
        else:
            plt.show()

    def plot_string(self):
        """self.strings内に格納されているStringを参照し,グラフ上に図示する
        """
        # print self.string.pos, self.string.vec
        i = 0  # to count how many line2D object
        for s in self.strings:
            start = 0
            for j, pos1, pos2 in zip(range(len(s.pos) - 1), s.pos[:-1],
                                     s.pos[1:]):
                dist_x = abs(self.lattice_X[pos1[0], pos1[1]] -
                             self.lattice_X[pos2[0], pos2[1]])
                dist_y = abs(self.lattice_Y[pos1[0], pos1[1]] -
                             self.lattice_Y[pos2[0], pos2[1]])
                # print j, pos1, pos2
                # print dist_x, dist_y
                # sqrt(2^{2} + (1/2)^{2}) ~ 2.06
                if dist_x > 2.1 * self.lattice.dx or dist_y > 2.1 * self.lattice.dx:
                    x = s.pos_x[start:j + 1]
                    y = s.pos_y[start:j + 1]
                    X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                    Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                    self.lines[i].set_data(X, Y)
                    start = j + 1
                    i += 1
            else:
                x = s.pos_x[start:]
                y = s.pos_y[start:]
                X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                self.lines[i].set_data(X, Y)
                i += 1

        num_plot_surface = 0
        if self.plot_surface:
            if self._num_surface == 1:
                num_plot_surface = 1
                neighbors = []
                for bonding_pairs in self.bonding_pairs.values():
                    # print(bonding_pairs)
                    for pos in bonding_pairs.keys():
                        neighbors.append(pos)
                neighbors = list(np.array(neighbors).T)
                # print(neighbors)
                X, Y = self.lattice_X[neighbors], self.lattice_Y[neighbors]
                # print(X, Y)
                self.lines[-1].set_data(X, Y)

            # ===
            else:
                w = {}
                for bonding_pairs in self.bonding_pairs.values():
                    # print(bonding_pairs)
                    for pos, bps in bonding_pairs.items():
                        for bp, _w in bps:
                            if w.has_key(_w):
                                w[_w].append(pos)
                            else:
                                w[_w] = [
                                    pos,
                                ]
                num_plot_surface = len(w)
                # W = sorted(w.keys(), reverse=True)
                sum_w = np.sum([len(w[_w]) for _w in w.keys()])
                W = [(_w, (_w * len(w[_w])) / sum_w) for _w in w.keys()]
                ave_W = np.average(W, axis=0)[1]
                min_W = np.exp(self.beta * (-2.5)) / sum_w
                max_W = np.exp(self.beta * 2.5) / sum_w
                for k, (wi, _w) in enumerate(W):
                    neighbors = list(np.array(w[wi]).T)
                    X, Y = self.lattice_X[neighbors], self.lattice_Y[neighbors]
                    self.lines[-(k + 1)].set_data(X, Y)
                    ## color setting
                    dw = _w - ave_W
                    if min_W == ave_W:
                        _c = 0.5
                    elif dw < 0:
                        _c = (0.5 / (ave_W - min_W)) * (_w - min_W)
                    else:
                        _c = (0.5 / (max_W - ave_W)) * dw + 0.5
                    self.lines[-(k + 1)].set_color(cm.plasma(_c))

        # 最終的に,iの数だけ線を引けばよくなる
        # それ以上のオブジェクトはリセット
        if self.plot_surface:
            max_obj = len(self.lines) - num_plot_surface
        else:
            max_obj = len(self.lines)
        for j in range(i, max_obj):
            self.lines[j].set_data([], [])

        return self.lines

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """

        # update each string
        for i, s in enumerate(self.strings):
            if self.pre_function is not None:
                self.pre_func_res.append(self.pre_function(self, i, s))
            ret = self.update_each_string(i)
            if self.post_function is not None:
                self.post_func_res.append(self.post_function(self, i, s))

        if self.plot or self.save_video:
            return self.plot_string()

    def update_each_string(self, key):
        X = self.get_neighbor_xy(key)
        if not X:
            raise StopIteration

        # print(X)
        s = self.strings[key]
        # update positions
        if len(X) == 4:
            i, r_rev, nx, ny = X
            s.x, s.y = nx, ny
            s.insert(0, r_rev)
            x, y = s.pos_x[0], s.pos_y[0]
        elif len(X) == 2:
            i, r = X
            s.insert(i + 1, r)
            x, y = s.pos_x[-1], s.pos_y[-1]
        else:
            i, r, r_rev = X
            s.vec[i] = r
            s.insert(i + 1, r_rev)
            x, y = s.pos_x[i + 1], s.pos_y[i + 1]

        self.occupied[x, y] = True

        # print("== start == (%d, %d)" % (x, y))

        # pp.pprint(self.bonding_pairs[key])

        for k, bonding_pairs in self.bonding_pairs.items():
            if bonding_pairs.has_key((x, y)):
                del self.bonding_pairs[k][(x, y)]
                # print("del self.bonding_pairs[%d][(%d, %d)]" % (k, x, y))

        # pp.pprint(self.bonding_pairs[key])

        index_start = i
        index_stop = len(s.pos)
        # print(index_start, index_stop)

        self.cleanup_bonding_pairs(key=key,
                                   index_start=index_start,
                                   index_stop=index_stop)

        value = self.get_bonding_pairs(s=self.strings[key],
                                       index_start=index_start,
                                       index_stop=index_stop)

        # pp.pprint(value)
        # pp.pprint(self.bonding_pairs[key])

        for k, v in value.items():
            if self.bonding_pairs[key].has_key(k):
                self.bonding_pairs[key][k] += v
            else:
                self.bonding_pairs[key][k] = v

        # pp.pprint(self.bonding_pairs[key])

        # print("== end ==")

        # pp.pprint(self.strings[key].pos)
        # pp.pprint(self.bonding_pairs[key].keys())

    def cleanup_bonding_pairs(self, key, index_start, index_stop):
        rang = range(index_start, index_stop)
        for pos, l in self.bonding_pairs[key].items():
            tmp = [l[i] for i, (bp, w) in enumerate(l) if not bp[0] in rang]
            if len(tmp) == 0:
                del self.bonding_pairs[key][pos]
            else:
                self.bonding_pairs[key][pos] = tmp

    def get_neighbor_xy(self, key):
        """Stringクラスのインスタンスsの隣接する非占有格子点の座標を取得する

        s (String): 対象とするStringクラスのインスタンス
        """
        if len(self.bonding_pairs[key]) == 0:
            return False

        # bonding_pairsの選ばれやすさを適切に重みを付けて評価
        weights = []
        bonding_pairs = []
        for (pair, w) in reduce(operator.add,
                                self.bonding_pairs[key].values()):
            bonding_pairs.append(pair)
            weights.append(w)

        weights = np.array(weights)
        weights = weights / np.sum(weights)
        # print(weights)

        choiced_index = np.random.choice(range(len(weights)), p=weights)
        # print(bonding_pairs[choiced_index])
        return bonding_pairs[choiced_index]

    def calc_weight(self, s, i, r_i=None, r_rev=None):
        """ベクトルの内積を元に,Boltzmann分布に従って成長点選択の重みを決定
        """

        if (i == 1) and (not s.loop):
            w = self.dot(r_rev, s.vec[i]) - self.dot(s.vec[0], s.vec[1]) \
                - self.weight_const
        elif (i == len(s.pos) - 1) and (not s.loop):
            w = self.dot(s.vec[i - 2], r_i) - \
                self.dot(s.vec[i - 2], s.vec[i - 1]) - self.weight_const
        else:
            # w = self.dot(s.vec[i - 2], r_i) + self.dot(r_rev, s.vec[i % len(s.vec)])
            w = (self.dot(s.vec[i - 2], r_i) + \
                 self.dot(r_rev, s.vec[i % len(s.vec)])) \
                - (self.dot(s.vec[i - 2], s.vec[i - 1]) + \
                   self.dot(s.vec[i - 1], s.vec[i % len(s.vec)])) \
                - self.weight_const

        W = np.exp(self.beta * w)
        return W

    def get_bonding_pairs(self, s, index_start, index_stop):
        bonding_pairs = {}
        neighbors_dict = {}
        rang = range(index_start, index_stop)

        if s.loop and (0 in rang):
            rang.append(0)

        for i in rang:
            x, y = s.pos[i]
            nnx, nny = self.lattice.neighbor_of(x, y)

            for r in [0, 1, 2, 3, 4, 5]:
                nx, ny = nnx[r], nny[r]
                if self.occupied[nx, ny] or nx == -1 or ny == -1:
                    continue

                r_rev = (r + 3) % 6

                if not neighbors_dict.has_key((nx, ny)):
                    if not s.loop:
                        if i == 0:
                            w = self.dot(r_rev, s.vec[0])
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs, (nx, ny),
                                              [[0, r_rev, nx, ny], W])
                        elif i == len(s.pos) - 1:
                            w = self.dot(s.vec[i - 1], r)
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs, (nx, ny),
                                              [[i, r], W])
                    neighbors_dict[(nx, ny)] = [
                        (i, r),
                    ]
                else:
                    if neighbors_dict[(nx, ny)][-1][0] == i - 1:
                        r_i = neighbors_dict[(nx, ny)][-1][1]
                        W = self.calc_weight(s, i, r_i, r_rev)
                        self._update_dict(bonding_pairs, (nx, ny),
                                          [[i - 1, r_i, r_rev], W])
                    neighbors_dict[(nx, ny)].append((i, r))
        return bonding_pairs
Exemplo n.º 18
0
    def __init__(self,
                 Lx=40,
                 Ly=40,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta=2.,
                 interval=0,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):

        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)

        ## randomize
        randomize(self.lattice)

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            self.triang_standard = tri.Triangulation(
                self.lattice.coordinates_x, self.lattice.coordinates_y)
            self.triang_random = tri.Triangulation(
                self.lattice.coordinates_x,
                self.lattice.coordinates_y,
                triangles=self.triang_standard.triangles)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError(
                    "`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames

        # 逆温度
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                # indexes=[[0, len(self.strings[key].pos)]]
                index_start=0,
                index_stop=len(self.strings[key].pos))

            self.bonding_pairs[key] = value

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
Exemplo n.º 19
0
class Sim(Main):
    def __init__(self,
                 Lx=40,
                 Ly=40,
                 boundary={
                     'h': 'periodic',
                     'v': 'periodic'
                 },
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta=2.,
                 interval=0,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):

        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary=boundary)

        ## randomize
        randomize(self.lattice)

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            self.triang_standard = tri.Triangulation(
                self.lattice.coordinates_x, self.lattice.coordinates_y)
            self.triang_random = tri.Triangulation(
                self.lattice.coordinates_x,
                self.lattice.coordinates_y,
                triangles=self.triang_standard.triangles)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            self.occupied[string.pos_x, string.pos_y] = True

        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError(
                    "`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video

        self.interval = interval
        self.frames = frames

        # 逆温度
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                # indexes=[[0, len(self.strings[key].pos)]]
                index_start=0,
                index_stop=len(self.strings[key].pos))

            self.bonding_pairs[key] = value

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
            # print("Image file is successfully saved at '%s'." % filename_image)

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        lattice_X = self.lattice.coordinates_x
        lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(lattice_X) - 0.1, max(lattice_X) + 0.1
        Y_min, Y_max = min(lattice_Y) - 0.1, max(lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            self.ax.triplot(self.triang_random, color='#d5d5d5', lw=0.5)

        self.lines = [
            self.ax.plot([], [],
                         linestyle='-',
                         color='black',
                         markerfacecolor='black',
                         markeredgecolor='black')[0]
            for i in range(self.number_of_lines)
        ]
        if self.plot_surface:
            self._num_surface = 1
            self.lines.append(self.ax.plot([], [], '.', color='#ff0000')[0])
        self.plot_string()

    def _vector(self, X1, Y1, X2, Y2):
        """Return 2-d vector from (X1, Y1) to (X2, Y2).
        Remark: X1, X2,... are grid coordinates and are not coordinates in
        real 2d space."""
        x1, y1 = self.lattice_X[X1][Y1], self.lattice_Y[X1][Y1]
        x2, y2 = self.lattice_X[X2][Y2], self.lattice_Y[X2][Y2]
        return np.array([x2 - x1, y2 - y1])

    def dot(self, vec1, vec2):
        """Calculate user-defined 'inner product' from the two 2d vectors
        `vec1` and `vec2`.
        """
        ## normal inner product
        # res = np.dot(vec1, vec2)

        ## only depend on angle
        res = np.dot(vec1 / np.linalg.norm(vec1), vec2 / np.linalg.norm(vec2))
        return res

    def get_bonding_pairs(self, s, index_start, index_stop):
        def _vec_(i):
            """Get vector from the point in string 's' indexed 'i' to the point
            indexed 'i+1'."""
            X1, Y1 = s.pos[i]
            X2, Y2 = s.pos[i + 1]
            return self._vector(X1, Y1, X2, Y2)

        bonding_pairs = {}
        neighbors_dict = {}
        rang = range(index_start, index_stop)

        if s.loop and (0 in rang):
            rang.append(0)

        for i in rang:
            x, y = s.pos[i]
            nnx, nny = self.lattice.neighbor_of(x, y)

            for r_int in [0, 1, 2, 3, 4, 5]:
                nx, ny = nnx[r_int], nny[r_int]
                if self.occupied[nx, ny] or nx == -1 or ny == -1:
                    continue

                r = self._vector(x, y, nx, ny)
                r_rev = self._vector(nx, ny, x, y)
                r_rev_int = (r_int + 3) % 6

                if not neighbors_dict.has_key((nx, ny)):
                    if not s.loop:
                        if i == 0:
                            w = self.dot(r_rev, _vec_(i % len(s.vec)))
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs, (nx, ny),
                                              [[0, r_rev_int, nx, ny], W])
                        elif i == len(s.pos) - 1:
                            w = self.dot(_vec_(i - 1), r)
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs, (nx, ny),
                                              [[i, r_int], W])
                    neighbors_dict[(nx, ny)] = [
                        (i, r, r_int),
                    ]
                else:
                    if neighbors_dict[(nx, ny)][-1][0] == i - 1:
                        r_i = neighbors_dict[(nx, ny)][-1][1]
                        r_i_int = neighbors_dict[(nx, ny)][-1][2]

                        if (i == 1) and (not s.loop):
                            w = (
                                self.dot(r_i, r_rev) + \
                                self.dot(r_rev, _vec_(i))
                            ) - (
                                self.dot(_vec_(i - 1), _vec_(i))
                            )

                        elif (i == len(s.pos) - 1) and (not s.loop):
                            w = (
                                self.dot(_vec_(i - 2), r_i) + \
                                self.dot(r_i, r_rev)
                            ) - (
                                self.dot(_vec_(i - 2), _vec_(i - 1))
                            )
                        else:
                            w = (
                                self.dot(_vec_(i - 2), r_i) + \
                                self.dot(r_i, r_rev) + \
                                self.dot(r_rev, _vec_(i % len(s.vec)))
                            ) - (
                                self.dot(_vec_(i - 2), _vec_(i - 1)) + \
                                self.dot(_vec_(i - 1), _vec_(i % len(s.vec)))
                            )

                        W = np.exp(self.beta * w)
                        self._update_dict(bonding_pairs, (nx, ny),
                                          [[i - 1, r_i_int, r_rev_int], W])
                    neighbors_dict[(nx, ny)].append((i, r, r_int))
        return bonding_pairs
Exemplo n.º 20
0
class Main:
    def __init__(self,
                 Lx=40,
                 Ly=40,
                 N=4,
                 size=[5, 4, 10, 12],
                 interval=50,
                 plot=True):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary={
                              'h': 'periodic',
                              'v': 'periodic'
                          })

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = plot
        self.interval = interval

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        if self.__dict__.has_key('frames'):
            frames = self.frames
        else:
            frames = 1000
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        lattice_X = self.lattice.coordinates_x
        lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(lattice_X) - 0.1, max(lattice_X) + 0.1
        Y_min, Y_max = min(lattice_Y) - 0.1, max(lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        triang = tri.Triangulation(lattice_X, lattice_Y)

        self.ax.triplot(triang, color='#d5d5d5', lw=0.5)

        self.lines = [
            self.ax.plot([], [],
                         marker='.',
                         linestyle='-',
                         color='black',
                         markerfacecolor='black',
                         markeredgecolor='black')[0]
            for i in range(self.number_of_lines)
        ]

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx, self.lattice.Ly)
        self.plot_string()

        def init_func(*arg):
            return self.lines

        ani = animation.FuncAnimation(self.fig,
                                      self.update,
                                      frames=frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True,
                                      repeat=False)
        plt.show()

    def plot_string(self):
        """self.strings内に格納されているStringを参照し,グラフ上に図示する
        """
        # print self.string.pos, self.string.vec

        i = 0  # to count how many line2D object
        for s in self.strings:
            start = 0
            for j, pos1, pos2 in zip(range(len(s.pos) - 1), s.pos[:-1],
                                     s.pos[1:]):
                dist_x = abs(self.lattice_X[pos1[0], pos1[1]] -
                             self.lattice_X[pos2[0], pos2[1]])
                dist_y = abs(self.lattice_Y[pos1[0], pos1[1]] -
                             self.lattice_Y[pos2[0], pos2[1]])
                # print j, pos1, pos2
                # print dist_x, dist_y
                if dist_x > 2.1 * self.lattice.dx or dist_y > 2.1 * self.lattice.dy:
                    x = s.pos_x[start:j + 1]
                    y = s.pos_y[start:j + 1]
                    X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                    Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                    self.lines[i].set_data(X, Y)
                    start = j + 1
                    i += 1
            else:
                x = s.pos_x[start:]
                y = s.pos_y[start:]
                X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                self.lines[i].set_data(X, Y)
                i += 1
        # 最終的に,iの数だけ線を引けばよくなる
        # それ以上のオブジェクトはリセット
        for j in range(i, len(self.lines)):
            self.lines[j].set_data([], [])

        return self.lines

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """
        # move head part of each strings (if possible)
        for s in self.strings:
            X = self.get_next_xy(s.x, s.y)
            if not X:
                raise StopIteration

            # update starting position
            x, y, vec = X
            rmx, rmy = s.follow((x, y, (vec + 3) % 6))
            self.occupied[x, y] = True
            self.occupied[rmx, rmy] = False

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_next_xy(self, x, y, *vec):
        nnx, nny = self.lattice.neighbor_of(x, y)
        vectors = [
            i for i in range(6)
            if not (self.occupied[nnx[i],
                                  nny[i]] or (nnx[i] == -1 or nny[i] == -1))
        ]
        if len(vectors) == 0:
            print_debug("no neighbors")
            return False

        # 確率的に方向を決定
        vector = random.choice(vectors)
        # 点の格子座標を返す
        x, y = nnx[vector], nny[vector]
        return x, y, vector

    def create_random_strings(self, N=3, size=[10, 5, 3]):
        """Create N strings of each size is specified with 'size'.

        This process is equivalent to self-avoiding walk on triangular lattice.
        """
        strings = []

        n = 0
        while n < N:
            # set starting point
            x = random.randint(0, self.lattice.Lx - 1)
            y = random.randint(0, self.lattice.Ly - 1)
            if self.occupied[x, y]:  # reset
                # print_debug("(%d, %d) is occupied already. continue." % (x, y))
                continue
            self.occupied[x, y] = True

            S = size[n]
            pos = [(x, y, np.random.choice(6))]
            trial, nmax = 0, 10
            double = 0
            while len(pos) < S:
                if trial > nmax:
                    for _x, _y, vec in pos:
                        self.occupied[_x, _y] = False
                    # print_debug("All reset")
                    break
                X = self.get_next_xy(x, y)
                if not X:
                    if len(pos) == 1:
                        # print_debug("len(pos) == 1")
                        double = 0
                        trial += 1
                        break
                    else:
                        # print_debug("back one step")
                        # print_debug(pos)
                        if double == 1:
                            # print_debug("two time. back two step")
                            # print_debug(pos)
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            x, y, vector = pos[-1]
                            trial += 1
                            # print_debug(pos)
                            break
                        oldx, oldy, oldvec = pos[-1]
                        del pos[-1]
                        self.occupied[oldx, oldy] = False
                        x, y, vector = pos[-1]
                        trial += 1
                        # print_debug(pos)
                        continue
                else:
                    double = 0
                    x, y, vector = X
                    self.occupied[x, y] = True
                    pos.append((x, y, vector))
                    # print_debug("add step normally")
                    # print_debug(pos)
            else:
                # print_debug("Done. Add string")
                vec = [v[2] for v in pos][1:]
                strings.append(
                    String(self.lattice, n, pos[0][0], pos[0][1], vec=vec))
                n += 1

        return strings
Exemplo n.º 21
0
class Main(base):

    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], plot=True):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10., boundary={'h': 'periodic', 'v': 'periodic'})

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size)

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = plot
        self.interval = 100

    def update(self, num=0):
        # move head part of each strings (if possible)
        for s in self.strings:
            X = self.get_next_xy(s.x, s.y, s.vec[0])
            if not X:
                raise StopIteration

            # update starting position
            x, y, vec = X
            rmx, rmy = s.follow((x, y, (vec + 3) % 6))
            self.occupied[x, y] = True
            self.occupied[rmx, rmy] = False

        ret = self.plot_string()

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_next_xy(self, x, y, vec):
        # 曲げ弾性の効果を再現するために,位置関係によって次の点の
        # 選ばれやすさが異なるようにする
        nnx, nny = self.lattice.neighbor_of(x, y)
        vectors = [i for i in range(6) if not self.occupied[nnx[i], nny[i]]]
        if len(vectors) == 0:
            print_debug("no neighbors")
            return False

        # 確率的に方向を決定
        # 先頭ベクトルを0とした時の相対ベクトルごとの選ばれやすさを設定
        # weights = [0., 1., 2., 3., 2., 1.]
        weights = [0., 0., 1., 4., 1., 0.]
        # weights = [0., 0., 2., 1., 2., 0.]
        # weights = [0., 0., 0., 1., 0., 0.]
        # 有効なものだけ取り出す
        weights = np.array([weights[(i + 6 - vec) % 6] for i in vectors])
        # 規格化
        weights = weights / np.sum(weights)
        # vectorsから一つ選択
        vector = np.random.choice(vectors, p=weights)
        # 点の格子座標を返す
        x, y = nnx[vector], nny[vector]
        return x, y, vector

    def create_random_strings(self, N=3, size=[10, 5, 3]):
        """Create N strings of each size is specified with 'size'.

        This process is equivalent to self-avoiding walk on triangular lattice.
        """
        strings = []

        n = 0
        while n < N:
            # set starting point
            x = random.randint(0, self.lattice.Lx - 1)
            y = random.randint(0, self.lattice.Ly - 1)
            if self.occupied[x, y]:  # reset
                print_debug("(%d, %d) is occupied already. continue." % (x, y))
                continue
            self.occupied[x, y] = True

            S = size[n]
            pos = [(x, y, np.random.choice(6))]
            trial, nmax = 0, 10
            double = 0
            while len(pos) < S:
                if trial > nmax:
                    for _x, _y, vec in pos:
                        self.occupied[_x, _y] = False
                    print_debug("All reset")
                    break
                X = self.get_next_xy(x, y, pos[-1][2])
                if not X:
                    if len(pos) == 1:
                        print_debug("len(pos) == 1")
                        double = 0
                        trial += 1
                        break
                    else:
                        print_debug("back one step")
                        print_debug(pos)
                        if double == 1:
                            print_debug("two time. back two step")
                            print_debug(pos)
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            x, y, vector = pos[-1]
                            trial += 1
                            print_debug(pos)
                            break
                        oldx, oldy, oldvec = pos[-1]
                        del pos[-1]
                        self.occupied[oldx, oldy] = False
                        x, y, vector = pos[-1]
                        trial += 1
                        print_debug(pos)
                        continue
                else:
                    double = 0
                    x, y, vector = X
                    self.occupied[x, y] = True
                    pos.append((x, y, vector))
                    print_debug("add step normally")
                    print_debug(pos)
            else:
                print_debug("Done. Add string")
                vec = [v[2] for v in pos][1:]
                strings.append(String(self.lattice, n, pos[0][0], pos[0][1],
                                      vec=vec))
                n += 1

        return strings
Exemplo n.º 22
0
class Main(base):
    """任意に設定したstringの近傍点に点を追加し成長させるモデル

    グラフ上で左端と右端に固定されたstringの近傍点を探索,ランダム(後には曲げ
    弾性による重み付けの効果を追加)に選択し,stringを成長させていくモデル
    """

    def __init__(self, Lx=40, Ly=40,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta = 2.,
                 interval=1,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):
        """Init function of Main class.

        Lx (int (even)): 格子のx方向(グラフではy軸)の格子点数
        Ly (int (even)): 格子のy方向(グラフではx軸)の格子点数
        """
        # Create triangular lattice with given parameters
        # self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
        #                   scale=float(max(Lx, Ly)), boundary=boundary)
        self.lattice = LT(
            np.zeros((Lx, Ly), dtype=np.int),
            scale=float(max(Lx, Ly)),
            boundary=boundary
        )

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            self.occupied[string.pos_x, string.pos_y] = True


        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError("`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video


        self.interval = interval
        self.frames = frames

        # 逆温度
        self.beta = beta
        # self.beta = 100. # まっすぐ(≒低温極限)
        # self.beta = 10. # まっすぐ
        # self.beta = 0. # 高温極限
        # self.beta = 5. # 中間的
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                # indexes=[[0, len(self.strings[key].pos)]]
                index_start=0,
                index_stop=len(self.strings[key].pos)
            )

            # TODO: 隣接点がないとき,全体のシミュレーションを終了する
            # if len(value) == 0:
            #     return False

            self.bonding_pairs[key] = value

        # pp.pprint(self.bonding_pairs)
        # print(self.strings[0].pos)
        # pp.pprint(self.bonding_pairs[0])


        # pp.pprint(self.bonding_pairs)
        # return None

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
            # print("Image file is successfully saved at '%s'." % filename_image)

    def _update_dict(self, dict, key, value):
        if dict.has_key(key):
            dict[key].append(value)
        else:
            dict[key] = [value]

    def dot(self, v, w):
        """0〜5で表された6つのベクトルの内積を計算する。

        v, w (int): ベクトル(0〜5の整数で表す)"""
        if (w + 6 - v) % 6 == 0:
            return 1.
        elif (w + 6 - v) % 6 == 1 or (w + 6 - v) % 6 == 5:
            return 0.5
        elif (w + 6 - v) % 6 == 2 or (w + 6 - v) % 6 == 4:
            return -0.5
        elif (w + 6 - v) % 6 == 3:
            return -1.

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        lattice_X = self.lattice.coordinates_x
        lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(lattice_X) - 0.1, max(lattice_X) + 0.1
        Y_min, Y_max = min(lattice_Y) - 0.1, max(lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            triang = tri.Triangulation(lattice_X, lattice_Y)
            self.ax.triplot(triang, color='#d5d5d5', lw=0.5)


        self.lines = [self.ax.plot([], [], linestyle='-',
                                   color='black',
                                   markerfacecolor='black',
                                   markeredgecolor='black')[0]
                      for i in range(self.number_of_lines)]
        if self.plot_surface:
            # self._num_surface = 1
            # self.lines.append(self.ax.plot([], [], '.', color='#ff0000')[0])
            self._num_surface = 9
            self.lines += [self.ax.plot([], [], '.',
                                        )[0]
                           for i in range(self._num_surface)]

        self.plot_string()

    def start_animation(self, filename=""):
        if self.__dict__.has_key('frames'):
            frames = self.frames
        else:
            frames = 1000

        def init_func(*arg):
            return self.lines

        ani = animation.FuncAnimation(self.fig, self.update, frames=frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True, repeat=False)
        if filename != "":
            try:
                ani.save(filename, codec="libx264", bitrate=-1, fps=30)
            except:
                print("Can't saved.")
            else:
                print("Animation is successfully saved at '%s'." % filename)
        else:
            plt.show()

    def plot_string(self):
        """self.strings内に格納されているStringを参照し,グラフ上に図示する
        """
        # print self.string.pos, self.string.vec
        i = 0  # to count how many line2D object
        for s in self.strings:
            start = 0
            for j, pos1, pos2 in zip(range(len(s.pos) - 1), s.pos[:-1], s.pos[1:]):
                dist_x = abs(self.lattice_X[pos1[0], pos1[1]] -
                            self.lattice_X[pos2[0], pos2[1]])
                dist_y = abs(self.lattice_Y[pos1[0], pos1[1]] -
                            self.lattice_Y[pos2[0], pos2[1]])
                # print j, pos1, pos2
                # print dist_x, dist_y
                # sqrt(2^{2} + (1/2)^{2}) ~ 2.06
                if dist_x > 2.1 * self.lattice.dx or dist_y > 2.1 * self.lattice.dx:
                    x = s.pos_x[start:j + 1]
                    y = s.pos_y[start:j + 1]
                    X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                    Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                    self.lines[i].set_data(X, Y)
                    start = j + 1
                    i += 1
            else:
                x = s.pos_x[start:]
                y = s.pos_y[start:]
                X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                self.lines[i].set_data(X, Y)
                i += 1

        num_plot_surface = 0
        if self.plot_surface:
            if self._num_surface == 1:
                num_plot_surface = 1
                neighbors = []
                for bonding_pairs in self.bonding_pairs.values():
                    # print(bonding_pairs)
                    for pos in bonding_pairs.keys():
                        neighbors.append(pos)
                neighbors = list(np.array(neighbors).T)
                # print(neighbors)
                X, Y = self.lattice_X[neighbors], self.lattice_Y[neighbors]
                # print(X, Y)
                self.lines[-1].set_data(X, Y)

            # === 
            else:
                w = {}
                for bonding_pairs in self.bonding_pairs.values():
                    # print(bonding_pairs)
                    for pos, bps in bonding_pairs.items():
                        for bp, _w in bps:
                            if w.has_key(_w):
                                w[_w].append(pos)
                            else:
                                w[_w] = [pos,]
                num_plot_surface = len(w)
                # W = sorted(w.keys(), reverse=True)
                sum_w = np.sum([len(w[_w]) for _w in w.keys()])
                W = [(_w, (_w * len(w[_w])) / sum_w) for _w in w.keys()]
                ave_W = np.average(W, axis=0)[1] 
                min_W = np.exp(self.beta * (-2.5)) /sum_w
                max_W = np.exp(self.beta * 2.5) /sum_w
                for k, (wi, _w) in enumerate(W):
                    neighbors = list(np.array(w[wi]).T)
                    X, Y = self.lattice_X[neighbors], self.lattice_Y[neighbors]
                    self.lines[-(k + 1)].set_data(X, Y)
                    ## color setting
                    dw = _w - ave_W
                    if min_W == ave_W:
                        _c = 0.5
                    elif dw < 0:
                        _c = (0.5 / (ave_W - min_W)) * (_w - min_W)
                    else:
                        _c = (0.5 / (max_W - ave_W)) * dw + 0.5
                    self.lines[-(k + 1)].set_color(cm.plasma(_c))


        # 最終的に,iの数だけ線を引けばよくなる
        # それ以上のオブジェクトはリセット
        if self.plot_surface:
            max_obj = len(self.lines) - num_plot_surface
        else:
            max_obj = len(self.lines)
        for j in range(i, max_obj):
            self.lines[j].set_data([], [])

        return self.lines

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """

        # update each string
        for i, s in enumerate(self.strings): 
            if self.pre_function is not None:
                self.pre_func_res.append(self.pre_function(self, i, s))
            ret = self.update_each_string(i)
            if self.post_function is not None:
                self.post_func_res.append(self.post_function(self, i, s))

        if self.plot or self.save_video:
            return self.plot_string()

    def update_each_string(self, key):
        X = self.get_neighbor_xy(key)
        if not X:
            raise StopIteration

        # print(X)
        s = self.strings[key]
        # update positions
        if len(X) == 4:
            i, r_rev, nx, ny = X
            s.x, s.y = nx, ny
            s.insert(0, r_rev)
            x, y = s.pos_x[0], s.pos_y[0]
        elif len(X) == 2:
            i, r = X
            s.insert(i + 1, r)
            x, y = s.pos_x[-1], s.pos_y[-1]
        else:
            i, r, r_rev = X
            s.vec[i] = r
            s.insert(i + 1, r_rev)
            x, y = s.pos_x[i + 1], s.pos_y[i + 1]

        self.occupied[x, y] = True

        # print("== start == (%d, %d)" % (x, y))

        # pp.pprint(self.bonding_pairs[key])

        for k, bonding_pairs in self.bonding_pairs.items():
            if bonding_pairs.has_key((x, y)):
                del self.bonding_pairs[k][(x, y)]
                # print("del self.bonding_pairs[%d][(%d, %d)]" % (k, x, y))

        # pp.pprint(self.bonding_pairs[key])

        index_start = i
        index_stop = len(s.pos)
        # print(index_start, index_stop)

        self.cleanup_bonding_pairs(
            key=key,
            index_start=index_start,
            index_stop=index_stop
        )

        value = self.get_bonding_pairs(
            s=self.strings[key],
            index_start=index_start,
            index_stop=index_stop
        )

        # pp.pprint(value)
        # pp.pprint(self.bonding_pairs[key])

        for k, v in value.items():
            if self.bonding_pairs[key].has_key(k):
                self.bonding_pairs[key][k] += v
            else:
                self.bonding_pairs[key][k] = v

        # pp.pprint(self.bonding_pairs[key])

        # print("== end ==")

        # pp.pprint(self.strings[key].pos)
        # pp.pprint(self.bonding_pairs[key].keys())

    def cleanup_bonding_pairs(self, key, index_start, index_stop):
        rang = range(index_start, index_stop)
        for pos, l in self.bonding_pairs[key].items():
            tmp = [l[i] for i, (bp, w) in enumerate(l) if not bp[0] in rang]
            if len(tmp) == 0:
                del self.bonding_pairs[key][pos]
            else:
                self.bonding_pairs[key][pos] = tmp

    def get_neighbor_xy(self, key):
        """Stringクラスのインスタンスsの隣接する非占有格子点の座標を取得する

        s (String): 対象とするStringクラスのインスタンス
        """
        if len(self.bonding_pairs[key]) == 0:
            return False

        # bonding_pairsの選ばれやすさを適切に重みを付けて評価
        weights = []
        bonding_pairs = []
        for (pair, w) in reduce(operator.add, self.bonding_pairs[key].values()):
            bonding_pairs.append(pair)
            weights.append(w)

        weights = np.array(weights)
        weights = weights / np.sum(weights)
        # print(weights)

        choiced_index = np.random.choice(range(len(weights)), p=weights)
        # print(bonding_pairs[choiced_index])
        return bonding_pairs[choiced_index]

    def calc_weight(self, s, i, r_i=None, r_rev=None):
        """ベクトルの内積を元に,Boltzmann分布に従って成長点選択の重みを決定
        """

        if (i == 1) and (not s.loop):
            w = self.dot(r_rev, s.vec[i]) - self.dot(s.vec[0], s.vec[1]) \
                - self.weight_const
        elif (i == len(s.pos) - 1) and (not s.loop):
            w = self.dot(s.vec[i - 2], r_i) - \
                self.dot(s.vec[i - 2], s.vec[i - 1]) - self.weight_const
        else:
            # w = self.dot(s.vec[i - 2], r_i) + self.dot(r_rev, s.vec[i % len(s.vec)])
            w = (self.dot(s.vec[i - 2], r_i) + \
                 self.dot(r_rev, s.vec[i % len(s.vec)])) \
                - (self.dot(s.vec[i - 2], s.vec[i - 1]) + \
                   self.dot(s.vec[i - 1], s.vec[i % len(s.vec)])) \
                - self.weight_const

        W = np.exp(self.beta * w)
        return W

    def get_bonding_pairs(self, s, index_start, index_stop):
        bonding_pairs = {}
        neighbors_dict = {}
        rang = range(index_start, index_stop)

        if s.loop and (0 in rang):
            rang.append(0)

        for i in rang:
            x, y = s.pos[i]
            nnx, nny = self.lattice.neighbor_of(x, y)

            for r in [0, 1, 2, 3, 4, 5]:
                nx, ny = nnx[r], nny[r]
                if self.occupied[nx, ny] or nx == -1 or ny == -1:
                    continue

                r_rev = (r + 3) % 6

                if not neighbors_dict.has_key((nx, ny)):
                    if not s.loop:
                        if i == 0:
                            w = self.dot(r_rev, s.vec[0])
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs,
                                               (nx, ny),
                                               [[0, r_rev, nx, ny], W])
                        elif i == len(s.pos) - 1:
                            w = self.dot(s.vec[i - 1], r)
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs,
                                               (nx, ny),
                                               [[i, r], W])
                    neighbors_dict[(nx, ny)] = [(i, r),]
                else:
                    if neighbors_dict[(nx, ny)][-1][0] == i - 1:
                        r_i = neighbors_dict[(nx, ny)][-1][1]
                        W = self.calc_weight(s, i, r_i, r_rev)
                        self._update_dict(bonding_pairs,
                                           (nx, ny),
                                           [[i - 1, r_i, r_rev], W])
                    neighbors_dict[(nx, ny)].append((i, r))
        return bonding_pairs
Exemplo n.º 23
0
class Sim(Main):
    def __init__(self, Lx=40, Ly=40,
                 boundary={'h': 'periodic', 'v': 'periodic'},
                 size=[5, 4, 10, 12],
                 plot=True,
                 plot_surface=True,
                 save_image=False,
                 save_video=False,
                 filename_image="",
                 filename_video="",
                 frames=1000,
                 beta = 2.,
                 interval=0,
                 weight_const=0.5,
                 strings=None,
                 pre_function=None,
                 post_function=None):

        self.lattice = LT(
            np.zeros((Lx, Ly), dtype=np.int),
            scale=float(max(Lx, Ly)),
            boundary=boundary
        )

        ## randomize
        randomize(self.lattice)

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            self.triang_standard = tri.Triangulation(self.lattice.coordinates_x,
                                                     self.lattice.coordinates_y)
            self.triang_random = tri.Triangulation(
                self.lattice.coordinates_x,
                self.lattice.coordinates_y,
                triangles=self.triang_standard.triangles)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        if strings is None:
            # Put the strings to the lattice
            self.strings = self.create_random_strings(len(size), size)
        else:
            self.strings = [String(self.lattice, **st) for st in strings]
        for string in self.strings:
            self.occupied[string.pos_x, string.pos_y] = True


        self.plot = plot
        self.plot_surface = plot_surface
        self.save_image = save_image
        self.save_video = save_video
        if self.save_image:
            if filename_image == "":
                raise AttributeError("`filename_image` is empty.")
            else:
                self.filename_image = filename_image

        if self.save_video:
            if self.plot:
                raise AttributeError("`save` and `plot` method can't be set both True.")
            if filename_video == "":
                raise AttributeError("`filename_video` is empty.")
            else:
                self.filename_video = filename_video


        self.interval = interval
        self.frames = frames

        # 逆温度
        self.beta = beta
        self.weight_const = weight_const

        self.bonding_pairs = {i: {} for i in range(len(self.strings))}
        for key in self.bonding_pairs.keys():
            value = self.get_bonding_pairs(
                s=self.strings[key],
                # indexes=[[0, len(self.strings[key].pos)]]
                index_start=0,
                index_stop=len(self.strings[key].pos)
            )

            self.bonding_pairs[key] = value

        self.pre_function = pre_function
        self.post_function = post_function
        self.pre_func_res = []
        self.post_func_res = []

        # Plot triangular-lattice points, string on it, and so on
        if self.plot:
            self.plot_all()
            self.start_animation()
        elif self.save_video:
            self.plot_all()
            self.start_animation(filename=self.filename_video)
        else:
            t = 0
            while t < self.frames:
                try:
                    self.update()
                    t += 1
                except StopIteration:
                    break

        if self.save_image:
            if not self.__dict__.has_key('fig'):
                self.plot_all()
            self.fig.savefig(self.filename_image)
            plt.close()
            # print("Image file is successfully saved at '%s'." % filename_image)

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        lattice_X = self.lattice.coordinates_x
        lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(lattice_X) - 0.1, max(lattice_X) + 0.1
        Y_min, Y_max = min(lattice_Y) - 0.1, max(lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        ## if the lattice size exceeds 200, don't draw triangular lattice.
        if max(self.lattice.Lx, self.lattice.Ly) < 200:
            self.ax.triplot(self.triang_random, color='#d5d5d5', lw=0.5)


        self.lines = [self.ax.plot([], [], linestyle='-',
                                   color='black',
                                   markerfacecolor='black',
                                   markeredgecolor='black')[0]
                      for i in range(self.number_of_lines)]
        if self.plot_surface:
            self._num_surface = 1
            self.lines.append(self.ax.plot([], [], '.', color='#ff0000')[0])
        self.plot_string()

    def _vector(self, X1, Y1, X2, Y2):
        """Return 2-d vector from (X1, Y1) to (X2, Y2).
        Remark: X1, X2,... are grid coordinates and are not coordinates in
        real 2d space."""
        x1, y1 = self.lattice_X[X1][Y1], self.lattice_Y[X1][Y1]
        x2, y2 = self.lattice_X[X2][Y2], self.lattice_Y[X2][Y2]
        return np.array([x2 - x1, y2 - y1])

    def dot(self, vec1, vec2):
        """Calculate user-defined 'inner product' from the two 2d vectors
        `vec1` and `vec2`.
        """
        ## normal inner product
        # res = np.dot(vec1, vec2)

        ## only depend on angle
        res = np.dot(vec1 / np.linalg.norm(vec1), vec2 / np.linalg.norm(vec2))
        return res

    def get_bonding_pairs(self, s, index_start, index_stop):
        def _vec_(i):
            """Get vector from the point in string 's' indexed 'i' to the point
            indexed 'i+1'."""
            X1, Y1 = s.pos[i]
            X2, Y2 = s.pos[i + 1]
            return self._vector(X1, Y1, X2, Y2)

        bonding_pairs = {}
        neighbors_dict = {}
        rang = range(index_start, index_stop)

        if s.loop and (0 in rang):
            rang.append(0)

        for i in rang:
            x, y = s.pos[i]
            nnx, nny = self.lattice.neighbor_of(x, y)

            for r_int in [0, 1, 2, 3, 4, 5]:
                nx, ny = nnx[r_int], nny[r_int]
                if self.occupied[nx, ny] or nx == -1 or ny == -1:
                    continue

                r = self._vector(x, y, nx, ny)
                r_rev = self._vector(nx, ny, x, y)
                r_rev_int = (r_int + 3) % 6

                if not neighbors_dict.has_key((nx, ny)):
                    if not s.loop:
                        if i == 0:
                            w = self.dot(r_rev, _vec_(i % len(s.vec)))
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs,
                                              (nx, ny),
                                              [[0, r_rev_int, nx, ny], W])
                        elif i == len(s.pos) - 1:
                            w = self.dot(_vec_(i - 1), r)
                            W = np.exp(self.beta * w)
                            self._update_dict(bonding_pairs,
                                              (nx, ny),
                                              [[i, r_int], W])
                    neighbors_dict[(nx, ny)] = [(i, r, r_int),]
                else:
                    if neighbors_dict[(nx, ny)][-1][0] == i - 1:
                        r_i = neighbors_dict[(nx, ny)][-1][1]
                        r_i_int = neighbors_dict[(nx, ny)][-1][2]

                        if (i == 1) and (not s.loop):
                            w = (
                                self.dot(r_i, r_rev) + \
                                self.dot(r_rev, _vec_(i))
                            ) - (
                                self.dot(_vec_(i - 1), _vec_(i))
                            )

                        elif (i == len(s.pos) - 1) and (not s.loop):
                            w = (
                                self.dot(_vec_(i - 2), r_i) + \
                                self.dot(r_i, r_rev)
                            ) - (
                                self.dot(_vec_(i - 2), _vec_(i - 1))
                            )
                        else:
                            w = (
                                self.dot(_vec_(i - 2), r_i) + \
                                self.dot(r_i, r_rev) + \
                                self.dot(r_rev, _vec_(i % len(s.vec)))
                            ) - (
                                self.dot(_vec_(i - 2), _vec_(i - 1)) + \
                                self.dot(_vec_(i - 1), _vec_(i % len(s.vec)))
                            )

                        W = np.exp(self.beta * w)
                        self._update_dict(bonding_pairs,
                                           (nx, ny),
                                           [[i - 1, r_i_int, r_rev_int], W])
                    neighbors_dict[(nx, ny)].append((i, r, r_int))
        return bonding_pairs
Exemplo n.º 24
0
class Main:

    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], interval=50,
                 plot=True):
        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=float(max(Lx, Ly)),
                          boundary={'h': 'periodic', 'v': 'periodic'})

        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = Lx

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

        self.plot = plot
        self.interval = interval

    def plot_all(self):
        """軸の設定,三角格子の描画,線分描画要素の用意などを行う

        ここからFuncAnimationを使ってアニメーション表示を行うようにする
        """
        if self.__dict__.has_key('frames'):
            frames = self.frames
        else:
            frames = 1000
        self.fig, self.ax = plt.subplots(figsize=(8, 8))

        lattice_X = self.lattice.coordinates_x
        lattice_Y = self.lattice.coordinates_y
        X_min, X_max = min(lattice_X) - 0.1, max(lattice_X) + 0.1
        Y_min, Y_max = min(lattice_Y) - 0.1, max(lattice_Y) + 0.1
        self.ax.set_xlim([X_min, X_max])
        self.ax.set_ylim([Y_min, Y_max])
        self.ax.set_xticklabels([])
        self.ax.set_yticklabels([])
        self.ax.set_aspect('equal')

        triang = tri.Triangulation(lattice_X, lattice_Y)

        self.ax.triplot(triang, color='#d5d5d5', lw=0.5)

        self.lines = [self.ax.plot([], [], marker='.', linestyle='-',
                                   color='black',
                                   markerfacecolor='black',
                                   markeredgecolor='black')[0]
                      for i in range(self.number_of_lines)]

        self.lattice_X = self.lattice.coordinates_x.reshape(self.lattice.Lx,
                                                            self.lattice.Ly)
        self.lattice_Y = self.lattice.coordinates_y.reshape(self.lattice.Lx,
                                                            self.lattice.Ly)
        self.plot_string()

        def init_func(*arg):
            return self.lines

        ani = animation.FuncAnimation(self.fig, self.update, frames=frames,
                                      init_func=init_func,
                                      interval=self.interval,
                                      blit=True, repeat=False)
        plt.show()

    def plot_string(self):
        """self.strings内に格納されているStringを参照し,グラフ上に図示する
        """
        # print self.string.pos, self.string.vec

        i = 0  # to count how many line2D object
        for s in self.strings:
            start = 0
            for j, pos1, pos2 in zip(range(len(s.pos) - 1), s.pos[:-1], s.pos[1:]):
                dist_x = abs(self.lattice_X[pos1[0], pos1[1]] -
                            self.lattice_X[pos2[0], pos2[1]])
                dist_y = abs(self.lattice_Y[pos1[0], pos1[1]] -
                            self.lattice_Y[pos2[0], pos2[1]])
                # print j, pos1, pos2
                # print dist_x, dist_y
                if dist_x > 2.1 * self.lattice.dx or dist_y > 2.1 * self.lattice.dy:
                    x = s.pos_x[start:j + 1]
                    y = s.pos_y[start:j + 1]
                    X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                    Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                    self.lines[i].set_data(X, Y)
                    start = j + 1
                    i += 1
            else:
                x = s.pos_x[start:]
                y = s.pos_y[start:]
                X = [self.lattice_X[_x, _y] for _x, _y in zip(x, y)]
                Y = [self.lattice_Y[_x, _y] for _x, _y in zip(x, y)]
                self.lines[i].set_data(X, Y)
                i += 1
        # 最終的に,iの数だけ線を引けばよくなる
        # それ以上のオブジェクトはリセット
        for j in range(i, len(self.lines)):
            self.lines[j].set_data([], [])

        return self.lines

    def update(self, num=0):
        """FuncAnimationから各フレームごとに呼び出される関数

        1時間ステップの間に行う計算はすべてここに含まれる。
        """
        # move head part of each strings (if possible)
        for s in self.strings:
            X = self.get_next_xy(s.x, s.y)
            if not X:
                raise StopIteration

            # update starting position
            x, y, vec = X
            rmx, rmy = s.follow((x, y, (vec + 3) % 6))
            self.occupied[x, y] = True
            self.occupied[rmx, rmy] = False

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_next_xy(self, x, y, *vec):
        nnx, nny = self.lattice.neighbor_of(x, y)
        vectors = [i for i in range(6)
                   if not (self.occupied[nnx[i], nny[i]]
                   or (nnx[i] == -1 or nny[i] == -1))
                   ]
        if len(vectors) == 0:
            print_debug("no neighbors")
            return False

        # 確率的に方向を決定
        vector = random.choice(vectors)
        # 点の格子座標を返す
        x, y = nnx[vector], nny[vector]
        return x, y, vector

    def create_random_strings(self, N=3, size=[10, 5, 3]):
        """Create N strings of each size is specified with 'size'.

        This process is equivalent to self-avoiding walk on triangular lattice.
        """
        strings = []

        n = 0
        while n < N:
            # set starting point
            x = random.randint(0, self.lattice.Lx - 1)
            y = random.randint(0, self.lattice.Ly - 1)
            if self.occupied[x, y]:  # reset
                # print_debug("(%d, %d) is occupied already. continue." % (x, y))
                continue
            self.occupied[x, y] = True

            S = size[n]
            pos = [(x, y, np.random.choice(6))]
            trial, nmax = 0, 10
            double = 0
            while len(pos) < S:
                if trial > nmax:
                    for _x, _y, vec in pos:
                        self.occupied[_x, _y] = False
                    # print_debug("All reset")
                    break
                X = self.get_next_xy(x, y)
                if not X:
                    if len(pos) == 1:
                        # print_debug("len(pos) == 1")
                        double = 0
                        trial += 1
                        break
                    else:
                        # print_debug("back one step")
                        # print_debug(pos)
                        if double == 1:
                            # print_debug("two time. back two step")
                            # print_debug(pos)
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            x, y, vector = pos[-1]
                            trial += 1
                            # print_debug(pos)
                            break
                        oldx, oldy, oldvec = pos[-1]
                        del pos[-1]
                        self.occupied[oldx, oldy] = False
                        x, y, vector = pos[-1]
                        trial += 1
                        # print_debug(pos)
                        continue
                else:
                    double = 0
                    x, y, vector = X
                    self.occupied[x, y] = True
                    pos.append((x, y, vector))
                    # print_debug("add step normally")
                    # print_debug(pos)
            else:
                # print_debug("Done. Add string")
                vec = [v[2] for v in pos][1:]
                strings.append(String(self.lattice, n, pos[0][0], pos[0][1],
                                      vec=vec))
                n += 1

        return strings
Exemplo n.º 25
0
class Main(base):

    def __init__(self, Lx=40, Ly=40, N=4, size=[5, 4, 10, 12], plot=True,
                 beta=4.):
        self.plot = plot
        self.beta = beta
        self.interval = 1
        self.frames = 20000

        # Create triangular lattice with given parameters
        self.lattice = LT(np.zeros((Lx, Ly), dtype=np.int),
                          scale=10.,
                          boundary={'h': 'periodic', 'v': 'periodic'}
                          )
        randomize(self.lattice)
        self.triang_standard = tri.Triangulation(self.lattice.coordinates_x,
                                                 self.lattice.coordinates_y)
        self.triang_random = tri.Triangulation(
            self.lattice.coordinates_x,
            self.lattice.coordinates_y,
            triangles=self.triang_standard.triangles)

        self.lattice_X = self.lattice.coordinates_x.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.lattice_Y = self.lattice.coordinates_y.reshape(
            self.lattice.Lx,
            self.lattice.Ly
        )
        self.occupied = np.zeros((Lx, Ly), dtype=np.bool)
        self.number_of_lines = sum(size)

        # Put the strings to the lattice
        self.strings = self.create_random_strings(N, size)

    def _vector(self, X1, Y1, X2, Y2):
        """Return 2-d vector from (X1, Y1) to (X2, Y2).
        Remark: X1, X2,... are grid coordinates and are not coordinates in
        real 2d space."""
        x1, y1 = self.lattice_X[X1][Y1], self.lattice_Y[X1][Y1]
        x2, y2 = self.lattice_X[X2][Y2], self.lattice_Y[X2][Y2]
        return np.array([x2 - x1, y2 - y1])

    def _vec_(self, s, i):
        """Get vector from the point in string 's' indexed 'i' to the point
        indexed 'i+1'."""
        X1, Y1 = s.pos[i]
        X2, Y2 = s.pos[i + 1]
        return self._vector(X1, Y1, X2, Y2)

    def dot(self, vec1, vec2):
        """Calculate user-defined 'inner product' from the two 2d vectors
        `vec1` and `vec2`.
        """
        ## normal inner product
        # res = np.dot(vec1, vec2)

        ## only depend on angle
        res = np.dot(vec1 / np.linalg.norm(vec1), vec2 / np.linalg.norm(vec2))
        return res

    def update(self, num=0):
        # move head part of each strings (if possible)
        for s in self.strings:
            X = self.get_next_xy(s.x, s.y, self._vec_(s, 0))
            if not X:
                ## Stop all simulation
                # raise StopIteration

                ## Stop one string
                # continue

                ## Reverse head
                s.x, s.y = s.pos_x[-1], s.pos_y[-1]
                s.vec = [(vec + 3) % 6 for vec in reversed(s.vec)]
                s.update_pos()
                continue

            # update starting position
            x, y, vec = X
            rmx, rmy = s.follow((x, y, (vec + 3) % 6))
            self.occupied[x, y] = True
            self.occupied[rmx, rmy] = False

        ret = self.plot_string()

        if self.plot:
            ret = self.plot_string()
            return ret

    def get_next_xy(self, x, y, vec):
        # 曲げ弾性の効果を再現するために,位置関係によって次の点の
        # 選ばれやすさが異なるようにする
        nnx, nny = self.lattice.neighbor_of(x, y)
        vectors = [i for i in range(6) if not self.occupied[nnx[i], nny[i]]]
        if len(vectors) == 0:
            # print_debug("no neighbors")
            return False

        # 確率的に方向を決定
        if type(vec) == np.ndarray:
            weights = np.array([
                np.exp(
                    self.beta * self.dot(self._vector(nnx[i], nny[i], x, y), vec)
                ) for i in vectors])
        else:
            weights = np.array([1.] * len(vectors))
        # 規格化
        weights = weights / np.sum(weights)
        # vectorsから一つ選択
        selected_vector = np.random.choice(vectors, p=weights)
        # 点の格子座標を返す
        x, y = nnx[selected_vector], nny[selected_vector]
        return x, y, selected_vector

    def create_random_strings(self, N=3, size=[10, 5, 3]):
        """Create N strings of each size is specified with 'size'.

        This process is equivalent to self-avoiding walk on triangular lattice.
        """
        strings = []

        n = 0
        while n < N:
            # set starting point
            x = random.randint(0, self.lattice.Lx - 1)
            y = random.randint(0, self.lattice.Ly - 1)
            if self.occupied[x, y]:  # reset
                # print_debug("(%d, %d) is occupied already. continue." % (x, y))
                continue
            self.occupied[x, y] = True

            S = size[n]
            pos = [(x, y, np.random.choice(6))]
            trial, nmax = 0, 10
            double = 0
            while len(pos) < S:
                if trial > nmax:
                    for _x, _y, vec in pos:
                        self.occupied[_x, _y] = False
                    # print_debug("All reset")
                    break
                if len(pos) == 1:
                    X = self.get_next_xy(x, y, 1)
                else:
                    X = self.get_next_xy(x, y, self._vector(
                        pos[-2][0], pos[-2][1], pos[-1][0], pos[-1][1]))
                if not X:
                    if len(pos) == 1:
                        # print_debug("len(pos) == 1")
                        double = 0
                        trial += 1
                        break
                    else:
                        # print_debug("back one step")
                        # print_debug(pos)
                        if double == 1:
                            # print_debug("two time. back two step")
                            # print_debug(pos)
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            oldx, oldy, oldvec = pos[-1]
                            del pos[-1]
                            self.occupied[oldx, oldy] = False
                            x, y, vector = pos[-1]
                            trial += 1
                            # print_debug(pos)
                            break
                        oldx, oldy, oldvec = pos[-1]
                        del pos[-1]
                        self.occupied[oldx, oldy] = False
                        x, y, vector = pos[-1]
                        trial += 1
                        # print_debug(pos)
                        continue
                else:
                    double = 0
                    x, y, vector = X
                    self.occupied[x, y] = True
                    pos.append((x, y, vector))
                    # print_debug("add step normally")
                    # print_debug(pos)
            else:
                # print_debug("Done. Add string")
                vec = [v[2] for v in pos][1:]
                strings.append(String(self.lattice, n, pos[0][0], pos[0][1],
                                      vec=vec))
                n += 1

        return strings