質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

429閲覧

数値計算の式をまとめる方法

suugaku_nyumon

総合スコア37

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/12/10 17:09

質問内容

2次元の感染症のセルオートマトンを書いてコードは書けていたのですが、コードのdef execCellの部分がとても長くなっており、式が羅列している状態で見づらいので短い表現に変えられるならば変えたいと思っているのですが、自分では思いつきません。

下のコードのexecCellを短くまとめるにはどうすればよいのでしょうか?
###execCellの内容
縦31マス、横31マスのセルで考えています。そのセルに動物Aと動物Bがおり、ウイルスの感染の広がりはどうなのかをセルオートマトンでモデル化しようとしています。

A[n][i][j]はnステップ目における(i,j)のセルの状態値を表しており、1であれば感染した動物A、2であれば感染していない動物A、3であれば感染した動物B、4であれば感染していない動物Bを表しています。

ここで動物の移動は考えておらず、動物の状態=セルの状態で考えています。

ここで感染度と感染確率を定義しますが、感染確率に関しては動物Aから動物Aではp_cc=0.25、動物Bから動物Aではp_bc=0.75、動物Aから動物Bでは0.10、動物Bから動物Bでは0.40と考えています。

また2重感染は考えておらず、感染していない個体のみ他の縦か横で隣接するマスからうつされると仮定します。alphaは自己回復率で、隣接する個体からの感染が無い場合、次のステップの感染度は今のステップの自身の感染度の(1-α)倍となるように式を設定しています。

なぜ式が長くなったかというと、まず自身が感染しているかどうかの場合分けと、そして自身が感染していない場合に隣接する4つのマスのそれぞれの状態を場合分けで考え、さらに感染度によって感染しているか否か、次の状態を考えているためそこでも場合分けが生じます。

せめて隣接するマスの場合分けを少なくできればよいと思ったのですが、ためしに自分がやってみるとプログラム自体が変わってしまったので、どうにかプログラムを変えずに変形できるかと悩んでおりました。

自身の次のステップの感染度の計算は

(自身の今のステップの感染度)×(1-回復率)+(隣接する4マスのそれぞれの感染度に、感染確率を掛け合わせたものの総和)

で計算しています。

コード

python3

