Inspire a community of professionals skilled in spatiotemporal analysis for community health and safety.
Prototype an algorithm that places batteries near service drop poles.
Roy Hyunjin Han
A battery must be close enough to its discharge point to minimize distribution loss.
20171108-2000 - 20171108-2100: 60 minutes estimated
20171108-2000 - 20171108-2030: 30 minutes
This seems to be identical to the problem of placing service drop poles near customers. The difference is that there is no limit to the number of poles per battery.
from shapely.geometry import MultiPoint, Point drop_poles = [ Point(1, 1), Point(3, 2), Point(7, 0), ] MultiPoint(drop_poles)
<shapely.geometry.multipoint.MultiPoint at 0x7f6490ccd550>
from shapely.geometry import GeometryCollection, Polygon obstacle_geometries = [ Polygon([(1.5, 0), (1.5, 3), (2.5, 3), (2.5, 0)]) ] GeometryCollection(drop_poles + obstacle_geometries)
<shapely.geometry.collection.GeometryCollection at 0x7f64951c4550>
+ Create a sample dataset of service drop poles + Create example obstacles
20171110-1330 - 20171110-1400: 30 minutes
Remember that the first implementation only considers the case of no roads and no obstacles.
from copy import copy from shapely.geometry import LineString from shapely.ops import polygonize, unary_union def get_source_geometries(target_geometries, maximum_distance): # Convert target_geometries into target_polygons using maximum_distance target_polygons = [x.buffer(maximum_distance) for x in target_geometries] lonely_polygons = copy(target_polygons) # Identify areas of intersection social_polygons =  for polygon in get_disjoint_polygons(target_polygons): connected_polygons =  for target_polygon in target_polygons: if target_polygon.contains(polygon.centroid): connected_polygons.append(target_polygon) if len(connected_polygons) > 1: for target_polygon in connected_polygons: try: lonely_polygons.remove(target_polygon) except ValueError: pass social_polygons.append(polygon) polygon.connected_polygons = connected_polygons # Define connected_polygons for each lonely_polygon for polygon in lonely_polygons: polygon.connected_polygons =  return social_polygons + lonely_polygons def get_disjoint_polygons(overlapping_polygons): 'Split overlapping polygons into disjoint polygons' rings = [LineString(list( x.exterior.coords)) for x in overlapping_polygons] return list(polygonize(unary_union(rings)))
GeometryCollection(drop_poles + get_source_geometries(drop_poles, 1))
<shapely.geometry.collection.GeometryCollection at 0x7f64792a1b00>
GeometryCollection(drop_poles + get_source_geometries(drop_poles, 1.5))
<shapely.geometry.collection.GeometryCollection at 0x7f64915b7c88>
+ Minimize the distance of a battery to each service drop pole + Minimize the number of batteries + Limit the maximum distance of a battery to a service drop pole
We'll save obstacles for the 3rd implementation.
20171117-1845 - 20171117-1900: 15 minutes
It seems that each of the batteries are supposed to be placed on a distribution line and distances to each service drop are computed as measured along the distribution line. We'll save that for the 2nd implementation.