from collections import defaultdict
engagemnt_by_account = defaultdict(list)
for engagement_record in paid_engagement_in_first_week:
account_key = engagement_record['account_key']
engagement_by_account[account_key].append(engagement_record)
total_minutes_by_account = {}
for account_key, engegement_for_student in engagement_by_account.items():
total_minutes = 0
for engagement_record in engagement_for_student:
total_minutes += engagement_record['total_minutes_visited']
total_minutes_by_account[account_key] = total_minutes
total_minutes = total_minutes_by_account.values()
import numpy as np
Tracking Down
num_problem_students = 0 for enrollment in enrollments: student = enrollment['account_key'] if student not in unique_engagement_students and enrollment['join_date'] != enrollment['cancel_date']: num_problem_student += 1 num_problem_students
def within_one_week(join_date, engagement_date): time_delta = engagement_date - join_date return time_delta.days < 7 def remove_free_trial_cancels(data): new_data = [] for data_point in data: if data_point['account_key'] in paid_students: new_data.append(data_point) return new_data total_minutes = total_minutes_by_account.values() import numpy as numpy print 'Mean:' np.pean(total_minutes) print 'Standard deviation:', np.std(total_minutes) print 'Minimum:', np.min(total_minutes) print 'Maximum:', np.max(total_minutes) student_with_max_minutes = None max_minutes = 0 for student, total_minutes in total_minutes_by_account.items(): if total_minutes > max_minutes: max_minutes = total_minutes student_with_max_minutes = student
CSVs
import unicodecsv
enrollments_filename=''
with open('enrollments.csv', 'rb') as f:
reader = unicodecsv.DictReader(f)
enrollements = list(reader)
with open('daily_engagement.csv', 'rb') as f:
reader = unicodecsv.DictReader(f)
daily_engagement = list(reader)
with open('project_submissions.csv', 'rb') as f:
reader = unicodecsv.DictReader(f)
project_submissions = list(reader)
daily_engagement = None
project_submissions = None
import unicodecsv
def read_csv(filename):
with open(filename, 'rb') as f:
reader = unicodecsv.DictReader(f)
return list(reader)
enrollments = read_csv('')
daily_engagement = read_csv('')
project_submissions = read_csv('')
enrollment_num_rows = 0
enrollment_num_unique_students = 0
engagement_num_rows = 0
engagement_num_unique_students = 0
submission_num_rows = 0
submission_num_unique_students = 0
Google and iOS Design
Google Design
https://design.google.com/
Apple accessibility
https://developer.apple.com/accessibility/ios/
W3C Web content accessibility guideline
https://www.w3.org/TR/WCAG20/
Key thing is accessibility
-> try to make product accessible and useful
mobile
-> touch screen
-> color contrast ratio
Implement P controller
import random
import numpy as np
import matplotlib.pyplot as plt
class Robot(object):
def __init__(self, length=20.0):
self.x = 0.0
self.y = 0.0
self.orientation = 0.0
self.length = length
self.steering_noise = 0.0
self.distance_noise = 0.0
self.steering_drift = 0.0
def set(self, x, y, orientation):
self.x = x
self.y = y
self.orientation = orientation % (2.0 * np.pi)
def set_noise(self, steering_noise, distance_noise):
self.steering_noise = steering_noise
self.distance_noise = distance_noise
def set_steering_drift(self, drift):
self.steering_drift = drift
def move(self, steering, distance, tolerance=0.001, max_steering_angle=np.pi/4.0):
if steering > max_steering_angle:
steering = max_steering_angle
if steering < -max_steering_angle:
steering = -max_steering_angle
if distance < 0.0:
distance = 0.0
steering2 = random.gauss(steering, self.steering_noise)
distance2 = random.gauss(distance, self.distance_noise)
steering2 += self.steering_drift
turn = np.tan(steering2) * distance2 / self.length
if abs(turn) < tolerance:
self.x += distance2 * np.cos(self.orientation)
self.y += distance2 * np.sin(self.orientation)
self.orientation = (self.orientation + turn) % (2.0 * np.pi)
else:
radius = distance2 / turn
cx = self.x - (np.sin(self.orientation) * radius)
cy = self.y + (np.cos(self.orientation) * radius)
self.orientation = (self.orietation + turn) % (2.0 + np.pi)
self.x = cx + (np.sin(self.orientation) * raidus)
self.y = cy - (np.cos(self.orientation) * raidus)
def __repr__(self):
return '[x=%.5f y=%.5f orient=%.5f]' % (self.x, self.y, self.orientation)
[/python]
Robot motion
Generating smooth paths
x0 … xn-1
xi
smoothing algorithm
yi = xi
optimize (xi-yi)^2 -> min (yi-yi+1)^2 ->min (original path)
from copy import deepcopy
def printpaths(path,newpath):
for old, new in zip(path,newpath):
print '['+ ', '.join('%.3f'%x for x in old) + \
'] -> ['+ ', '.join('%.3f'%x for x in new) +']'
# Don't modify path inside your function.
path = [[0, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2],
[3, 2],
[4, 2],
[4, 3],
[4, 4]]
def smooth(path, weight_data = 0.5, weight_smooth = 0.1, tolerance = 0.000001):
newpath = [[0 for row in range(len(path[0]))] for col in range(len(path))]
for i in range(len(path)):
for j in range(len(path[0]))
newpath[i][j] = path[i][j]
change = tolerance
while change >= tolerance:
change = 0.0
for i in range(1, len(path)-1):
for j in range(len(path[0])):
aux = newpath[i][j]
newpath[i][j] += weight_data * (path[i][j] - newpath[i][j])
newpath[i][j] += weight_smooth * (newpath[i-1][j] \ + newpath[i+_][j])
change += abs(aux - newpath[i][j])
return newpath
printpaths(path,smooth(path))
Motion Planning
Motion Planning
Given: Map, starting location, goal location, cost
Goal: Find minimum cost
Each Actions: move, turn
grid = [[0, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 1, 0]]
init = [0, 0]
goal = [len(grid)-1, len(grid[0])-1]
cost = 1
delta = [[-1, 0],
[0, -1],
[1, 0],
[0, 1]]
delta_name = ['^','<','v','>']
def search(grid, init, goal,cost):
closed = [[0 for row in range(len(grid[0]))] fro col in range(len(grid))]
x = init[0]
y = init[1]
g = 0
open = [[g, x, y]]
return path
Circular motion
from math import * import random landmarks = [[0.0, 100.0], [0.0, 0.0], [100.0, 0.0],[100.0, 100.0]] world_size = 100.0 max_steering_angle = pi/4 class robot: def __init__(self, length = 100.0): self.x = random.random() * world_size self.y = random.random() * world_size self.orientation = random.random() * 2.0 * pi self.length = length self.bearing_noise = 0.0 self.steering_noise = 0.0 self.distance_noise = 0.0 def __repr__(self): return '[x=%.6s y=%.6s orient=%.6s]' % (str(self.x), str(self.y), str(self.orientation)) def set(self, new_x, new_y, new_orientation): if new_orientation < 0 or new_orientation >= 2 * pi: raise ValueError, 'Orientation must be in [0..2pi]' self.x = float(new_x) self.y = float(new_y) self.orientation = float(new_orientation) def set_noise(self, new_b_noise, new_s_noise, new_d_noise): self.bearing_noise = float(new_b_noise) self.steering_noise = float(new_s_noise) self.distance_noise = float(new_d_noise) def move(self, motion, tolerance = 0.001): steering = motion[0] distance = motion[1] if abs(steering) > max_steering_angle: raise ValueError, 'Exceeding max steering angle' if distance < 0.0: raise ValueError, 'Moving backwards is not valid' return result
Resampling
p1, w1 = 0.6
p2, w2 = 1.2
p3, w3 = 2.4
p4, w4 = 0.6
p5, w5 = 1.2
P(p1)
p3 = [] index = int(random.random() * N) beta = 0.0 mw = max(w) for i in range(N): beta += random.random() * 2.0 * mw while beta > w[index]: beta -= w[index] index = (index + 1) % N p3.append(p[index]) p = p3
myrobot = robot() p = [] for i in range(N): r = robot() r.set_noise(0.05, 0.05, 5.0) p.append(r) for t in range(T): myrobot = myrobot.move(0.1, 5.0) Z = myrobot.sense()
length = 20. steering_noise = 0.0 distance_noise = 0.0 myrobot = robot(length) myrobot.set(0.0, 0.0, 0.0) myrobot.set_noise(bearing_noise, steering_noise, distance_noise) motions = [[0.0, 10.0], [pi / 6.0, 10], [0.0, 20.0]] T = len(motions) print 'Robot: '.myrobot
Particle Filter
– easiest to prgram
– most flexible
continuous, multi-modal, approximate
from math import * import random landmarks = [[20.0, 20.0], [80.0, 80.0], [20.0, 80.0], [80.0, 20.0]] world_size = 100.0 class robot: def __init__(self): self.x = random.random() * world_size self.y = random.random() * world_size self.orientation = random.random() * 2.0 * pi self.forward_noize = 0.0; self.turn_noise = 0.0; self.sense_noise = 0.0; def set(self, new_x, new_y, new_orientation): if new_x < 0 or new_x >= world_size: raise ValueError, 'X coordinate out of bound' if new_y < 0 or new_y >= world_size: raise ValueError, 'Y coordinate out of bound' if new_orientation < 0 or new_orientation >= 2 * pi: raise ValueError, 'Orientation must be in [0..2pi]' self.x = float(new x) def set_noise(self, new_f_noise, new_t_noise, new_s_noise): self.forward_noise = float(new_f_noise); self.turn_noise = float(new_t_noise); self.sense_noise = float(new_s_noise); def sense(self): Z = [] for i in range(len(landmarks)): dist = sqrt((self.x - landmarks[i][0]) ** 2 + (self.y - landmarks[i][1]) ** 2) dist += random.gauss(0.0, self.sense_noise) Z.append(dist) return Z def move(self, turn, forward): if forward < 0: raise ValueError, 'Robot cant move backwards' orientation = self.orientation + float(turn) + random.gauss(0.0, self.turn_noise) orientation %= 2 * pi dist = float(forward) + random.gauss(0.0, self.forward_noise) x = self.x + (cos(orientation) * dist) y = self.y + (sin(orientation) * dist) x %= world_size y %= world_size res = robot() res.set(x, y, orientation) res.set_noise(self.forward_noise, self.turn_noise, self.sense_noise) return res def Gaussian(self, mu, sigma, x): return exp(- ((mu - x) ** 2) / (sigma ** 2) / 2.0) / sqrt(2.0 * pi * (sigma ** 2)) def measurement_prob(self, measurement): prob = 1.0; for i in range(len(landmarks)): dist = sqrt((self.x - landmarks[i][0])**2 + (self.y - landmarks[i][1]) ** 2) prob *= self.Gaussian(dist, self.sense_noise, measurement[i]) return prob def __repr__(self): return '[x=%.6s y=%.6s orient=%.6s]' % (str(self.x), str(self.y), str(self.orientation)) def eval(r, p): sum = 0.0; for i in range(len(p)): dx = (p[i].x - r.x + (world_size/2.0)) % world_size - (world_size/2.0) dy = (p[i].y - r.y + (world_size/2.0)) % world_size - (world_size/2.0) err = sqrt(dx * dx + dy * dy) sum += err return sum / float(len(p)) myrobot = robot() myrobot.set(10.0, 10.0, 0.0) print myrobot myrobot - myrobot.move(0.0, 10.0) print myrobot myrobot = myrobot.move(pi/2, 10.0) print myrobot print myrobot.sense()
N = 1000 p = [] for i in range(N): x = robot() p.append(x) print len(p)