1from tkinter import * 2import time 3import tkinter as tk 4import random 5import math 6#配列の宣言 7def array2(N1,N2): 8 return [[0 for j in range(N2)]for k in range(N1)] 9def array3(N1,N2,N3): 10 return [array2(N2,N3)for k in range(N1)] 11#セルの初期設定 12def initdt(): 13 A=array3(1000,31,31) 14 B=array3(1000,31,31) 15 for i in range(1,31): 16 for j in range(1,31): 17 if (i == 15 and j == 15): 18 A[0][i][j] = 1 19 B[0][i][j] = 1 20 else: 21 r_i=random.random() 22 if (r_i <= 0.5): 23 A[0][i][j] = 2 24 B[0][i][j] = 0 25 if (r_i > 0.5): 26 A[0][i][j] = 4 27 B[0][i][j] = 0 28 return A , B 29#セルオートマトンの実行 30def execCell(A,B,i1): 31 i2 = 1 + i1 32 for i in range(1,30): 33 for j in range(1,30): 34 alpha = 0.50 35 p_cc = 0.25 36 p_bc = 0.75 37 p_cb = 0.10 38 p_bb = 0.40 39 a = 0.60 40 if A[i1][i][j] == 1: 41 B[i2][i][j] = (1 - alpha) * B[i1][i][j] 42 if (B[i2][i][j] >= 0 and B[i2][i][j] < a): 43 A[i2][i][j] = 2 44 if (B[i2][i][j] >= a and B[i2][i][j] <= 1.0): 45 A[i2][i][j] = 1 46 if A[i1][i][j] == 2: 47 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 48 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 49 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 50 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 51 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 52 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 53 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 54 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 55 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 56 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 57 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 58 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 59 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 60 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 61 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 62 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 63 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 64 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 65 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 66 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 67 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 68 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 69 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 1 or A[i1][i][j-1] == 2)): 70 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_cc * B[i1][i][j-1] 71 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 1 or A[i1][i][j+1] == 2) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 72 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_cc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 73 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 1 or A[i1][i-1][j] == 2) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 74 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_cc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 75 if ((A[i1][i+1][j] == 1 or A[i1][i+1][j] == 2) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 76 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_cc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 77 if ((A[i1][i+1][j] == 3 or A[i1][i+1][j] == 4) and (A[i1][i-1][j] == 3 or A[i1][i-1][j] == 4) and (A[i1][i][j+1] == 3 or A[i1][i][j+1] == 4) and (A[i1][i][j-1] == 3 or A[i1][i][j-1] == 4)): 78 B[i2][i][j] = (1 - alpha) * B[i1][i][j] + p_bc * B[i1][i+1][j] + p_bc * B[i1][i-1][j] + p_bc * B[i1][i][j+1] + p_bc * B[i1][i][j-1] 79 if (B[i2][i][j] >= 0 and B[i2][i][j] < a): 80 A[i2][i][j] = 2 81 if (B[i2][i][j] >= a and B[i2][i][j] <= 1.0): 82 A[i2][i][j] = 1 83 if (B[i2][i][j] > 1.0): 84 A[i2][i][j] = 1 85 B[i2][i][j] = 1.0 86 (ここから先は文字数が10000字を超えるので省略) 87 88#セルの位置決めとIDの設定 89def drawCell(canvas,A,k): 90 x2=0 91 CID=array2(31,31) 92 for i in range(1,30): 93 x1=x2 94 x2=x1+20 95 y2=0 96 for j in range(1,30): 97 y1=y2 98 y2=y1+20 99 CID[i][j]=canvas.create_rectangle(x1,y1,x2,y2,fill='black') 100 return CID 101#セルの色設定 102def modifyCell(canvas,A,k,CID): 103 CL=['black','#ffffff','#ff0000','#ffffff','#0000ff'] 104 for i in range(1,30): 105 for j in range(1,30): 106 canvas.itemconfig(CID[i][j],fill=CL[A[k][i][j]]) 107 canvas.itemconfig(CID[i][j],outline=CL[A[k][i][j]]) 108#Tk初期設定 109def initTk(): 110 tk=Tk(); tk.title("2D Cell Automaton"); tk.resizable(0,0) 111 return tk 112#画面キャプチャ用 113def leftMouseDown(event): 114 global canvas, A,k,CID 115 modifyCell(canvas,A,k,CID) 116 execCell(A,B,k) 117#実行メイン 118A,B=initdt() 119root=initTk() 120canvas=Canvas(root,width=580,height=580,highlightthickness=0) 121canvas.pack() 122CID=drawCell(canvas,A,0) 123k=0 124 125def animate(): 126 global k 127 modifyCell(canvas, A, k, CID) 128 execCell(A,B,k) 129 k = 1 + k 130 root.after(1000, animate) 131 132root.after(1000, animate) 133root.mainloop()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

(A) データの表現方法を工夫する(その1)

例えばある世代i1のセル位置(i,j)にAが存在するかという判定を
A[i1][i][j] == 1 or A[i1][i][j] == 2
としていますが、もし配列の要素の定義を「AがいるかどうかをTrue/Falseで表現する」なら
a_exists[i1][i][j]
でよくなります。もちろん感染しているかどうかは別の変数にする必要があります。

(B) データの表現方法を工夫する(その2)

このプログラムではA, Bが存在するかどうかと感染有無を一つの数値で表現しようとしていますが、複数の情報を一つの数値で表す場合、bitごとに意味を持たせるように定義すると判定を幾分単純にできます。
例えば配列の要素の数値を0bBAI(Pythonの二進数の表現と考えてください)という3bitと考え
A: Aが存在すれば1
B: Bが存在すれば1
I: 感染しているなら1
という定義にすると

