Skip to content

Commit

Permalink
more final touches
Browse files Browse the repository at this point in the history
  • Loading branch information
joey-obrien committed Apr 7, 2024
1 parent eacd1e0 commit 79c994d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 74 deletions.
19 changes: 11 additions & 8 deletions pyrorl/pyrorl/envs/environment/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
FUEL_MEAN = 8.5
FUEL_STDEV = 3


class FireWorld:
"""
We represent the world as a 5 by n by m tensor:
Expand Down Expand Up @@ -156,9 +157,9 @@ def __init__(
# Initialize fuel levels
# Note: make the fire spread parameters to constants?
num_values = num_rows * num_cols
self.state_space[FUEL_INDEX] = np.random.normal(FUEL_MEAN, FUEL_STDEV, num_values).reshape(
(num_rows, num_cols)
)
self.state_space[FUEL_INDEX] = np.random.normal(
FUEL_MEAN, FUEL_STDEV, num_values
).reshape((num_rows, num_cols))

# Initialize populated areas
pop_rows, pop_cols = populated_areas[:, 0], populated_areas[:, 1]
Expand Down Expand Up @@ -272,8 +273,12 @@ def update_paths_and_evactuations(self):
self.evacuating_timestamps[pop_rows, pop_cols] -= 1
done_evacuating = np.where(self.evacuating_timestamps == 0)

self.state_space[EVACUATING_INDEX, done_evacuating[0], done_evacuating[1]] = 0
self.state_space[POPULATED_INDEX, done_evacuating[0], done_evacuating[1]] = 0
self.state_space[
EVACUATING_INDEX, done_evacuating[0], done_evacuating[1]
] = 0
self.state_space[
POPULATED_INDEX, done_evacuating[0], done_evacuating[1]
] = 0

# Note that right now it is going to be vastly often the case that two
# population cases don't finish evacuating along the same path at the
Expand Down Expand Up @@ -308,9 +313,7 @@ def accumulate_reward(self):
evacuating = self.state_space[EVACUATING_INDEX][populated_areas]

# Mark enflamed areas as no longer populated or evacuating
enflamed_populated_areas = np.where(
fire == 1
)[0]
enflamed_populated_areas = np.where(fire == 1)[0]
enflamed_rows = populated_areas[0][enflamed_populated_areas]
enflamed_cols = populated_areas[1][enflamed_populated_areas]

Expand Down
123 changes: 57 additions & 66 deletions pyrorl/pyrorl/map_helpers/create_map_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,32 @@ def generate_pop_locations(num_rows, num_cols, num_populated_areas):
"""
populated_areas = set()
for _ in range(num_populated_areas):
# We don't generate populated cells on the edge of the
# map
pop_row = random.randint(1, num_rows - 2)
pop_col = random.randint(1, num_cols - 2)
# make sure that n
# Continue generating populated areas until one that
# has not already been created is made
while (pop_row, pop_col) in populated_areas:
pop_row = random.randint(1, num_rows - 2)
pop_col = random.randint(1, num_cols - 2)
populated_areas.add((pop_row, pop_col))
populated_areas = np.array(list(populated_areas))
return populated_areas


