Commit
•
d75dabd
1
Parent(s):
c399fb5
INI: deploy app's first version
Browse files- app.py +241 -0
- config.py +6 -0
- data/circuit.zip +0 -0
- data/paris_quadratic_edges.geojson +0 -0
- network.py +41 -0
- requirements.txt +334 -0
- utils.py +47 -0
app.py
ADDED
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from concrete import fhe
|
2 |
+
import folium
|
3 |
+
import geopandas
|
4 |
+
from shapely.geometry import Point
|
5 |
+
import streamlit as st
|
6 |
+
from streamlit_folium import st_folium
|
7 |
+
|
8 |
+
import config
|
9 |
+
from network import get_frames
|
10 |
+
from utils import generate_path, set_up_server, set_up_client, display_encrypted
|
11 |
+
|
12 |
+
|
13 |
+
st.set_page_config(layout="wide")
|
14 |
+
ways = geopandas.read_file(config.roads_filepath)
|
15 |
+
nodes, _, rel = get_frames(ways)
|
16 |
+
|
17 |
+
server = set_up_server()
|
18 |
+
client = set_up_client(server.client_specs.serialize())
|
19 |
+
|
20 |
+
m = nodes.explore(
|
21 |
+
color="red",
|
22 |
+
marker_kwds=dict(radius=5, fill=True, name='node_id'),
|
23 |
+
tooltip="node_id",
|
24 |
+
tooltip_kwds=dict(labels=False),
|
25 |
+
zoom_control=False,
|
26 |
+
)
|
27 |
+
|
28 |
+
|
29 |
+
c1, c2, c3 = st.columns([1, 3, 1])
|
30 |
+
|
31 |
+
with c1:
|
32 |
+
st.write("**Client-side**")
|
33 |
+
|
34 |
+
with c3:
|
35 |
+
st.write("**Server-side**")
|
36 |
+
|
37 |
+
|
38 |
+
if 'evaluation_key' not in st.session_state:
|
39 |
+
with c1:
|
40 |
+
if st.button('Generate keys'):
|
41 |
+
with st.spinner('Generating keys'):
|
42 |
+
client.keys.load_if_exists_generate_and_save_otherwise(config.keys_filepath)
|
43 |
+
# client.keys.save(config.keys_filepath)
|
44 |
+
st.session_state['evaluation_key'] = client.evaluation_keys.serialize()
|
45 |
+
st.rerun()
|
46 |
+
else:
|
47 |
+
with c1:
|
48 |
+
st.write("Encryption/decryption keys and evaluation keys are generated.")
|
49 |
+
st.write("The evaluation key is sent to the server.")
|
50 |
+
with c3:
|
51 |
+
st.write(f"Evaluation key: {display_encrypted(st.session_state['evaluation_key'])}")
|
52 |
+
|
53 |
+
|
54 |
+
if 'origin' not in st.session_state :
|
55 |
+
with c1:
|
56 |
+
st.write("Select the origin on the map")
|
57 |
+
|
58 |
+
with c2:
|
59 |
+
st_data_origin = st_folium(m, width=725, key="origin", returned_objects=["last_object_clicked"])
|
60 |
+
|
61 |
+
with c3:
|
62 |
+
st.write("")
|
63 |
+
|
64 |
+
if st_data_origin["last_object_clicked"]:
|
65 |
+
origin = Point(st_data_origin["last_object_clicked"]["lng"], st_data_origin["last_object_clicked"]["lat"])
|
66 |
+
origin_node = nodes[nodes['geometry'] == origin]['node_id'].values[0]
|
67 |
+
st.session_state['origin'] = origin
|
68 |
+
st.session_state['origin_node'] = origin_node
|
69 |
+
st.write(f"Selected node is node number: {origin_node}")
|
70 |
+
st.rerun()
|
71 |
+
|
72 |
+
if 'origin' in st.session_state and 'destination' not in st.session_state:
|
73 |
+
origin = st.session_state['origin']
|
74 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
75 |
+
origin_node = st.session_state['origin_node']
|
76 |
+
with c1:
|
77 |
+
st.write(f"Selected origin is node number: {origin_node}")
|
78 |
+
st.write("Select the destination on the map")
|
79 |
+
with c2:
|
80 |
+
st_data_destination = st_folium(m, width=725, key="destination", returned_objects=["last_object_clicked"])
|
81 |
+
with c3:
|
82 |
+
st.write("")
|
83 |
+
st.write("")
|
84 |
+
|
85 |
+
if st_data_destination["last_object_clicked"]:
|
86 |
+
destination = Point(st_data_destination["last_object_clicked"]["lng"], st_data_destination["last_object_clicked"]["lat"])
|
87 |
+
st.session_state['destination'] = destination
|
88 |
+
st.session_state['destination_node'] = nodes[nodes['geometry'] == destination]['node_id'].values[0]
|
89 |
+
st.write(st_data_destination["last_object_clicked"])
|
90 |
+
st.rerun()
|
91 |
+
|
92 |
+
if 'origin' in st.session_state and 'destination' in st.session_state and 'encrypted_origin' not in st.session_state :
|
93 |
+
origin = st.session_state['origin']
|
94 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
95 |
+
destination = st.session_state['destination']
|
96 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
97 |
+
# breakpoint()
|
98 |
+
origin_node = st.session_state['origin_node']
|
99 |
+
destination_node = st.session_state['destination_node']
|
100 |
+
with c1:
|
101 |
+
st.write(f"Selected origin is node number: {origin_node}")
|
102 |
+
st.write(f"Selected destination is node number: {destination_node}")
|
103 |
+
if st.button('Encrypt and send inputs'):
|
104 |
+
with st.spinner('Encrypting inputs'):
|
105 |
+
client.keys.load(config.keys_filepath)
|
106 |
+
origin, destination = client.encrypt(origin_node, destination_node)
|
107 |
+
st.session_state['encrypted_origin'] = origin.serialize()
|
108 |
+
st.session_state['encrypted_destination'] = destination.serialize()
|
109 |
+
st.rerun()
|
110 |
+
with c2:
|
111 |
+
st_data_final = st_folium(m, width=725, key="destination", returned_objects=[])
|
112 |
+
with c3:
|
113 |
+
st.write("")
|
114 |
+
st.write("")
|
115 |
+
|
116 |
+
if 'encrypted_origin' in st.session_state and 'encrypted_shortest_path' not in st.session_state:
|
117 |
+
origin = st.session_state['origin']
|
118 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
119 |
+
destination = st.session_state['destination']
|
120 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
121 |
+
|
122 |
+
origin_node = st.session_state['origin_node']
|
123 |
+
destination_node = st.session_state['destination_node']
|
124 |
+
with c1:
|
125 |
+
st.write(f"Selected origin is node number: {origin_node}")
|
126 |
+
st.write(f"Selected destination is node number: {destination_node}")
|
127 |
+
with c2:
|
128 |
+
origin = st.session_state['origin']
|
129 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
130 |
+
destination = st.session_state['destination']
|
131 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
132 |
+
st_data_final = st_folium(m, width=725, key="destination", returned_objects=[])
|
133 |
+
with c3:
|
134 |
+
st.write("")
|
135 |
+
st.write("")
|
136 |
+
st.write(f"Received origin: {display_encrypted(st.session_state['encrypted_origin'])}")
|
137 |
+
st.write(f"Received destination: {display_encrypted(st.session_state['encrypted_destination'])}")
|
138 |
+
if st.button('Compute shortest path'):
|
139 |
+
with st.spinner('Computing'):
|
140 |
+
deserialized_origin = fhe.Value.deserialize(st.session_state['encrypted_origin'])
|
141 |
+
deserialized_destination = fhe.Value.deserialize(st.session_state['encrypted_destination'])
|
142 |
+
deserialized_evaluation_keys = fhe.EvaluationKeys.deserialize(st.session_state['evaluation_key'])
|
143 |
+
client.keys.load_if_exists_generate_and_save_otherwise(config.keys_filepath)
|
144 |
+
origin = st.session_state['origin_node']
|
145 |
+
destination = st.session_state['destination_node']
|
146 |
+
path = [origin, ]
|
147 |
+
encrypted_path = [st.session_state['encrypted_origin'], ]
|
148 |
+
o, d = deserialized_origin, deserialized_destination
|
149 |
+
for _ in range(nodes.shape[0] - 1):
|
150 |
+
# Careful: breaking early could lead to information leak
|
151 |
+
if origin == destination:
|
152 |
+
break
|
153 |
+
o = server.run(o, d, evaluation_keys=client.evaluation_keys)
|
154 |
+
origin = client.decrypt(o)
|
155 |
+
encrypted_path.append(o.serialize())
|
156 |
+
path.append(origin)
|
157 |
+
|
158 |
+
st.session_state['encrypted_shortest_path'] = encrypted_path
|
159 |
+
st.session_state['decrypted_shortest_path'] = path
|
160 |
+
st.rerun()
|
161 |
+
|
162 |
+
if 'encrypted_shortest_path' in st.session_state and 'decrypted_result' not in st.session_state :
|
163 |
+
origin = st.session_state['origin']
|
164 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
165 |
+
destination = st.session_state['destination']
|
166 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
167 |
+
|
168 |
+
origin_node = st.session_state['origin_node']
|
169 |
+
destination_node = st.session_state['destination_node']
|
170 |
+
with c1:
|
171 |
+
st.write(f"Selected origin is node number: {origin_node}")
|
172 |
+
st.write(f"Selected destination is node number: {destination_node}")
|
173 |
+
st.write("Received path is:")
|
174 |
+
st.write(f"{display_encrypted(st.session_state['encrypted_shortest_path'][0])}")
|
175 |
+
st.write("...")
|
176 |
+
st.write(f"{display_encrypted(st.session_state['encrypted_shortest_path'][-1])}")
|
177 |
+
|
178 |
+
if st.button('Decrypt and show shortest path'):
|
179 |
+
with st.spinner('Computing'):
|
180 |
+
client.keys.load_if_exists_generate_and_save_otherwise(config.keys_filepath)
|
181 |
+
path = []
|
182 |
+
for enc_value in st.session_state['encrypted_shortest_path']:
|
183 |
+
deserialized_result = fhe.Value.deserialize(enc_value)
|
184 |
+
path.append(client.decrypt(deserialized_result))
|
185 |
+
st.session_state['decrypted_result'] = path
|
186 |
+
st.rerun()
|
187 |
+
with c2:
|
188 |
+
|
189 |
+
origin = st.session_state['origin']
|
190 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
191 |
+
|
192 |
+
destination = st.session_state['destination']
|
193 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
194 |
+
st_data_final = st_folium(m, width=725, key="destination", returned_objects=[])
|
195 |
+
with c3:
|
196 |
+
st.write("")
|
197 |
+
st.write("")
|
198 |
+
st.write(f"Received origin: {display_encrypted(st.session_state['encrypted_origin'])}")
|
199 |
+
st.write(f"Received destination: {display_encrypted(st.session_state['encrypted_destination'])}")
|
200 |
+
# st.write(f"Next node is {display_encrypted(st.session_state['encrypted_shortest_path'])} and is sent to client")
|
201 |
+
if 'decrypted_result' in st.session_state :
|
202 |
+
origin = st.session_state['origin']
|
203 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
204 |
+
destination = st.session_state['destination']
|
205 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
206 |
+
|
207 |
+
origin_node = st.session_state['origin_node']
|
208 |
+
destination_node = st.session_state['destination_node']
|
209 |
+
with c1:
|
210 |
+
st.write(f"Selected origin is node number: {origin_node}")
|
211 |
+
st.write(f"Selected destination is node number: {destination_node}")
|
212 |
+
st.write("Received path is:")
|
213 |
+
st.write(f"{display_encrypted(st.session_state['encrypted_shortest_path'][0])}")
|
214 |
+
st.write("...")
|
215 |
+
st.write(f"{display_encrypted(st.session_state['encrypted_shortest_path'][-1])}")
|
216 |
+
st.write(f"Decrypted result is: {st.session_state['decrypted_result']}")
|
217 |
+
if st.button('Restart'):
|
218 |
+
for key in st.session_state.keys():
|
219 |
+
del st.session_state[key]
|
220 |
+
st.rerun()
|
221 |
+
with c2:
|
222 |
+
origin = st.session_state['origin']
|
223 |
+
folium.Marker([origin.y, origin.x], popup="Origin", tooltip="Origin").add_to(m)
|
224 |
+
destination = st.session_state['destination']
|
225 |
+
folium.Marker([destination.y, destination.x], popup="Destination", tooltip="Destination").add_to(m)
|
226 |
+
shortest_path_list = st.session_state['decrypted_result']
|
227 |
+
final_result = generate_path(shortest_path_list, rel)
|
228 |
+
final_result.explore(
|
229 |
+
m=m,
|
230 |
+
color="green",
|
231 |
+
style_kwds = {"weight":5},
|
232 |
+
tooltip="name",
|
233 |
+
popup=["name"],
|
234 |
+
name="Quadratic-Paris",
|
235 |
+
)
|
236 |
+
st_data_final = st_folium(m, width=725, key="destination", returned_objects=[])
|
237 |
+
with c3:
|
238 |
+
st.write("")
|
239 |
+
st.write("")
|
240 |
+
st.write(f"Received origin: {display_encrypted(st.session_state['encrypted_origin'])}")
|
241 |
+
st.write(f"Received destination: {display_encrypted(st.session_state['encrypted_destination'])}")
|
config.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pathlib import Path
|
2 |
+
|
3 |
+
data_path = Path(__file__).parent / "data"
|
4 |
+
roads_filepath = data_path / "paris_quadratic_edges.geojson"
|
5 |
+
circuit_filepath = data_path / "circuit.zip"
|
6 |
+
keys_filepath = data_path / "keys.zip"
|
data/circuit.zip
ADDED
Binary file (5.24 kB). View file
|
|
data/paris_quadratic_edges.geojson
ADDED
The diff for this file is too large to render.
See raw diff
|
|
network.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import geopandas
|
2 |
+
import networkx
|
3 |
+
import numpy
|
4 |
+
|
5 |
+
|
6 |
+
def get_frames(ways: geopandas.GeoDataFrame):
|
7 |
+
edges = ways.explode(index_parts=False)[["id", "name", "geometry"]]
|
8 |
+
edges.index.name = "way_id"
|
9 |
+
edges = edges.reset_index()
|
10 |
+
nodes = geopandas.GeoDataFrame({"geometry": edges.boundary.explode(index_parts=False).geometry.unique()})
|
11 |
+
nodes.index.name = "node_id"
|
12 |
+
nodes.reset_index(inplace=True)
|
13 |
+
rel = edges.sjoin(nodes).to_crs("epsg:2154")
|
14 |
+
return nodes, edges, rel
|
15 |
+
|
16 |
+
|
17 |
+
def get(ways: geopandas.GeoDataFrame) -> networkx.Graph:
|
18 |
+
nodes, edges, rel = get_frames(ways)
|
19 |
+
graph = networkx.Graph()
|
20 |
+
for node in rel['node_id'].unique():
|
21 |
+
graph.add_node(node, shape=nodes.loc[node, "geometry"])
|
22 |
+
for idx in rel['way_id'].unique():
|
23 |
+
node_id1, node_id2 = rel.loc[idx]['node_id']
|
24 |
+
way = edges.loc[idx]
|
25 |
+
way_length = rel.loc[idx]['geometry'].iloc[0].length
|
26 |
+
graph.add_edge(
|
27 |
+
node_id1, node_id2,
|
28 |
+
weight=way.geometry.length,
|
29 |
+
shape=way.geometry,
|
30 |
+
id_=idx,
|
31 |
+
)
|
32 |
+
return graph
|
33 |
+
|
34 |
+
|
35 |
+
def weighted_adjacency_matrix(graph: networkx.Graph) -> numpy.ndarray:
|
36 |
+
weights = numpy.full((graph.number_of_nodes(),)*2, numpy.inf)
|
37 |
+
numpy.fill_diagonal(weights, 0., wrap=False)
|
38 |
+
for i in graph:
|
39 |
+
for j in graph[i]:
|
40 |
+
weights[i, j] = graph[i][j]["weight"]
|
41 |
+
return weights
|
requirements.txt
ADDED
@@ -0,0 +1,334 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#
|
2 |
+
# This file is autogenerated by pip-compile with Python 3.10
|
3 |
+
# by the following command:
|
4 |
+
#
|
5 |
+
# pip-compile requirements.in
|
6 |
+
#
|
7 |
+
altair==5.1.1
|
8 |
+
# via streamlit
|
9 |
+
asttokens==2.4.0
|
10 |
+
# via stack-data
|
11 |
+
attrs==23.1.0
|
12 |
+
# via
|
13 |
+
# fiona
|
14 |
+
# jsonschema
|
15 |
+
# referencing
|
16 |
+
backcall==0.2.0
|
17 |
+
# via ipython
|
18 |
+
blinker==1.6.2
|
19 |
+
# via streamlit
|
20 |
+
branca==0.6.0
|
21 |
+
# via
|
22 |
+
# folium
|
23 |
+
# streamlit-folium
|
24 |
+
cachetools==5.3.1
|
25 |
+
# via streamlit
|
26 |
+
certifi==2023.7.22
|
27 |
+
# via
|
28 |
+
# fiona
|
29 |
+
# pyproj
|
30 |
+
# requests
|
31 |
+
charset-normalizer==3.2.0
|
32 |
+
# via requests
|
33 |
+
click==8.1.7
|
34 |
+
# via
|
35 |
+
# click-plugins
|
36 |
+
# cligj
|
37 |
+
# fiona
|
38 |
+
# streamlit
|
39 |
+
click-plugins==1.1.1
|
40 |
+
# via fiona
|
41 |
+
cligj==0.7.2
|
42 |
+
# via fiona
|
43 |
+
cmake==3.27.5
|
44 |
+
# via triton
|
45 |
+
comm==0.1.4
|
46 |
+
# via ipykernel
|
47 |
+
concrete-python==2.0.0
|
48 |
+
# via -r requirements.in
|
49 |
+
contourpy==1.1.1
|
50 |
+
# via matplotlib
|
51 |
+
cycler==0.11.0
|
52 |
+
# via matplotlib
|
53 |
+
debugpy==1.8.0
|
54 |
+
# via ipykernel
|
55 |
+
decorator==5.1.1
|
56 |
+
# via ipython
|
57 |
+
exceptiongroup==1.1.3
|
58 |
+
# via ipython
|
59 |
+
executing==1.2.0
|
60 |
+
# via stack-data
|
61 |
+
filelock==3.12.4
|
62 |
+
# via
|
63 |
+
# torch
|
64 |
+
# triton
|
65 |
+
fiona==1.9.4.post1
|
66 |
+
# via geopandas
|
67 |
+
folium==0.14.0
|
68 |
+
# via
|
69 |
+
# -r requirements.in
|
70 |
+
# streamlit-folium
|
71 |
+
fonttools==4.42.1
|
72 |
+
# via matplotlib
|
73 |
+
geopandas==0.14.0
|
74 |
+
# via -r requirements.in
|
75 |
+
gitdb==4.0.10
|
76 |
+
# via gitpython
|
77 |
+
gitpython==3.1.37
|
78 |
+
# via streamlit
|
79 |
+
idna==3.4
|
80 |
+
# via requests
|
81 |
+
importlib-metadata==6.8.0
|
82 |
+
# via streamlit
|
83 |
+
ipykernel==6.25.2
|
84 |
+
# via -r requirements.in
|
85 |
+
ipython==8.15.0
|
86 |
+
# via ipykernel
|
87 |
+
jedi==0.19.0
|
88 |
+
# via ipython
|
89 |
+
jinja2==3.1.2
|
90 |
+
# via
|
91 |
+
# altair
|
92 |
+
# branca
|
93 |
+
# folium
|
94 |
+
# pydeck
|
95 |
+
# streamlit-folium
|
96 |
+
# torch
|
97 |
+
joblib==1.3.2
|
98 |
+
# via scikit-learn
|
99 |
+
jsonschema==4.19.1
|
100 |
+
# via altair
|
101 |
+
jsonschema-specifications==2023.7.1
|
102 |
+
# via jsonschema
|
103 |
+
jupyter-client==8.3.1
|
104 |
+
# via ipykernel
|
105 |
+
jupyter-core==5.3.1
|
106 |
+
# via
|
107 |
+
# ipykernel
|
108 |
+
# jupyter-client
|
109 |
+
kiwisolver==1.4.5
|
110 |
+
# via matplotlib
|
111 |
+
lit==16.0.6
|
112 |
+
# via triton
|
113 |
+
mapclassify==2.6.0
|
114 |
+
# via -r requirements.in
|
115 |
+
markdown-it-py==3.0.0
|
116 |
+
# via rich
|
117 |
+
markupsafe==2.1.3
|
118 |
+
# via jinja2
|
119 |
+
matplotlib==3.8.0
|
120 |
+
# via -r requirements.in
|
121 |
+
matplotlib-inline==0.1.6
|
122 |
+
# via
|
123 |
+
# ipykernel
|
124 |
+
# ipython
|
125 |
+
mdurl==0.1.2
|
126 |
+
# via markdown-it-py
|
127 |
+
mpmath==1.3.0
|
128 |
+
# via sympy
|
129 |
+
nest-asyncio==1.5.8
|
130 |
+
# via ipykernel
|
131 |
+
networkx==3.1
|
132 |
+
# via
|
133 |
+
# concrete-python
|
134 |
+
# mapclassify
|
135 |
+
# torch
|
136 |
+
numpy==1.26.0
|
137 |
+
# via
|
138 |
+
# -r requirements.in
|
139 |
+
# altair
|
140 |
+
# concrete-python
|
141 |
+
# contourpy
|
142 |
+
# folium
|
143 |
+
# mapclassify
|
144 |
+
# matplotlib
|
145 |
+
# pandas
|
146 |
+
# pyarrow
|
147 |
+
# pydeck
|
148 |
+
# scikit-learn
|
149 |
+
# scipy
|
150 |
+
# shapely
|
151 |
+
# streamlit
|
152 |
+
nvidia-cublas-cu11==11.10.3.66
|
153 |
+
# via
|
154 |
+
# nvidia-cudnn-cu11
|
155 |
+
# nvidia-cusolver-cu11
|
156 |
+
# torch
|
157 |
+
nvidia-cuda-cupti-cu11==11.7.101
|
158 |
+
# via torch
|
159 |
+
nvidia-cuda-nvrtc-cu11==11.7.99
|
160 |
+
# via torch
|
161 |
+
nvidia-cuda-runtime-cu11==11.7.99
|
162 |
+
# via torch
|
163 |
+
nvidia-cudnn-cu11==8.5.0.96
|
164 |
+
# via torch
|
165 |
+
nvidia-cufft-cu11==10.9.0.58
|
166 |
+
# via torch
|
167 |
+
nvidia-curand-cu11==10.2.10.91
|
168 |
+
# via torch
|
169 |
+
nvidia-cusolver-cu11==11.4.0.1
|
170 |
+
# via torch
|
171 |
+
nvidia-cusparse-cu11==11.7.4.91
|
172 |
+
# via torch
|
173 |
+
nvidia-nccl-cu11==2.14.3
|
174 |
+
# via torch
|
175 |
+
nvidia-nvtx-cu11==11.7.91
|
176 |
+
# via torch
|
177 |
+
packaging==23.1
|
178 |
+
# via
|
179 |
+
# altair
|
180 |
+
# geopandas
|
181 |
+
# ipykernel
|
182 |
+
# matplotlib
|
183 |
+
# streamlit
|
184 |
+
pandas==2.1.1
|
185 |
+
# via
|
186 |
+
# altair
|
187 |
+
# geopandas
|
188 |
+
# mapclassify
|
189 |
+
# streamlit
|
190 |
+
parso==0.8.3
|
191 |
+
# via jedi
|
192 |
+
pexpect==4.8.0
|
193 |
+
# via ipython
|
194 |
+
pickleshare==0.7.5
|
195 |
+
# via ipython
|
196 |
+
pillow==9.5.0
|
197 |
+
# via
|
198 |
+
# matplotlib
|
199 |
+
# streamlit
|
200 |
+
platformdirs==3.10.0
|
201 |
+
# via jupyter-core
|
202 |
+
prompt-toolkit==3.0.39
|
203 |
+
# via ipython
|
204 |
+
protobuf==4.24.3
|
205 |
+
# via streamlit
|
206 |
+
psutil==5.9.5
|
207 |
+
# via ipykernel
|
208 |
+
ptyprocess==0.7.0
|
209 |
+
# via pexpect
|
210 |
+
pure-eval==0.2.2
|
211 |
+
# via stack-data
|
212 |
+
pyarrow==13.0.0
|
213 |
+
# via streamlit
|
214 |
+
pydeck==0.8.1b0
|
215 |
+
# via streamlit
|
216 |
+
pygments==2.16.1
|
217 |
+
# via
|
218 |
+
# ipython
|
219 |
+
# rich
|
220 |
+
pyparsing==3.1.1
|
221 |
+
# via matplotlib
|
222 |
+
pyproj==3.6.1
|
223 |
+
# via geopandas
|
224 |
+
python-dateutil==2.8.2
|
225 |
+
# via
|
226 |
+
# jupyter-client
|
227 |
+
# matplotlib
|
228 |
+
# pandas
|
229 |
+
# streamlit
|
230 |
+
pytz==2023.3.post1
|
231 |
+
# via pandas
|
232 |
+
pyzmq==25.1.1
|
233 |
+
# via
|
234 |
+
# ipykernel
|
235 |
+
# jupyter-client
|
236 |
+
referencing==0.30.2
|
237 |
+
# via
|
238 |
+
# jsonschema
|
239 |
+
# jsonschema-specifications
|
240 |
+
requests==2.31.0
|
241 |
+
# via
|
242 |
+
# folium
|
243 |
+
# streamlit
|
244 |
+
rich==13.5.3
|
245 |
+
# via streamlit
|
246 |
+
rpds-py==0.10.3
|
247 |
+
# via
|
248 |
+
# jsonschema
|
249 |
+
# referencing
|
250 |
+
scikit-learn==1.3.1
|
251 |
+
# via mapclassify
|
252 |
+
scipy==1.11.2
|
253 |
+
# via
|
254 |
+
# concrete-python
|
255 |
+
# mapclassify
|
256 |
+
# scikit-learn
|
257 |
+
shapely==2.0.1
|
258 |
+
# via
|
259 |
+
# -r requirements.in
|
260 |
+
# geopandas
|
261 |
+
six==1.16.0
|
262 |
+
# via
|
263 |
+
# asttokens
|
264 |
+
# fiona
|
265 |
+
# python-dateutil
|
266 |
+
smmap==5.0.1
|
267 |
+
# via gitdb
|
268 |
+
stack-data==0.6.2
|
269 |
+
# via ipython
|
270 |
+
streamlit==1.27.0
|
271 |
+
# via
|
272 |
+
# -r requirements.in
|
273 |
+
# streamlit-folium
|
274 |
+
streamlit-folium==0.14.0
|
275 |
+
# via -r requirements.in
|
276 |
+
sympy==1.12
|
277 |
+
# via torch
|
278 |
+
tenacity==8.2.3
|
279 |
+
# via streamlit
|
280 |
+
threadpoolctl==3.2.0
|
281 |
+
# via scikit-learn
|
282 |
+
toml==0.10.2
|
283 |
+
# via streamlit
|
284 |
+
toolz==0.12.0
|
285 |
+
# via altair
|
286 |
+
torch==2.0.1
|
287 |
+
# via
|
288 |
+
# concrete-python
|
289 |
+
# triton
|
290 |
+
tornado==6.3.3
|
291 |
+
# via
|
292 |
+
# ipykernel
|
293 |
+
# jupyter-client
|
294 |
+
# streamlit
|
295 |
+
traitlets==5.10.0
|
296 |
+
# via
|
297 |
+
# comm
|
298 |
+
# ipykernel
|
299 |
+
# ipython
|
300 |
+
# jupyter-client
|
301 |
+
# jupyter-core
|
302 |
+
# matplotlib-inline
|
303 |
+
triton==2.0.0
|
304 |
+
# via torch
|
305 |
+
typing-extensions==4.8.0
|
306 |
+
# via
|
307 |
+
# altair
|
308 |
+
# streamlit
|
309 |
+
# torch
|
310 |
+
tzdata==2023.3
|
311 |
+
# via pandas
|
312 |
+
tzlocal==5.0.1
|
313 |
+
# via streamlit
|
314 |
+
urllib3==2.0.5
|
315 |
+
# via requests
|
316 |
+
validators==0.22.0
|
317 |
+
# via streamlit
|
318 |
+
watchdog==3.0.0
|
319 |
+
# via streamlit
|
320 |
+
wcwidth==0.2.6
|
321 |
+
# via prompt-toolkit
|
322 |
+
wheel==0.41.2
|
323 |
+
# via
|
324 |
+
# nvidia-cublas-cu11
|
325 |
+
# nvidia-cuda-cupti-cu11
|
326 |
+
# nvidia-cuda-runtime-cu11
|
327 |
+
# nvidia-curand-cu11
|
328 |
+
# nvidia-cusparse-cu11
|
329 |
+
# nvidia-nvtx-cu11
|
330 |
+
zipp==3.17.0
|
331 |
+
# via importlib-metadata
|
332 |
+
|
333 |
+
# The following packages are considered to be unsafe in a requirements file:
|
334 |
+
# setuptools
|
utils.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
from concrete import fhe
|
3 |
+
from config import circuit_filepath
|
4 |
+
|
5 |
+
|
6 |
+
def set_up_server():
|
7 |
+
# Setting up a server
|
8 |
+
try:
|
9 |
+
server = fhe.Server.load(circuit_filepath)
|
10 |
+
except Exception:
|
11 |
+
raise Exception(f"Something went wrong with the circuit. Make sure that the circuit exists in {circuit_filepath}. If not run python generate_circuit.py.")
|
12 |
+
|
13 |
+
return server
|
14 |
+
|
15 |
+
def set_up_client(serialized_client_specs):
|
16 |
+
# Setting up client
|
17 |
+
client_specs = fhe.ClientSpecs.deserialize(serialized_client_specs)
|
18 |
+
client = fhe.Client(client_specs)
|
19 |
+
|
20 |
+
return client
|
21 |
+
|
22 |
+
def display_encrypted(encrypted_object):
|
23 |
+
encoded_text = encrypted_object.hex()
|
24 |
+
res = '...' + encoded_text[-10:]
|
25 |
+
return res
|
26 |
+
|
27 |
+
def shortest_path(circuit, N_NODES, origin, destination):
|
28 |
+
path = [origin, ]
|
29 |
+
o, d = circuit.encrypt(origin, destination)
|
30 |
+
for _ in range(N_NODES - 1):
|
31 |
+
# Careful: breaking early could lead to information leak
|
32 |
+
if origin == destination:
|
33 |
+
break
|
34 |
+
o = circuit.run(o, d)
|
35 |
+
origin = circuit.decrypt(o)
|
36 |
+
path.append(origin)
|
37 |
+
return path
|
38 |
+
|
39 |
+
def generate_path(shortest_path_list, rel):
|
40 |
+
pairs_list = []
|
41 |
+
for i in range(len(shortest_path_list) - 1):
|
42 |
+
current_element = shortest_path_list[i]
|
43 |
+
next_element = shortest_path_list[i + 1]
|
44 |
+
result = rel.groupby('way_id').filter(lambda x: set([current_element, next_element]).issubset(x['node_id']))
|
45 |
+
pairs_list.append(result)
|
46 |
+
final_result = pd.concat(pairs_list)
|
47 |
+
return final_result
|