セルの意味セルの値
A感染なし2(==0b010)
A感染あり3(==0b011)
B感染なし4(==0b100)
B感染あり5(==0b101)
動物不在0(==0b000)

こう考えると「Aであるか」の判定は
A[i1][i][j] & 2
「Bであるか」の判定は
A[i1][i][j] & 4
「動物がいるか」の判定は
A[i1][i][j] & 6
「感染した動物がいるか」の判定は
A[i1][i][j] & 1
などとなります。

(C) 直接だらだら書かずに関数化する

本件に限らず一般的なテクニックですが、そもそもややこしいコードをだらだら記述すると「似たようなコードがあちこちに出現するため読みづらくバグの元になる」という問題が起きます。そういうときは「わかりやすい単位で関数化する」ことでコードが読みやすくまたバグが減らせます。

python

1# あるセルの値により「Aであるか」を判定する 2def exists_a(c): 3 return c == 1 or c == 2 4 5def execCell(A, B, i1): 6 ... 7 if exists_a(A[i1][i+1][j]) or exists_a(A[i1][i-1][j]) or ...: 8 ...

関数化に慣れてくると「似たようなパターンを記述することに強い抵抗を覚える」ようになります。上記の他にも「上下左右が特定の状態か」という判定パターンが何度も出てくることにお気づきと思いますがそれも関数化すると・・・

python

1# あるセルの値により「Aであるか」を判定する 2def exists_a(c): 3 return c == 1 or c == 2 4 5# ある世代i1のセルi,jの上下左右にAがいるか 6def exists_a_next_to(A, i1, i, j): 7 return exists_a(A[i1][i-1][j]) or exists_a(A[i1][i+1][j]) or \ 8 exists_a(A[i1][i][j-1]) or exists_a(A[i1][i][j+1]) 9 10def execCell(A, B, i1): 11 ... 12 if exists_a_next_to(A, i1, i, j): 13 ...

さらに「隣がAか」と「隣がBか」という似たような関数を定義するのが苦痛にもなってきます。そんな場合は高階関数を利用するテクニックもあります。

# あるセルの値により「Aであるか」を判定する def exists_a(c): return c == 1 or c == 2 def exists_b(c): return c == 3 or c == 4 # ある世代i1のセルi,jの上下左右が「テストを満たすか」 def judge_next_to(A, i1, i, j, judge): return judge(A[i1][i-1][j]) or judge(A[i1][i+1][j]) or \ judge(A[i1][i][j-1]) or judge(A[i1][i][j+1]) def execCell(A, B, i1): ... # 世代i1、セルi,jの上下左右がAか if judge_next_to(A, i1, i, j, exists_a): ... # 世代i1、セルi,jの上下左右がBか if judge_next_to(A, i1, i, j, exists_b): ...

3つ挙げましたが正直言えば(A),(B)はおまけみたいなもので、個人的に(C)の関数化が重要と思います。


余談1:
Pythonではif (条件式):のように条件式を括弧で囲むのは冗長です。他の言語では文法上括弧を必要とするものがあります(C, Javaなど)がPythonではそうでないので括弧をつけるとむしろ不自然です。

余談2:
本件のテーマとの関係はそれほど深くないですがPython/numpyの場合「配列の各要素に対して同様の処理をループで実装する」というパターンをループなしで表現することも考えたくなります。ただしひょっとすると(A),(B),(C)などに慣れていない段階でnumpyを活用しようとするのは難しいかも知れません。ループを書く書かないの前にやはり(A),(B),(C)のような基本テクニックをよく学んだほうがよいと思います。

投稿2018/12/10 20:39

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suugaku_nyumon

2018/12/11 14:33

ご回答ありがとうございます。 (C)の関数化を考えてみて、隣の動物のセルが違うと感染確率が異なりますが、その他感染度などの要素は区別する必要がないため、予め感染確率を出す関数を作ったところ、短いコードができました。 ただ、その際プログラムにエラーが出て起動できませんが、この質問の件とは無関係なので新たに質問することに致します。ありがとうございました。
guest