def save_map_info(
num_rows, num_cols, num_populated_areas, populated_areas, paths, paths_to_pops
):
"""
This function saves five files:
- map_info.txt: lets the user easily see the number of rows,
the number of columns, and the number of populated areas
- populated_areas_array.pkl: saves the populated areas array
- paths_array.pkl: saves the paths array
- paths_to_pops_array.pkl: saves the paths to pops array
- map_size_and_percent_populated_list.pkl: saves a list that contains
the number of rows, number of columns, and number of populated areas
"""
# the map information is saved in the user's current working directory
user_working_directory = os.getcwd()
maps_info_directory = os.path.join(user_working_directory, MAP_DIRECTORY)
Expand All @@ -72,24 +84,14 @@ def save_map_info(
percent_pop_info = "num_populated_areas: " + str(num_populated_areas)
f.write(percent_pop_info)

# saved the populated areas array
populated_areas_filename = os.path.join(
current_map_directory, "populated_areas_array.pkl"
)
with open(populated_areas_filename, "wb") as f:
pkl.dump(populated_areas, f)

# save the paths array
paths_filename = os.path.join(current_map_directory, "paths_array.pkl")
with open(paths_filename, "wb") as f:
pkl.dump(paths, f)

# save the paths to pops array
paths_to_pops_filename = os.path.join(
current_map_directory, "paths_to_pops_array.pkl"
)
with open(paths_to_pops_filename, "wb") as f:
pkl.dump(paths_to_pops, f)
# saved the populated areas array, paths array, and paths_to_pops arrays
def save_array_to_pickle(current_map_directory, array, name):
array_filename = os.path.join(current_map_directory, name)
with open(array_filename, "wb") as f:
pkl.dump(array, f)
save_array_to_pickle(current_map_directory, populated_areas, "populated_areas_array.pkl")
save_array_to_pickle(current_map_directory, paths, "paths_array.pkl")
save_array_to_pickle(current_map_directory, paths_to_pops, "paths_to_pops_array.pkl")

# save the number of rows, number of columns, and number of populated areas
map_size_and_percent_populated_list = [num_rows, num_cols, num_populated_areas]
Expand All @@ -99,31 +101,30 @@ def save_map_info(
with open(map_size_and_percent_populated_list_filename, "wb") as f:
pkl.dump(map_size_and_percent_populated_list, f)


def load_map_info(map_directory_path):
# load the populated areas array
populated_areas_filename = os.path.join(
map_directory_path, "populated_areas_array.pkl"
)
with open(populated_areas_filename, "rb") as f:
populated_areas = pkl.load(f)

# load the paths array
paths_filename = os.path.join(map_directory_path, "paths_array.pkl")
with open(paths_filename, "rb") as f:
paths = pkl.load(f)
"""
This function loads in six variables to initialize a wildfire environment:
- number of rows
- number of columns
- populated areas array
- paths array
- paths to pops array
- number of populated areas
"""
def load_pickle_file(name):
array_filename = os.path.join(
map_directory_path, name
)
with open(array_filename, "rb") as f:
return pkl.load(f)

# load the paths to pops array
paths_to_pops_filename = os.path.join(map_directory_path, "paths_to_pops_array.pkl")
with open(paths_to_pops_filename, "rb") as f:
paths_to_pops = pkl.load(f)
# load the populated areas array, paths array, and paths_to_pops arrays
populated_areas = load_pickle_file("populated_areas_array.pkl")
paths = load_pickle_file("paths_array.pkl")
paths_to_pops = load_pickle_file("paths_to_pops_array.pkl")

# load the number of rows, number of columns, and number of populated areas
map_size_and_percent_populated_list_filename = os.path.join(
map_directory_path, "map_size_and_percent_populated_list.pkl"
)
with open(map_size_and_percent_populated_list_filename, "rb") as f:
map_size_and_percent_populated_list = pkl.load(f)
map_size_and_percent_populated_list = load_pickle_file("map_size_and_percent_populated_list.pkl")
num_rows = map_size_and_percent_populated_list[0]
num_cols = map_size_and_percent_populated_list[1]
num_populated_areas = map_size_and_percent_populated_list[2]
Expand All @@ -148,7 +149,10 @@ def generate_map_info(
num_paths_mean=3,
num_paths_stdev=1,
):
if num_populated_areas > (num_rows * num_cols - (2 * num_rows + 2 * num_cols)):
"""
This function generates the populated areas and paths for a map.
"""
if num_populated_areas > (num_rows * num_cols - (2 * num_rows + 2 * num_cols - 4)):
raise ValueError("Cannot have more than 100 percent of the map be populated!")
if num_rows <= 0:
raise ValueError("Number of rows must be a positive value!")
Expand All @@ -171,7 +175,7 @@ def generate_map_info(
paths_to_pops = {}
populated_areas = generate_pop_locations(num_rows, num_cols, num_populated_areas)

# the number of paths for each populated area is chosen from normal distribution
# the number of paths for each populated area is chosen from a normal distribution
num_paths_array = np.random.normal(
num_paths_mean, num_paths_stdev, num_populated_areas
).astype(int)
Expand All @@ -190,25 +194,23 @@ def generate_map_info(

cur_row, cur_col = pop_row, pop_col

# initialize bounds to not restrict to start
x_min = num_rows
x_max = -1
y_min = num_cols
y_max = -1
# Initialize bounds to not restrict to start
x_min, x_max = num_rows, -1
y_min, y_max = num_cols, -1

# which direction to span out from first
# Which orientaion to span out from first
orientation = random.choice(["north", "south", "east", "west"])

# We loop until we reach the edge of the map
done = False
while not done:
num_steps = random.randint(steps_lower_bound, steps_upper_bound)

# we want to make sure that the current
# We want to make sure that the current
# path will not intersect with itself
direction_chosen = False
num_steps = random.randint(steps_lower_bound, steps_upper_bound)

while not direction_chosen:
# choose whether to go straight, left, or right based
# Choose whether to go straight, left, or right based
# on percent_go_straight -> if we don't go straight,
# we go left or right with equal probability
direction_index = 0
Expand Down Expand Up @@ -239,7 +241,7 @@ def generate_map_info(
cur_row += row_update
cur_col += col_update

# update bounds if necessary
# Update bounds if necessary
# (so that paths do not intersect with themselves)
if cur_row > x_max:
x_max = cur_row
Expand All @@ -250,17 +252,6 @@ def generate_map_info(
if cur_col < y_min:
y_min = cur_col

# the population center is on the edge of the map,
# so we don't want to add a path in this direction
if (
cur_row == -1
or cur_row == num_cols
or cur_col == -1
or cur_col == num_rows
):
done = True
break

current_path.append([cur_row, cur_col])
if (
cur_row == 0
Expand All @@ -270,7 +261,7 @@ def generate_map_info(
):
# we want unique paths
done = True
if current_path in paths:
if current_path in paths or [pop_row, pop_col] in current_path:
break
paths.append(current_path)
paths_to_pops[path_num] = [[pop_row, pop_col]]
Expand Down

0 comments on commit 79c994d

Please sign in to comment.