forked from shibing624/python-tutorial
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path03.forest.py
More file actions
181 lines (149 loc) · 5.03 KB
/
03.forest.py
File metadata and controls
181 lines (149 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# -*- coding: utf-8 -*-
"""
@description: 森林火灾模拟
@author:XuMing
"""
from __future__ import print_function # 兼容python3的print写法
from __future__ import unicode_literals # 兼容python3的编码处理
# 1 对森林建模
# 2 随机生长
# 2.1 在原来的基础上,我们要先让树生长,即定义 grow_trees() 方法
# 2.2 定义方法之前,我们要先指定两个属性:
# 2.2.1 每个位置随机生长出树木的概率
# 2.2.2 每个位置随机被闪电击中的概率
# 2.3 为了方便,我们定义一个辅助函数来生成随机 bool 矩阵,大小与森林大小一致
import numpy as np
class Forest(object):
"""Forest can grow trees"""
def __init__(self, size=(150, 150), p_sapling=0.0025, p_lightning=5.0e-6):
self.size = size
self.trees = np.zeros(self.size, dtype=bool)
self.fires = np.zeros((self.size), dtype=bool)
self.p_sapling = p_sapling
self.p_lightning = p_lightning
def __repr__(self):
my_repr = "{}(size={})".format(self.__class__.__name__, self.size)
return my_repr
def __str__(self):
return self.__class__.__name__
@property
def num_cells(self):
"""Number of cells available for grwoing trees"""
return np.prod(self.size)
@property
def tree_fraction(self):
"""Fraction of trees"""
num_trees = self.trees.sum()
return float(num_trees) / self.num_cells
@property
def fire_fraction(self):
"""Fraction of fires"""
num_fires = self.fires.sum()
return float(num_fires) / self.num_cells
def _rand_bool(self, p):
"""Random boolean distributed according to p, less than p will be True"""
return np.random.uniform(size=self.trees.shape) < p
def grow_trees(self):
"""Growing trees"""
growth_sites = self._rand_bool(self.p_sapling)
self.trees[growth_sites] = True
# Test
forest = Forest()
print(forest.tree_fraction)
forest.grow_trees()
print(forest.tree_fraction)
# 火灾模拟
# 1 定义 start_fires():
# 按照给定的概率生成被闪电击中的位置
# 如果闪电击中的位置有树,那么将其设为着火点
# 2 定义 burn_trees():
# 如果一棵树的上下左右有火,那么这棵树也会着火
# 3 定义 advance_one_step():
# 进行一次生长,起火,燃烧
class FireForest(object):
""" Forest can grow trees which eventually die."""
def __init__(self, size=(150, 150), p_sapling=0.0025, p_lightning=5.0e-6):
self.size = size
self.trees = np.zeros(self.size, dtype=bool)
self.fires = np.zeros((self.size), dtype=bool)
self.p_sapling = p_sapling
self.p_lightning = p_lightning
def __repr__(self):
my_repr = "{}(size={})".format(self.__class__.__name__, self.size)
return my_repr
def __str__(self):
return self.__class__.__name__
@property
def num_cells(self):
"""Number of cells available for growing trees"""
return np.prod(self.size)
@property
def tree_fraction(self):
"""
Fraction of trees
"""
num_trees = self.trees.sum()
return float(num_trees) / self.num_cells
@property
def fire_fraction(self):
"""
Fraction of fires
"""
num_fires = self.fires.sum()
return float(num_fires) / self.num_cells
def _rand_bool(self, p):
"""
Random boolean distributed according to p, less than p will be True
"""
return np.random.uniform(size=self.trees.shape) < p
def grow_trees(self):
"""
Growing trees
"""
growth_sites = self._rand_bool(self.p_sapling)
self.trees[growth_sites] = True
def start_fires(self):
"""
Start of fire
"""
lightning_strikes = (self._rand_bool(self.p_lightning) &
self.trees)
self.fires[lightning_strikes] = True
def burn_trees(self):
"""
Burn trees
"""
fires = np.zeros((self.size[0] + 2, self.size[1] + 2), dtype=bool)
fires[1:-1, 1:-1] = self.fires
north = fires[:-2, 1:-1]
south = fires[2:, 1:-1]
east = fires[1:-1, :-2]
west = fires[1:-1, 2:]
new_fires = (north | south | east | west) & self.trees
self.trees[self.fires] = False
self.fires = new_fires
def advance_one_step(self):
"""
Advance one step
"""
self.grow_trees()
self.start_fires()
self.burn_trees()
fire = FireForest()
for i in range(100):
fire.advance_one_step()
# 显示树木图像
import matplotlib.pyplot as plt
from matplotlib import cm
plt.matshow(fire.trees, cmap=cm.Greens)
plt.show()
# 查看不同着火概率下的森林覆盖率趋势变化:
forest = FireForest()
forest2 = FireForest(p_lightning=5e-4)
tree_fractions = []
for i in range(2000):
forest.advance_one_step()
forest2.advance_one_step()
tree_fractions.append((forest.tree_fraction, forest2.tree_fraction))
plt.plot(tree_fractions)
plt.show()