联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> Python编程Python编程

日期:2018-10-28 09:49

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 1/16

CMSE 201 - Fall 2018

Homework 4: Programming a Robotic

Sheepdog

In this homework you will continue to learn about agent-based modeling, by developing and

implementing a set of rules for how agents (sheep, sheepdog) interacts with each other. We will

measure its effectiveness and compare different sets of rules to each other. Make sure to use Slack

and help room hours if you run into issues!

Goals

By the end of the homework assignment you will have practiced:

1. Modeling a real world scenario.

2. Building and manipulating agent-based models.

3. Assessing model outcomes.

4. Defining functions to check the state of a model

Assignment instructions

Work through the following assignment, making sure to follow all of the directions and answer all of

the questions.

This assignment is due at 11:59pm on Friday, October 26th. It should be uploaded into the

"Homework Assignments" submission folder for Homework #4. Submission instructions can be

found at the end of the notebook.

Grading

Question 1: Scattering sheep (3 points)

Question 2: These sheep were made for walkin' (8 points)

Question 3: All bark and no bite (6 points)

Question 4: Go dog go (6 points)

Question 5: Test for success (6 points)

Question 6: Better dog path (4 points)

Question 7: Your turn (5 points)

Total points possible: 38

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 2/16

Introduction

An agent-based model is a model where a set of agents interact according to a set of rules. This is

a general framework that can model many different phenomena. Here we will use a 2D grid, where

the cells are given numbers to represent one of the following:

0 = empty space

1 = fence

2 = sheep

3 = dog

The fence forms a pen where the sheep need to sleep every night. However, the sheep don't

always like to go to the pen, and would rather stay up past their bedtime.

One particular farmer (you) has come up with a 21st century solution: a robotic sheepdog. This

dog will help round up the sheep and get them into their pen at night. One problem is that we're not

sure the best way to program this robot in order to get the sheep into the pen as fast as possible.

Let's get started by defining our grid:

In [ ]:

Now lets define a function to plot our state, using symbols for the fence, the dog and the sheep.

import matplotlib.pyplot as plt

%matplotlib inline

import numpy as np

nx = 40

ny = 40

fenceline = 10

states = ['empty','fence','sheep','dog']

state_color = np.linspace(0,1,len(states))

system_state = np.zeros([ny,nx]) # intialize everything to empty

dog_start_pos = [int(ny-1),int(nx/2)]

system_state[dog_start_pos[0],dog_start_pos[1]] = 3 # put a dog at the top, in th

system_state[fenceline,:] = 1 # put a fence along y = 10

system_state[fenceline,17:24] = 0 # put a hole in the fence

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 3/16

In [ ]:

In [ ]:

Doesn't really look like a dog, but let's use our imaginations. We're almost ready, but we're missing

something.... oh yes. The sheep.

Question 1: Scattering sheep (3 points)

Write a function that randomly places the sheep in the field above the fence. It should take as an

argument the system_state, the number of sheep to place (N), and a fenceline parameter that

describes the y-position of the fence. It should return a new state with the sheep.

Importantly, the sheep cannot overlap with anything that is not empty space (i.e.

state[try_y,try_x] must equal zero), and the sheep must be placed above the fenceline!

def plotstate(state,time=0):


# first create two vectors based on the x and y sizes of the grid

x_range = np.linspace(0, state.shape[0], state.shape[0])

y_range = np.linspace(0, state.shape[1], state.shape[1])


# use the numpy meshgrid function to create two matrices

# of the same size as myarray with x and y indexes

x_indexes, y_indexes = np.meshgrid(x_range, y_range)


# make a list of all the x and y indexes that are not empty.

fence_x = x_indexes[state == 1];

fence_y = y_indexes[state == 1];

sheep_x = x_indexes[state == 2];

sheep_y = y_indexes[state == 2];

dog_x = x_indexes[state == 3];

dog_y = y_indexes[state == 3];

# plot the squares and triangles. make the size of the polygons

# larger than the default so they're easy to see!

plt.plot(fence_x,fence_y, 's',markersize=20)

plt.plot(sheep_x,sheep_y, 'o',markersize=20)

plt.plot(dog_x,dog_y, '1',markersize=20)


