Commit 6f85727b authored by 张晓彤's avatar 张晓彤

更新锁定禁止,更新穿越装载区,更新二次调度

parent 0481fc30
......@@ -126,7 +126,7 @@ def dispatch_request():
submission = DispatchSubmission(dump, excavator, truck)
# 实例化调度分组
group = Group(group_id, truck, pre_sch)
group = Group(group_id, truck, pre_sch, excavator, dump)
# 更新调度分组信息
group.info_update()
......
{
"para": {
"log_path": "./Logs/",
"log_path": "/usr/local/fleet-log/dispatch",
"empty_speed": 17,
"heavy_speed": 17,
"dump_target_mass": 5000,
......@@ -8,23 +8,23 @@
},
"mysql": {
"host": "172.16.0.103",
"host": "192.168.9.152",
"port": "3306",
"user": "root",
"password": "Huituo@123",
"database": "ht_zhunneng_0913"
"database": "waytous"
},
"postgresql": {
"host": "172.16.0.103",
"host": "192.168.9.152",
"port": "5432",
"user": "postgres",
"password": "Huituo@123",
"database": "gis_zhunneng_0913"
"database": "shenbao_2021520"
},
"redis": {
"host": "172.16.0.103",
"host": "192.168.9.152",
"password": "Huituo@123"
}
}
}
\ No newline at end of file
......@@ -3,15 +3,6 @@
# @Time : 2022/5/30 15:35
# @Author : Opfer
# @Site :
# @File : group.py
# @Software: PyCharm
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/5/30 15:35
# @Author : Opfer
# @Site :
# @File : group.py
# @Software: PyCharm
......@@ -94,6 +85,10 @@ class Group:
self.unload_area_uuid_index_dict = bidict()
self.dump_uuid_index_dict = bidict()
# device bind
self.dump_truck_bind = {}
self.excavator_truck_bind = {}
# truck info.
self.truck_info_list = {}
......@@ -218,6 +213,34 @@ class Group:
# self.logger.info(es)
# self.logger.info("error-12")
def update_device_bind(self):
"""
update device bind.
:return:
"""
self.dump_truck_bind = {}
self.excavator_truck_bind = {}
for truck_id, dump_id in self.truck.truck_dump_bind.items():
if dump_id not in self.dump_truck_bind:
self.dump_truck_bind[dump_id] = [truck_id]
else:
self.dump_truck_bind[dump_id].append(truck_id)
for truck_id, excavator_id in self.truck.truck_excavator_bind.items():
if excavator_id not in self.excavator_truck_bind:
self.excavator_truck_bind[excavator_id] = [truck_id]
else:
self.excavator_truck_bind[excavator_id].append(truck_id)
def get_device_exclude(self, truck_id):
"""
get device exclude modify vector.
:param truck_id: request truck id
:return:
"""
pass
def info_update(self):
"""
......@@ -252,12 +275,15 @@ class Group:
if self.group_mode == 1:
if truck_task in [-2, 3, 4, 5]:
try:
if i in self.truck.truck_excavator_bind:
next_excavator_id = self.truck.truck_excavator_bind[i]
else:
next_excavator_value = s.solve(truck_info)
# next_excavator_value = s.solve(i, truck_task, truck_trip)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index = np.argmin(next_excavator_value)
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
next_excavator_value = s.solve(truck_info)
# next_excavator_value = s.solve(i, truck_task, truck_trip)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index = np.argmin(next_excavator_value)
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
if truck_task == -2:
next_unload_area_id = "Park"
else:
......@@ -280,18 +306,22 @@ class Group:
self.logger.info(self.unload_area_uuid_index_dict)
self.logger.info(self.excavator_uuid_index_dict)
tmp = self.group_walk_available[
self.excavator_uuid_index_dict[next_excavator_id], :].flatten()
self.logger.info(f'group_walk_available_pick {tmp}')
self.logger.info(f'next_excavator_id {next_excavator_id}')
self.logger.info(next_unload_area_value)
next_unload_area_value *= self.group_walk_available[
self.excavator_uuid_index_dict[next_excavator_id], :].flatten()
self.logger.info(next_unload_area_value)
min_index = np.argmin(next_unload_area_value)
next_unload_area_id = self.unload_area_uuid_index_dict.inverse[min_index]
# next_excavator_id = self.excavator_uuid_index_dict.inverse[truck_trip[-1]]
if i in self.truck.truck_dump_bind:
dump_uuid_to_unload_area_uuid_dict = get_value("dump_uuid_to_unload_area_uuid_dict")
next_unload_area_id = dump_uuid_to_unload_area_uuid_dict[self.truck.truck_dump_bind[i]]
else:
tmp = self.group_walk_available[
self.excavator_uuid_index_dict[next_excavator_id], :].flatten()
self.logger.info(f'group_walk_available_pick {tmp}')
self.logger.info(f'next_excavator_id {next_excavator_id}')
self.logger.info(next_unload_area_value)
next_unload_area_value *= self.group_walk_available[
self.excavator_uuid_index_dict[next_excavator_id], :].flatten()
self.logger.info(next_unload_area_value)
min_index = np.argmin(next_unload_area_value)
next_unload_area_id = self.unload_area_uuid_index_dict.inverse[min_index]
# next_excavator_id = self.excavator_uuid_index_dict.inverse[truck_trip[-1]]
truck_dispatch[i] = [next_excavator_id, next_unload_area_id]
......@@ -304,10 +334,13 @@ class Group:
if truck_task in [-2, 3, 4, 5]:
try:
next_excavator_value = s.solve(truck_info)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index = np.argmin(next_excavator_value)
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
if i in self.truck.truck_excavator_bind:
next_excavator_id = self.truck.truck_excavator_bind[i]
else:
next_excavator_value = s.solve(truck_info)
# min_index = next_excavator_list.index(min(next_excavator_list))
min_index = np.argmin(next_excavator_value)
next_excavator_id = self.excavator_uuid_index_dict.inverse[min_index]
if truck_task == -2:
next_unload_area_id = "Park"
else:
......@@ -354,7 +387,12 @@ class Group:
try:
next_unload_area_id = DistributionRatio(next_exactor_id, self.truck).ratio_main()
if i in self.truck.truck_dump_bind:
dump_uuid_to_unload_area_uuid_dict = get_value("dump_uuid_to_unload_area_uuid_dict")
next_unload_area_id = dump_uuid_to_unload_area_uuid_dict[self.truck.truck_dump_bind[i]]
else:
next_unload_area_id = DistributionRatio(next_exactor_id, self.truck).ratio_main()
except Exception as es:
......
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/8/18 13:53
# @Author : Opfer
# @Site :
# @File : ruler.py
# @Software: PyCharm
\ No newline at end of file
......@@ -69,6 +69,10 @@ class TruckInfo(WalkManage):
self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
# 各装载区矿卡数量
self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
# 驶往各卸载区矿卡集合
self.dump_hold_truck_list = {item: [] for item in get_value("dynamic_dump_set")}
# 驶往各装载区矿卡集合
self.excavator_hold_truck_list = {item: [] for item in get_value("dynamic_excavator_set")}
# 日志
self.logger = get_logger("zxt.truck")
# # 初始化读取参数
......@@ -438,6 +442,11 @@ class TruckInfo(WalkManage):
# 目的地矿卡数加一
self.excavator_hold_truck_num[end_eqp_index] = self.excavator_hold_truck_num[end_eqp_index] + 1
# 目的地矿卡集合增加
if item.exactor_id not in self.excavator_hold_truck_list:
self.excavator_hold_truck_list[item.exactor_id] = [truck_id]
else:
self.excavator_hold_truck_list[item.exactor_id].append(truck_id)
# 若矿卡状态为重载(含卸载出场)
elif task in [3, 4, 5]:
......@@ -446,6 +455,11 @@ class TruckInfo(WalkManage):
# 目的地矿卡数加一
self.dump_hold_truck_num[end_eqp_index] = self.dump_hold_truck_num[end_eqp_index] + 1
# 目的地矿卡集合增加
if item.dump_id not in self.dump_hold_truck_list:
self.dump_hold_truck_list[item.dump_id] = [truck_id]
else:
self.dump_hold_truck_list[item.dump_id].append(truck_id)
# 其他状态,矿卡状态为-2,equipment_pair表不存在该矿卡
else:
pass
......@@ -753,6 +767,10 @@ class TruckInfo(WalkManage):
self.dump_hold_truck_num = np.zeros(get_value("dynamic_dump_num"))
# 各装载区矿卡数量
self.excavator_hold_truck_num = np.zeros(get_value("dynamic_excavator_num"))
# 驶往各卸载区矿卡集合
self.dump_hold_truck_list = {item: [] for item in get_value("dynamic_dump_set")}
# 驶往各装载区矿卡集合
self.excavator_hold_truck_list = {item: [] for item in get_value("dynamic_excavator_set")}
# 对象域更新
self.dump = dump
self.excavator = excavator
......
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/8/29 15:51
# @Author : Opfer
# @Site :
# @File : __init__.py
# @Software: PyCharm
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/8/29 15:26
# @Author : Opfer
# @Site :
# @File : gothrough_digging.py
# @Software: PyCharm
from flask import Flask, request
from flask.json import jsonify
from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from core.dispatcher import Dispatcher, PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo
from core.dispatcher import DispatchSubmission
from app import app
import uuid
@app.route("/redispatch", methods=["POST"])
def redispatch_request():
# 获取报文数据
data_json = request.get_json()
# 车辆id
request_truck_id = data_json.get("truck_id")
# 调度开始时间
rtd_start_time = datetime.now()
# 初始化日志
set_log()
# 获取日志器
logger = get_logger("zxt.Request")
# 更新周期参数
logger.info("#####################################请求调度更新开始#####################################")
try:
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
except Exception as es:
logger.error("数据库访问异常")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=501)
try:
# 全局参数更新
global_period_para_update()
# get_global_para_from_cache(cache)
except Exception as es:
logger.error("全局参数更新异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=502)
try:
# 更新调度信息
DispatchInfo.reset()
DispatchInfo.update_device_group_structure()
group_id = DispatchInfo.truck_group_dict[request_truck_id]
DispatchInfo.update_route_distance()
DispatchInfo.update_group_mode()
DispatchInfo.update_group_name()
except Exception as es:
logger.error("调度信息更新异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=503)
logger.info("Dispatchinfo,更新后信息")
logger.info("group_set")
logger.info(DispatchInfo.group_set)
logger.info("group_excavator_dict")
logger.info(DispatchInfo.group_excavator_dict)
logger.info("group_unload_area_dict")
logger.info(DispatchInfo.group_unload_area_dict)
logger.info("group_truck_dict")
logger.info(DispatchInfo.group_truck_dict)
logger.info("group_mode")
logger.info(DispatchInfo.group_mode)
logger.info("load_distance")
logger.info(DispatchInfo.load_distance)
logger.info("unload_distance")
logger.info(DispatchInfo.unload_distance)
# try:
# # 实例化设备对象
dump = DumpInfo()
excavator = ExcavatorInfo()
truck = TruckInfo(dump, excavator)
# 设备信息更新
dump.dump_para_period_update()
excavator.excavator_para_period_update()
truck.truck_para_period_update(dump, excavator)
truck.state_period_update()
#
# # 实例化调度预测器
# pre_sch = PreSchedule(truck, excavator, dump)
#
# # 实例化输出器
# submission = DispatchSubmission(dump, excavator, truck)
#
# # 实例化调度分组
# group = Group(group_id, truck, None, excavator, dump)
#
# # 更新调度分组信息
# group.update_group_device()
excavators_id = DispatchInfo.get_excavator(group_id)
# 读取车辆位置信息
truck_locates_dict = get_trucks_locate()
# 装载区区分
closer_area_id, further_area_id = area_analysis(excavators_id)
# 装载区入场点
closer_entrance_node_id = session_postgre.query(DiggingWorkArea).filter_by(Id=closer_area_id).first().EntranceNodeId
further_entrance_node_id = session_postgre.query(DiggingWorkArea).filter_by(
Id=further_area_id).first().EntranceNodeId
# 车辆位置判断
if not truck_pass_first_area(request_truck_id, truck_locates_dict[request_truck_id], closer_entrance_node_id, further_entrance_node_id):
truck_dispatch_to_redis(request_truck_id, group_id, DispatchInfo.load_excavator_dict[further_area_id])
else:
# logger.info(" ")
# logger.info(truck.excavator_hold_truck_list)
# logger.info(list(excavators_id)[0])
# logger.info(list(excavators_id)[1])
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[0]])
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[1]])
# 统计驶往两装载区的车辆
arrival_truck_set = truck.excavator_hold_truck_list[list(excavators_id)[0]]\
+ truck.excavator_hold_truck_list[list(excavators_id)[1]]
# 统计车辆抵达时间
arrival_truck_reach_time = [truck.cur_truck_reach_excavator[truck.truck_uuid_to_index_dict[truck_id]] for \
truck_id in arrival_truck_set]
logger.info(" ")
logger.info(arrival_truck_reach_time)
# arrival_truck_set = ['309705a0-5ddf-4559-b6c4-ee17a57677ad', '899705a0-5ddf-4559-b6c4-ee17a57677ad']
#
# arrival_truck_reach_time = [8.04, 6.05]
arrival_truck_list = list(zip(np.array(arrival_truck_set), np.array(arrival_truck_reach_time)))
arrival_truck_list = sorted(arrival_truck_list, key=lambda item: item[1])
lane_set = get_lanes_between_entrances(closer_entrance_node_id, further_entrance_node_id)
goto_closer_area_num = 0
goto_further_area_num = 0
for truck_id, reach_time in zip(*arrival_truck_list):
truck_lane_id = truck_locates_dict[truck_id]
if truck_lane_id in lane_set:
goto_closer_area_num += 1
else:
pass
logger.info(" ")
logger.info(arrival_truck_list)
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[0]])
# logger.info(truck.excavator_hold_truck_list[list(excavators_id)[1]])
# except Exception as es:
# logger.error("对象实例化异常")
# logger.error(es)
# session_mysql.rollback()
# session_postgre.rollback()
# return jsonify(msg="未知异常, 请联系管理员", code=504)
# try:
#
# # 调度分组派车计划计算
# try:
# truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
# except Exception as es:
# logger.error(es)
# logger.error(f'分组{group.group_id} 调度计算异常')
#
# try:
#
# logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
# submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
# except Exception as es:
# logger.error(es)
# logger.error(f'分组{group.group_id} 调度写入异常')
#
# except Exception as es:
# logger.error("最外层异常捕获")
# logger.error(es)
# return jsonify(msg="未知异常, 请联系管理员", code=505)
#
# session_mysql.close()
# session_postgre.close()
logger.info("#####################################请求调度更新结束#####################################")
# 调度结束时间
rtd_end_time = datetime.now()
print(f'调度时耗 {rtd_end_time - rtd_start_time}')
return jsonify(msg="success", code=0)
def area_analysis(load_area_uuid):
"""
Analysis which area is closer.
:param load_area_uuid:
:return: closer_area_uuid, further_area_uuid
"""
excavator_uuid_to_load_area_uuid_dict = get_value("excavator_uuid_to_load_area_uuid_dict")
load_area_uuid = list(load_area_uuid)
load_area_uuid[0] = excavator_uuid_to_load_area_uuid_dict[load_area_uuid[0]]
load_area_uuid[1] = excavator_uuid_to_load_area_uuid_dict[load_area_uuid[1]]
distance_a = session_postgre.query(WalkTimePark)\
.filter_by(load_area_id=load_area_uuid[0]).first().park_load_distance
distance_b = session_postgre.query(WalkTimePark)\
.filter_by(load_area_id=load_area_uuid[1]).first().park_load_distance
if distance_a > distance_b:
return load_area_uuid[1], load_area_uuid[0]
else:
return load_area_uuid[0], load_area_uuid[1]
def truck_pass_first_area(truck_id, lane_id, closer_entrance_node_id, further_entrance_node_id):
"""
Truck has gone through the first area.
:param truck_id:
:param lane_id:
:param closer_entrance_node_id:
:param further_entrance_node_id:
:return:
"""
max_find_it = 100
while max_find_it > 0:
logger.info(" ")
logger.info(lane_id)
node_id = session_postgre.query(Lane).filter_by(Id=lane_id).first().EndNodeId
logger.info(node_id)
if node_id == closer_entrance_node_id:
return True
if node_id == further_entrance_node_id:
return False
lane_id = session_postgre.query(Lane).filter_by(StartNodeId=node_id, Type=2).first().Id
def get_trucks_locate():
truck_name_to_uuid_dict = get_value("truck_name_to_uuid_dict")
truck_locate_dict = {}
device_name_set = redis2.keys()
for item in device_name_set:
item = item.decode(encoding='utf-8')
# json_value = json.loads(redis2.get(item))
key_value_dict = redis2.hgetall(item)
device_type = key_value_dict[str_to_byte('type')]
is_online = key_value_dict[str_to_byte('online')]
key_set = key_value_dict.keys()
if (device_type == str_to_byte("1")) \
and (str_to_byte('online') in key_set) \
and (bytes.decode(is_online) in ["true" or "True"]) \
and (str_to_byte('laneId') in key_set):
truck_locate = key_value_dict[str_to_byte('laneId')]
truck_locate_dict[truck_name_to_uuid_dict[item]] = eval(truck_locate)
return truck_locate_dict
def truck_dispatch_to_redis(truck_id, group_id, excavator_id):
# 查询车辆相关派车计划
record = {}
try:
# dump_id = DispatchInfo.unload_area_dump_dict[unload_area_id]
item = (session_mysql.query(DispatchSetting).filter_by(exactor_id=excavator_id, group_id=group_id,
isdeleted=0, ).first())
if item is None:
raise Exception("调度计划配置异常")
except Exception as es:
item = (session_mysql.query(DispatchSetting).filter_by(group_id=group_id, isdeleted=0, ).first())
logger.error(es)
# 其余调度信息写入
try:
# record["dispatchId"] = item.id
record["dispatchId"] = str(uuid.uuid1())
record["exactorId"] = item.exactor_id
record["loadAreaId"] = item.load_area_id
record["dumpId"] = item.dump_id
record["unloadAreaId"] = item.unload_area_id
record["groupId"] = group_id
record["isdeleted"] = False
record["isTemp"] = False
record["haulFlag"] = -1
record["groupName"] = DispatchInfo.group_name[group_id]
logger.info(f'redis 注入 {record}')
except Exception as es:
logger.error("调度结果写入异常-矿卡空载")
logger.error(es)
finally:
redis5.set(truck_id, str(json.dumps(record)))
def get_lanes_between_entrances(closer_node_id, further_node_id):
max_find_it = 100
next_node_id = closer_node_id
lane_set = []
while max_find_it > 0 and next_node_id != further_node_id:
item = session_postgre.query(Lane).filter_by(StartNodeId=next_node_id, Type=2).first()
next_lane_id = item.Id
next_node_id = item.EndNodeId
lane_set.append(next_lane_id)
max_find_it -= 1
return lane_set
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/8/3 17:53
# @Author : Opfer
# @Site :
# @File : redispatch.py
# @Software: PyCharm
from flask import Flask, request
from flask.json import jsonify
from para_config import *
from equipment.truck import TruckInfo
from equipment.excavator import ExcavatorInfo
from equipment.dump import DumpInfo
from core.dispatcher import Dispatcher, PreSchedule
from core.group import Group
from flask_caching import Cache
from alg.algorithm import ExpectedTime
from data.dispatchInfo import DispatchInfo
from core.dispatcher import DispatchSubmission
from graph_load import graph_construct
config = {
"DEBUG": True, # some Flask specific configs
"CACHE_TYPE": "SimpleCache", # Flask-Caching related configs
"CACHE_DEFAULT_TIMEOUT": 300
}
app = Flask(__name__)
app.config.from_mapping(config)
cache = Cache(app)
def update_truck_loacate(truck_id):
# 读取矿卡所在路段信息
try:
truck_locate_dict = {}
device_name_set = redis2.keys()
for item in device_name_set:
item = item.decode(encoding='utf-8')
# json_value = json.loads(redis2.get(item))
key_value_dict = redis2.hgetall(item)
device_type = key_value_dict[str_to_byte('type')]
is_online = key_value_dict[str_to_byte('online')]
key_set = key_value_dict.keys()
if (device_type == str_to_byte("1")) \
and (str_to_byte('online') in key_set) \
and (bytes.decode(is_online) in ["true" or "True"]) \
and (str_to_byte('laneId') in key_set):
truck_locate = key_value_dict[str_to_byte('laneId')]
truck_locate_dict[get_value("truck_name_to_uuid_dict")[item]] = eval(truck_locate)
except Exception as es:
logger.error(" ")
return truck_locate_dict[truck_id]
@app.route("/redispatch", methods=["POST"])
def dispatch_request():
# 获取报文数据
data_json = request.get_json()
# 车辆id
truck_id = data_json.get("truck_id")
# 调度开始时间
rtd_start_time = datetime.now()
# 初始化日志
set_log()
# 获取日志器
logger = get_logger("zxt.truck-request")
# 更新周期参数
logger.info("#####################################请求调度更新开始#####################################")
try:
# 清空数据库缓存
session_mysql.commit()
session_mysql.flush()
# 清空数据库缓存
session_postgre.commit()
session_postgre.flush()
except Exception as es:
logger.error("数据库访问异常")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=501)
try:
# 全局参数更新
global_period_para_update()
# get_global_para_from_cache(cache)
except Exception as es:
logger.error("全局参数更新异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=502)
try:
# 更新调度信息
DispatchInfo.reset()
DispatchInfo.update_device_group_structure()
if group_id not in DispatchInfo.truck_group_dict:
raise Exception("请求调度车辆不存在")
DispatchInfo.update_route_distance()
DispatchInfo.update_group_mode()
DispatchInfo.update_group_name()
except Exception as es:
logger.error("调度信息更新异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=503)
logger.info("Dispatchinfo,更新后信息")
logger.info("group_set")
logger.info(DispatchInfo.group_set)
logger.info("group_excavator_dict")
logger.info(DispatchInfo.group_excavator_dict)
logger.info("group_unload_area_dict")
logger.info(DispatchInfo.group_unload_area_dict)
logger.info("group_truck_dict")
logger.info(DispatchInfo.group_truck_dict)
logger.info("group_mode")
logger.info(DispatchInfo.group_mode)
logger.info("load_distance")
logger.info(DispatchInfo.load_distance)
logger.info("unload_distance")
logger.info(DispatchInfo.unload_distance)
try:
# 实例化设备对象
dump = DumpInfo()
excavator = ExcavatorInfo()
truck = TruckInfo(dump, excavator)
group_id = DispatchInfo.truck_group_dict[truck_id]
# 设备信息更新
dump.dump_para_period_update()
excavator.excavator_para_period_update()
truck.truck_para_period_update(dump, excavator)
truck.state_period_update()
# 实例化调度预测器
pre_sch = PreSchedule(truck, excavator, dump)
# 实例化输出器
submission = DispatchSubmission(dump, excavator, truck)
# 实例化调度分组
group = Group(group_id, truck, pre_sch)
# 更新调度分组信息
group.info_update()
truck_trip = truck.get_truck_current_trip()[truck.truck_uuid_to_index_dict[truck_id]]
truck_task = truck.get_truck_current_task()[truck_id]
truck_lane = update_truck_loacate(truck_id)
excavators = DispatchInfo.group_excavator_dict[group_id]
dumps = DispatchInfo.dump_group_dict[group_id]
topo = graph_construct()
next_target = None
if truck_task in [-2, 0]:
excavator_distance_dict = topo.get_load_target_node_real(truck_lane, None)
MAX_DIS = 100000000
for excavator_id in excavators:
if excavator_distance_dict[excavator_id] < MAX_DIS:
next_target = excavator_id
MAX_DIS = excavator_distance_dict[excavator_id]
elif truck_task == 3:
dump_distance_dict = topo.get_unload_target_node_real(truck_lane, None)
MAX_DIS = 100000000
for dump_id in dumps:
if dump_distance_dict[dump_id] < MAX_DIS:
next_target = dump_id
MAX_DIS = dump_distance_dict[dump_id]
except Exception as es:
logger.error("对象实例化异常")
logger.error(es)
session_mysql.rollback()
session_postgre.rollback()
return jsonify(msg="未知异常, 请联系管理员", code=504)
try:
# 调度分组派车计划计算
try:
truck_dispatch_plan_dict = group.group_dispatch(ExpectedTime)
except Exception as es:
logger.error(es)
logger.error(f'分组{group.group_id} 调度计算异常')
try:
logger.info(f'调度分组: {group.group_id} {DispatchInfo.group_name[group.group_id]}')
submission.group_dispatch_to_redis(group, truck_dispatch_plan_dict)
except Exception as es:
logger.error(es)
logger.error(f'分组{group.group_id} 调度写入异常')
except Exception as es:
logger.error("最外层异常捕获")
logger.error(es)
return jsonify(msg="未知异常, 请联系管理员", code=505)
session_mysql.close()
session_postgre.close()
logger.info("#####################################请求调度更新结束#####################################")
# 调度结束时间
rtd_end_time = datetime.now()
print(f'调度时耗 {rtd_end_time - rtd_start_time}')
return jsonify(msg="success", code=0)
\ No newline at end of file
# from para_config import *
from settings import *
import numpy as np
......@@ -8,6 +7,7 @@ import matplotlib.pyplot as plt
# from path_plan.path_plannner import *
import networkx as nx
class Topo():
""" class for the topo.
Description:
......@@ -15,10 +15,12 @@ class Topo():
Attribute:
equipment class: None
"""
def __init__(self):
# to unload graph
self.unload_G = nx.Graph() # 建立空的简单无向图
# self.unload_G = nx.DiGra/ph()
self.unload_G = nx.Graph()
self.unload_G_nodes = np.array(self.unload_G)
self.unload_G_num_of_nodes = self.unload_G.number_of_nodes()
......@@ -31,6 +33,7 @@ class Topo():
# self.unload_path_dict = {}
# to load graph
# self.load_G = nx.DiGraph()
self.load_G = nx.Graph()
self.load_G_nodes = np.array(self.load_G)
......@@ -44,15 +47,16 @@ class Topo():
# self.load_path_dict = {}
self.work_area_distance_info = []
self.park_distance_info = []
# self.laneinfo = LaneInfo()
# 获取日志器
self.logger = get_logger("zxt.topo")
"""
unload_G funcions
"""
def get_unload_G(self):
return self.unload_G
......@@ -71,6 +75,7 @@ class Topo():
"""
load_G functions
"""
def get_load_G(self):
return self.load_G
......@@ -86,28 +91,50 @@ class Topo():
def get_load_G_num_of_edges(self):
return self.load_G_num_of_edges
def get_work_area_distance_info(self):
try:
for item in session_postgre.query(WalkTime).all():
self.work_area_distance_info.append([[str(item.load_area_id), str(item.unload_area_id)], item.to_unload_lanes, item.to_load_lanes])
self.work_area_distance_info.append(
[[str(item.load_area_id), str(item.unload_area_id)], item.to_unload_lanes, item.to_load_lanes])
except Exception as es:
self.logger.error(es)
self.logger.error("获取地图信息出错")
def return_work_area_distance_info(self):
self.get_work_area_distance_info()
return self.work_area_distance_info
def get_park_distance_info(self):
try:
for item in session_postgre.query(WalkTimePark).all():
self.park_distance_info.append([[str(item.park_area_id), str(item.load_area_id)], item.park_load_lanes])
except Exception as es:
self.logger.error(es)
self.logger.error("获取地图备停区信息出错")
"""
generate_topo_graph: unload_G and load_G
"""
def generate_topo_graph(self):
self.get_work_area_distance_info()
self.get_park_distance_info()
trip = self.work_area_distance_info
park_trip = self.park_distance_info
for item in trip:
# item = [[load_area_id, unload_area_id], to_unload_lanes, to_load_lanes]
# path_node_for_trip= []
# unload_G
Exitnode_for_digging = str(session_postgre.query(DiggingWorkArea).filter_by(Id =item[0][0]).first().ExitNodeId)
Exitnode_for_digging = str(
session_postgre.query(DiggingWorkArea).filter_by(Id=item[0][0]).first().ExitNodeId)
digging_name = str(
session_postgre.query(DiggingWorkArea).filter_by(Id=item[0][0]).first().Name)
Entrancenode_for_dump = str(session_postgre.query(DumpArea).filter_by(Id=item[0][1]).first().EntranceNodeId)
dump_name = str(session_postgre.query(DumpArea).filter_by(Id=item[0][1]).first().Name)
self.unload_G.add_node(Exitnode_for_digging, name='digging', type=digging_name)
self.unload_G.add_node(Entrancenode_for_dump, name='dump', type=dump_name)
# path_node_for_trip.append(Exitnode_for_digging) # add start node for trip
......@@ -119,16 +146,15 @@ class Topo():
self.unload_G_all_nodes.append(Entrancenode_for_dump)
self.unload_G_dump_nodes.append(Entrancenode_for_dump)
self.unload_G.add_node(Exitnode_for_digging, name='digging')
self.unload_G.add_node(Entrancenode_for_dump, name='dump')
try:
unload_saved_lane = []
for i in item[1]: # for each lane in a to_unload route
for i in item[1]: # for each lane in a to_unload route
i_startpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().StartNodeId)
i_endpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().EndNodeId)
# add [start_point, end_point, length, lane_id] to unload_saved_lane
unload_saved_lane.append([str(i_startpoint), str(i_endpoint), float(session_postgre.query(Lane).filter_by(Id=i).first().Length), i])
unload_saved_lane.append([str(i_startpoint), str(i_endpoint),
float(session_postgre.query(Lane).filter_by(Id=i).first().Length), i])
# son_lane_num = sum(1 for i in session_postgre.query(Lane).filter_by(StartNodeId = i_endpoint).all())
son_lane_num = len(session_postgre.query(Lane).filter_by(StartNodeId=i_endpoint).all())
......@@ -141,10 +167,12 @@ class Topo():
# lanes dict {lane_id: length, length}
lanes = {}
for lane_info in unload_saved_lane:
lanes[lane_info[-1]] = list([lane_info[2],lane_info[2]])
# lane_info: [start_point, end_point, length, lane_id]
lanes[lane_info[-1]] = list([lane_info[2], lane_info[2]])
self.unload_G.add_edge(unload_saved_lane[0][0], unload_saved_lane[-1][1], real_distance = sum(value[0] for value in lanes.values()),
locked_distance = sum(value[1] for value in lanes.values()),lane = lanes)
self.unload_G.add_edge(unload_saved_lane[0][0], unload_saved_lane[-1][1],
real_distance=sum(value[0] for value in lanes.values()),
locked_distance=sum(value[1] for value in lanes.values()), lane=lanes)
self.unload_G.add_node(unload_saved_lane[0][0])
self.unload_G.add_node(unload_saved_lane[-1][1])
# self.unload_G_land_edges_map[lanes] = [unload_saved_lane[0][0], unload_saved_lane[-1][1]]
......@@ -158,14 +186,18 @@ class Topo():
except Exception as es:
self.logger.error(es)
self.logger.error("去卸载区拓扑图出错")
# path_node_for_trip.append(Exitnode_for_digging) # add node for trip
# if i_endpoint in self.unload_G_dump_nodes:
# path_node_for_trip.append(Exitnode_for_digging) # add node for trip
# if i_endpoint in self.unload_G_dump_nodes:
# load_G
Entrancenode_for_digging = str(session_postgre.query(DiggingWorkArea).filter_by(Id =item[0][0]).first().EntranceNodeId)
Entrancenode_for_digging = str(
session_postgre.query(DiggingWorkArea).filter_by(Id=item[0][0]).first().EntranceNodeId)
digging_name = str(
session_postgre.query(DiggingWorkArea).filter_by(Id=item[0][0]).first().Name)
Exitnode_for_dump = str(session_postgre.query(DumpArea).filter_by(Id=item[0][1]).first().ExitNodeId)
dump_name = str(session_postgre.query(DumpArea).filter_by(Id=item[0][1]).first().Name)
# find the exitnodeid for dumparea, entrancenodeid for diggingarea,
# find the exit node_id for digging_area, entrance node_id for dumparea,
if Exitnode_for_dump not in self.load_G_all_nodes:
self.load_G_all_nodes.append(Exitnode_for_dump)
self.load_G_dump_nodes.append(Exitnode_for_dump)
......@@ -173,98 +205,107 @@ class Topo():
self.load_G_all_nodes.append(Entrancenode_for_digging)
self.load_G_digging_nodes.append(Entrancenode_for_digging)
self.load_G.add_node(Exitnode_for_dump, name='dump')
self.load_G.add_node(Entrancenode_for_digging, name='digging')
self.load_G.add_node(Exitnode_for_dump, name='dump', type=digging_name)
self.load_G.add_node(Entrancenode_for_digging, name='digging', type=dump_name)
try:
load_saved_lane = []
# 处理特殊点:备停区出场点
lane_p = ["7b9c8e89-7134-63ac-9c44-f183674b090c", "7e120229-b426-461b-91a4-05e01fb37ed8"]
lane_park_dict = {}
lane_parks= []
for i in lane_p:
i_startpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().StartNodeId)
i_endpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().EndNodeId)
lane_parks.append([str(i_startpoint), str(i_endpoint),
float(session_postgre.query(Lane).filter_by(Id=i).first().Length), i])
for l in lane_parks:
lane_park_dict[l[-1]] = list([l[2], l[2]])
self.load_G.add_edge(lane_parks[0][0], lane_parks[-1][1],
real_distance=sum(value[0] for value in lane_park_dict.values()),
locked_distance=sum(value[-1] for value in lane_park_dict.values()), lane=lane_park_dict)
self.load_G.add_node(lane_parks[0][0])
self.load_G.add_node(lane_parks[-1][1])
# lane_park = session_postgre.query(Lane).filter_by(Id="7b9c8e89-7134-63ac-9c44-f183674b090c").first()
# lane_park_startnode = str(lane_park.StartNodeId)
# lane_park_endnode = str(lane_park.EndNodeId)
# lane_park_length = lane_park.Length
# self.load_G.add_edge("d346992e-d134-63ac-9b08-76812d6e3b1d", "1c85bc2c-9134-6281-1265-fd19d0dcbd52",
# real_distance=lane_park_length,
# locked_distance=lane_park_length, lane={"7b9c8e89-7134-63ac-9c44-f183674b090c": [lane_park_length,lane_park_length]})
# self.load_G.add_node("d346992e-d134-63ac-9b08-76812d6e3b1d")
# self.load_G.add_node("1c85bc2c-9134-6281-1265-fd19d0dcbd52")
for i in item[2]:
i_startpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().StartNodeId)
i_endpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().EndNodeId)
load_i_startpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().StartNodeId)
load_i_endpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().EndNodeId)
load_saved_lane.append([str(i_startpoint), str(i_endpoint), float(session_postgre.query(Lane).filter_by(Id=i).first().Length), i])
# son_lane_num = sum(1 for i in session_postgre.query(Lane).filter_by(StartNodeId = i_endpoint).all())
son_lane_num = len(session_postgre.query(Lane).filter_by(StartNodeId=i_endpoint).all())
load_saved_lane.append([str(load_i_startpoint), str(load_i_endpoint),
float(session_postgre.query(Lane).filter_by(Id=i).first().Length), i])
# son_lane_num = sum(1 for i in session_postgre.query(Lane).filter_by(StartNodeId = load_i_endpoint).all())
son_lane_num = len(session_postgre.query(Lane).filter_by(StartNodeId=load_i_endpoint).all())
nodes = list(self.load_G.nodes)
# 可以添加的节点:分叉口或终点
if son_lane_num > 1 or i_endpoint in self.load_G_digging_nodes:
if son_lane_num > 1 or load_i_endpoint in self.load_G_digging_nodes or load_i_endpoint in nodes:
# print("item",item[0])
# print(load_saved_lane)
# print("\n")
lanes = {}
for lane_info in load_saved_lane:
lanes[lane_info[-1]] = list([lane_info[2],lane_info[2]])
lanes[lane_info[-1]] = list([lane_info[2], lane_info[2]])
# lanes.append(i[0])
# lanes.append(i[1])
# self.load_G.add_edge(load_saved_lane[0][0], load_saved_lane[-1][1], real_distance = sum(n[2] for n in load_saved_lane), lane = lanes)
self.load_G.add_edge(load_saved_lane[0][0], load_saved_lane[-1][1],
real_distance=sum(value[0] for value in lanes.values()), locked_distance = sum(value[-1] for value in lanes.values()), lane=lanes)
real_distance=sum(value[0] for value in lanes.values()),
locked_distance=sum(value[-1] for value in lanes.values()), lane=lanes)
self.load_G.add_node(load_saved_lane[0][0])
self.load_G.add_node(load_saved_lane[-1][1])
# self.load_G_land_edges_map[lanes] = [load_saved_lane[0][0], load_saved_lane[-1][1]]
# if [load_saved_lane[0][0], load_saved_lane[-1][1]] not in self.load_G_edges:
# self.load_G_edges.append([load_saved_lane[0][0], load_saved_lane[-1][1]])
load_saved_lane = []
if i_startpoint not in self.load_G_all_nodes:
self.load_G_all_nodes.append(i_startpoint)
if i_endpoint not in self.load_G_all_nodes:
self.load_G_all_nodes.append(i_endpoint)
if load_i_startpoint not in self.load_G_all_nodes:
self.load_G_all_nodes.append(load_i_startpoint)
if load_i_endpoint not in self.load_G_all_nodes:
self.load_G_all_nodes.append(load_i_endpoint)
except Exception as es:
self.logger.error(es)
self.logger.error("去装载区拓扑图生成失败")
# """
# update blocked distance for graph
# """
# def update_blocked_distance(self):
#
def return_node_path(self, source_node, target_node):
try:
distance, path = nx.single_source_dijkstra(self.unload_G, source=source_node, target=target_node, weight="real_distance")
except Exception as es:
self.logger.error(es)
self.logger.error("dijkstra最短路径生成失败")
return list(path)
print(self.load_G.nodes.data())
for k in park_trip:
try:
load_saved_lane = []
for i in k[1]:
load_i_startpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().StartNodeId)
load_i_endpoint = str(session_postgre.query(Lane).filter_by(Id=i).first().EndNodeId)
load_saved_lane.append([str(load_i_startpoint), str(load_i_endpoint),
float(session_postgre.query(Lane).filter_by(Id=i).first().Length), i])
# son_lane_num = sum(1 for i in session_postgre.query(Lane).filter_by(StartNodeId = load_i_endpoint).all())
son_lane_num = len(session_postgre.query(Lane).filter_by(StartNodeId=load_i_endpoint).all())
nodes = list(self.load_G.nodes)
# 可以添加的节点:分叉口或终点
if son_lane_num > 1 or load_i_endpoint in self.load_G_digging_nodes or load_i_endpoint in nodes:
# print("item",item[0])
# print(load_saved_lane)
# print("\n")
lanes = {}
for lane_info in load_saved_lane:
lanes[lane_info[-1]] = list([lane_info[2], lane_info[2]])
# lanes.append(i[0])
# lanes.append(i[1])
# self.load_G.add_edge(load_saved_lane[0][0], load_saved_lane[-1][1], real_distance = sum(n[2] for n in load_saved_lane), lane = lanes)
self.load_G.add_edge(load_saved_lane[0][0], load_saved_lane[-1][1],
real_distance=sum(value[0] for value in lanes.values()),
locked_distance=sum(value[-1] for value in lanes.values()), lane=lanes)
self.load_G.add_node(load_saved_lane[0][0])
self.load_G.add_node(load_saved_lane[-1][1])
# self.load_G_land_edges_map[lanes] = [load_saved_lane[0][0], load_saved_lane[-1][1]]
# if [load_saved_lane[0][0], load_saved_lane[-1][1]] not in self.load_G_edges:
# self.load_G_edges.append([load_saved_lane[0][0], load_saved_lane[-1][1]])
load_saved_lane = []
if load_i_startpoint not in self.load_G_all_nodes:
self.load_G_all_nodes.append(load_i_startpoint)
if load_i_endpoint not in self.load_G_all_nodes:
self.load_G_all_nodes.append(load_i_endpoint)
except Exception as es:
self.logger.error(es)
self.logger.error("备停区部分装载拓扑图生成失败")
"""
unload source node for reschedule
"""
def get_unload_source_node(self, truck_location_lane):
def get_unload_edge_node(self, truck_location_lane):
try:
# truck_location_lane = self.laneinfo.update_truck_loacate()[truck_id]
for (startnode,endnode,lane) in self.unload_G.edges.data('lane'):
for (startnode, endnode, lane) in self.unload_G.edges.data('lane'):
if truck_location_lane in lane:
return startnode
return startnode, endnode
except Exception as es:
self.logger.error(es)
self.logger.error("卸载图,矿卡所在路段返回失败")
......@@ -272,14 +313,15 @@ class Topo():
"""
unload_G target
"""
def get_unload_target_node_real(self, truck_location_lane,pre_target):
source_node = self.get_unload_source_node(truck_location_lane)
def get_unload_target_node_real(self, truck_location_lane, pre_target):
source_node = self.get_unload_edge_node(truck_location_lane)
target_list = []
for (u, wt) in self.unload_G.nodes.data('name'):
# select next reachable target
if wt == 'dump' and u != pre_target :
if wt == 'dump' and u != pre_target:
target_list.append(u)
if not len(target_list):
......@@ -290,7 +332,8 @@ class Topo():
for i in target_list:
try:
distance, path = nx.single_source_dijkstra(self.unload_G, source=source_node, target=i, weight="real_distance")
distance, path = nx.single_source_dijkstra(self.unload_G, source=source_node, target=i,
weight="real_distance")
path_length_map[distance] = path
# print(path)
except Exception as es:
......@@ -308,27 +351,72 @@ class Topo():
"""
load source node for reschedule
"""
def get_load_source_node (self, truck_location_lane):
def get_load_edge_node(self, truck_location_lane):
try:
# truck_location_lane = self.laneinfo.update_truck_loacate()[truck_id]
for (startnode,endnode,lane) in self.load_G.edges.data('lane'):
for (startnode, endnode, lane) in self.load_G.edges.data('lane'):
if truck_location_lane in lane:
return startnode
return startnode, endnode
except Exception as es:
self.logger.error(es)
self.logger.error("装载图,矿卡所在路段返回失败")
"""
update load_G locked_distance
"""
def update_load_G_locked_distance(self, path, alpha, beta):
for i in range(len(path) - 1):
data = dict(self.load_G[path[i]][path[i + 1]]['lane'])
for u, v in data.items():
data[u] = [v[0], v[0]]
self.load_G[path[i]][path[i + 1]]['locked_distance'] = sum(i[-1] for i in list(data.values()))
"""
return relative distance between node and lane (graph_type: 0=load, 1=unload)
"""
def relative_distance(self, truck_location_lane, graph_type):
distance_start_node = 0
distance_end_node = 0
if graph_type == 1:
start_node, end_node = self.get_unload_edge_node(truck_location_lane)
edge_length = self.unload_G[start_node][end_node]['real_distance']
lane_dict = self.unload_G[start_node][end_node]['lane']
else:
start_node, end_node = self.get_load_edge_node(truck_location_lane)
edge_length = self.load_G[start_node][end_node]['real_distance']
lane_dict = self.load_G[start_node][end_node]['lane']
for i, j in lane_dict.items():
if i != truck_location_lane:
distance_start_node += list(j)[0]
else:
distance_start_node += (list(j)[0]) / 2
break
distance_end_node = edge_length - distance_start_node
return distance_start_node, distance_end_node
"""
load_G target
"""
def get_load_target_node_real(self, truck_location_lane,pre_target ):
source_node = self.get_load_source_node(truck_location_lane)
target_list = []
def get_load_target_node_real(self, truck_location_lane, pre_target):
# source_node = self.get_load_edge_node(truck_location_lane)
source_node, end_node = self.get_load_edge_node(truck_location_lane)
distance_source_node, distance_end_node = self.relative_distance(truck_location_lane, graph_type=0)
for (node, wt) in self.load_G.nodes.data('name'):
# update target_list
pre_destination_node = str(
session_postgre.query(DiggingWorkArea).filter_by(Id=pre_target).first().EntranceNodeId)
target_list = []
for (node, att) in self.load_G.nodes.data('name'):
# select next reachable target
if wt == 'digging' and node != pre_target :
if att == 'digging' and node != pre_destination_node:
target_list.append(node)
if not len(target_list):
......@@ -339,37 +427,23 @@ class Topo():
# build the path_length_map from source node
for i in target_list:
try:
distance, path = nx.single_source_dijkstra(self.load_G, source=source_node, target= i, weight="real_distance")
distance, path = nx.single_source_dijkstra(self.load_G, source=source_node, target=i,
weight="real_distance")
path_length_map[distance] = path
# print(path)
except Exception as es:
self.logger.info(es)
self.logger.info(f"装载图中{source_node} 与 {i} 之间道路不通")
# return the target area's entrance point and target area
min_dis_path = path_length_map[sorted(list(path_length_map.keys()))[0]]
entrance_point = min_dis_path[-1]
target_digging_area = str(session_postgre.query(DiggingWorkArea).filter_by(EntranceNodeId=entrance_point).first().Id)
# target_digging_area_name = str(session_postgre.query(DiggingWorkArea).filter_by(EntranceNodeId=entrance_point).first().Name)
return min_dis_path, entrance_point, target_digging_area
"""
update load_G locked_distance
"""
def update_load_G_locked_distance(self, path, alpha, beta):
for i in range(len(path) - 1):
data = dict(self.load_G[path[i]][path[i + 1]]['lane'])
for u, v in data.items():
data[u] = [v[0], v[0]]
self.load_G[path[i]][path[i + 1]]['locked_distance'] = sum(i[-1] for i in list(data.values()))
# """
# update unload_G locked_distance
# """
# def update_unload_G_locked_distance(self, path):
# for i in range(len(path) - 1):
# data = dict(self.unload_G[path[i]][path[i + 1]]['lane'])
# for u, v in data.items():
# data[u] = [v[0], v[0]]
# self.unload_G[path[i]][path[i + 1]]['locked_distance'] = sum(i[-1] for i in list(data.values()))
reachable_destinations = {}
# 如果列表最后是标识符,0表示需要掉头的目的地,1表示不需要掉头的目的地
for k, v in path_length_map.items():
entrance_point = v[-1]
target_digging_area = str(
session_postgre.query(DiggingWorkArea).filter_by(EntranceNodeId=entrance_point).first().Id)
if end_node not in v:
reachable_destinations[target_digging_area] = [k + distance_source_node, 0]
else:
reachable_destinations[target_digging_area] = [k + distance_end_node, 1]
return reachable_destinations
......@@ -60,15 +60,15 @@ def set_log():
# 创建日志目录
if not os.path.exists(log_path):
os.mkdir(log_path)
# if not os.path.exists(log_path):
# os.mkdir(log_path)
# logging初始化工作
logging.basicConfig()
# timefilehandler = logging.handlers.TimedRotatingFileHandler(log_path + "/dispatch.log", when='M', interval=1, backupCount=60)
filehandler = logging.handlers.RotatingFileHandler(log_path + "/dispatch.log", maxBytes=30*1024*1024, backupCount=10, encoding="utf-8")
# filehandler = logging.handlers.RotatingFileHandler("./Logs/dispatch.log", maxBytes=3 * 1024 * 1024, backupCount=10, encoding="utf-8")
# filehandler = logging.handlers.RotatingFileHandler(log_path + "/dispatch.log", maxBytes=30*1024*1024, backupCount=10, encoding="utf-8")
filehandler = logging.handlers.RotatingFileHandler("./Logs/dispatch.log", maxBytes=3 * 1024 * 1024, backupCount=10, encoding="utf-8")
# 设置后缀名称,跟strftime的格式一样
filehandler.suffix = "%Y-%m-%d_%H-%M.log"
......
......@@ -284,13 +284,15 @@ class Lane(Base):
MaxSpeed = Column(Float)
StartNodeId = Column(VARCHAR(36))
EndNodeId = Column(VARCHAR(36))
Type = Column(Integer)
def __init__(self, Id, Length, MaxSpeed, StartNodeId, EndNodeId):
def __init__(self, Id, Length, MaxSpeed, StartNodeId, EndNodeId, Type):
self.Id = Id
self.Length = Length
self.MaxSpeed = MaxSpeed
self.StartNodeId = StartNodeId
self.EndNodeId = EndNodeId
self.Type = Type
class Dispatch(Base):
......@@ -507,6 +509,7 @@ class DumpArea(Base):
__tablename__ = 'Geo_DumpArea'
Id = Column(VARCHAR(50), primary_key=True)
Name = Column(VARCHAR(36))
BindList = Column(VARCHAR(1000))
UnloadAbililty = Column(Float)
Disabled = Column(Integer)
......@@ -517,8 +520,9 @@ class DumpArea(Base):
ExitNodeId = Column(VARCHAR(50))
Name = Column(VARCHAR(36))
def __init__(self, Id, BindList, UnloadAbililty, Disabled, Materials, Priority, DumpEquipmentId, EntranceNodeId,ExitNodeId, Name):
def __init__(self, Id, Name, BindList, UnloadAbililty, Disabled, Materials, Priority, DumpEquipmentId, EntranceNodeId,ExitNodeId):
self.Id = Id
self.Name = Name
self.BindList = BindList
self.UnloadAbililty = UnloadAbililty
self.Disabled = Disabled
......@@ -527,21 +531,22 @@ class DumpArea(Base):
self.DumpEquipmentId = DumpEquipmentId
self.EntranceNodeId = EntranceNodeId
self.ExitNodeId = ExitNodeId
self.Name = Name
class DiggingWorkArea(Base):
__tablename__ = 'Geo_DiggingWorkArea'
Id = Column(VARCHAR(50), primary_key=True)
Name = Column(VARCHAR(36))
Material = Column(VARCHAR(36))
ExactorId = Column(VARCHAR(36))
ExactorUuid = Column(VARCHAR(50))
EntranceNodeId = Column(VARCHAR(50))
ExitNodeId = Column(VARCHAR(50))
def __init__(self, Id, Material, ExactorId, ExactorUuid, EntranceNodeId, ExitNodeId):
def __init__(self, Id, Name, Material, ExactorId, ExactorUuid, EntranceNodeId, ExitNodeId):
self.Id = Id
self.Name = Name
self.Material = Material
self.ExactorId = ExactorId
self.ExactorUuid = ExactorUuid
......
from path_plan.topo_graph import *
import networkx as nx
import matplotlib.pyplot as plt
# from redispatch.topo_graph import *
# import networkx as nx
# import matplotlib.pyplot as plt
#
# topo = Topo()
# topo.generate_topo_graph()
# load_G = topo.get_load_G()
# pos = nx.shell_layout(load_G)
# nx.draw(load_G, pos, with_labels=True, node_color='red', edge_color='blue', font_size=18, width=5, node_size=600,
# alpha=0.5)
# # topo.get_unload_target_node_real()
# plt.show()
topo = Topo()
topo.generate_topo_graph()
load_G = topo.get_load_G()
pos = nx.shell_layout(load_G)
nx.draw(load_G, pos, with_labels=True, node_color='red', edge_color='blue', font_size=18, width=5, node_size=600,
alpha=0.5)
plt.show()
A = [['309705a0-5ddf-4559-b6c4-ee17a57677ad', 9.04], ['899705a0-5ddf-4559-b6c4-ee17a57677ad', 6.05]]
A = sorted(A, key=lambda item: item[1])
print(A)
\ No newline at end of file
#!E:\Pycharm Projects\Waytous
# -*- coding: utf-8 -*-
# @Time : 2022/8/2 17:07
# @Author : Opfer
# @Site :
# @File : topo_sql.py.py
# @Software: PyCharm
import sqlite3
conn = sqlite3.connect('test.db')
c = conn.cursor()
print ("数据库打开成功")
cursor = c.execute("SELECT * FROM GRAPH")
# c.execute("INSERT INTO GRAPH (id, startNodeId, endNodeId, distance) VALUES ('text_id12', 'as4343', 'sdsdsd', 20000.00 )")
# conn.commit()
for row in cursor:
print("id = ", row[0])
print("startNodeId = ", row[1])
print("endNodeId = ", row[2])
print("distance= ", row[3])
print("dir= ", row[4])
print ("数据操作成功")
conn.close()
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"## 1. 导入包"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"from redispatch.topo_graph import *\n",
"import networkx as nx\n",
"import matplotlib.pyplot as plt\n",
"import uuid\n",
"import sqlite3"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 拓扑图生成与写入"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"text": [
"数据库打开成功\n"
],
"output_type": "stream"
}
],
"source": [
"conn = sqlite3.connect('test.db')\n",
"c = conn.cursor()\n",
"print (\"数据库打开成功\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"清空数据库数据"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"cursor = c.execute(\n",
" \"DELETE FROM GRAPH_EDGE\")\n",
"conn.commit()\n",
"\n",
"cursor = c.execute(\n",
" \"DELETE FROM GRAPH_NODE\")\n",
"\n",
"conn.commit()\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"生成拓扑图"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"text": [
"[('1edde59c-b134-3ef1-fc1b-2f5690eff02e', {'name': 'dump', 'type': '02号土方装载区'}), ('d8c59e25-4134-3ef2-1182-d8ddd3a4ffd7', {'name': 'digging', 'type': '04号土方卸载区'}), ('390574ea-3134-6281-1277-375d88cc74cc', {}), ('2e1b3039-e134-6281-127c-425a66a8b3ec', {}), ('da82a489-5134-6281-127d-fa08107043e8', {}), ('b290795e-8134-6281-129b-8717e1326fe0', {}), ('c66f355d-c134-3ef3-cdff-3b6a05335c00', {'name': 'dump', 'type': '02号土方装载区'}), ('84db153f-8134-3ef3-91e5-3b780dfd39a3', {'name': 'dump', 'type': '02号土方装载区'}), ('3ebc0b68-8134-6281-1264-0d52dfc6308d', {'name': 'digging', 'type': '04号土方卸载区'}), ('5c15ecf3-6134-3ef1-ac23-bd1f1480ea7a', {'name': 'dump', 'type': '02号土方装载区'}), ('81be6a9e-8134-3ef2-141e-4bb045b8d097', {'name': 'dump', 'type': '02号土方装载区'}), ('763a5edd-c134-3ef2-1154-912159da8391', {'name': 'digging', 'type': '04号土方卸载区'}), ('84b1ccbd-8134-6281-129c-629b79da9319', {}), ('74604c4b-a134-3ef2-1263-e99e323b4d0f', {'name': 'digging', 'type': '04号土方卸载区'}), ('71bb2875-1134-627f-140e-fb1d607711c4', {}), ('92eb8c73-d134-627e-de55-3dfd274b5bf6', {}), ('9b311d17-6134-3ef1-10bf-6918631c69e6', {'name': 'digging', 'type': '04号土方卸载区'}), ('39c0d01d-8134-3ef1-1140-b8d7698c1c16', {'name': 'digging', 'type': '04号土方卸载区'}), ('15332855-d134-3ef1-1364-6be98eb30b04', {'name': 'digging', 'type': '04号土方卸载区'}), ('92335f4a-2134-3ef1-103c-b83bc0c4aac6', {'name': 'digging', 'type': '04号土方卸载区'}), ('344a6d3d-7134-3ef2-ed00-cdfa2efb5d69', {'name': 'digging', 'type': '04号土方卸载区'}), ('7035254f-0134-6281-129d-c46ae9265ba0', {}), ('35518449-0134-8b1d-ad46-b767d078c25e', {'name': 'dump', 'type': 'fyh测试装载区'}), ('03ab6512-9134-8b1d-adbb-7cba14e8810c', {'name': 'digging', 'type': 'fyhvrdhi卸载区'}), ('47ca51af-1134-8b1d-adb0-5b8187fdabf2', {})]\n"
],
"output_type": "stream"
}
],
"source": [
"topo = Topo()\n",
"topo.generate_topo_graph()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"获取装载路径拓扑图"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"load_G = topo.get_load_G()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"装载路径拓扑图数据写入数据库"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"for item in load_G.edges.data():\n",
" id = str(uuid.uuid4())\n",
" startNodeId = item[0]\n",
" endNodeId = item[1]\n",
" distance = item[2]['real_distance']\n",
" lanes = item[2]['lane']\n",
" \n",
" lanes_sql = str(\" \".join(lanes))\n",
"\n",
" sql = \"INSERT INTO GRAPH_EDGE VALUES ('%s', '%s', '%s', '%f', 1, '%s')\" % (id, startNodeId, endNodeId, distance, lanes_sql)\n",
" \n",
" cursor = c.execute(sql)\n",
" \n",
" conn.commit()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"装载节点写入数据库"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"for item in load_G.nodes.data():\n",
" nodeId = item[0]\n",
" if item[1] != {} and item[1]['name'] != None:\n",
" name = item[1]['name']\n",
" else:\n",
" name = 'None'\n",
"\n",
" sql = \"INSERT INTO GRAPH_NODE VALUES ('%s', '%s')\" % (nodeId, name)\n",
" \n",
" cursor = c.execute(sql)\n",
" \n",
" conn.commit()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"获取卸载路径拓扑图"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"unload_G = topo.get_unload_G()"
]
},
{
"cell_type": "markdown",
"source": [
"卸载路径拓扑图写入数据库"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%% md\n"
}
}
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"text": [
"('9a08b6c1-9134-3ef2-11b9-679974d45727', 'daed5da4-7134-627d-a833-4df28d1b4531', {'real_distance': 785.4348356325944, 'locked_distance': 785.4348356325944, 'lane': {'4dc2fffe-ffff-42dd-8a2e-7ec04a5de1da': [105.121219804173, 105.121219804173], '4211e05f-0d77-4642-b90a-f1832a48d977': [135.156888571761, 135.156888571761], '6604ac8f-6175-48d2-8d68-7b44004efe23': [199.721525284214, 199.721525284214], '21c9ff90-e8c1-4a3d-a3d1-6a123c126e6d': [173.577436580541, 173.577436580541], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('dc3c075c-a134-3ef1-fbca-97af66533db0', 'a5da64fd-e134-6281-138e-0f685363ca20', {'real_distance': 238.448694428394, 'locked_distance': 238.448694428394, 'lane': {'e921be37-9fc5-4873-8262-2ec4d9f30daa': [116.17584600305, 116.17584600305], 'd63446cd-04a6-41f6-b374-25c1820cb351': [122.272848425344, 122.272848425344]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', 'a5da64fd-e134-6281-138e-0f685363ca20', {'real_distance': 288.076336719578, 'locked_distance': 288.076336719578, 'lane': {'f7808c9f-57f5-4b78-8012-e4a6b0f580fe': [140.404866806394, 140.404866806394], '04a45173-16ce-45db-bebf-cc817222aeda': [147.671469913184, 147.671469913184]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', '548b406e-e134-627e-aaf2-f0a0fdfe3e15', {'real_distance': 3474.8892959464947, 'locked_distance': 3474.8892959464947, 'lane': {'930acba3-ac72-4aa4-8c36-569ab81da7d2': [199.228755124064, 199.228755124064], '7de40e4b-92ad-42a5-bcd6-cd9e0e36509d': [199.411569079021, 199.411569079021], '851afe4f-6b32-4f6b-a60c-952e8f4f8837': [199.33512549022, 199.33512549022], 'b0687a4b-4a8e-4c7c-b073-7dd57104e251': [199.258884545305, 199.258884545305], '727149c9-2f56-4b13-987a-c4468a50decb': [199.36784415186, 199.36784415186], '55e2f42f-2dee-40c0-9749-0595b904aa2d': [199.306272121708, 199.306272121708], 'ff20e913-7082-46e3-8850-6a7e26161b81': [199.728074275453, 199.728074275453], 'bbc8aafd-d0e7-4a22-bd0f-f181173862b4': [160.035182206423, 160.035182206423], 'f8b88453-1869-4408-aa5f-8eb11e7b1ea7': [142.606151156767, 142.606151156767], 'c3fa9b94-a27e-4b23-87d4-bfcd489a4807': [199.783962534088, 199.783962534088], '82a71193-d140-4dbc-8ae8-6d75837f9e88': [199.124567815462, 199.124567815462], '1def4b73-a6d9-4d19-ae97-912e00132513': [199.436727538322, 199.436727538322], '300258e9-00c2-4025-8b6a-20c832845f41': [199.450003270525, 199.450003270525], 'b3bd86c8-d0a1-4abb-a42a-6ca3a4eb940a': [199.338834031107, 199.338834031107], '8d0a7d87-3940-4374-b4ad-429dca4de29b': [199.409394293222, 199.409394293222], '49713fd0-61a6-4bf6-951e-9ac103782154': [199.40266776486, 199.40266776486], 'e20580fe-ed64-4863-bf13-0c0ede8b3295': [199.383767742938, 199.383767742938], 'fd926630-5d39-41aa-9327-28c7786ff6ee': [181.28151280515, 181.28151280515]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', '805018ad-0134-3ef2-109d-e66e28634b17', {'real_distance': 1116.1488952323416, 'locked_distance': 1116.1488952323416, 'lane': {'71841169-8a8c-467c-b14d-6f3781fdb1de': [46.4007045485661, 46.4007045485661], '44c8f55e-b63c-4e3f-8c10-f087b657fb08': [124.89227175158, 124.89227175158], 'bba3c27e-58cc-465e-ad4b-a9c5b6e8dbba': [129.791466456589, 129.791466456589], 'dee73a87-fa6a-40be-9e77-f6f3a2380e67': [134.750836647185, 134.750836647185], '4211e05f-0d77-4642-b90a-f1832a48d977': [135.156888571761, 135.156888571761], '6604ac8f-6175-48d2-8d68-7b44004efe23': [199.721525284214, 199.721525284214], '21c9ff90-e8c1-4a3d-a3d1-6a123c126e6d': [173.577436580541, 173.577436580541], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', 'a158be2d-3134-3ef2-128b-6ea0a711ddd4', {'real_distance': 1435.0854127377575, 'locked_distance': 1435.0854127377575, 'lane': {'3530c7e6-1fba-4aae-94db-7713685c3102': [162.614892253932, 162.614892253932], 'ed95a92c-4c71-4e91-9aaf-9d85df33e92d': [145.618701410732, 145.618701410732], 'f5fbac37-5d09-4a2d-aab2-bda9a3a3823a': [199.90078488044, 199.90078488044], 'ecff2467-072d-4701-bdd2-c6eb9f145a27': [199.759900296874, 199.759900296874], '218487ec-f427-4757-b739-2f1881b81099': [199.640966001596, 199.640966001596], '55f277c0-6e08-4f63-a5bc-6323b5f14b37': [94.72300368216, 94.72300368216], '9af76124-02b6-40c8-8475-ce23ce981d47': [105.075267139363, 105.075267139363], 'e9ba2c12-3134-627e-dd08-9e2faf862787': [155.894131680755, 155.894131680755], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', 'a56eb6b8-d134-3ef2-127e-24cb1d9efe8b', {'real_distance': 1526.5866650207024, 'locked_distance': 1526.5866650207024, 'lane': {'c6f62624-47dd-4577-b53a-9411a54bcbe3': [119.832519955945, 119.832519955945], '3ee9eaf4-1526-4960-8087-05e8e5973a5a': [134.283624580932, 134.283624580932], 'ed95a92c-4c71-4e91-9aaf-9d85df33e92d': [145.618701410732, 145.618701410732], 'f5fbac37-5d09-4a2d-aab2-bda9a3a3823a': [199.90078488044, 199.90078488044], 'ecff2467-072d-4701-bdd2-c6eb9f145a27': [199.759900296874, 199.759900296874], '218487ec-f427-4757-b739-2f1881b81099': [199.640966001596, 199.640966001596], '55f277c0-6e08-4f63-a5bc-6323b5f14b37': [94.72300368216, 94.72300368216], '9af76124-02b6-40c8-8475-ce23ce981d47': [105.075267139363, 105.075267139363], 'e9ba2c12-3134-627e-dd08-9e2faf862787': [155.894131680755, 155.894131680755], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', '4a80bcb7-8134-3ef1-1145-cbae9ab5cd9a', {'real_distance': 471.0712009243544, 'locked_distance': 471.0712009243544, 'lane': {'8623c942-04d1-41a5-b54d-64f65b2bfc67': [153.827431099722, 153.827431099722], '3a7492a5-e8a0-43b0-bf11-c3260a6366a9': [145.386004432727, 145.386004432727], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', '1e692e26-0134-3ef1-1346-d4adb1f2cde4', {'real_distance': 1285.8775228454335, 'locked_distance': 1285.8775228454335, 'lane': {'e4b978cd-0364-4b2b-a7f6-68eaf6a5c033': [199.775865623081, 199.775865623081], 'a232fecf-0344-44a5-a0fa-7b34f63e10ef': [199.941252816337, 199.941252816337], '0cc6b7af-3b50-47a3-af8e-801fbee786b8': [199.93411256102, 199.93411256102], '71821930-af85-4193-9a65-66bbcc0c60ef': [124.879678489679, 124.879678489679], '3be972a3-1134-627e-104f-e382f7895135': [128.519449143293, 128.519449143293], '9af76124-02b6-40c8-8475-ce23ce981d47': [105.075267139363, 105.075267139363], 'e9ba2c12-3134-627e-dd08-9e2faf862787': [155.894131680755, 155.894131680755], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', '55fe1809-f134-3ef2-f70f-cd6635509428', {'real_distance': 2090.376853680292, 'locked_distance': 2090.376853680292, 'lane': {'e2d40684-316e-4e73-8c15-1ef7452b9cd3': [87.6462584131344, 87.6462584131344], 'f6ba0409-6081-4251-bd7a-f4ae55e3a34e': [119.29748307586, 119.29748307586], '17772169-2a06-4863-97b1-55d7757c6de7': [139.861713235727, 139.861713235727], '17c1ec39-c205-4f94-8b5e-ce0325401ac3': [199.809988474552, 199.809988474552], '04cb0542-dfa6-4217-959e-2a69201e8558': [199.459495856064, 199.459495856064], '38fae563-50bb-408d-8668-7c65969ce8df': [129.378478836282, 129.378478836282], '8c9b4f3b-7854-4dc7-a0c4-43c2cfad048a': [145.175245104897, 145.175245104897], '44c8f55e-b63c-4e3f-8c10-f087b657fb08': [124.89227175158, 124.89227175158], 'bba3c27e-58cc-465e-ad4b-a9c5b6e8dbba': [129.791466456589, 129.791466456589], 'dee73a87-fa6a-40be-9e77-f6f3a2380e67': [134.750836647185, 134.750836647185], '4211e05f-0d77-4642-b90a-f1832a48d977': [135.156888571761, 135.156888571761], '6604ac8f-6175-48d2-8d68-7b44004efe23': [199.721525284214, 199.721525284214], '21c9ff90-e8c1-4a3d-a3d1-6a123c126e6d': [173.577436580541, 173.577436580541], 'c7f15612-2d5f-4ed2-92b8-255a7fc84554': [85.5965935935173, 85.5965935935173], 'f3fc3f0e-09ce-4add-ad90-2b21f22abdee': [86.2611717983881, 86.2611717983881]}})\n",
"('a5da64fd-e134-6281-138e-0f685363ca20', 'c3bf2f33-2134-627d-a17a-7e903a38aaf7', {'real_distance': 293.201526970777, 'locked_distance': 293.201526970777, 'lane': {'05bb6b0e-90f8-4029-8598-e2c17e028029': [163.284643732243, 163.284643732243], '1521fc40-d594-478f-804f-5143e9d821f5': [129.916883238534, 129.916883238534]}})\n",
"('d4c1ea4d-1134-3ef3-aeba-93407138c07a', 'c3bf2f33-2134-627d-a17a-7e903a38aaf7', {'real_distance': 106.76805380722, 'locked_distance': 106.76805380722, 'lane': {'00bf5667-5899-4157-a13c-789cd0fbacb0': [106.76805380722, 106.76805380722]}})\n",
"('c3bf2f33-2134-627d-a17a-7e903a38aaf7', '5e86128e-7134-627d-a7e4-022cf2f86a3e', {'real_distance': 1138.450790281413, 'locked_distance': 1138.450790281413, 'lane': {'efbd912f-8bcc-42c6-b09b-8a339a8833c0': [268.493553318787, 268.493553318787], 'a280e8c9-28ca-4943-9a6d-ef756c6a4dcb': [200.009076458216, 200.009076458216], '9e32261c-2746-4f78-9217-f0af3dec8886': [199.100453903665, 199.100453903665], 'a46e0cff-223f-4b34-ad0d-1c4fac074c95': [199.361515973569, 199.361515973569], '1b6888ed-7112-479a-b4df-09447685c62d': [132.034570571589, 132.034570571589], '882296e1-5d30-4451-b44b-f66093e0a365': [66.536453226413, 66.536453226413], 'fe2a264d-f60a-411d-8646-e9073eb0cec2': [72.9151668291741, 72.9151668291741]}})\n",
"('c573c724-e134-3ef3-a85e-dae14f7067b0', '5e86128e-7134-627d-a7e4-022cf2f86a3e', {'real_distance': 108.775137769238, 'locked_distance': 108.775137769238, 'lane': {'bb8b8aad-a765-410e-8750-9f0cec443e86': [108.775137769238, 108.775137769238]}})\n",
"('5e86128e-7134-627d-a7e4-022cf2f86a3e', '21c30b97-b134-627d-a816-14340c5cd7e3', {'real_distance': 204.7916605686926, 'locked_distance': 204.7916605686926, 'lane': {'c13eee6e-48ed-451d-8a03-e0fd61bd1977': [126.237762651937, 126.237762651937], 'adc3c230-2738-43fa-ae29-9fde9606382c': [78.5538979167556, 78.5538979167556]}})\n",
"('5e86128e-7134-627d-a7e4-022cf2f86a3e', 'a04cd66c-b134-627d-a176-196081acffc8', {'real_distance': 139.4516200555871, 'locked_distance': 139.4516200555871, 'lane': {'882296e1-5d30-4451-b44b-f66093e0a365': [66.536453226413, 66.536453226413], 'fe2a264d-f60a-411d-8646-e9073eb0cec2': [72.9151668291741, 72.9151668291741]}})\n",
"('5e86128e-7134-627d-a7e4-022cf2f86a3e', '1f53a6c5-0134-3ef1-1043-e33fb6c4e19f', {'real_distance': 998.52905652976, 'locked_distance': 998.52905652976, 'lane': {'060f53b1-b922-43f3-9bba-552d0f055daa': [197.365585299043, 197.365585299043], '6b5dcb78-23aa-47cd-8dd0-00ba8e550991': [199.810142356299, 199.810142356299], '3983b6c5-f7dd-4d40-9849-8c593ce87566': [199.283606724291, 199.283606724291], '9faaf913-59c0-4ecf-b5f6-c9207d88a721': [262.61810209454, 262.61810209454], '882296e1-5d30-4451-b44b-f66093e0a365': [66.536453226413, 66.536453226413], 'fe2a264d-f60a-411d-8646-e9073eb0cec2': [72.9151668291741, 72.9151668291741]}})\n",
"('e913de05-1134-3ef2-e710-5b4947a51da7', '548b406e-e134-627e-aaf2-f0a0fdfe3e15', {'real_distance': 76.1590867329917, 'locked_distance': 76.1590867329917, 'lane': {'5f10aada-c880-4b11-8f12-f23a9a228e77': [76.1590867329917, 76.1590867329917]}})\n",
"('ec91d7cd-7134-3ef3-11a7-3911025a05f0', '21c30b97-b134-627d-a816-14340c5cd7e3', {'real_distance': 992.2232320151439, 'locked_distance': 992.2232320151439, 'lane': {'d82f2017-8cce-4849-82e7-5d068e9d1492': [120.827022194615, 120.827022194615], '0ef992c6-b960-469b-8e48-917c34315e95': [198.880690398198, 198.880690398198], 'b4fb0fea-376c-4783-8576-71f9193c87aa': [199.980841600332, 199.980841600332], '5aa14cdd-99fb-4dc7-a33f-9faac9396c47': [199.731067939263, 199.731067939263], '4b9d3bc8-2865-40d8-82a7-e91f106a4015': [134.82738253192, 134.82738253192], 'ea645c34-3a71-4098-8ac4-6602b681b86e': [137.976227350816, 137.976227350816]}})\n",
"('21c30b97-b134-627d-a816-14340c5cd7e3', '2f2d10d0-0134-3ef1-fa54-f3133db99ae7', {'real_distance': 100.466166431139, 'locked_distance': 100.466166431139, 'lane': {'f515306f-5074-4329-842a-0e7cf3136e33': [100.466166431139, 100.466166431139]}})\n",
"('b766bdd8-1134-8b1d-ac72-176e4ff75207', 'a5992398-1134-8b1d-acea-65965e2590e9', {'real_distance': 395.568451720973, 'locked_distance': 395.568451720973, 'lane': {'e91ef643-7134-8b1d-acc7-93948fc16203': [148.047327767466, 148.047327767466], 'ab05888a-e134-8b1d-cc58-872201fe24fd': [247.521123953507, 247.521123953507]}})\n",
"('9ac1e7cc-5134-8b1d-ad30-cbe81ecbd4d2', 'f1200636-f134-8b1d-acf6-48f37747266d', {'real_distance': 223.631430896756, 'locked_distance': 223.631430896756, 'lane': {'123b1f98-9134-8b1d-cca4-12b7506591a3': [223.631430896756, 223.631430896756]}})\n",
"('a5992398-1134-8b1d-acea-65965e2590e9', 'f1200636-f134-8b1d-acf6-48f37747266d', {'real_distance': 249.324125427189, 'locked_distance': 249.324125427189, 'lane': {'f179ce3f-8134-8b1d-cc7c-d74258c8de68': [249.324125427189, 249.324125427189]}})\n"
],
"output_type": "stream"
}
],
"source": [
"for item in unload_G.edges.data():\n",
" print(item)\n",
" id = str(uuid.uuid4())\n",
" startNodeId = item[0]\n",
" endNodeId = item[1]\n",
" distance = item[2]['real_distance']\n",
" lanes = item[2]['lane']\n",
" \n",
" lanes_sql = str(\" \".join(lanes))\n",
"\n",
" sql = \"INSERT INTO GRAPH_EDGE VALUES ('%s', '%s', '%s', '%f', 2, '%s')\" % (id, startNodeId, endNodeId, distance, lanes_sql)\n",
" \n",
" cursor = c.execute(sql)\n",
" \n",
" conn.commit()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"卸载节点写入数据库"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"for item in unload_G.nodes.data():\n",
" nodeId = item[0]\n",
" if item[1] != {} and item[1]['name'] != None:\n",
" name = item[1]['name']\n",
" else:\n",
" name = 'None'\n",
"\n",
" sql = \"INSERT INTO GRAPH_NODE VALUES ('%s', '%s')\" % (nodeId, name)\n",
" \n",
" cursor = c.execute(sql)\n",
" \n",
" conn.commit()\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"## 3. 拓扑图重构"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"conn = sqlite3.connect('test.db')\n",
"c = conn.cursor()"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"获取节点标签"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% \n"
}
},
"outputs": [
{
"name": "stdout",
"text": [
"('1edde59c-b134-3ef1-fc1b-2f5690eff02e', 'dump')\n",
"('d8c59e25-4134-3ef2-1182-d8ddd3a4ffd7', 'digging')\n",
"('390574ea-3134-6281-1277-375d88cc74cc', 'None')\n",
"('2e1b3039-e134-6281-127c-425a66a8b3ec', 'None')\n",
"('da82a489-5134-6281-127d-fa08107043e8', 'None')\n",
"('b290795e-8134-6281-129b-8717e1326fe0', 'None')\n",
"('c66f355d-c134-3ef3-cdff-3b6a05335c00', 'dump')\n",
"('84db153f-8134-3ef3-91e5-3b780dfd39a3', 'dump')\n",
"('3ebc0b68-8134-6281-1264-0d52dfc6308d', 'digging')\n",
"('5c15ecf3-6134-3ef1-ac23-bd1f1480ea7a', 'dump')\n",
"('81be6a9e-8134-3ef2-141e-4bb045b8d097', 'dump')\n",
"('763a5edd-c134-3ef2-1154-912159da8391', 'digging')\n",
"('84b1ccbd-8134-6281-129c-629b79da9319', 'None')\n",
"('74604c4b-a134-3ef2-1263-e99e323b4d0f', 'digging')\n",
"('71bb2875-1134-627f-140e-fb1d607711c4', 'None')\n",
"('92eb8c73-d134-627e-de55-3dfd274b5bf6', 'None')\n",
"('9b311d17-6134-3ef1-10bf-6918631c69e6', 'digging')\n",
"('39c0d01d-8134-3ef1-1140-b8d7698c1c16', 'digging')\n",
"('15332855-d134-3ef1-1364-6be98eb30b04', 'digging')\n",
"('92335f4a-2134-3ef1-103c-b83bc0c4aac6', 'digging')\n",
"('344a6d3d-7134-3ef2-ed00-cdfa2efb5d69', 'digging')\n",
"('7035254f-0134-6281-129d-c46ae9265ba0', 'None')\n",
"('35518449-0134-8b1d-ad46-b767d078c25e', 'dump')\n",
"('03ab6512-9134-8b1d-adbb-7cba14e8810c', 'digging')\n",
"('47ca51af-1134-8b1d-adb0-5b8187fdabf2', 'None')\n",
"('fd993b08-6134-63ad-fc29-72c597c1d5f2', 'None')\n",
"('9a08b6c1-9134-3ef2-11b9-679974d45727', 'digging')\n",
"('dc3c075c-a134-3ef1-fbca-97af66533db0', 'dump')\n",
"('daed5da4-7134-627d-a833-4df28d1b4531', 'None')\n",
"('a5da64fd-e134-6281-138e-0f685363ca20', 'None')\n",
"('d4c1ea4d-1134-3ef3-aeba-93407138c07a', 'dump')\n",
"('c3bf2f33-2134-627d-a17a-7e903a38aaf7', 'None')\n",
"('c573c724-e134-3ef3-a85e-dae14f7067b0', 'dump')\n",
"('5e86128e-7134-627d-a7e4-022cf2f86a3e', 'None')\n",
"('e913de05-1134-3ef2-e710-5b4947a51da7', 'dump')\n",
"('548b406e-e134-627e-aaf2-f0a0fdfe3e15', 'None')\n",
"('ec91d7cd-7134-3ef3-11a7-3911025a05f0', 'dump')\n",
"('21c30b97-b134-627d-a816-14340c5cd7e3', 'None')\n",
"('2f2d10d0-0134-3ef1-fa54-f3133db99ae7', 'dump')\n",
"('805018ad-0134-3ef2-109d-e66e28634b17', 'digging')\n",
"('a158be2d-3134-3ef2-128b-6ea0a711ddd4', 'digging')\n",
"('a56eb6b8-d134-3ef2-127e-24cb1d9efe8b', 'digging')\n",
"('a04cd66c-b134-627d-a176-196081acffc8', 'digging')\n",
"('4a80bcb7-8134-3ef1-1145-cbae9ab5cd9a', 'digging')\n",
"('1e692e26-0134-3ef1-1346-d4adb1f2cde4', 'digging')\n",
"('1f53a6c5-0134-3ef1-1043-e33fb6c4e19f', 'digging')\n",
"('55fe1809-f134-3ef2-f70f-cd6635509428', 'digging')\n",
"('b766bdd8-1134-8b1d-ac72-176e4ff75207', 'digging')\n",
"('9ac1e7cc-5134-8b1d-ad30-cbe81ecbd4d2', 'dump')\n",
"('a5992398-1134-8b1d-acea-65965e2590e9', 'None')\n",
"('f1200636-f134-8b1d-acf6-48f37747266d', 'None')\n",
"{'1edde59c-b134-3ef1-fc1b-2f5690eff02e': 'dump', 'd8c59e25-4134-3ef2-1182-d8ddd3a4ffd7': 'digging', '390574ea-3134-6281-1277-375d88cc74cc': 'None', '2e1b3039-e134-6281-127c-425a66a8b3ec': 'None', 'da82a489-5134-6281-127d-fa08107043e8': 'None', 'b290795e-8134-6281-129b-8717e1326fe0': 'None', 'c66f355d-c134-3ef3-cdff-3b6a05335c00': 'dump', '84db153f-8134-3ef3-91e5-3b780dfd39a3': 'dump', '3ebc0b68-8134-6281-1264-0d52dfc6308d': 'digging', '5c15ecf3-6134-3ef1-ac23-bd1f1480ea7a': 'dump', '81be6a9e-8134-3ef2-141e-4bb045b8d097': 'dump', '763a5edd-c134-3ef2-1154-912159da8391': 'digging', '84b1ccbd-8134-6281-129c-629b79da9319': 'None', '74604c4b-a134-3ef2-1263-e99e323b4d0f': 'digging', '71bb2875-1134-627f-140e-fb1d607711c4': 'None', '92eb8c73-d134-627e-de55-3dfd274b5bf6': 'None', '9b311d17-6134-3ef1-10bf-6918631c69e6': 'digging', '39c0d01d-8134-3ef1-1140-b8d7698c1c16': 'digging', '15332855-d134-3ef1-1364-6be98eb30b04': 'digging', '92335f4a-2134-3ef1-103c-b83bc0c4aac6': 'digging', '344a6d3d-7134-3ef2-ed00-cdfa2efb5d69': 'digging', '7035254f-0134-6281-129d-c46ae9265ba0': 'None', '35518449-0134-8b1d-ad46-b767d078c25e': 'dump', '03ab6512-9134-8b1d-adbb-7cba14e8810c': 'digging', '47ca51af-1134-8b1d-adb0-5b8187fdabf2': 'None', 'fd993b08-6134-63ad-fc29-72c597c1d5f2': 'None', '9a08b6c1-9134-3ef2-11b9-679974d45727': 'digging', 'dc3c075c-a134-3ef1-fbca-97af66533db0': 'dump', 'daed5da4-7134-627d-a833-4df28d1b4531': 'None', 'a5da64fd-e134-6281-138e-0f685363ca20': 'None', 'd4c1ea4d-1134-3ef3-aeba-93407138c07a': 'dump', 'c3bf2f33-2134-627d-a17a-7e903a38aaf7': 'None', 'c573c724-e134-3ef3-a85e-dae14f7067b0': 'dump', '5e86128e-7134-627d-a7e4-022cf2f86a3e': 'None', 'e913de05-1134-3ef2-e710-5b4947a51da7': 'dump', '548b406e-e134-627e-aaf2-f0a0fdfe3e15': 'None', 'ec91d7cd-7134-3ef3-11a7-3911025a05f0': 'dump', '21c30b97-b134-627d-a816-14340c5cd7e3': 'None', '2f2d10d0-0134-3ef1-fa54-f3133db99ae7': 'dump', '805018ad-0134-3ef2-109d-e66e28634b17': 'digging', 'a158be2d-3134-3ef2-128b-6ea0a711ddd4': 'digging', 'a56eb6b8-d134-3ef2-127e-24cb1d9efe8b': 'digging', 'a04cd66c-b134-627d-a176-196081acffc8': 'digging', '4a80bcb7-8134-3ef1-1145-cbae9ab5cd9a': 'digging', '1e692e26-0134-3ef1-1346-d4adb1f2cde4': 'digging', '1f53a6c5-0134-3ef1-1043-e33fb6c4e19f': 'digging', '55fe1809-f134-3ef2-f70f-cd6635509428': 'digging', 'b766bdd8-1134-8b1d-ac72-176e4ff75207': 'digging', '9ac1e7cc-5134-8b1d-ad30-cbe81ecbd4d2': 'dump', 'a5992398-1134-8b1d-acea-65965e2590e9': 'None', 'f1200636-f134-8b1d-acf6-48f37747266d': 'None'}\n"
],
"output_type": "stream"
}
],
"source": [
"cursor = c.execute(\"SELECT * FROM GRAPH_NODE\")\n",
"\n",
"node_label = {}\n",
"for row in cursor:\n",
" node_label[row[0]] = row[1]\n",
"\n",
"print(node_label)\n",
"\n",
"node_type = {}\n",
"for row in cursor:\n",
" node_type[row[0]] = row[2]\n",
"\n",
"print(node_type)"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"数据处理与图重构"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"name": "stdout",
"text": [
"5f9e5ce7-9ddb-4c3a-a323-813b07bfcd2d\n",
"e2567819-9c4f-492f-a223-46e3aabbe07f\n",
"28de5e56-7a1e-4ca6-9381-eba01ec61205\n",
"70f2464b-6134-8abb-1436-82028896b4c0\n",
"70483a5e-31d2-49da-afa5-e1e826cef775\n",
"3ddf5083-39d5-48b3-ad80-d4e726609e87\n",
"1683e675-7000-4bc7-9fb6-f70186bdb5a3\n",
"edb4f9c0-80ab-4543-b984-4f9594302fb0\n",
"e510963c-5d07-4a27-af30-5ab3843ccb5d\n",
"8ab1d94d-92cf-4601-98ad-3ec6568b11b3\n",
"d16fa18c-60d0-442f-b857-3bf0643b7287\n",
"0a48900a-e411-4e9b-868a-5781060a2ca6\n",
"d76151e2-866c-407e-869a-beeee27982ad\n",
"77d56d16-61ff-4560-96aa-7516ea5d1aa8\n",
"1683e675-7000-4bc7-9fb6-f70186bdb5a3\n",
"edb4f9c0-80ab-4543-b984-4f9594302fb0\n",
"e510963c-5d07-4a27-af30-5ab3843ccb5d\n",
"a84e1492-1bed-4455-a958-41ad747358e2\n",
"42aeb07a-7e12-43f1-889a-73b95228e250\n",
"016dc588-2132-4c85-ac44-a3ee7882770f\n",
"2e5d1f54-a6c9-4c93-89d1-2d9b69fd1e4f\n",
"f31479d3-6134-627f-1419-2e43acb951d7\n",
"ee287d4f-1134-627f-141b-79817eefd272\n",
"0f5a7be6-fca3-4b3e-ae29-fd571feebc24\n",
"66feccd9-a1b1-41ef-9de1-a3e414a1a5f1\n",
"80f4d9ea-1397-4caf-8d57-a8b28d810f58\n",
"c016c06f-3134-63ad-fc99-842f556c6ed3\n",
"2fb89031-2efb-408c-867a-35b2b43ffa32\n",
"bcb83312-9c81-488f-bc9c-02dac06da8c6\n",
"75ff9b3d-2417-486e-b3e9-692eab2a877c\n",
"34613390-9c60-445f-8ca6-1d1eaa30857d\n",
"802655bb-d380-4089-b2ea-5f8b9975f439\n",
"046b81f9-dee6-4285-851e-1995eda8d3b2\n",
"a7940350-7014-4260-b881-4fd4186f6fb3\n",
"00ecad9a-9166-4bf5-a771-73849e5e3ac7\n",
"cae77fcb-df17-496f-8962-9b10c97da7d6\n",
"0fcbcea2-2541-4478-8ac8-d2721c1424a2\n",
"ef99b721-ac3f-4389-b257-fa54f522fa80\n",
"7e120229-b426-461b-91a4-05e01fb37ed8\n",
"34613390-9c60-445f-8ca6-1d1eaa30857d\n",
"50ab9d25-f5db-4b2e-ac10-a0c29aa05dbb\n",
"ef99b721-ac3f-4389-b257-fa54f522fa80\n",
"7e120229-b426-461b-91a4-05e01fb37ed8\n",
"34613390-9c60-445f-8ca6-1d1eaa30857d\n",
"07ca6191-4782-4b1e-9319-a253da7519e6\n",
"d22a65e5-437e-4c2a-9f7d-062a5a263f00\n",
"da701135-5c70-44b2-869d-687c25af1427\n",
"c5a85316-798e-4a5c-9492-bba4debc23d7\n",
"59f95664-7ddb-45ec-b9e2-c5284ffbfa90\n",
"de94ea7a-08e4-4a01-967b-a1b658b4c378\n",
"6b417083-83b0-4eec-a8bd-2f85f96cb029\n",
"a6b6bedc-fd55-41b8-9903-6b6898dd6a53\n",
"152d088b-0c98-40f4-af90-30264970678d\n",
"bd07bede-678f-4502-887e-e7c9963b7f12\n",
"79152862-8b7c-4455-83d0-f56ec822825d\n",
"bb3ab68a-a556-4604-93b8-d3fa7d0c417d\n",
"39ae4f6b-fda7-409f-8beb-9991ac48fd8e\n",
"1ac6ad2c-5427-464c-86af-f08e0f966426\n",
"bc0e81f9-a5c6-4817-acde-91c7c9ef7745\n",
"3564b3f9-e8bb-4398-bb49-e84e68eddc3b\n",
"b5fcd3e6-00ff-476c-95e2-4da7d758adbd\n",
"ab109c98-37d8-478f-8487-bca7cc6543b6\n",
"f735f136-5269-403b-9860-b7fba9c1ab71\n",
"fbe15232-00fa-4fd3-9db0-ac79115b7cee\n",
"7fd075c6-70f1-4e8b-936b-1c4b1dbac5ea\n",
"ebb83244-f134-8b21-db96-c77f7b8d076d\n",
"7f6541aa-0134-8b21-1065-426cf3693172\n",
"cb21693d-2807-4951-901b-bd6d9cbaacd6\n",
"4c6ffc6e-9134-8b1d-ccc9-7b6d3b6e962d\n",
"d7babd90-6134-8b1d-ccf0-72ee3408409c\n",
"cc20f7dd-9134-8b1d-cd1a-835dc76e984b\n",
"3d2ae0c0-1134-8b1d-cd3e-c1faa96b8333\n",
"4dc2fffe-ffff-42dd-8a2e-7ec04a5de1da\n",
"4211e05f-0d77-4642-b90a-f1832a48d977\n",
"6604ac8f-6175-48d2-8d68-7b44004efe23\n",
"21c9ff90-e8c1-4a3d-a3d1-6a123c126e6d\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"e921be37-9fc5-4873-8262-2ec4d9f30daa\n",
"d63446cd-04a6-41f6-b374-25c1820cb351\n",
"f7808c9f-57f5-4b78-8012-e4a6b0f580fe\n",
"04a45173-16ce-45db-bebf-cc817222aeda\n",
"930acba3-ac72-4aa4-8c36-569ab81da7d2\n",
"7de40e4b-92ad-42a5-bcd6-cd9e0e36509d\n",
"851afe4f-6b32-4f6b-a60c-952e8f4f8837\n",
"b0687a4b-4a8e-4c7c-b073-7dd57104e251\n",
"727149c9-2f56-4b13-987a-c4468a50decb\n",
"55e2f42f-2dee-40c0-9749-0595b904aa2d\n",
"ff20e913-7082-46e3-8850-6a7e26161b81\n",
"bbc8aafd-d0e7-4a22-bd0f-f181173862b4\n",
"f8b88453-1869-4408-aa5f-8eb11e7b1ea7\n",
"c3fa9b94-a27e-4b23-87d4-bfcd489a4807\n",
"82a71193-d140-4dbc-8ae8-6d75837f9e88\n",
"1def4b73-a6d9-4d19-ae97-912e00132513\n",
"300258e9-00c2-4025-8b6a-20c832845f41\n",
"b3bd86c8-d0a1-4abb-a42a-6ca3a4eb940a\n",
"8d0a7d87-3940-4374-b4ad-429dca4de29b\n",
"49713fd0-61a6-4bf6-951e-9ac103782154\n",
"e20580fe-ed64-4863-bf13-0c0ede8b3295\n",
"fd926630-5d39-41aa-9327-28c7786ff6ee\n",
"71841169-8a8c-467c-b14d-6f3781fdb1de\n",
"44c8f55e-b63c-4e3f-8c10-f087b657fb08\n",
"bba3c27e-58cc-465e-ad4b-a9c5b6e8dbba\n",
"dee73a87-fa6a-40be-9e77-f6f3a2380e67\n",
"4211e05f-0d77-4642-b90a-f1832a48d977\n",
"6604ac8f-6175-48d2-8d68-7b44004efe23\n",
"21c9ff90-e8c1-4a3d-a3d1-6a123c126e6d\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"3530c7e6-1fba-4aae-94db-7713685c3102\n",
"ed95a92c-4c71-4e91-9aaf-9d85df33e92d\n",
"f5fbac37-5d09-4a2d-aab2-bda9a3a3823a\n",
"ecff2467-072d-4701-bdd2-c6eb9f145a27\n",
"218487ec-f427-4757-b739-2f1881b81099\n",
"55f277c0-6e08-4f63-a5bc-6323b5f14b37\n",
"9af76124-02b6-40c8-8475-ce23ce981d47\n",
"e9ba2c12-3134-627e-dd08-9e2faf862787\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"c6f62624-47dd-4577-b53a-9411a54bcbe3\n",
"3ee9eaf4-1526-4960-8087-05e8e5973a5a\n",
"ed95a92c-4c71-4e91-9aaf-9d85df33e92d\n",
"f5fbac37-5d09-4a2d-aab2-bda9a3a3823a\n",
"ecff2467-072d-4701-bdd2-c6eb9f145a27\n",
"218487ec-f427-4757-b739-2f1881b81099\n",
"55f277c0-6e08-4f63-a5bc-6323b5f14b37\n",
"9af76124-02b6-40c8-8475-ce23ce981d47\n",
"e9ba2c12-3134-627e-dd08-9e2faf862787\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"8623c942-04d1-41a5-b54d-64f65b2bfc67\n",
"3a7492a5-e8a0-43b0-bf11-c3260a6366a9\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"e4b978cd-0364-4b2b-a7f6-68eaf6a5c033\n",
"a232fecf-0344-44a5-a0fa-7b34f63e10ef\n",
"0cc6b7af-3b50-47a3-af8e-801fbee786b8\n",
"71821930-af85-4193-9a65-66bbcc0c60ef\n",
"3be972a3-1134-627e-104f-e382f7895135\n",
"9af76124-02b6-40c8-8475-ce23ce981d47\n",
"e9ba2c12-3134-627e-dd08-9e2faf862787\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"e2d40684-316e-4e73-8c15-1ef7452b9cd3\n",
"f6ba0409-6081-4251-bd7a-f4ae55e3a34e\n",
"17772169-2a06-4863-97b1-55d7757c6de7\n",
"17c1ec39-c205-4f94-8b5e-ce0325401ac3\n",
"04cb0542-dfa6-4217-959e-2a69201e8558\n",
"38fae563-50bb-408d-8668-7c65969ce8df\n",
"8c9b4f3b-7854-4dc7-a0c4-43c2cfad048a\n",
"44c8f55e-b63c-4e3f-8c10-f087b657fb08\n",
"bba3c27e-58cc-465e-ad4b-a9c5b6e8dbba\n",
"dee73a87-fa6a-40be-9e77-f6f3a2380e67\n",
"4211e05f-0d77-4642-b90a-f1832a48d977\n",
"6604ac8f-6175-48d2-8d68-7b44004efe23\n",
"21c9ff90-e8c1-4a3d-a3d1-6a123c126e6d\n",
"c7f15612-2d5f-4ed2-92b8-255a7fc84554\n",
"f3fc3f0e-09ce-4add-ad90-2b21f22abdee\n",
"05bb6b0e-90f8-4029-8598-e2c17e028029\n",
"1521fc40-d594-478f-804f-5143e9d821f5\n",
"00bf5667-5899-4157-a13c-789cd0fbacb0\n",
"efbd912f-8bcc-42c6-b09b-8a339a8833c0\n",
"a280e8c9-28ca-4943-9a6d-ef756c6a4dcb\n",
"9e32261c-2746-4f78-9217-f0af3dec8886\n",
"a46e0cff-223f-4b34-ad0d-1c4fac074c95\n",
"1b6888ed-7112-479a-b4df-09447685c62d\n",
"882296e1-5d30-4451-b44b-f66093e0a365\n",
"fe2a264d-f60a-411d-8646-e9073eb0cec2\n",
"bb8b8aad-a765-410e-8750-9f0cec443e86\n",
"c13eee6e-48ed-451d-8a03-e0fd61bd1977\n",
"adc3c230-2738-43fa-ae29-9fde9606382c\n",
"882296e1-5d30-4451-b44b-f66093e0a365\n",
"fe2a264d-f60a-411d-8646-e9073eb0cec2\n",
"060f53b1-b922-43f3-9bba-552d0f055daa\n",
"6b5dcb78-23aa-47cd-8dd0-00ba8e550991\n",
"3983b6c5-f7dd-4d40-9849-8c593ce87566\n",
"9faaf913-59c0-4ecf-b5f6-c9207d88a721\n",
"882296e1-5d30-4451-b44b-f66093e0a365\n",
"fe2a264d-f60a-411d-8646-e9073eb0cec2\n",
"5f10aada-c880-4b11-8f12-f23a9a228e77\n",
"d82f2017-8cce-4849-82e7-5d068e9d1492\n",
"0ef992c6-b960-469b-8e48-917c34315e95\n",
"b4fb0fea-376c-4783-8576-71f9193c87aa\n",
"5aa14cdd-99fb-4dc7-a33f-9faac9396c47\n",
"4b9d3bc8-2865-40d8-82a7-e91f106a4015\n",
"ea645c34-3a71-4098-8ac4-6602b681b86e\n",
"f515306f-5074-4329-842a-0e7cf3136e33\n",
"e91ef643-7134-8b1d-acc7-93948fc16203\n",
"ab05888a-e134-8b1d-cc58-872201fe24fd\n",
"123b1f98-9134-8b1d-cca4-12b7506591a3\n",
"f179ce3f-8134-8b1d-cc7c-d74258c8de68\n",
"数据操作成功\n"
],
"output_type": "stream"
}
],
"source": [
"load_G = nx.Graph()\n",
"\n",
"unload_G = nx.Graph()\n",
"\n",
"cursor = c.execute(\"SELECT * FROM GRAPH_EDGE\")\n",
"\n",
"for row in cursor:\n",
" # print(\"id = \", row[0])\n",
" # print(\"startNodeId = \", row[1])\n",
" # print(\"endNodeId = \", row[2])\n",
" # print(\"distance= \", row[3])\n",
" # print(\"dir= \", row[4])\n",
" # print(row[1], row[2], row[3])\n",
" \n",
" # 处理边包含路段\n",
" lanes = row[5].split(\" \")\n",
" \n",
" lane_info = {}\n",
" \n",
" for item in lanes:\n",
" try:\n",
" print(item)\n",
" distance = session_postgre.query(Lane).filter_by(Id=item).first().Length\n",
" lane_info[item] = list([distance, distance])\n",
" except Exception as es:\n",
" print(es)\n",
" \n",
" # 重构卸载路径拓扑图\n",
" if row[4] == 1:\n",
" load_G.add_node(row[1], name=node_label[row[1]])\n",
" load_G.add_node(row[2], name=node_label[row[2]])\n",
" load_G.add_edge(str(row[1]), str(row[2]), real_distance=row[3], lane=lane_info)\n",
" # 重构装载路径拓扑图\n",
" else:\n",
" unload_G.add_node(row[1], name=node_label[row[1]])\n",
" unload_G.add_node(row[2], name=node_label[row[2]])\n",
" unload_G.add_edge(str(row[1]), str(row[2]), real_distance=row[3], lane=lane_info)\n",
"print (\"数据操作成功\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%% md\n"
}
},
"source": [
"处理节点标签"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mKeyError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp\\ipykernel_39624\\4087052788.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 8\u001b[0m \u001b[0mnode_label_load\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mnode\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m \u001b[0mnode_label_load\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mnode\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnode_label\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mnode\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'type'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 11\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mnode_label_load\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mnode\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mKeyError\u001b[0m: 'type'"
],
"ename": "KeyError",
"evalue": "'type'",
"output_type": "error"
}
],
"source": [
"node_label_load = {}\n",
"\n",
"node_label_unload = {}\n",
"\n",
"for node in load_G.nodes:\n",
" if node in node_label:\n",
" if node_label[node] == \"None\":\n",
" node_label_load[node] = ''\n",
" else:\n",
" node_label_load[node] = node_label[node]\n",
" else:\n",
" node_label_load[node] = ''\n",
"\n",
"for node in unload_G.nodes:\n",
" if node in node_label:\n",
" if node_label[node] == \"None\":\n",
" node_label_unload[node] = ''\n",
" else:\n",
" node_label_unload[node] = node_label[node]\n",
" else:\n",
" node_label_unload[node] = ''"
]
},
{
"cell_type": "markdown",
"metadata": {
"pycharm": {
"name": "#%% md\n"
}
},
"source": [
"重构拓扑图可视化"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"data": {
"text/plain": "<Figure size 432x288 with 1 Axes>",
"image/png": "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\n"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": "<Figure size 432x288 with 1 Axes>",
"image/png": "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\n"
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pos1 = nx.planar_layout(load_G)\n",
"# nx.draw(load_G, pos1, with_labels=False, node_color='red', edge_color='blue', font_size=30, width=3, node_size=200,\n",
"# alpha=0.5)\n",
"\n",
"nx.draw_networkx(load_G, pos=pos1, labels=node_label_load, with_labels=True, node_color='red', \\\n",
" edge_color='blue', font_size=10, width=1.5, node_size=100, alpha=0.5)\n",
"plt.show()\n",
"\n",
"pos2 = nx.planar_layout(unload_G)\n",
"# pos2 = nx.shell_layout(unload_G)\n",
"# nx.draw(load_G, pos1, with_labels=False, node_color='red', edge_color='blue', font_size=30, width=3, node_size=200,\n",
"# alpha=0.5)\n",
"\n",
"nx.draw_networkx(unload_G, pos=pos2, labels=node_label_unload, with_labels=True, node_color='red', \\\n",
" edge_color='blue', font_size=15, width=3, node_size=200, alpha=0.5)\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"pycharm": {
"is_executing": false,
"name": "#%%\n"
}
},
"outputs": [
{
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m~\\AppData\\Local\\Temp\\ipykernel_11640\\3855894054.py\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;31m# topo.load_G = load_G\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;31m# topo.unload_G = unload_G\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtopo\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_load_target_node_real\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"c016c06f-3134-63ad-fc99-842f556c6ed3\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m\"1010cbfe-b134-3ef1-91bb-d746241c975a\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 6\u001b[0m \u001b[1;33m{\u001b[0m\u001b[1;34m'f1d5f017-5134-65a0-f657-89eed06eacc1'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1741.3137956186365\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'b621213e-3134-3ef1-9199-07822602b6c9'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1039.5570241419628\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'07c83253-9134-3ef1-9255-6634f8b46754'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1292.5391766185112\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'97ec7f40-4134-3ef1-9232-9a28f2b967b1'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1426.4143606784255\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'aad657a0-c134-64d7-fb2e-6bf6af5c2491'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m329.7992270761207\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'32077cb1-e134-3ef1-9171-a9792efadd4c'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m2001.3170597156063\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'505ae86e-e134-3ef1-9209-e3ee0ba2db7a'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m1194.3315966772175\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'ef89f721-5134-3ef1-91e2-95b4e5004675'\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;36m2577.4462426937125\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m}\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32mE:\\Pycharm Projects\\Waytous\\integrated-scheduling-v4.0\\integrated-scheduling-v3\\redispatch\\topo_graph.py\u001b[0m in \u001b[0;36mget_load_target_node_real\u001b[1;34m(self, truck_location_lane, pre_target)\u001b[0m\n\u001b[0;32m 397\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 398\u001b[0m \u001b[1;31m# source_node = self.get_load_edge_node(truck_location_lane)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 399\u001b[1;33m \u001b[0msource_node\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend_node\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_load_edge_node\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtruck_location_lane\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 400\u001b[0m \u001b[0mdistance_source_node\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdistance_end_node\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrelative_distance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtruck_location_lane\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mgraph_type\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 401\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mTypeError\u001b[0m: cannot unpack non-iterable NoneType object"
],
"ename": "TypeError",
"evalue": "cannot unpack non-iterable NoneType object",
"output_type": "error"
}
],
"source": [
"# topo = Topo()\n",
"# topo.load_G = load_G\n",
"# topo.unload_G = unload_G\n",
"print(topo.get_load_target_node_real(\"c016c06f-3134-63ad-fc99-842f556c6ed3\", \"1010cbfe-b134-3ef1-91bb-d746241c975a\"))\n",
"\n",
"{'f1d5f017-5134-65a0-f657-89eed06eacc1': [1741.3137956186365, 0], 'b621213e-3134-3ef1-9199-07822602b6c9': [1039.5570241419628, 0], '07c83253-9134-3ef1-9255-6634f8b46754': [1292.5391766185112, 0], '97ec7f40-4134-3ef1-9232-9a28f2b967b1': [1426.4143606784255, 0], 'aad657a0-c134-64d7-fb2e-6bf6af5c2491': [329.7992270761207, 0], '32077cb1-e134-3ef1-9171-a9792efadd4c': [2001.3170597156063, 0], '505ae86e-e134-3ef1-9209-e3ee0ba2db7a': [1194.3315966772175, 0], 'ef89f721-5134-3ef1-91e2-95b4e5004675': [2577.4462426937125, 0]}\n",
"{'f1d5f017-5134-65a0-f657-89eed06eacc1': [1741.3137956517917, 0], 'aad657a0-c134-64d7-fb2e-6bf6af5c2491': [329.7992266517915, 0], 'ef89f721-5134-3ef1-91e2-95b4e5004675': [2577.4462426517916, 0], 'b621213e-3134-3ef1-9199-07822602b6c9': [1039.5570246517914, 0], '07c83253-9134-3ef1-9255-6634f8b46754': [1292.5391766517914, 0], '505ae86e-e134-3ef1-9209-e3ee0ba2db7a': [1194.3315966517916, 0], '97ec7f40-4134-3ef1-9232-9a28f2b967b1': [1426.4143606517914, 0], '32077cb1-e134-3ef1-9171-a9792efadd4c': [2001.3170596517916, 0]}"
]
},
{
"cell_type": "code",
"execution_count": 17,
"outputs": [
{
"data": {
"text/plain": "NodeDataView({'1edde59c-b134-3ef1-fc1b-2f5690eff02e': {'name': 'dump'}, '390574ea-3134-6281-1277-375d88cc74cc': {'name': 'None'}, 'd8c59e25-4134-3ef2-1182-d8ddd3a4ffd7': {'name': 'digging'}, 'b290795e-8134-6281-129b-8717e1326fe0': {'name': 'None'}, '2e1b3039-e134-6281-127c-425a66a8b3ec': {'name': 'None'}, 'c66f355d-c134-3ef3-cdff-3b6a05335c00': {'name': 'dump'}, '3ebc0b68-8134-6281-1264-0d52dfc6308d': {'name': 'digging'}, 'da82a489-5134-6281-127d-fa08107043e8': {'name': 'None'}, '71bb2875-1134-627f-140e-fb1d607711c4': {'name': 'None'}, '39c0d01d-8134-3ef1-1140-b8d7698c1c16': {'name': 'digging'}, 'fd993b08-6134-63ad-fc29-72c597c1d5f2': {'name': 'None'}, '84b1ccbd-8134-6281-129c-629b79da9319': {'name': 'None'}, '84db153f-8134-3ef3-91e5-3b780dfd39a3': {'name': 'dump'}, '5c15ecf3-6134-3ef1-ac23-bd1f1480ea7a': {'name': 'dump'}, '81be6a9e-8134-3ef2-141e-4bb045b8d097': {'name': 'dump'}, '92335f4a-2134-3ef1-103c-b83bc0c4aac6': {'name': 'digging'}, '763a5edd-c134-3ef2-1154-912159da8391': {'name': 'digging'}, '7035254f-0134-6281-129d-c46ae9265ba0': {'name': 'None'}, '74604c4b-a134-3ef2-1263-e99e323b4d0f': {'name': 'digging'}, '92eb8c73-d134-627e-de55-3dfd274b5bf6': {'name': 'None'}, '15332855-d134-3ef1-1364-6be98eb30b04': {'name': 'digging'}, '9b311d17-6134-3ef1-10bf-6918631c69e6': {'name': 'digging'}, '344a6d3d-7134-3ef2-ed00-cdfa2efb5d69': {'name': 'digging'}, '35518449-0134-8b1d-ad46-b767d078c25e': {'name': 'dump'}, '47ca51af-1134-8b1d-adb0-5b8187fdabf2': {'name': 'None'}, '03ab6512-9134-8b1d-adbb-7cba14e8810c': {'name': 'digging'}})"
},
"metadata": {},
"output_type": "execute_result",
"execution_count": 17
}
],
"source": [
"load_G.nodes.data()"
],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n",
"is_executing": false
}
}
}
],
"metadata": {
"kernelspec": {
"name": "pycharm-acbff253",
"language": "python",
"display_name": "PyCharm (integrated-scheduling-v3)"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.10"
},
"pycharm": {
"stem_cell": {
"cell_type": "raw",
"source": [],
"metadata": {
"collapsed": false
}
}
},
"toc": {
"base_numbering": 1,
"nav_menu": {},
"number_sections": true,
"sideBar": true,
"skip_h1_title": false,
"title_cell": "Table of Contents",
"title_sidebar": "Contents",
"toc_cell": false,
"toc_position": {},
"toc_section_display": true,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 1
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment