class TransModel: def __init__(self): # database self.db = db.Database() trip_per_person = self.db.general_information(s.transpotation_type) # graph self.g = Graph() table = self.db.get_graph() self.g.create_graph(table) # length self.g.set_edge_property("length", self.db.get_edge_property("length")) # speed self.g.set_edge_property("speed", self.db.get_edge_property(s.speed)) # vertical ditance pos = np.array(self.db.get_edge_property("vertical_distance_pos")) neg = np.array(self.db.get_edge_property("vertical_distance_neg")) vd = pos + neg self.g.set_edge_property("vd", vd) # edge id self.g.set_edge_property("id", self.db.get_edge_property("id")) # geometry self.g.set_edge_property("geometry", map(lambda x: json.loads(x), self.db.get_edge_property("ST_asgeojson(ST_transform(geometry,4326))"))) # compute first path self.g.change_cost(1, 0, 0) self.O = np.array(map(lambda x: x * trip_per_person, self.db.get_zone_property("num_of_people"))) #origin zones self.D = np.array(map(lambda x: x * trip_per_person, self.db.get_zone_property("num_of_people"))) #destination zones #zones property self.zones_property_type = self.db.get_zone_property("type") self.zones_property_subtype = self.db.get_zone_property("subtype") self.zones_property_id = self.db.get_zone_property("id") self.zones_property_node_id = self.db.get_zone_property("node_id") self.zones_property_age_cat = [] for age_column in s.age_category: self.zones_property_age_cat.append(self.db.get_zone_property(age_column)) #cost matrix self.C = None #transport matrix self.T = np.ndarray(shape=(self.O.size, self.D.size)) self.prepare_od() #only for testing # for computing info self.compute_info = ComputeInfo() #olny for test!! def prepare_od(self): """ define O and D value for non home zones this function is for testing only :return: """ sum_home = 0 non_home_count = 0 for i in xrange(0, len(self.O)): if self.zones_property_type[i] == "home": sum_home += self.O[i] else: non_home_count += 1 for i in xrange(0, len(self.O)): if self.zones_property_type[i] != "home": self.O[i] = sum_home/float(non_home_count) self.D[i] = sum_home/float(non_home_count) def _is_enable_combination(self, i, j): """ Is it enable combination (type of zones) :param i: row index in T matrix :param j: column index in T matrix :return: True if enable combination (boolen) """ target_type = self.zones_property_type[j] source_type = self.zones_property_type[i] if target_type in s.enable_type_combination[source_type]: return True else: return False def _get_od_rules(self,i,pair_type): """ :param i: zone index (source/destination) :param pair_type: zone type (source/destination) :return: Number of people who travel from/to zone i from/to zone type """ offer = 0 num_of_age_cat = 0 for age_rule in s.age_category_rules: if pair_type in age_rule: offer += self.O[i] * self.zones_property_age_cat[num_of_age_cat][i] num_of_age_cat += 1 return offer def _model(self, i, j): """ Transport model. :param i: row index in transportation matrix (T) :param j: column index in transportation matrix (T) :return: model value for cell """ if self._is_enable_combination(i, j): if self.zones_property_type[i] == "home": Ti = self._get_od_rules(i,self.zones_property_type[j]) Tj = self.D[j] elif self.zones_property_type[j] == "home": Tj = self._get_od_rules(j,self.zones_property_type[i]) Ti = self.O[i] else: Ti = self.O[i] Tj = self.D[j] if Ti == 0 or Tj == 0: print Ti, Tj return Ti * Tj * self._f(self.C[i][j]) else: return 0 def _f(self, c): """ Function for model (1/x^2) (gravity model) :param c: input cost :return: function value """ if c == 0: return 0 return c**(-2) def _insert_to_T(self,function): """ :param function: function for insert to matrix T e.g self._model :return: matrix T """ Tn = np.ndarray(shape=self.T.shape) for i in xrange(0, self.T.shape[0]): for j in xrange(0, self.T.shape[1]): Tn[i][j] = function(i, j) return Tn def trip_destination(self, maximum_delta, maximum_iterations): """ Compute transportation matrix :param maximum_delta: maximum error in balancing matrix :param maximum_iterations: maximum number of iteration in balancing matrix :return: (delta, average_delta) error in balancing matrix """ self.C = self.g.get_cost_matrix(self.zones_property_node_id) self.T = self._insert_to_T(self._model) delta = float("inf") delta_mid = float("inf") num_of_iter = 0 while delta > maximum_delta: nf_row = np.zeros((self.T.shape[0])) i = 0 for row in self.T: if sum(row) == 0: nf_row[i] = 1 else: nf_row[i] = self.O[i] / sum(row) i += 1 self.T = self._insert_to_T(lambda i,j: self.T[i][j] * nf_row[i]) nf_column = np.zeros((self.T.shape[1])) i = 0 for column in self.T.transpose(): if sum(column) == 0: nf_column[i] = 1 else: nf_column[i] = self.D[i] / sum(column) i += 1 self.T = self._insert_to_T(lambda i, j: self.T[i][j] * nf_column[j]) delta = max(abs(nf_column - 1)) delta_mid = sum(abs(nf_column - 1)) / len(nf_column) num_of_iter += 1 if num_of_iter > maximum_iterations: break #np.save("cache/T", self.T) return (delta, delta_mid) def load_t(self): """ Load T matrix from cache. :return: """ self.T = np.load("cache/T.npy") def save_t(self): """ Save T matrix to database (table OD_pairs). :return: """ self.db.save_t(self.T, self.zones_property_id) def count_transport(self): # je treba jeste dudelat distribuci cen!!!! """ Compute traffic for all roads """ pb = Progress_bar(len(self.zones_property_node_id)) i = 0 for node_id in self.zones_property_node_id: for cost in s.cost: self.g.change_cost(cost[0], cost[1], cost[2]) paths = self.g.one_to_n(node_id, self.zones_property_node_id) j = 0 for path in paths: for edge in path: self.g.p["traffic"][edge] = self.g.p["traffic"][edge] + cost[3] * self.T[i][j] j += 1 i += 1 self.compute_info.progress = pb.go(i) def save_traffic(self): """ Save traffic to database table "tramap.traffic" """ ids = self.g.p["id"].tolist() traffic = self.g.p["traffic"].tolist() direction = self.g.p["direction"].tolist() self.db.save_traffic(ids, traffic, direction)