# Set the x and y limits to include half a space overlap so we don't cut off

plt.ylim([-0.5,state.shape[0] + 0.5])

plt.xlim([-0.5,state.shape[0] + 0.5])


# display the current time on the plot

plt.text(0,0,"time={0}".format(time),fontsize=18)


# Turn the axes off

plt.tick_params(axis='both', which='both', bottom=False, top=False, labelbotto

plt.gca().set_aspect('equal', adjustable='box')

plt.figure(figsize=(10,10))

plotstate(system_state)

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 4/16

In [ ]:

Let's call this state initial_state since we'll use it to start our agent-based model simulations.

The following should plot your new system. Run it a few times and make sure it always gives you

something appropriate.

In [ ]:

Question 2: These sheep were made for walkin' (8

points)

Of course these sheep aren't going to just stand there. They will move, randomly over time. For

each time step (say, 1 second), let's say they will move according to the following probabilities and

rules:

- choose to move with probability p_move

- if moving

- choose direction (up, down, left, right) with equal probability

- do not execute the move if it goes beyond the borders

- only execute the move if the new space is empty

- do not execute an upward move if sheep is at the fenceline

Where the latter condition assumes that once the sheep are in the pen, they remember how good it

feels to be home.

Here is a function that takes in: 1) a system state, 2) a sheep's x and y position, 3) p_move and 4)

the fenceline. This function will attempt to move the specified sheep according to the rules above.

Provide comments and insert code where requested below

from copy import copy

def place_sheep(state,N,fenceline):


newstate = copy(state)


sheep_placed = 0

while sheep_placed < N:

# suggest somewhere for a sheep to be placed

try_y = # hint: use np.random.randint

try_x = #


# check if this is appropriate.

# if yes, set good_place to True. if no, set good_place to False.


# if good, place the sheep, if not try again

if good_place is True:

sheep_placed += 1

newstate[try_y,try_x] = 2


return newstate

initial_state = place_sheep(system_state,20,fenceline)

plt.figure(figsize=(10,10))

plotstate(initial_state)

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 5/16

In [ ]:

Great! Now let's write a function to move the whole system forward in time. This will use the

move_sheep function. First we need to find all the sheep. This can be done easily with the

np.where function. You might not have seen this before, so read the doc page before you use it.

In [ ]:

What is sheep_loc? What do the first and second axes represent?

def move_sheep(state,sheep_x,sheep_y,pmove,fenceline):

# what are the next two lines doing?

# (answer here)

r1 = np.random.random()

if r1 < pmove:

# now decide to move up, down, left or right

# store the new location in the variables try_x and try_y

r2 = np.random.random()

if r2 < 0.25: # move left

try_x = sheep_x - 1

try_y = sheep_y

elif r2 < 0.5: # move up

if sheep_y != fenceline:

try_x = sheep_x

try_y = sheep_y + 1

else:

try_x = sheep_x

try_y = sheep_y

elif r2 < 0.75: # move right

try_x = sheep_x + 1

try_y = sheep_y

else: # move down

try_x = sheep_x

try_y = sheep_y - 1

# check and see if the move is good

good_move = True


# set good_move to False if conditions are violated

if try_x < 0 or try_x >= state.shape[1]:

good_move = False

elif try_y < 0 or try_y >= state.shape[0]:

good_move = False

elif state[try_y,try_x] != 0:

good_move = False


# check if the move is good, if so make the move

# INSERT CODE HERE


# return the state

return state

sheep_loc = np.array(np.where(initial_state==2))

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 6/16

// Answer here

Use sheep_loc below to get the x and y position of the first sheep:

In [ ]:

Use sheep_loc to get the total number of sheep:

In [ ]:

Now use sheep_loc to finish the evolve_system function below, which will (at least try to)

move all of the sheep.

In [ ]:

OK, now we'll test out our code:

# code here

x = #?

y = #?

print("There is a sheep at x, y = ({0},{1})".format(x,y))

# code here

nsheep = #?

print("There are {0} sheep in total".format(nsheep))

def evolve_system(state,pmove,fenceline):

sheep_loc = np.array(np.where(state==2))


# use sheep_loc to determine how many sheep there are

