vimmoos@Thor commited on
Commit
09a4b49
·
1 Parent(s): 6ca282a
app.py CHANGED
@@ -1,276 +1,13 @@
1
  import streamlit as st
2
- import gymnasium as gym
3
- import numpy as np
4
- from PIL import Image
5
- import time
6
 
7
- # Initialize session state variables if they don't exist
8
- if "env" not in st.session_state:
9
- st.session_state.env = gym.make("LunarLander-v2", render_mode="rgb_array")
10
- st.session_state.env.reset()
11
- st.session_state.frame = st.session_state.env.render()
12
- if "paused" not in st.session_state:
13
- st.session_state.paused = False
14
 
 
15
 
16
- # Function to reset the environment
17
- def reset_environment():
18
- st.session_state.env.reset()
19
 
 
20
 
21
- # Function to toggle pause state
22
- def toggle_pause():
23
- st.session_state.paused = not st.session_state.paused
24
-
25
-
26
- # Create the Streamlit app
27
- st.title("Gymnasium Environment Viewer")
28
-
29
- # Add control buttons in a horizontal layout
30
- col1, col2 = st.columns(2)
31
- with col1:
32
- st.button("Reset Environment", on_click=reset_environment)
33
- with col2:
34
- if st.session_state.paused:
35
- st.button("Resume", on_click=toggle_pause)
36
- else:
37
- st.button("Pause", on_click=toggle_pause)
38
-
39
- # Create a placeholder for the image
40
- image_placeholder = st.empty()
41
-
42
- # Create a container for environment info
43
- sidebar_container = st.sidebar.container()
44
-
45
- # Main simulation loop using rerun
46
- if not st.session_state.paused:
47
- # Take a random action
48
- action = st.session_state.env.action_space.sample()
49
- observation, reward, terminated, truncated, info = (
50
- st.session_state.env.step(action)
51
- )
52
-
53
- # Render the environment
54
- st.session_state.frame = st.session_state.env.render()
55
-
56
- # Reset if the episode is done
57
- if terminated or truncated:
58
- st.session_state.env.reset()
59
- # Display the frame
60
- if st.session_state.paused:
61
- image_placeholder.image(
62
- st.session_state.frame,
63
- caption="Environment Visualization (Paused)",
64
- use_column_width=True,
65
- )
66
- else:
67
- image_placeholder.image(
68
- st.session_state.frame,
69
- caption="Environment Visualization",
70
- use_column_width=True,
71
- )
72
-
73
- # Display some information about the environment
74
- with sidebar_container:
75
- st.header("Environment Info")
76
- st.write(f"Action Space: {st.session_state.env.action_space}")
77
- st.write(f"Observation Space: {st.session_state.env.observation_space}")
78
-
79
- # Add auto-refresh logic
80
- if not st.session_state.paused:
81
- time.sleep(0.1) # Add a small delay to control refresh rate
82
- st.rerun()
83
-
84
- # fig, ax = plt.subplots()
85
- # ax.imshow(env.render())
86
- # st.pyplot(fig)
87
- # st.image(env.render())
88
-
89
-
90
- # import gymnasium as gym
91
- # import streamlit as st
92
- # import numpy as np
93
- # from udrl.policies import SklearnPolicy
94
- # from udrl.agent import UpsideDownAgent, AgentHyper
95
- # from pathlib import Path
96
-
97
- # # import json
98
-
99
-
100
- # def normalize_value(value, is_bounded, low=None, high=None):
101
- # return (value - low) / (high - low)
102
-
103
-
104
- # def visualize_environment(
105
- # state,
106
- # env,
107
- # # paused,
108
- # feature_importances,
109
- # epoch,
110
- # max_epoch=200,
111
- # ):
112
-
113
- # st.image(env.render())
114
- # st.image(e)
115
- # # Render the Gym environment
116
- # # env_render = env.render()
117
-
118
- # # # Display the rendered image using Streamlit
119
- # # st.image(env_render, caption=f"Epoch {epoch}", use_column_width=True)
120
-
121
- # # Display feature importances using Streamlit metrics
122
- # # cols = st.columns(len(feature_importances))
123
- # # for i, col in enumerate(cols):
124
- # # col.metric(
125
- # # label=f"Importance {i}", value=f"{feature_importances[i]:.2f}"
126
- # # )
127
-
128
- # # Create buttons using Streamlit
129
- # # reset_button = st.button("Reset")
130
- # # pause_play_button = st.button("Pause" if not paused else "Play")
131
- # # next_button = st.button("Next")
132
- # # save_button = st.button("Save")
133
-
134
- # # return reset_button, pause_play_button, next_button, save_button
135
-
136
-
137
- # def run_visualization(
138
- # env_name,
139
- # agent,
140
- # init_desired_return,
141
- # init_desired_horizon,
142
- # max_epoch,
143
- # base_path,
144
- # ):
145
- # # base_path = (
146
- # # Path(base_path) / env_name / agent.policy.estimator.__str__()[:-2]
147
- # # )
148
- # # base_path.mkdir(parents=True, exist_ok=True)
149
- # desired_return = init_desired_return
150
- # desired_horizon = init_desired_horizon
151
-
152
- # # Initialize the Gym environment
153
- # env = gym.make(env_name, render_mode="rgb_array")
154
- # state, _ = env.reset()
155
-
156
- # epoch = 0
157
- # # save_index = 0
158
-
159
- # # paused = False
160
- # # step = False
161
-
162
- # # # Use Streamlit session state to manage paused state
163
- # # if "paused" not in st.session_state:
164
- # # st.session_state.paused = False
165
-
166
- # while True:
167
- # # Render and display the environment
168
- # env_render = env.render()
169
- # # if not st.session_state.pausedor step:
170
- # command = np.array(
171
- # [
172
- # desired_return * agent.conf.return_scale,
173
- # desired_horizon * agent.conf.horizon_scale,
174
- # ]
175
- # )
176
- # command = np.expand_dims(command, axis=0)
177
- # state = np.expand_dims(state, axis=0)
178
-
179
- # action = agent.policy(state, command, True)
180
-
181
- # ext_state = np.concatenate((state, command), axis=1)
182
-
183
- # state, reward, done, truncated, info = env.step(action)
184
-
185
- # feature_importances = {idx: [] for idx in range(ext_state.shape[1])}
186
-
187
- # for t in agent.policy.estimator.estimators_:
188
- # branch = np.array(t.decision_path(ext_state).todense(), dtype=bool)
189
- # imp = t.tree_.impurity[branch[0]]
190
-
191
- # for f, i in zip(
192
- # t.tree_.feature[branch[0]][:-1], imp[:-1] - imp[1:]
193
- # ):
194
- # feature_importances.setdefault(f, []).append(i)
195
-
196
- # # Line 8 Algorithm 2
197
- # desired_return -= reward
198
- # # Line 9 Algorithm 2
199
- # desired_horizon = max(desired_horizon - 1, 1)
200
-
201
- # summed_importances = [
202
- # sum(feature_importances.get(k, [0.001]))
203
- # for k in range(len(feature_importances.keys()))
204
- # ]
205
-
206
- # epoch += 1
207
- # visualize_environment(
208
- # state,
209
- # env,
210
- # # st.session_state.paused, # Use session state
211
- # summed_importances,
212
- # epoch,
213
- # max_epoch,
214
- # )
215
- # # reset_button, pause_play_button, next_button, save_button = (
216
-
217
- # # )
218
-
219
- # if done or truncated:
220
- # state, _ = env.reset()
221
- # desired_horizon = init_desired_horizon
222
- # desired_return = init_desired_return
223
- # epoch = 0
224
-
225
- # # step = False
226
-
227
- # # Handle button clicks
228
- # # if reset_button:
229
- # # state, _ = env.reset()
230
- # # desired_horizon = init_desired_horizon
231
- # # desired_return = init_desired_return
232
- # # epoch = 0
233
- # # elif pause_play_button:
234
- # # st.session_state.paused = (
235
- # # not st.session_state.paused
236
- # # ) # Toggle paused state
237
- # # elif next_button and st.session_state.paused:
238
- # # step = True
239
- # # elif save_button:
240
- # # # Save image and info using Streamlit
241
- # # st.image(
242
- # # env_render, caption=f"Epoch {epoch}", use_column_width=True
243
- # # )
244
- # # st.write(
245
- # # {
246
- # # "state": {i: str(val) for i, val in enumerate(state)},
247
- # # "feature": {
248
- # # i: str(val) for i, val in enumerate(summed_importances)
249
- # # },
250
- # # "action": str(action),
251
- # # "reward": str(reward),
252
- # # "desired_return": str(desired_return + reward),
253
- # # "desired_horizon": str(desired_horizon + 1),
254
- # # }
255
- # # )
256
-
257
- # env.close()
258
-
259
-
260
- # env = "Acrobot-v1"
261
- # desired_return = -79
262
- # desired_horizon = 82
263
- # max_epoch = 500
264
-
265
-
266
- # policy = SklearnPolicy.load("policy")
267
- # hyper = AgentHyper(
268
- # env,
269
- # warm_up=0,
270
- # )
271
-
272
- # agent = UpsideDownAgent(hyper, policy)
273
-
274
- # run_visualization(
275
- # env, agent, desired_return, desired_horizon, max_epoch, "data/viz_examples"
276
- # )
 
1
  import streamlit as st
2
+ from st_pages import add_page_title, get_nav_from_toml
 
 
 
3
 
4
+ st.set_page_config(layout="wide")
 
 
 
 
 
 
5
 
6
+ nav = get_nav_from_toml("pages.toml")
7
 
8
+ # st.logo("logo.png")
 
 
9
 
10
+ pg = st.navigation(nav)
11
 
12
+ add_page_title(pg)
13
+ pg.run()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
pages.toml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ [[pages]]
2
+ path = "udrl/app/home.py"
3
+ name = "Home"
4
+ icon = "🏠"
5
+
6
+ [[pages]]
7
+ path = "udrl/app/sim.py"
8
+ name = "Feature Importance Visualization"
9
+ icon = ":robot_face:"
10
+ url_path = "simulation"
poetry.lock CHANGED
@@ -91,101 +91,116 @@ files = [
91
 
92
  [[package]]
93
  name = "charset-normalizer"
94
- version = "3.3.2"
95
  description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
96
  optional = false
97
  python-versions = ">=3.7.0"
98
  files = [
99
- {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
100
- {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
101
- {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
102
- {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
103
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
104
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
105
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
106
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
107
- {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
108
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
109
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
110
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
111
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
112
- {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
113
- {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
114
- {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
115
- {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
116
- {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
117
- {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
118
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
119
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
120
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
121
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
122
- {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
123
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
124
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
125
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
126
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
127
- {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
128
- {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
129
- {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
130
- {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
131
- {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
132
- {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
133
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
134
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
135
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
136
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
137
- {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
138
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
139
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
140
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
141
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
142
- {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
143
- {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
144
- {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
145
- {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
146
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
147
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
148
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
149
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
150
- {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
151
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
152
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
153
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
154
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
155
- {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
156
- {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
157
- {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
158
- {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
159
- {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
160
- {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
161
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
162
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
163
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
164
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
165
- {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
166
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
167
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
168
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
169
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
170
- {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
171
- {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
172
- {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
173
- {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
174
- {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
175
- {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
176
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
177
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
178
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
179
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
180
- {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
181
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
182
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
183
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
184
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
185
- {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
186
- {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
187
- {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
188
- {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  ]
190
 
191
  [[package]]
@@ -803,72 +818,72 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
803
 
804
  [[package]]
805
  name = "markupsafe"
806
- version = "3.0.0"
807
  description = "Safely add untrusted strings to HTML/XML markup."
808
  optional = false
809
  python-versions = ">=3.9"
810
  files = [
811
- {file = "MarkupSafe-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:380faf314c3c84c1682ca672e6280c6c59e92d0bc13dc71758ffa2de3cd4e252"},
812
- {file = "MarkupSafe-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ee9790be6f62121c4c58bbced387b0965ab7bffeecb4e17cc42ef290784e363"},
813
- {file = "MarkupSafe-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddf5cb8e9c00d9bf8b0c75949fb3ff9ea2096ba531693e2e87336d197fdb908"},
814
- {file = "MarkupSafe-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b36473a2d3e882d1873ea906ce54408b9588dc2c65989664e6e7f5a2de353d7"},
815
- {file = "MarkupSafe-3.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba0f83119b9514bc37272ad012f0cc03f0805cc6a2bea7244e19250ac8ff29f"},
816
- {file = "MarkupSafe-3.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:409535e0521c4630d5b5a1bf284e9d3c76d2fc2f153ebb12cf3827797798cc99"},
817
- {file = "MarkupSafe-3.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64a7c7856c3a409011139b17d137c2924df4318dab91ee0530800819617c4381"},
818
- {file = "MarkupSafe-3.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4deea1d9169578917d1f35cdb581bc7bab56a7e8c5be2633bd1b9549c3c22a01"},
819
- {file = "MarkupSafe-3.0.0-cp310-cp310-win32.whl", hash = "sha256:3cd0bba31d484fe9b9d77698ddb67c978704603dc10cdc905512af308cfcca6b"},
820
- {file = "MarkupSafe-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4ca04c60006867610a06575b46941ae616b19da0adc85b9f8f3d9cbd7a3da385"},
821
- {file = "MarkupSafe-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e64b390a306f9e849ee809f92af6a52cda41741c914358e0e9f8499d03741526"},
822
- {file = "MarkupSafe-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7c524203207f5b569df06c96dafdc337228921ee8c3cc5f6e891d024c6595352"},
823
- {file = "MarkupSafe-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c409691696bec2b5e5c9efd9593c99025bf2f317380bf0d993ee0213516d908a"},
824
- {file = "MarkupSafe-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64f7d04410be600aa5ec0626d73d43e68a51c86500ce12917e10fd013e258df5"},
825
- {file = "MarkupSafe-3.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:105ada43a61af22acb8774514c51900dc820c481cc5ba53f17c09d294d9c07ca"},
826
- {file = "MarkupSafe-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a5fd5500d4e4f7cc88d8c0f2e45126c4307ed31e08f8ec521474f2fd99d35ac3"},
827
- {file = "MarkupSafe-3.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25396abd52b16900932e05b7104bcdc640a4d96c914f39c3b984e5a17b01fba0"},
828
- {file = "MarkupSafe-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3efde9a8c56c3b6e5f3fa4baea828f8184970c7c78480fedb620d804b1c31e5c"},
829
- {file = "MarkupSafe-3.0.0-cp311-cp311-win32.whl", hash = "sha256:12ddac720b8965332d36196f6f83477c6351ba6a25d4aff91e30708c729350d7"},
830
- {file = "MarkupSafe-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:658fdf6022740896c403d45148bf0c36978c6b48c9ef8b1f8d0c7a11b6cdea86"},
831
- {file = "MarkupSafe-3.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d261ec38b8a99a39b62e0119ed47fe3b62f7691c500bc1e815265adc016438c1"},
832
- {file = "MarkupSafe-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e363440c8534bf2f2ef1b8fdc02037eb5fff8fce2a558519b22d6a3a38b3ec5e"},
833
- {file = "MarkupSafe-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7835de4c56066e096407a1852e5561f6033786dd987fa90dc384e45b9bd21295"},
834
- {file = "MarkupSafe-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6cc46a27d904c9be5732029769acf4b0af69345172ed1ef6d4db0c023ff603b"},
835
- {file = "MarkupSafe-3.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0411641d31aa6f7f0cc13f0f18b63b8dc08da5f3a7505972a42ab059f479ba3"},
836
- {file = "MarkupSafe-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b2a7afd24d408b907672015555bc10be2382e6c5f62a488e2d452da670bbd389"},
837
- {file = "MarkupSafe-3.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c8ab7efeff1884c5da8e18f743b667215300e09043820d11723718de0b7db934"},
838
- {file = "MarkupSafe-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8219e2207f6c188d15614ea043636c2b36d2d79bf853639c124a179412325a13"},
839
- {file = "MarkupSafe-3.0.0-cp312-cp312-win32.whl", hash = "sha256:59420b5a9a5d3fee483a32adb56d7369ae0d630798da056001be1e9f674f3aa6"},
840
- {file = "MarkupSafe-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:7ed789d0f7f11fcf118cf0acb378743dfdd4215d7f7d18837c88171405c9a452"},
841
- {file = "MarkupSafe-3.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:27d6a73682b99568916c54a4bfced40e7d871ba685b580ea04bbd2e405dfd4c5"},
842
- {file = "MarkupSafe-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:494a64efc535e147fcc713dba58eecfce3a79f1e93ebe81995b387f5cd9bc2e1"},
843
- {file = "MarkupSafe-3.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5243044a927e8a6bb28517838662a019cd7f73d7f106bbb37ab5e7fa8451a92"},
844
- {file = "MarkupSafe-3.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63dae84964a9a3d2610808cee038f435d9a111620c37ccf872c2fcaeca6865b3"},
845
- {file = "MarkupSafe-3.0.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dcbee57fedc9b2182c54ffc1c5eed316c3da8bbfeda8009e1b5d7220199d15da"},
846
- {file = "MarkupSafe-3.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f846fd7c241e5bd4161e2a483663eb66e4d8e12130fcdc052f310f388f1d61c6"},
847
- {file = "MarkupSafe-3.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:678fbceb202382aae42c1f0cd9f56b776bc20a58ae5b553ee1fe6b802983a1d6"},
848
- {file = "MarkupSafe-3.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bd9b8e458e2bab52f9ad3ab5dc8b689a3c84b12b2a2f64cd9a0dfe209fb6b42f"},
849
- {file = "MarkupSafe-3.0.0-cp313-cp313-win32.whl", hash = "sha256:1fd02f47596e00a372f5b4af2b4c45f528bade65c66dfcbc6e1ea1bfda758e98"},
850
- {file = "MarkupSafe-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:b94bec9eda10111ec7102ef909eca4f3c2df979643924bfe58375f560713a7d1"},
851
- {file = "MarkupSafe-3.0.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:509c424069dd037d078925b6815fc56b7271f3aaec471e55e6fa513b0a80d2aa"},
852
- {file = "MarkupSafe-3.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81be2c0084d8c69e97e3c5d73ce9e2a6e523556f2a19c4e195c09d499be2f808"},
853
- {file = "MarkupSafe-3.0.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b43ac1eb9f91e0c14aac1d2ef0f76bc7b9ceea51de47536f61268191adf52ad7"},
854
- {file = "MarkupSafe-3.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b231255770723f1e125d63c14269bcd8b8136ecfb620b9a18c0297e046d0736"},
855
- {file = "MarkupSafe-3.0.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c182d45600556917f811aa019d834a89fe4b6f6255da2fd0bdcf80e970f95918"},
856
- {file = "MarkupSafe-3.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9f91c90f8f3bf436f81c12eeb4d79f9ddd263c71125e6ad71341906832a34386"},
857
- {file = "MarkupSafe-3.0.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:a7171d2b869e9be238ea318c196baf58fbf272704e9c1cd4be8c380eea963342"},
858
- {file = "MarkupSafe-3.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cb244adf2499aa37d5dc43431990c7f0b632d841af66a51d22bd89c437b60264"},
859
- {file = "MarkupSafe-3.0.0-cp313-cp313t-win32.whl", hash = "sha256:96e3ed550600185d34429477f1176cedea8293fa40e47fe37a05751bcb64c997"},
860
- {file = "MarkupSafe-3.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:1d151b9cf3307e259b749125a5a08c030ba15a8f1d567ca5bfb0e92f35e761f5"},
861
- {file = "MarkupSafe-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:23efb2be7221105c8eb0e905433414d2439cb0a8c5d5ca081c1c72acef0f5613"},
862
- {file = "MarkupSafe-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81ee9c967956b9ea39b3a5270b7cb1740928d205b0dc72629164ce621b4debf9"},
863
- {file = "MarkupSafe-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5509a8373fed30b978557890a226c3d30569746c565b9daba69df80c160365a5"},
864
- {file = "MarkupSafe-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1c13c6c908811f867a8e9e66efb2d6c03d1cdd83e92788fe97f693c457dc44f"},
865
- {file = "MarkupSafe-3.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d7e63d1977d3806ce0a1a3e0099b089f61abdede5238ca6a3f3bf8877b46d095"},
866
- {file = "MarkupSafe-3.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d2c099be5274847d606574234e494f23a359e829ba337ea9037c3a72b0851942"},
867
- {file = "MarkupSafe-3.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e042ccf8fe5bf8b6a4b38b3f7d618eb10ea20402b0c9f4add9293408de447974"},
868
- {file = "MarkupSafe-3.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:98fb3a2bf525ad66db96745707b93ba0f78928b7a1cb2f1cb4b143bc7e2ba3b3"},
869
- {file = "MarkupSafe-3.0.0-cp39-cp39-win32.whl", hash = "sha256:a80c6740e1bfbe50cea7cbf74f48823bb57bd59d914ee22ff8a81963b08e62d2"},
870
- {file = "MarkupSafe-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:5d207ff5cceef77796f8aacd44263266248cf1fbc601441524d7835613f8abec"},
871
- {file = "markupsafe-3.0.0.tar.gz", hash = "sha256:03ff62dea2fef3eadf2f1853bc6332bcb0458d9608b11dfb1cd5aeda1c178ea6"},
872
  ]
873
 
874
  [[package]]
@@ -964,13 +979,13 @@ tests = ["pytest (>=4.6)"]
964
 
965
  [[package]]
966
  name = "narwhals"
967
- version = "1.9.1"
968
  description = "Extremely lightweight compatibility layer between dataframe libraries"
969
  optional = false
970
  python-versions = ">=3.8"
971
  files = [
972
- {file = "narwhals-1.9.1-py3-none-any.whl", hash = "sha256:0375f40f98795e94d3622d085eb8e1df2d67f4fdcb281dcfa6f2158e52a36afe"},
973
- {file = "narwhals-1.9.1.tar.gz", hash = "sha256:c926f931cd72436eab258088ce6a4a068d272e64d680be8174ce1337b52f0648"},
974
  ]
975
 
976
  [package.extras]
@@ -983,20 +998,21 @@ pyarrow = ["pyarrow (>=11.0.0)"]
983
 
984
  [[package]]
985
  name = "networkx"
986
- version = "3.3"
987
  description = "Python package for creating and manipulating graphs and networks"
988
  optional = false
989
  python-versions = ">=3.10"
990
  files = [
991
- {file = "networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2"},
992
- {file = "networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9"},
993
  ]
994
 
995
  [package.extras]
996
- default = ["matplotlib (>=3.6)", "numpy (>=1.23)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"]
997
  developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"]
998
- doc = ["myst-nb (>=1.0)", "numpydoc (>=1.7)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"]
999
- extra = ["lxml (>=4.6)", "pydot (>=2.0)", "pygraphviz (>=1.12)", "sympy (>=1.10)"]
 
1000
  test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"]
1001
 
1002
  [[package]]
@@ -1543,6 +1559,16 @@ files = [
1543
  [package.extras]
1544
  windows-terminal = ["colorama (>=0.4.6)"]
1545
 
 
 
 
 
 
 
 
 
 
 
1546
  [[package]]
1547
  name = "pyparsing"
1548
  version = "3.1.4"
@@ -1934,6 +1960,20 @@ files = [
1934
  {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"},
1935
  ]
1936
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1937
  [[package]]
1938
  name = "streamlit"
1939
  version = "1.39.0"
@@ -1969,6 +2009,20 @@ watchdog = {version = ">=2.1.5,<6", markers = "platform_system != \"Darwin\""}
1969
  [package.extras]
1970
  snowflake = ["snowflake-connector-python (>=2.8.0)", "snowflake-snowpark-python[modin] (>=1.17.0)"]
1971
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1972
  [[package]]
1973
  name = "swig"
1974
  version = "4.2.1"
@@ -2275,4 +2329,4 @@ watchmedo = ["PyYAML (>=3.10)"]
2275
  [metadata]
2276
  lock-version = "2.0"
2277
  python-versions = "3.10.14"
2278
- content-hash = "242769eee3ba46263412257aec5f7cc4535d825cf0ff355e5f649bdd2461631c"
 
91
 
92
  [[package]]
93
  name = "charset-normalizer"
94
+ version = "3.4.0"
95
  description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
96
  optional = false
97
  python-versions = ">=3.7.0"
98
  files = [
99
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"},
100
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"},
101
+ {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"},
102
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"},
103
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"},
104
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"},
105
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"},
106
+ {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"},
107
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"},
108
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"},
109
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"},
110
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"},
111
+ {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"},
112
+ {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"},
113
+ {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"},
114
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"},
115
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"},
116
+ {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"},
117
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"},
118
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"},
119
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"},
120
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"},
121
+ {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"},
122
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"},
123
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"},
124
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"},
125
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"},
126
+ {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"},
127
+ {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"},
128
+ {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"},
129
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"},
130
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"},
131
+ {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"},
132
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"},
133
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"},
134
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"},
135
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"},
136
+ {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"},
137
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"},
138
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"},
139
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"},
140
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"},
141
+ {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"},
142
+ {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"},
143
+ {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"},
144
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"},
145
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"},
146
+ {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"},
147
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"},
148
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"},
149
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"},
150
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"},
151
+ {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"},
152
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"},
153
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"},
154
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"},
155
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"},
156
+ {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"},
157
+ {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"},
158
+ {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"},
159
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"},
160
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"},
161
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"},
162
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"},
163
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"},
164
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"},
165
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"},
166
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"},
167
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"},
168
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"},
169
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"},
170
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"},
171
+ {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"},
172
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"},
173
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"},
174
+ {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"},
175
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"},
176
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"},
177
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"},
178
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"},
179
+ {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"},
180
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"},
181
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"},
182
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"},
183
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"},
184
+ {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"},
185
+ {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"},
186
+ {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"},
187
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"},
188
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"},
189
+ {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"},
190
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"},
191
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"},
192
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"},
193
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"},
194
+ {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"},
195
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"},
196
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"},
197
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"},
198
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"},
199
+ {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"},
200
+ {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"},
201
+ {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"},
202
+ {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"},
203
+ {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"},
204
  ]
205
 
206
  [[package]]
 
818
 
819
  [[package]]
820
  name = "markupsafe"
821
+ version = "3.0.1"
822
  description = "Safely add untrusted strings to HTML/XML markup."
823
  optional = false
824
  python-versions = ">=3.9"
825
  files = [
826
+ {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:db842712984e91707437461930e6011e60b39136c7331e971952bb30465bc1a1"},
827
+ {file = "MarkupSafe-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ffb4a8e7d46ed96ae48805746755fadd0909fea2306f93d5d8233ba23dda12a"},
828
+ {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67c519635a4f64e495c50e3107d9b4075aec33634272b5db1cde839e07367589"},
829
+ {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48488d999ed50ba8d38c581d67e496f955821dc183883550a6fbc7f1aefdc170"},
830
+ {file = "MarkupSafe-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f31ae06f1328595d762c9a2bf29dafd8621c7d3adc130cbb46278079758779ca"},
831
+ {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80fcbf3add8790caddfab6764bde258b5d09aefbe9169c183f88a7410f0f6dea"},
832
+ {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3341c043c37d78cc5ae6e3e305e988532b072329639007fd408a476642a89fd6"},
833
+ {file = "MarkupSafe-3.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cb53e2a99df28eee3b5f4fea166020d3ef9116fdc5764bc5117486e6d1211b25"},
834
+ {file = "MarkupSafe-3.0.1-cp310-cp310-win32.whl", hash = "sha256:db15ce28e1e127a0013dfb8ac243a8e392db8c61eae113337536edb28bdc1f97"},
835
+ {file = "MarkupSafe-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:4ffaaac913c3f7345579db4f33b0020db693f302ca5137f106060316761beea9"},
836
+ {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:26627785a54a947f6d7336ce5963569b5d75614619e75193bdb4e06e21d447ad"},
837
+ {file = "MarkupSafe-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b954093679d5750495725ea6f88409946d69cfb25ea7b4c846eef5044194f583"},
838
+ {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973a371a55ce9ed333a3a0f8e0bcfae9e0d637711534bcb11e130af2ab9334e7"},
839
+ {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:244dbe463d5fb6d7ce161301a03a6fe744dac9072328ba9fc82289238582697b"},
840
+ {file = "MarkupSafe-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d98e66a24497637dd31ccab090b34392dddb1f2f811c4b4cd80c230205c074a3"},
841
+ {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ad91738f14eb8da0ff82f2acd0098b6257621410dcbd4df20aaa5b4233d75a50"},
842
+ {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:7044312a928a66a4c2a22644147bc61a199c1709712069a344a3fb5cfcf16915"},
843
+ {file = "MarkupSafe-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a4792d3b3a6dfafefdf8e937f14906a51bd27025a36f4b188728a73382231d91"},
844
+ {file = "MarkupSafe-3.0.1-cp311-cp311-win32.whl", hash = "sha256:fa7d686ed9883f3d664d39d5a8e74d3c5f63e603c2e3ff0abcba23eac6542635"},
845
+ {file = "MarkupSafe-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ba25a71ebf05b9bb0e2ae99f8bc08a07ee8e98c612175087112656ca0f5c8bf"},
846
+ {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8ae369e84466aa70f3154ee23c1451fda10a8ee1b63923ce76667e3077f2b0c4"},
847
+ {file = "MarkupSafe-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40f1e10d51c92859765522cbd79c5c8989f40f0419614bcdc5015e7b6bf97fc5"},
848
+ {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a4cb365cb49b750bdb60b846b0c0bc49ed62e59a76635095a179d440540c346"},
849
+ {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee3941769bd2522fe39222206f6dd97ae83c442a94c90f2b7a25d847d40f4729"},
850
+ {file = "MarkupSafe-3.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62fada2c942702ef8952754abfc1a9f7658a4d5460fabe95ac7ec2cbe0d02abc"},
851
+ {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c2d64fdba74ad16138300815cfdc6ab2f4647e23ced81f59e940d7d4a1469d9"},
852
+ {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb532dd9900381d2e8f48172ddc5a59db4c445a11b9fab40b3b786da40d3b56b"},
853
+ {file = "MarkupSafe-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0f84af7e813784feb4d5e4ff7db633aba6c8ca64a833f61d8e4eade234ef0c38"},
854
+ {file = "MarkupSafe-3.0.1-cp312-cp312-win32.whl", hash = "sha256:cbf445eb5628981a80f54087f9acdbf84f9b7d862756110d172993b9a5ae81aa"},
855
+ {file = "MarkupSafe-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:a10860e00ded1dd0a65b83e717af28845bb7bd16d8ace40fe5531491de76b79f"},
856
+ {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e81c52638315ff4ac1b533d427f50bc0afc746deb949210bc85f05d4f15fd772"},
857
+ {file = "MarkupSafe-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:312387403cd40699ab91d50735ea7a507b788091c416dd007eac54434aee51da"},
858
+ {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ae99f31f47d849758a687102afdd05bd3d3ff7dbab0a8f1587981b58a76152a"},
859
+ {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c97ff7fedf56d86bae92fa0a646ce1a0ec7509a7578e1ed238731ba13aabcd1c"},
860
+ {file = "MarkupSafe-3.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7420ceda262dbb4b8d839a4ec63d61c261e4e77677ed7c66c99f4e7cb5030dd"},
861
+ {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45d42d132cff577c92bfba536aefcfea7e26efb975bd455db4e6602f5c9f45e7"},
862
+ {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c8817557d0de9349109acb38b9dd570b03cc5014e8aabf1cbddc6e81005becd"},
863
+ {file = "MarkupSafe-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a54c43d3ec4cf2a39f4387ad044221c66a376e58c0d0e971d47c475ba79c6b5"},
864
+ {file = "MarkupSafe-3.0.1-cp313-cp313-win32.whl", hash = "sha256:c91b394f7601438ff79a4b93d16be92f216adb57d813a78be4446fe0f6bc2d8c"},
865
+ {file = "MarkupSafe-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:fe32482b37b4b00c7a52a07211b479653b7fe4f22b2e481b9a9b099d8a430f2f"},
866
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:17b2aea42a7280db02ac644db1d634ad47dcc96faf38ab304fe26ba2680d359a"},
867
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:852dc840f6d7c985603e60b5deaae1d89c56cb038b577f6b5b8c808c97580f1d"},
868
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0778de17cff1acaeccc3ff30cd99a3fd5c50fc58ad3d6c0e0c4c58092b859396"},
869
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:800100d45176652ded796134277ecb13640c1a537cad3b8b53da45aa96330453"},
870
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d06b24c686a34c86c8c1fba923181eae6b10565e4d80bdd7bc1c8e2f11247aa4"},
871
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:33d1c36b90e570ba7785dacd1faaf091203d9942bc036118fab8110a401eb1a8"},
872
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:beeebf760a9c1f4c07ef6a53465e8cfa776ea6a2021eda0d0417ec41043fe984"},
873
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:bbde71a705f8e9e4c3e9e33db69341d040c827c7afa6789b14c6e16776074f5a"},
874
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-win32.whl", hash = "sha256:82b5dba6eb1bcc29cc305a18a3c5365d2af06ee71b123216416f7e20d2a84e5b"},
875
+ {file = "MarkupSafe-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:730d86af59e0e43ce277bb83970530dd223bf7f2a838e086b50affa6ec5f9295"},
876
+ {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4935dd7883f1d50e2ffecca0aa33dc1946a94c8f3fdafb8df5c330e48f71b132"},
877
+ {file = "MarkupSafe-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e9393357f19954248b00bed7c56f29a25c930593a77630c719653d51e7669c2a"},
878
+ {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40621d60d0e58aa573b68ac5e2d6b20d44392878e0bfc159012a5787c4e35bc8"},
879
+ {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f94190df587738280d544971500b9cafc9b950d32efcb1fba9ac10d84e6aa4e6"},
880
+ {file = "MarkupSafe-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6a387d61fe41cdf7ea95b38e9af11cfb1a63499af2759444b99185c4ab33f5b"},
881
+ {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8ad4ad1429cd4f315f32ef263c1342166695fad76c100c5d979c45d5570ed58b"},
882
+ {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e24bfe89c6ac4c31792793ad9f861b8f6dc4546ac6dc8f1c9083c7c4f2b335cd"},
883
+ {file = "MarkupSafe-3.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2a4b34a8d14649315c4bc26bbfa352663eb51d146e35eef231dd739d54a5430a"},
884
+ {file = "MarkupSafe-3.0.1-cp39-cp39-win32.whl", hash = "sha256:242d6860f1fd9191aef5fae22b51c5c19767f93fb9ead4d21924e0bcb17619d8"},
885
+ {file = "MarkupSafe-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:93e8248d650e7e9d49e8251f883eed60ecbc0e8ffd6349e18550925e31bd029b"},
886
+ {file = "markupsafe-3.0.1.tar.gz", hash = "sha256:3e683ee4f5d0fa2dde4db77ed8dd8a876686e3fc417655c2ece9a90576905344"},
887
  ]
888
 
889
  [[package]]
 
979
 
980
  [[package]]
981
  name = "narwhals"
982
+ version = "1.9.2"
983
  description = "Extremely lightweight compatibility layer between dataframe libraries"
984
  optional = false
985
  python-versions = ">=3.8"
986
  files = [
987
+ {file = "narwhals-1.9.2-py3-none-any.whl", hash = "sha256:9cb9a9a384cd7547e022f9601512c93f8bd784ab6cf55cc5fa76f724bb014989"},
988
+ {file = "narwhals-1.9.2.tar.gz", hash = "sha256:f5b02ec2ff3f5a668719a01e8d434b3fa100fbf1f4fb0d0653202b5c31695c9a"},
989
  ]
990
 
991
  [package.extras]
 
998
 
999
  [[package]]
1000
  name = "networkx"
1001
+ version = "3.4"
1002
  description = "Python package for creating and manipulating graphs and networks"
1003
  optional = false
1004
  python-versions = ">=3.10"
1005
  files = [
1006
+ {file = "networkx-3.4-py3-none-any.whl", hash = "sha256:46dad0ec74a825a968e2b36c37ef5b91faa3868f017b2283d9cbff33112222ce"},
1007
+ {file = "networkx-3.4.tar.gz", hash = "sha256:1269b90f8f0d3a4095f016f49650f35ac169729f49b69d0572b2bb142748162b"},
1008
  ]
1009
 
1010
  [package.extras]
1011
+ default = ["matplotlib (>=3.7)", "numpy (>=1.24)", "pandas (>=2.0)", "scipy (>=1.10,!=1.11.0,!=1.11.1)"]
1012
  developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"]
1013
+ doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.15)", "sphinx (>=7.3)", "sphinx-gallery (>=0.16)", "texext (>=0.6.7)"]
1014
+ example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=1.9)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"]
1015
+ extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"]
1016
  test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"]
1017
 
1018
  [[package]]
 
1559
  [package.extras]
1560
  windows-terminal = ["colorama (>=0.4.6)"]
1561
 
1562
+ [[package]]
1563
+ name = "pylatexenc"
1564
+ version = "2.10"
1565
+ description = "Simple LaTeX parser providing latex-to-unicode and unicode-to-latex conversion"
1566
+ optional = false
1567
+ python-versions = "*"
1568
+ files = [
1569
+ {file = "pylatexenc-2.10.tar.gz", hash = "sha256:3dd8fd84eb46dc30bee1e23eaab8d8fb5a7f507347b23e5f38ad9675c84f40d3"},
1570
+ ]
1571
+
1572
  [[package]]
1573
  name = "pyparsing"
1574
  version = "3.1.4"
 
1960
  {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"},
1961
  ]
1962
 
1963
+ [[package]]
1964
+ name = "st-pages"
1965
+ version = "1.0.1"
1966
+ description = "An experimental version of Streamlit Multi-Page Apps"
1967
+ optional = false
1968
+ python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,!=3.8.*,>=3.9"
1969
+ files = [
1970
+ {file = "st_pages-1.0.1-py3-none-any.whl", hash = "sha256:9098fb4d96bc1dfa56cc2c56ef6fe44e607c69261ff4bceee1f6e9c1e0c2acb4"},
1971
+ {file = "st_pages-1.0.1.tar.gz", hash = "sha256:2641cfbff1c768ff146858ed742d282b30a3a4c3e4f7717898705bbaee717736"},
1972
+ ]
1973
+
1974
+ [package.dependencies]
1975
+ streamlit = ">=1.36.0"
1976
+
1977
  [[package]]
1978
  name = "streamlit"
1979
  version = "1.39.0"
 
2009
  [package.extras]
2010
  snowflake = ["snowflake-connector-python (>=2.8.0)", "snowflake-snowpark-python[modin] (>=1.17.0)"]
2011
 
2012
+ [[package]]
2013
+ name = "streamlit-javascript"
2014
+ version = "0.1.5"
2015
+ description = "component to run javascript code in streamlit application"
2016
+ optional = false
2017
+ python-versions = ">=3.6"
2018
+ files = [
2019
+ {file = "streamlit-javascript-0.1.5.tar.gz", hash = "sha256:9da5176522a0acf2c39d3b0bec9f856fdd8ea3c70bb1066841a546ab1348ae1d"},
2020
+ {file = "streamlit_javascript-0.1.5-py3-none-any.whl", hash = "sha256:36ca4d8c46fd5b6526d1a705530472e03cb6e5bb24694330649f21d5c436d280"},
2021
+ ]
2022
+
2023
+ [package.dependencies]
2024
+ streamlit = ">=0.75"
2025
+
2026
  [[package]]
2027
  name = "swig"
2028
  version = "4.2.1"
 
2329
  [metadata]
2330
  lock-version = "2.0"
2331
  python-versions = "3.10.14"
2332
+ content-hash = "f767bbf8a5395a83cb5196ec5a0313fcc057af9023b4430c635f5135e65c1eff"
pyproject.toml CHANGED
@@ -31,8 +31,11 @@ scikit-image = "^0.24.0"
31
  tqdm = "^4.66.5"
32
  torch = "^2.4.1"
33
  streamlit = "^1.39.0"
 
 
 
34
 
35
 
36
  [build-system]
37
  requires = ["poetry-core"]
38
- build-backend = "poetry.core.masonry.api"
 
31
  tqdm = "^4.66.5"
32
  torch = "^2.4.1"
33
  streamlit = "^1.39.0"
34
+ st-pages = "^1.0.1"
35
+ streamlit-javascript = "^0.1.5"
36
+ pylatexenc = "^2.10"
37
 
38
 
39
  [build-system]
40
  requires = ["poetry-core"]
41
+ build-backend = "poetry.core.masonry.api"
requirements.txt CHANGED
@@ -1,60 +1,84 @@
1
- absl-py==2.1.0
2
- astunparse==1.6.3
 
 
 
3
  certifi==2024.8.30
4
  charset-normalizer==3.3.2
 
5
  cloudpickle==3.0.0
6
- colorama==0.4.6
7
  contourpy==1.3.0
8
  cycler==0.12.1
9
- farama-notifications==0.0.4
10
- flatbuffers==24.3.25
11
- fonttools==4.53.1
12
- gast==0.6.0
13
- google-pasta==0.2.0
14
- grpcio==1.66.1
15
  gymnasium==0.29.1
16
- h5py==3.11.0
17
  idna==3.10
18
  imageio==2.35.1
 
19
  joblib==1.4.2
20
- keras==3.5.0
 
21
  kiwisolver==1.4.7
22
- lazy-loader==0.4
23
- libclang==18.1.1
24
  markdown-it-py==3.0.0
25
- markdown==3.7
26
- markupsafe==2.1.5
27
  matplotlib==3.9.2
28
  mdurl==0.1.2
29
- ml-dtypes==0.4.1
30
- namex==0.0.8
31
  networkx==3.3
32
  numpy==1.24.4
33
- opt-einsum==3.3.0
34
- optree==0.12.1
 
 
 
 
 
 
 
 
 
 
35
  packaging==24.1
 
36
  pillow==10.4.0
37
- protobuf==4.25.4
38
- pygments==2.18.0
 
 
 
 
39
  pyparsing==3.1.4
40
  python-dateutil==2.9.0.post0
 
 
41
  requests==2.32.3
42
- rich==13.8.1
 
43
  scikit-image==0.24.0
44
  scikit-learn==1.5.2
45
  scipy==1.14.1
46
- setuptools==75.1.0
47
  six==1.16.0
48
- tensorboard-data-server==0.7.2
49
- tensorboard==2.17.1
50
- tensorflow-io-gcs-filesystem==0.37.1
51
- tensorflow==2.17.0
52
- termcolor==2.4.0
 
 
53
  threadpoolctl==3.5.0
54
- tifffile==2024.8.30
 
 
 
55
  tqdm==4.66.5
56
- typing-extensions==4.12.2
 
 
57
  urllib3==2.2.3
58
- werkzeug==3.0.4
59
- wheel==0.44.0
60
- wrapt==1.16.0
 
1
+ altair==5.4.1
2
+ attrs==24.2.0
3
+ blinker==1.8.2
4
+ box2d-py==2.3.5
5
+ cachetools==5.5.0
6
  certifi==2024.8.30
7
  charset-normalizer==3.3.2
8
+ click==8.1.7
9
  cloudpickle==3.0.0
 
10
  contourpy==1.3.0
11
  cycler==0.12.1
12
+ Farama-Notifications==0.0.4
13
+ filelock==3.16.1
14
+ fonttools==4.54.1
15
+ fsspec==2024.9.0
16
+ gitdb==4.0.11
17
+ GitPython==3.1.43
18
  gymnasium==0.29.1
 
19
  idna==3.10
20
  imageio==2.35.1
21
+ Jinja2==3.1.4
22
  joblib==1.4.2
23
+ jsonschema==4.23.0
24
+ jsonschema-specifications==2024.10.1
25
  kiwisolver==1.4.7
26
+ lazy_loader==0.4
 
27
  markdown-it-py==3.0.0
28
+ MarkupSafe==3.0.0
 
29
  matplotlib==3.9.2
30
  mdurl==0.1.2
31
+ mpmath==1.3.0
32
+ narwhals==1.9.1
33
  networkx==3.3
34
  numpy==1.24.4
35
+ nvidia-cublas-cu12==12.1.3.1
36
+ nvidia-cuda-cupti-cu12==12.1.105
37
+ nvidia-cuda-nvrtc-cu12==12.1.105
38
+ nvidia-cuda-runtime-cu12==12.1.105
39
+ nvidia-cudnn-cu12==9.1.0.70
40
+ nvidia-cufft-cu12==11.0.2.54
41
+ nvidia-curand-cu12==10.3.2.106
42
+ nvidia-cusolver-cu12==11.4.5.107
43
+ nvidia-cusparse-cu12==12.1.0.106
44
+ nvidia-nccl-cu12==2.20.5
45
+ nvidia-nvjitlink-cu12==12.6.77
46
+ nvidia-nvtx-cu12==12.1.105
47
  packaging==24.1
48
+ pandas==2.2.3
49
  pillow==10.4.0
50
+ protobuf==5.28.2
51
+ pyarrow==17.0.0
52
+ pydeck==0.9.1
53
+ pygame==2.6.1
54
+ Pygments==2.18.0
55
+ pylatexenc==2.10
56
  pyparsing==3.1.4
57
  python-dateutil==2.9.0.post0
58
+ pytz==2024.2
59
+ referencing==0.35.1
60
  requests==2.32.3
61
+ rich==13.9.2
62
+ rpds-py==0.20.0
63
  scikit-image==0.24.0
64
  scikit-learn==1.5.2
65
  scipy==1.14.1
 
66
  six==1.16.0
67
+ smmap==5.0.1
68
+ st-pages==1.0.1
69
+ streamlit==1.39.0
70
+ streamlit-javascript==0.1.5
71
+ swig==4.2.1
72
+ sympy==1.13.3
73
+ tenacity==9.0.0
74
  threadpoolctl==3.5.0
75
+ tifffile==2024.9.20
76
+ toml==0.10.2
77
+ torch==2.4.1
78
+ tornado==6.4.1
79
  tqdm==4.66.5
80
+ triton==3.0.0
81
+ typing_extensions==4.12.2
82
+ tzdata==2024.2
83
  urllib3==2.2.3
84
+ watchdog==5.0.3
 
 
resources/Acrobot-v1/ExtraTrees/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "Acrobot-v1",
3
+ "estimator_name": "ensemble.ExtraTreesClassifier",
4
+ "seed": 42,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 1,
8
+ "batch_size": 0,
9
+ "warm_up": 50,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": -152,
17
+ "final_desired_horizon": 154
18
+ }
resources/Acrobot-v1/ExtraTrees/policy.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac05d51dcf842dadf19ce69f97c3d68579d4ea061c2590d8fc3ebb0ccc63ca28
3
+ size 6551357
resources/Acrobot-v1/Neural/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "Acrobot-v1",
3
+ "estimator_name": "neural",
4
+ "seed": 43,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 100,
8
+ "batch_size": 256,
9
+ "warm_up": 260,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": -63,
17
+ "final_desired_horizon": 64
18
+ }
resources/Acrobot-v1/Neural/policy.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:480d6e152d1620dd3244f313264cc8d591d8d50fb119630d4934302f72a10bb8
3
+ size 171858
resources/Acrobot-v1/RandomForest/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "Acrobot-v1",
3
+ "estimator_name": "ensemble.RandomForestClassifier",
4
+ "seed": 44,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 1,
8
+ "batch_size": 0,
9
+ "warm_up": 50,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": -79,
17
+ "final_desired_horizon": 82
18
+ }
resources/Acrobot-v1/RandomForest/policy.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:940f574693050cadc3f8134e559d47204b4a42d6b7168e7d0ccee1528e264a17
3
+ size 1876900
resources/Acrobot-v1/info.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "Acrobot-v1",
3
+ "state": {
4
+ "0":["$\\sin{\\theta_1}$","Sine of the first link" ],
5
+ "1":["$\\cos{\\theta_1}$","Cosine of the first link" ],
6
+ "2":["$\\sin{\\theta_2}$","Sine of the second link" ],
7
+ "3":["$\\cos{\\theta_2}$","Cosine of the second link" ],
8
+ "4":["$\\dot{\\theta}_1$","Angular velocity of first link" ],
9
+ "5":["$\\dot{\\theta}_2$","Angular velocity of second link" ]
10
+ }
11
+ }
resources/CartPole-v0/ExtraTrees/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "CartPole-v0",
3
+ "estimator_name": "ensemble.ExtraTreesClassifier",
4
+ "seed": 46,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 1,
8
+ "batch_size": 0,
9
+ "warm_up": 50,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": 200,
17
+ "final_desired_horizon": 200
18
+ }
resources/CartPole-v0/ExtraTrees/policy.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7879d9708d67fd2080b5d0f9e5d69a85216f263f47bee5acc17c03010047daf3
3
+ size 5966089
resources/CartPole-v0/Neural/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "CartPole-v0",
3
+ "estimator_name": "neural",
4
+ "seed": 44,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 100,
8
+ "batch_size": 256,
9
+ "warm_up": 260,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": 200,
17
+ "final_desired_horizon": 200
18
+ }
resources/CartPole-v0/Neural/policy.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0cbbd302ea0ab1dce7d54b9e21f81be047f07d585393e8ad001b479246e240ac
3
+ size 169554
resources/CartPole-v0/RandomForest/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "CartPole-v0",
3
+ "estimator_name": "ensemble.RandomForestClassifier",
4
+ "seed": 46,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 1,
8
+ "batch_size": 0,
9
+ "warm_up": 50,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": 200,
17
+ "final_desired_horizon": 200
18
+ }
resources/CartPole-v0/RandomForest/policy.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:98520072de5d1bd3d6a0a78a0100ad313874b367a1d56ce1015752d7671bca4f
3
+ size 1649888
resources/CartPole-v0/info.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "CartPole-v0",
3
+ "state": {
4
+ "0": ["$x$","Cart Position"],
5
+ "1": ["$\\dot{x}$","Cart Velocity"],
6
+ "2": ["$\\theta$","Pole Angle"],
7
+ "3": ["$\\dot{\\theta}$","Pole Angular Velocity"]
8
+ }
9
+ }
resources/LunarLander-v2/ExtraTrees/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "LunarLander-v2",
3
+ "estimator_name": "ensemble.ExtraTreesClassifier",
4
+ "seed": 42,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 1,
8
+ "batch_size": 0,
9
+ "warm_up": 50,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": 73,
17
+ "final_desired_horizon": 209
18
+ }
resources/LunarLander-v2/ExtraTrees/policy.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:973c1bf72f20983c6262aff367d74286f4550e6b43e373cef834d6c2b81c6146
3
+ size 6514542
resources/LunarLander-v2/Neural/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "LunarLander-v2",
3
+ "estimator_name": "neural",
4
+ "seed": 44,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 100,
8
+ "batch_size": 256,
9
+ "warm_up": 260,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return":49,
17
+ "final_desired_horizon": 101
18
+ }
resources/LunarLander-v2/Neural/policy.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b414a79f78938bece951dd20e20e74f94da2a52e0bfe1feaf71b742aa766e0ca
3
+ size 174162
resources/LunarLander-v2/RandomForest/conf.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "env_name": "LunarLander-v2",
3
+ "estimator_name": "ensemble.RandomForestClassifier",
4
+ "seed": 43,
5
+ "max_episode": 500,
6
+ "collect_iter": 15,
7
+ "train_per_iter": 1,
8
+ "batch_size": 0,
9
+ "warm_up": 50,
10
+ "memory_size": 700,
11
+ "last_few": 75,
12
+ "testing_period": 10,
13
+ "horizon_scale": 0.02,
14
+ "return_scale": 0.02,
15
+ "epsilon": 0.2,
16
+ "final_desired_return": 57,
17
+ "final_desired_horizon": 102
18
+ }
resources/LunarLander-v2/RandomForest/policy.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:927333c79f366e2bcb1e6122da5632f71f88c2dbb9caa60ff6185de1dde41a03
3
+ size 2310018
resources/LunarLander-v2/info.json ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ {
3
+ "env_name": "LunarLander-v2",
4
+ "state": {
5
+ "0":["$x$","X position"],
6
+ "1":["$y$","Y position"],
7
+ "2":["$\\dot{x}$","X linear velocity"],
8
+ "3":["$\\dot{y}$","Y linear velocity"],
9
+ "4":["$\\theta$","Angle"],
10
+ "5":["$\\dot{\\theta}$","Angular velocity"],
11
+ "6":["L_contact","Left leg contact points"],
12
+ "7":["R_contact","Right leg contact points"]
13
+ }
14
+ }
udrl/app/home.py ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import streamlit as st
2
+
3
+ st.write("TODO")
udrl/app/sim.py ADDED
@@ -0,0 +1,405 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import gymnasium as gym
3
+ import numpy as np
4
+ import time
5
+ from dataclasses import dataclass, field
6
+ from typing import Dict, Callable, List
7
+ from typing_extensions import Self
8
+ from types import MethodType
9
+ from pathlib import Path
10
+ import re
11
+ from streamlit_javascript import st_javascript
12
+ from skimage.transform import resize
13
+ from udrl.agent import UpsideDownAgent, AgentHyper
14
+ from udrl.policies import SklearnPolicy, NeuralPolicy
15
+ import altair as alt
16
+ import pandas as pd
17
+ import json
18
+
19
+ # from pylatexenc.latex2text import LatexNodes2Text
20
+
21
+
22
+ @dataclass
23
+ class BaseState:
24
+ callbacks: List[Callable[[Self, ...], None]]
25
+
26
+ def __post_init__(self):
27
+ for k, v in self.callbacks.items():
28
+ setattr(self, k, MethodType(v, self))
29
+
30
+
31
+ @dataclass
32
+ class State(BaseState):
33
+ paused: bool = True
34
+ next: bool = False
35
+ reward: float = 0
36
+ epoch: int = 0
37
+
38
+ env_name: str = field(init=False)
39
+ algo_name: str = field(init=False)
40
+ init_desired_return: int = field(init=False)
41
+ init_desired_horizon: int = field(init=False)
42
+ desired_return: int = field(init=False)
43
+ desired_horizon: int = field(init=False)
44
+ agent: UpsideDownAgent = field(init=False)
45
+ feature_importances: List[float] = field(init=False, default_factory=list)
46
+ env: gym.Env = field(init=False)
47
+ frame: np.array = field(init=False, default=None)
48
+ obs: np.array = field(init=False)
49
+
50
+ def __post_init__(self):
51
+ super().__post_init__()
52
+
53
+
54
+ # Function to toggle pause state
55
+ def toggle_pause(state: State):
56
+ state.paused = not state.paused
57
+
58
+
59
+ def next_epoch(state: State):
60
+ state.next = True
61
+
62
+
63
+ def update_frame(state: State):
64
+ state.frame = resize(state.env.render(), (400, 600, 3))
65
+
66
+
67
+ def reset_env(state: State):
68
+ state.obs, _ = state.env.reset()
69
+ state.desired_horizon = state.init_desired_horizon
70
+ state.desired_return = state.init_desired_return
71
+ state.reward = 0
72
+ state.epoch = 0
73
+ update_frame(state)
74
+
75
+
76
+ def sync_state(state: State):
77
+ state.env_name = st.session_state.get("env_name", state.env_name)
78
+ state.algo_name = st.session_state.get("algo_name", state.algo_name)
79
+ state.init_desired_return = st.session_state.get(
80
+ "desired_return", state.init_desired_return
81
+ )
82
+ state.init_desired_horizon = st.session_state.get(
83
+ "desired_horizon", state.init_desired_horizon
84
+ )
85
+
86
+
87
+ def make_env(state: State):
88
+ state.env = gym.make(state.env_name, render_mode="rgb_array")
89
+ reset_env(state)
90
+
91
+
92
+ def make_agent(state: State):
93
+ hyper = AgentHyper(state.env_name, warm_up=0)
94
+ policy_path = str(
95
+ Path("resources") / state.env_name / state.algo_name / "policy"
96
+ )
97
+ if state.algo_name == "Neural":
98
+ policy = NeuralPolicy.load(policy_path)
99
+ else:
100
+ policy = SklearnPolicy.load(policy_path)
101
+
102
+ state.agent = UpsideDownAgent(hyper, policy)
103
+
104
+
105
+ def merge_callbacks(list_fun):
106
+ def callback():
107
+ for f in list_fun:
108
+ f()
109
+
110
+ return callback
111
+
112
+
113
+ CALLBACKS = [
114
+ toggle_pause,
115
+ update_frame,
116
+ reset_env,
117
+ make_env,
118
+ sync_state,
119
+ next_epoch,
120
+ make_agent,
121
+ ]
122
+
123
+
124
+ def init():
125
+ state = State({c.__name__: c for c in CALLBACKS})
126
+ return state
127
+
128
+
129
+ def get_envs():
130
+ return [
131
+ p.name
132
+ for p in Path("resources").iterdir()
133
+ if re.match(r".*-v.*", p.name)
134
+ ]
135
+
136
+
137
+ def get_algo(env):
138
+
139
+ return [
140
+ p.name
141
+ for p in (Path("resources") / env).iterdir()
142
+ if p.name != "info.json"
143
+ ]
144
+
145
+
146
+ def make_exp_parameters(state):
147
+ with st.form("exp_param"):
148
+ col1, col2, col3 = st.columns(3)
149
+ with col1:
150
+ state.env_name = st.radio(
151
+ "Available Environments", sorted(get_envs()), key="env_name"
152
+ )
153
+ with col2:
154
+ state.algo_name = st.radio(
155
+ "Available Estimators",
156
+ sorted(get_algo(state.env_name)),
157
+ key="algo_name",
158
+ )
159
+ with col3:
160
+ state.init_desired_return = st.number_input(
161
+ "Desired return:", step=1, key="desired_return", value=200
162
+ )
163
+ state.init_desired_horizon = st.number_input(
164
+ "Desired horizon:", step=1, key="desired_horizon", value=200
165
+ )
166
+
167
+ st.form_submit_button(
168
+ "Update Experiment",
169
+ on_click=merge_callbacks(
170
+ [state.sync_state, state.make_env, state.make_agent]
171
+ ),
172
+ )
173
+ return state
174
+
175
+
176
+ @st.cache_data
177
+ def load_env_info(env_name):
178
+ info_path = Path("resources") / env_name / "info.json"
179
+ with open(str(info_path), "r") as f:
180
+ info = json.load(f)
181
+ return info
182
+
183
+
184
+ def make_viz(state):
185
+ with st.container(key="viz"):
186
+ sim_col, featur_col = st.columns([3, 2], vertical_alignment="center")
187
+
188
+ with sim_col:
189
+ st.header("Environment Visualization", divider=True)
190
+ image_placeholder = st.empty()
191
+ image_placeholder.image(
192
+ state.frame,
193
+ caption=f"Environment Visualization {'(Paused)' if state.paused else ''}",
194
+ use_column_width=True,
195
+ )
196
+
197
+ val = st_javascript(
198
+ 'window.parent.document.getElementsByClassName("st-key-viz")[0].querySelector("img").height'
199
+ )
200
+
201
+ with featur_col:
202
+ st.header("Feature Importance", divider=True)
203
+ if state.algo_name == "Neural":
204
+ st.write(
205
+ "Unable to show Feature Importance for this estimator"
206
+ )
207
+ elif not state.feature_importances:
208
+ st.write(
209
+ "Run the simulation to calculate the feature importance"
210
+ )
211
+ elif (
212
+ len(state.feature_importances)
213
+ != len(list(load_env_info(state.env_name)["state"].values()))
214
+ + 2
215
+ ):
216
+ st.write(
217
+ "Run the simulation to calculate the feature importance"
218
+ )
219
+
220
+ else:
221
+ data = pd.DataFrame(
222
+ {
223
+ "f": state.feature_importances,
224
+ "index": [
225
+ # LatexNodes2Text().latex_to_text(v[0])
226
+ v[1][:17]
227
+ for v in load_env_info(state.env_name)[
228
+ "state"
229
+ ].values()
230
+ ]
231
+ + ["d_r", "d_t"],
232
+ }
233
+ )
234
+ base = (
235
+ alt.Chart(data)
236
+ .mark_bar()
237
+ .encode(
238
+ x=alt.X(
239
+ "f",
240
+ scale=alt.Scale(domain=[-10, 30]),
241
+ ),
242
+ y="index:O",
243
+ color="index:N",
244
+ )
245
+ .properties(height=int(val))
246
+ )
247
+
248
+ st.altair_chart(
249
+ base + base.mark_text(align="left", dx=2),
250
+ use_container_width=True,
251
+ )
252
+
253
+ return state
254
+
255
+
256
+ def make_commands(state):
257
+ # Add control buttons in a horizontal layout
258
+ col1, col2, col3, col4 = st.columns(4)
259
+ with col1:
260
+ st.button("Reset Environment", on_click=state.reset_env)
261
+ with col2:
262
+ st.button(
263
+ "Resume" if state.paused else "Pause", on_click=state.toggle_pause
264
+ )
265
+ with col3:
266
+ st.button("Next", on_click=state.next_epoch)
267
+ with col4:
268
+ st.button("Save")
269
+ return state
270
+
271
+
272
+ def calculate_feat_imp(state: State, ext_state):
273
+ if state.algo_name == "Neural":
274
+ state.feature_importances = []
275
+ return
276
+
277
+ feature_importances = {idx: [] for idx in range(ext_state.shape[1])}
278
+
279
+ for t in state.agent.policy.estimator.estimators_:
280
+ branch = np.array(t.decision_path(ext_state).todense(), dtype=bool)
281
+ imp = t.tree_.impurity[branch[0]]
282
+
283
+ for f, i in zip(t.tree_.feature[branch[0]][:-1], imp[:-1] - imp[1:]):
284
+ feature_importances.setdefault(f, []).append(i)
285
+
286
+ state.feature_importances = [
287
+ sum(feature_importances.get(k, [0.001]))
288
+ for k in range(len(feature_importances.keys()))
289
+ ]
290
+
291
+
292
+ @st.cache_data
293
+ def env_info_md(env_name):
294
+ info = load_env_info(env_name)
295
+ str_info = f"Environment name: {info['env_name']}\n"
296
+ str_info += "State dimensions: \n"
297
+ str_info += "&nbsp;&nbsp;&nbsp;&nbsp;" + "\n&nbsp;&nbsp;&nbsp;&nbsp;".join(
298
+ [f"{v[0]} -> {v[1]}" for k, v in info["state"].items()]
299
+ )
300
+ return str_info
301
+
302
+
303
+ @st.cache_data
304
+ def load_algo_info(env_name, algo_name):
305
+ info_path = Path("resources") / env_name / algo_name / "conf.json"
306
+ with open(str(info_path), "r") as f:
307
+ info = json.load(f)
308
+ return info
309
+
310
+
311
+ @st.cache_data
312
+ def algo_info_md(env_name, algo_name):
313
+ info = load_algo_info(env_name, algo_name)
314
+ str_info = f"Algorithm: {info['estimator_name']}\n"
315
+ str_info += f"Suggested Desired Return: {info['final_desired_return']}\n"
316
+ str_info += f"Suggested Desired Horizon: {info['final_desired_horizon']}\n"
317
+ full_conf = "&nbsp;&nbsp;&nbsp;&nbsp;" + "\n&nbsp;&nbsp;&nbsp;&nbsp;".join(
318
+ [f"{k} -> {v}" for k, v in info.items()]
319
+ )
320
+
321
+ return str_info, full_conf
322
+
323
+
324
+ def make_metrics(state: State):
325
+ col1, col2, col3, col4 = st.columns(4)
326
+ with col1:
327
+ st.metric("Epoch", state.epoch)
328
+ with col2:
329
+ st.metric("Cum Reward", state.reward)
330
+ with col3:
331
+ st.metric("Desired Return", state.desired_return)
332
+ with col4:
333
+ st.metric("Desired Horizon", state.desired_horizon)
334
+
335
+
336
+ def run(state: State):
337
+ make_exp_parameters(state)
338
+ if state.frame is None:
339
+ state.sync_state()
340
+ state.make_env()
341
+ state.make_agent()
342
+ make_metrics(state)
343
+ make_viz(state)
344
+ make_commands(state)
345
+
346
+ if not state.paused or state.next:
347
+ command = np.array(
348
+ [
349
+ state.desired_return * state.agent.conf.return_scale,
350
+ state.desired_horizon * state.agent.conf.horizon_scale,
351
+ ]
352
+ )
353
+ command = np.expand_dims(command, axis=0)
354
+ obs = np.expand_dims(state.obs, axis=0)
355
+
356
+ action = state.agent.policy(obs, command, True)
357
+
358
+ ext_state = np.concatenate((obs, command), axis=1)
359
+
360
+ state.obs, reward, ter, tru, info = state.env.step(action)
361
+
362
+ calculate_feat_imp(state, ext_state)
363
+
364
+ # Line 8 Algorithm 2
365
+ state.desired_return -= reward
366
+ # Line 9 Algorithm 2
367
+ state.desired_horizon = max(state.desired_horizon - 1, 1)
368
+
369
+ state.update_frame()
370
+ state.next = False
371
+ state.epoch += 1
372
+ state.reward += reward
373
+ if ter or tru:
374
+ state.reset_env()
375
+
376
+ # Create a container for environment info
377
+ sidebar_container = st.sidebar.container()
378
+ with sidebar_container:
379
+ st.slider(
380
+ "Refresh Rate", min_value=1, max_value=20, key="refresh_rate"
381
+ )
382
+ st.header("Environment Info")
383
+ for line in env_info_md(state.env_name).split("\n"):
384
+ st.markdown(line)
385
+ st.header("Algorithm Info")
386
+ algo_info, conf_info = algo_info_md(state.env_name, state.algo_name)
387
+ for line in algo_info.split("\n"):
388
+ st.markdown(line)
389
+ with st.expander("Full Configuration"):
390
+ for line in conf_info.split("\n"):
391
+ st.markdown(line)
392
+
393
+ # Add auto-refresh logic
394
+ if not state.paused:
395
+ sleep_time = 1 - (st.session_state.refresh_rate - 1) * (1 - 0.05) / 19
396
+ time.sleep(sleep_time) # Add a small delay to control refresh rate
397
+ st.rerun()
398
+
399
+ return state
400
+
401
+
402
+ if "sim" not in st.session_state:
403
+ st.session_state.sim = init()
404
+
405
+ run(st.session_state.sim)