File size: 7,562 Bytes
1d1124e
d75dabd
 
1d1124e
 
 
 
d75dabd
 
1d1124e
 
 
 
 
 
 
 
d75dabd
 
1d1124e
 
 
d75dabd
 
 
 
1d1124e
 
 
 
 
 
 
 
 
d75dabd
 
 
 
 
 
1d1124e
 
 
 
 
 
 
 
d75dabd
 
 
 
1d1124e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d75dabd
 
1d1124e
 
 
 
d75dabd
1d1124e
 
 
 
 
 
 
 
 
 
 
d75dabd
1d1124e
 
 
 
d75dabd
 
 
1d1124e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0fdd317
 
1d1124e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# Contains a set of useful functions
import pandas as pd
from concrete import fhe
from config import circuit_filepath, keys_filepath
import streamlit as st
import folium
from streamlit_folium import st_folium

def set_up_server():
    """Load a server instance from a specified circuit file

    Raises:
        OSError: If there is an issue loading the FHE server.

    Returns:
       concrete.fhe.compilation.server.Server: A server instance loaded from the circuit file.
    """
    try:
        server = fhe.Server.load(circuit_filepath)
    except OSError as e:
        raise OSError(f"Something went wrong with the circuit. Make sure that the circuit \
            exists in {circuit_filepath}.If not run python generate_circuit.py.") from e

    return server

def set_up_client(serialized_client_specs):
    """Generate a client instance from a specified circuit file

    Args:
        serialized_client_specs (bytes): A serialized client specs

    Returns:
        concrete.fhe.compilation.client.Client: A client instance created from the client specs
    """
    
    client_specs = fhe.ClientSpecs.deserialize(serialized_client_specs)
    client = fhe.Client(client_specs)

    return client

def display_encrypted(encrypted_object):
    """Display a truncated representation of an encrypted object as a hexadecimal string

    Args:
        encrypted_object (bytes): A serialized encrypted object to display

    Returns:
        str: A truncated hexadecimal representation of the encrypted object
    """
    encoded_text = encrypted_object.hex()
    res = '...' + encoded_text[-10:]
    return res

def compute_shortest_path(nodes_nb, client, server):
    """Calculate the shortest path between two nodes

    Args:
        nodes_nb (int): The number of nodes in the network
        client (concrete.fhe.compilation.client.Client): A client instance
        server (concrete.fhe.compilation.server.Server): A server instance

    Returns:
        List[bytes]: A list of encrypted values representing the path
    """
    deserialized_origin = fhe.Value.deserialize(st.session_state['encrypted_origin'])
    deserialized_destination = fhe.Value.deserialize(st.session_state['encrypted_destination'])
    deserialized_evaluation_keys = fhe.EvaluationKeys.deserialize(st.session_state['evaluation_key'])
    client.keys.load_if_exists_generate_and_save_otherwise(keys_filepath)
    origin = st.session_state['origin_node']
    destination = st.session_state['destination_node']
    encrypted_path = [st.session_state['encrypted_origin'], ]
    o, d = deserialized_origin, deserialized_destination
    for _ in range(nodes_nb):
        if origin == destination:
            break
        o = server.run(o, d, evaluation_keys=deserialized_evaluation_keys)
        origin = client.decrypt(o)
        encrypted_path.append(o.serialize())
    return encrypted_path

    
def generate_path(shortest_path, roads):
    """Generate a path from a list of nodes using road data.

    Args:
        shortest_path (List[int]): A list of nodes representing the shortest path.
        roads (geopandas.DataFrame): A DataFrame containing the ways between the nodes.

    Returns:
       pandas.DataFrame: A DataFrame representing the road segments that form the shortest path.
    """
    pairs_list = []
    for i in range(len(shortest_path) - 1):
        current_element = shortest_path[i]
        next_element = shortest_path[i + 1]
        result = roads.groupby('way_id').filter(lambda x: set([current_element, next_element]).issubset(x['node_id']))
        pairs_list.append(result)
    final_result = pd.concat(pairs_list)
    return final_result




def decrypt_shortest_path(client):
    """Decrypt and store the shortest path in the session state

    Args:
        client (concrete.fhe.compilation.client.Client): A client instance
    """
    client.keys.load_if_exists_generate_and_save_otherwise(keys_filepath)
    path = []
    for enc_value in st.session_state['encrypted_shortest_path']:
        deserialized_result = fhe.Value.deserialize(enc_value)
        path.append(client.decrypt(deserialized_result))
    st.session_state['decrypted_result'] = path

def init_session():
    """Initialize the Streamlit session and layout configuration.

    Returns:
        Streamlit.columns: A tuple of Streamlit columns for layout customization.
    """
    st.set_page_config(layout="wide")
    
    if 'markers' not in st.session_state:
        st.session_state['markers'] = []
    if 'server_side' not in st.session_state:
            st.session_state['server_side'] = []    
    if 'client_side' not in st.session_state:
            st.session_state['client_side'] = []

    c1, c2, c3 = st.columns([1, 3, 1])

    return c1, c2, c3

def add_marker(coordinates, name):
    """Add a marker with coordinates and a name to the Streamlit session.

    Args:
        coordinates (Point): The coordinates of the marker 
        name (str): The name or label for the marker
    """
    data = {'coordinates': coordinates, 'name': name}
    st.session_state['markers'].append(data)


def display_map(nodes, returned_objects=None, path=None):
    """Display the map with nodes and optional markers and paths.

    Args:
        nodes (geopandas.DataFrame): A dataframe containing the nodes to display
        returned_objects (List[str], optional): Objects to be returned when interacting with the map. Defaults to None.
        path (pandas.DataFrame, optional): A DataFrame representing the road segments that form the shortest path. Defaults to None.

    Returns:
        Streamlit.FoliumMap: An interactive map displaying nodes, markers, and paths
    """
    m = nodes.explore(
        color="red",  
        marker_kwds=dict(radius=5, fill=True, name='node_id'),  
        tooltip="node_id",  
        tooltip_kwds=dict(labels=False), 
        zoom_control=False,
    )

    if 'markers' in st.session_state:
        for mrk in st.session_state['markers']:
            folium.Marker([mrk['coordinates'].y, mrk['coordinates'].x], popup=mrk['name'], tooltip=mrk['name']).add_to(m)

    if path is not None:
        path.explore(
                m=m,  
                color="green",
                style_kwds = {"weight":5},
                tooltip="name",
                popup=["name"],
                name="Quadratic-Paris", 
            )
        
    return st_folium(m, width=725, key="origin", returned_objects=returned_objects)


def add_to_server_side(message):
    """Add a message to the server side of the view

    Args:
        message (str): The message to be added to the server side
    """
    st.session_state['server_side'].append(message)

def add_to_client_side(message):
    """Add a message to the client side of the view

    Args:
        message (str): The message to be added to the client side
    """
    st.session_state['client_side'].append(message)

def display_server_side():
    """Display the messages stored in the server-side view.
    """
    st.write("**Server-side**")
    for message in st.session_state['server_side']:
        st.write(message)

def display_client_side():
    """Display the messages stored in the client-side view.
    """
    st.write("**Client-side**")
    for message in st.session_state['client_side']:
        st.write(message)

def restart_session():
    """Clear the session state to restart
    """
    if st.button('Restart'):
        for key in st.session_state.items():
            if key[0] != 'evaluation_key':
                del st.session_state[key[0]]
        st.rerun()