nsheep = #?


# write a loop to iterate over each sheep

for i in range(nsheep):

sheep_x = #?

sheep_y = #?

# call move_sheep for each sheep_x and sheep_y position

state = move_sheep(state,sheep_x,sheep_y,pmove,fenceline)

return state

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 7/16

In [ ]:

Wow! Just... wow.

Question 3: All bark and no bite (6 points)

Now we need some sheep-sheepdog interaction. Time to make some changes to our rule set:

- choose to move with probability p_move

- if moving

- choose x dir or y dir with equal probability

- choose toward dog or away from dog as follows

* p = 0.5 - delta (towards dog)

* p = 0.5 + delta (away from dog)

- do not execute the move if it goes beyond the borders

- only execute the move if the new space is empty

- do not execute an upward move if sheep is at the fenceline

where we've introduced another parameter delta which can take on values between 0 and 0.5.

Here is a new move_sheep_bias function that accounts for the dog's position:

from copy import copy

from IPython.display import display, clear_output

import time

nsteps = 20

pmove = 0.5

fenceline = 10

state = copy(initial_state)

fig = plt.figure(figsize=(8,8))

for i in range(nsteps):

state = evolve_system(state,pmove,fenceline)

plotstate(state,time=i)

time.sleep(0.01) # Sleep for 0.01 s to slow down the animation

clear_output(wait=True) # Clear output for dynamic display

display(fig) # Reset display

fig.clear() # Prevent overlapping and layered plots

plt.close() # Close dynamic display

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 8/16

In [ ]: def move_sheep_bias(state,sheep_x,sheep_y,pmove,fenceline,delta):

# set default "try" position at current position

try_x = sheep_x

try_y = sheep_y


# get dog's position

dog_y = np.where(state==3)[0][0]

dog_x = np.where(state==3)[1][0]


# choose whether to move

r1 = np.random.random()

if r1 < pmove:

# first decide x dir or y dir

r2 = np.random.random()

if r2 < 0.5:

x_or_y = 'x'

else:

x_or_y = 'y'


# choose toward dog or away from dog

r3 = np.random.random()

if r3 < 0.5 + delta:

# move away from dog

if x_or_y == 'x':

if sheep_x < dog_x:

try_x = sheep_x - 1

else:

try_x = sheep_x + 1

elif x_or_y == 'y':

if sheep_y < dog_y:

try_y = sheep_y - 1

else:

# moving up, check if you are at the fenceline

if sheep_y != fenceline:

try_y = sheep_y + 1

else:

# move towards dog

if x_or_y == 'x':

if sheep_x < dog_x:

try_x = sheep_x + 1

else:

try_x = sheep_x - 1

elif x_or_y == 'y':

if sheep_y < dog_y:

# moving up, check if you are at the fenceline

if sheep_y != fenceline:

try_y = sheep_y + 1

else:

try_y = sheep_y - 1


# check and see if the move is good

good_move = True

if try_x < 0 or try_x >= state.shape[1]:

good_move = False

elif try_y < 0 or try_y >= state.shape[0]:

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 9/16

Below create an evolve_system_bias function to call this new function. (Don't forget to

include the delta parameter):

In [ ]:

Then test our code again, this time only plotting every 10 steps:

In [ ]:

Maybe a little too intense. I don't think our dog should be that scary.

Add a cutoff distance (d_cut), where if sheep are closer to the dog than d_cut then they use

move_sheep_bias, but if they are farther then they move normally with move_sheep.

Note: calculate distance as , where is the x-position of the sheep,

and is the x-position of the dog, etc.

d = (xs xd)2 + (ys yd)2√ xs

xd

good_move = False

elif state[try_y,try_x] != 0:

good_move = False


if good_move is True:

# make the move

state[sheep_y,sheep_x] = 0

state[try_y,try_x] = 2


return state

def evolve_system_bias(state,pmove,fenceline,delta):


# insert code here


return state

from IPython.display import display, clear_output

import time

nsteps = 500

plot_every = 10

pmove = 0.5

fenceline = 10

delta = 0.25

state = copy(initial_state)

fig = plt.figure(figsize=(8,8))

for i in range(nsteps):

state = evolve_system_bias(state,pmove,fenceline,delta)