0

とりあえずコメント。

また2重感染は考えておらず、感染していない個体のみ他の縦か横で隣接するマスからうつされると仮定します。alphaは自己回復率で、隣接する個体からの感染が無い場合、次のステップの感染度は今のステップの自身の感染度の(1-α)倍となるように式を設定しています。

自身の次のステップの感染度の計算は
(自身の今のステップの感染度)×(1-回復率)+(隣接する4マスのそれぞれの感染度に、感染確率を掛け合わせたものの総和)
で計算しています。

このあたりの解釈がよくわかりません。コードをちゃんと追っていないので的はずれな意見かもしれませんが、

  • 感染している/していないの定義は? コードを見ると0.5が閾値っぽいですが、それで合っていますか?
  • 「2重感染は考えておらず、感染していない個体のみ」あたりの意味がわかりません
  • 常に下の式で更新されるのでしょうか。それとも、条件によって違う更新式があるのでしょうか

(感染した個体は(自身の今のステップの感染度)×(1-回復率)の項だけになるということ?)

  • セルの状態値14と感染度があってややこしいですが、ほんとうの意味で状態と言えるのは感染度(増減する)で、あとはセルごとの固定パラメータとして動物の種類があるということですよね。状態値14をあえて更新していく意義を感じません。

セルオートマトンを書くなら、セルの座標値i,jを取って次の状態を返す関数を定義するところから始めると良いと思います。

あとは全座標総なめにして、返り値を次のステップのフィールド用の配列に突っ込んでいけば更新できます。

追記

python

1import random 2from itertools import product 3import matplotlib.pyplot as plt 4 5alpha = 0.7 6field_w, field_h = 100, 100 7 8# animal_map = [[random.randrange(2) for x in range(field_w)] 9# for y in range(field_h)] 10animal_map = [[0]*field_w]*(field_h//2) + [[1]*field_w]*(field_h//2) 11 12infection_map = [[0.51 if random.random() > 0.999 else 0 for x in range(field_w)] 13 for y in range(field_h)] 14 15color_conds = {(True, True): 1, (True, False):2, 16 (False, True):3, (False, False):4} 17def gen_color_map(): 18 result = [[None]*field_w for _ in range(field_h)] 19 for i in range(field_h): 20 for j in range(field_w): 21 result[i][j] = color_conds[(animal_map[i][j] == 0, 22 infection_map[i][j] > 0.5)] 23 return result 24 25color_map = gen_color_map() 26 27def next_field(): 28 result = [[None]*field_w for _ in range(field_h)] 29 for i in range(field_h): 30 for j in range(field_w): 31 result[i][j] = next_cell(i, j) 32 return result 33 34def get_neighbors(i, j): 35 return [x for x in [(i+1, j), (i-1, j), (i, j+1), (i, j-1)] 36 if (0 <= x[0] < field_h) and (0 <= x[1] < field_w)] 37 38# infect_probs = {(0,0):0.25, (0,1):0.10, (1,0):0.75, (1,1):0.40} 39infect_probs = {(0,0):0.18, (0,1):0.10, (1,0):0.55, (1,1):0.20} 40def next_cell(i, j): 41 if infection_map[i][j] > 0.5: 42 return infection_map[i][j]*(1-alpha) 43 else: 44 self_kind = animal_map[i][j] 45 s = 0 46 for ni, nj in get_neighbors(i, j): 47 n_kind = animal_map[ni][nj] 48 n_infection = infection_map[ni][nj] 49 s += infect_probs[(n_kind, self_kind)] * n_infection 50 return infection_map[i][j]*(1-alpha) + s 51 52def exec_field(): 53 global infection_map, color_map 54 infection_map = next_field() 55 color_map = gen_color_map() 56 57fig, axes = plt.subplots(ncols=2) 58ax, ax2 = axes 59img = ax.imshow(color_map) 60img2 = ax2.imshow(infection_map, cmap="gray", vmin=0, vmax=2) 61plt.draw() 62plt.pause(2) 63 64for i in range(1000): 65 print(i, "step") 66 exec_field() 67 img.set_data(color_map) 68 img2.set_data(infection_map) 69 plt.draw() 70 plt.pause(0.05) 71