if i % plot_every == 0:

plotstate(state,time=i)

time.sleep(0.01) # Sleep for 0.01 s to slow down the animation

clear_output(wait=True) # Clear output for dynamic display

display(fig) # Reset display

fig.clear() # Prevent overlapping and layered plots

plt.close() # Close dynamic display

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 10/16

In [ ]:

In [ ]:

That's better.

Question 4: Go dog go (6 points)

Here's the chance we've been waiting for! Time to make our dog move. But how? We'll assume our

robot can move much faster than the sheep, so we'll allow it to move one square every timestep.

But how should it move? To allow us to try out a set of different strategies, we'll assume we have

a path that the dog follows, which is a list of states that are no more than one square apart.

def evolve_system_bias_cutoff(state,pmove,fenceline,delta,dcut):

# find the dog

dog_loc = np.array(np.where(state==3))

dog_x = dog_loc[1][0]

dog_y = dog_loc[0][0]


sheep_loc = np.array(np.where(state==2))


# determine how many sheep there are

nsheep = #?


# write a loop to iterate over each sheep

for i in range(nsheep):

sheep_x = #?

sheep_y = #?


# use distance to dog to decide which move_sheep function to use


# INSERT CODE HERE

return state

nsteps = 500

plot_every = 10

pmove = 0.5

fenceline = 10

delta = 0.25

dcut = 15

state = copy(initial_state)

fig = plt.figure(figsize=(8,8))

for i in range(nsteps):

state = evolve_system_bias_cutoff(state,pmove,fenceline,delta,dcut)

if i % plot_every == 0:

plotstate(state,time=i)

time.sleep(0.01) # Sleep for 0.01 s to slow down the animation

clear_output(wait=True) # Clear output for dynamic display

display(fig) # Reset display

fig.clear() # Prevent overlapping and layered plots

plt.close() # Close dynamic display

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 11/16

In [ ]:

How many states are in this path? What does this path describe?

// Answer here

Make a path where the dog runs all the way to the left wall, then all the way to the right wall,

and then back to its starting position. Do this by filling in the missing lines below:

In [ ]:

Remember the dog can't move more than one square per loop, and since the dog will be running

this loop over and over again (until the sheep are in the pen), we need to check the endpoints as

well. Run this function below to see if your path is a good one:

In [ ]:

y0,x0 = dog_start_pos

short_dog_path = [(y0,x0),(y0,x0-1),(y0,x0-2),(y0,x0-1)]

dog_path = [(y0,x0)]

x = x0

y = y0

# first run to the left wall

while x > 0:

# update x

# append (x,y) tuple to dog_path

# then run to the right wall

while x < nx - 1:

# update x


# append (x,y) tuple to dog_path


# then run back to the middle

while x > x0+1:

# update x


# append (x,y) tuple to dog_path

def pathcheck(path):

# checks to see if the dog moves more than one square per timestep

oldp = path[-1]

goodpath = True

for p in path:

dy = p[0]-oldp[0]

dx = p[1]-oldp[1]

if abs(dx) + abs(dy) > 1:

goodpath = False

oldp = p

return goodpath

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 12/16

In [ ]:

OK, now we'll make a move_dog function that uses this path:

In [ ]:

Now let's add this move_dog command to a new evolve_system function:

In [ ]:

Let's test it out!

pathcheck(dog_path)

def move_dog(state,path,current_pos):


# check if the next position is occupied

next_pos = current_pos + 1

if next_pos >= len(path):

next_pos = 0

next_y,next_x = path[next_pos]


if state[next_y,next_x] == 0 or state[next_y,next_x] == 3:

# empty! or the dog is already there.

# Either way, its ok to move the dog


# find the dog

dog_loc = np.array(np.where(state==3))

dog_x = dog_loc[1][0]

dog_y = dog_loc[0][0]


# delete dog from current position

state[dog_y,dog_x] = 0


# add dog to next position

state[next_y,next_x] = 3


# update current_pos

current_pos = next_pos


return current_pos, state

def evolve_system_dog(state,pmove,fenceline,delta,dcut,path,current_pos):

state = evolve_system_bias_cutoff(state,pmove,fenceline,delta,dcut)