投稿2018/12/10 23:36

編集2018/12/14 10:32
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

suugaku_nyumon

2018/12/11 11:07

ご回答ありがとうございます。 •感染している/していないの定義は? コードを見ると0.5が閾値っぽいですが、それで合っていますか? A.これは感染度をBと定義しており、今回はa=0.6を超えているか否かで感染しているか調べています。alpha=0.5は回復率です。 •「2重感染は考えておらず、感染していない個体のみ」あたりの意味がわかりません A.これの意味することは、感染している個体は周りからの影響をうけないということです。感染度の式は(自身の今のステップの感染度)×(1-回復率)となります。 •常に下の式で更新されるのでしょうか。それとも、条件によって違う更新式があるのでしょうか A.感染した個体は(自身の今のステップの感染度)×(1-回復率)となります。感染していない個体は、その項にさらに縦か横で隣接する4つのセルにおいて(隣りのセルからの感染確率)×(隣のセルの感染度)を足し合わせています。 •セルの状態値1~4と感染度があってややこしいですが、ほんとうの意味で状態と言えるのは感染度(増減する)で、あとはセルごとの固定パラメータとして動物の種類があるということですよね。状態値1~4をあえて更新していく意義を感じません。 A.これはセルオートマトンモデルにする際、2種類の動物が非感染の時に色を区別するために状態を4分割しています。感染した時の色は同じですが、治癒後に元の色に戻すことを考えたら4つの状態で場合分けすべきかと思いました。
hayataka2049

2018/12/11 11:20

状況はわかりました。 最後のについて。概念的には、3種類のフィールドを表現する配列を使うと恐らく実装は楽です(ステップごとの状態を記録したりするので、配列を3つ作れば良いということではない)。 a:動物の配置を記録する配列(初期値のまま固定) b:セルごとの感染度を記録する配列(ステップごとに増減) c:セルに塗られる色を格納する配列(aとbから作る) セル1つの次の状態を求める関数を作っておき(a,b,i,jの情報があればできます)、ステップごとにbをその関数で総なめして次のステップのbを求めます。完了したらaと次のbを使って次のcを作れます。
suugaku_nyumon

2018/12/11 14:30

ご回答ありがとうございます。 結局は隣のセルからの感染確率が動物が違うと異なりますが、その他の感染度などは動物で区別する必要が無かったので、KSwordOfHasteさんのご回答で関数化をしたところ、かなり短くなりました。 ただ、3種類のフィールドを表現する配列を使う実装についても考えてみたいと思います。 お忙しい中ありがとうございました。
hayataka2049

2018/12/12 00:59 編集

「こんな感じで書けるかなぁ」と作っていたら一応動くところまで書けちゃったコードを追記で貼りました。パラメータはそれっぽく見えるように変えています。 動作の正しさについては責任を持ちません。未だに問題の解釈を間違えているかもしれないし、バグがあるかもしれません。また、コードの書き方もあまり綺麗ではありません(グローバル変数を多用していますが、計算部分はクラスに入れた方が賢明です。また、描画周りでも手抜きをしていますし、過去のステップも保存していません)。 参考程度に御覧ください。
suugaku_nyumon

2018/12/12 02:42

ありがとうございます! 作ってくれたコードで動かしてみて、動作不良やバグがあった際は、どう直せばよいか自分への課題として考えてみたいと思います。 自分は、セルからセルへの感染確率を関数化することで、隣接するセルが何かの場合分けを無くしてコードを短くしました。
hayataka2049

2018/12/14 10:33 編集

案の定というか、間違いがありました。get_neighborsの定義に間違いがあり、上下左右を返すべきところ右上右下左上左下の座標を返していました。お恥ずかしい・・・ コードを修正しましたので、ご確認ください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問