current_pos, state = move_dog(state,path,current_pos)

return current_pos, state

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 13/16

In [ ]:

Run this code for 5000 steps, with plot_every = 100, and for 20000 steps, with plot_every =

400

In [ ]:

What do you observe?

// Answer here

Question 5: Test for success (6 points)

OK our sheepdog is not very effective right now. Let's quantify exactly how bad it is. Write a function

that will check and see how many sheep are out of the pen (return an integer):

In [ ]:

Test this function to see how many are out of the pen in the initial and final states from

above:

nsteps = 500

plot_every = 10

pmove = 0.5

fenceline = 10

delta = 0.25

dcut = 15

path = dog_path

dog_pos = 0

state = copy(initial_state)

fig = plt.figure(figsize=(8,8))

for i in range(nsteps):

dog_pos, state = evolve_system_dog(state,pmove,fenceline,delta,dcut,path,dog_

if i % plot_every == 0:

plotstate(state,time=i)

time.sleep(0.01) # Sleep for 0.01 s to slow down the animation

clear_output(wait=True) # Clear output for dynamic display

display(fig) # Reset display

fig.clear() # Prevent overlapping and layered plots

plt.close() # Close dynamic display

# code here

def sheep_still_out(state,fenceline):

# return the number of sheep that are above the fenceline

# in the current state


# code here

return sheep_still_out

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 14/16

In [ ]:

Now let's use this function in a while loop to see how long it will take:

In [ ]:

Put the above code in a for loop, and run this simulation 10 times. Save the times in a list

called times.

In [ ]:

Run the cell below to get statistics of your sheepdog.

In [ ]:

What quantity is being reported after the +- signs?

// Answer here

Question 6: Better dog path (4 points)

Now that we have a well-defined measure of success, we can test out different dog_path lists to

see which is better. Let's try running in a rectangle, going down to y = 30, which is 20 above the

fenceline.

initial = #?

final = #?

print("Sheep out, initially: {0}".format(initial))

print("Sheep out, finally: {0}".format(final))

pmove = 0.5

fenceline = 10

delta = 0.25

dcut = 15

path = dog_path

dog_pos = 0

report_every = 1000

state = copy(initial_state)

i = 0

while (sheep_still_out(state,fenceline) > 0):

i += 1

dog_pos, state = evolve_system_dog(state,pmove,fenceline,delta,dcut,path,dog_

if i % report_every == 0:

print("At time = {0} there are {1} sheep still out".format(i,sheep_still_o

print("All sheep in the pen at time = {0}".format(i))

# code here

from math import sqrt

a = np.array(times)

print("It takes an average of {0} +- {1} s for this sheepdog to work".format(a.mea

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 15/16

In [ ]:

First we'll check if this is a good path:

In [ ]:

Run a single 1000-step simulation with this dog path while visualizing every 10 steps

In [ ]:

Now, use dog_path2 to run 10 simulations, and report the results

In [ ]:

Which worked better, and why?

// Answer here

Question 7: Your turn (5 points)

Make a new dog path of your choosing, test it using pathcheck, and then run it 10 times. Compare

the average time and standard error measurements with the two paths above.

In [ ]:

Do you have any tips for an even better sheepdog herding strategy?

// Answer here

y0,x0 = dog_start_pos

dog_path2 = [(y0,x0)]

x = x0

y = y0

# first run to the left wall

# then run to y = 30


# then run to the right wall

# then run back to the top

# then run back to the middle

pathcheck(dog_path2)

# code here

# code here

# code here

10/27/2018 HW-04_Programming_a_robotic_sheepdog-STUDENT

http://localhost:8888/notebooks/HW-04_Programming_a_robotic_sheepdog-STUDENT.ipynb 16/16

Would this require any changes to the code above?

// Answer here

Assignment Wrap-up

Fill out the following Google form before you submit your assignment.

In [ ]:

Congratulations, you're done!

Submit this assignment by uploading it to the course Desire2Learn web page. Go to the "Homework

Assignments" section, find the submission folder link for Homework #3, and upload it there. Make

sure to upload the pictures of your compartmental models as well!

Copyright 2018, Michigan State University Board of Trustees


版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp