mirror of
https://github.com/gsi-upm/soil
synced 2025-08-24 03:52:20 +00:00
v1.0.0rc11
This commit is contained in:
355
examples/markov_chains/MarkovChains.ipynb
Normal file
355
examples/markov_chains/MarkovChains.ipynb
Normal file
@@ -0,0 +1,355 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "7641396c-a602-477e-bf03-09e1191ff549",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%load_ext autoreload"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "4f12285c-78db-4ee8-b9c6-7799d34f10f5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%autoreload 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "7710bb03-0cb9-413a-a407-fe48855ff917",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%aimport markov_sim"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"id": "2dffca0f-da9e-4f69-ac43-7afe52ad2d32",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%aimport soil\n",
|
||||
"%aimport soil.visualization"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "12871006-70ca-4c6f-8a3e-0aae1d0bce31",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"G = markov_sim.load_city_graph(\"Chamberi, Madrid\", network_type=\"drive\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"id": "31e96cc5-b703-4d2a-a006-7b9a2cedc365",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# env = markov_sim.CityEnv(G=G, n_assets=20, side=10, max_weight=1, seed=10)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"id": "5e070b36-0ba6-4780-8fd4-3c72fa3bb240",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# for i in range(2):\n",
|
||||
"# env.step()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 35,
|
||||
"id": "56f8b997-65b0-431d-9517-b93edb1cfcd8",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/j/.cache/pypoetry/virtualenvs/soil-cCX5yKRx-py3.10/lib/python3.10/site-packages/osmnx/plot.py:955: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown\n",
|
||||
" plt.show()\n",
|
||||
"/home/j/.cache/pypoetry/virtualenvs/soil-cCX5yKRx-py3.10/lib/python3.10/site-packages/osmnx/plot.py:955: UserWarning: FigureCanvasAgg is non-interactive, and thus cannot be shown\n",
|
||||
" plt.show()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "86e45bd44e434674b11805fd94e98414",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
"text/html": [
|
||||
"Cannot show widget. You probably want to rerun the code cell above (<i>Click in the code cell, and press Shift+Enter <kbd>⇧</kbd>+<kbd>↩</kbd></i>)."
|
||||
],
|
||||
"text/plain": [
|
||||
"Cannot show ipywidgets in text"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from soil.visualization import JupyterViz, GeoNetworkDrawer, Controller\n",
|
||||
"from soil import visualization\n",
|
||||
"from matplotlib import colors\n",
|
||||
"from matplotlib import colormaps\n",
|
||||
"plasma = colormaps.get_cmap('plasma')\n",
|
||||
"model_params = {\n",
|
||||
" \"n_assets\": {\n",
|
||||
" \"type\": \"SliderInt\",\n",
|
||||
" \"value\": 100,\n",
|
||||
" \"label\": \"Number of assets:\",\n",
|
||||
" \"min\": 1,\n",
|
||||
" \"max\": 1000,\n",
|
||||
" \"step\": 1,\n",
|
||||
" },\n",
|
||||
" \"max_weight\": {\n",
|
||||
" \"type\": \"SliderInt\",\n",
|
||||
" \"value\": 3,\n",
|
||||
" \"label\": \"Maximum edge weight:\",\n",
|
||||
" \"min\": 1,\n",
|
||||
" \"max\": 20,\n",
|
||||
" \"step\": 1,\n",
|
||||
" },\n",
|
||||
" \"ratio_lazy\": {\n",
|
||||
" \"type\": \"SliderFloat\",\n",
|
||||
" \"value\": 0,\n",
|
||||
" \"label\": \"Ratio of lazy agents (they prefer shorter streets):\",\n",
|
||||
" \"min\": 0,\n",
|
||||
" \"max\": 1,\n",
|
||||
" \"step\": 0.05,\n",
|
||||
" },\n",
|
||||
" \"side\": {\n",
|
||||
" \"type\": \"SliderInt\",\n",
|
||||
" \"value\": 10,\n",
|
||||
" \"label\": \"Size of the side:\",\n",
|
||||
" \"min\": 2,\n",
|
||||
" \"max\": 20,\n",
|
||||
" \"step\": 1,\n",
|
||||
" },\n",
|
||||
" \"gradual_move\": {\n",
|
||||
" \"type\": \"Checkbox\",\n",
|
||||
" \"value\": True,\n",
|
||||
" \"label\": \"Use gradual movement\",\n",
|
||||
" }, \n",
|
||||
" \"lockstep\": {\n",
|
||||
" \"type\": \"Checkbox\",\n",
|
||||
" \"value\": True,\n",
|
||||
" \"label\": \"Run in locksteps\",\n",
|
||||
" },\n",
|
||||
" \"G\": G,\n",
|
||||
" # \"width\": 10,\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"def colorize(d):\n",
|
||||
" # print(d)\n",
|
||||
" if any(a.waiting for a in d):\n",
|
||||
" return 'red'\n",
|
||||
" else:\n",
|
||||
" return 'blue'\n",
|
||||
"\n",
|
||||
"def network_portrayal(graph, spring=True):\n",
|
||||
" global pos, l\n",
|
||||
" node_size = [10*(len(node[1][\"agent\"])) for node in graph.nodes(data=True)]\n",
|
||||
" node_color = [colorize(d[\"agent\"]) for (k, d) in graph.nodes(data=True)]\n",
|
||||
" # pos = {node: (d[\"x\"], d[\"y\"]) for node, d in graph.nodes(data=True)}\n",
|
||||
" edge_width = [graph.edges[k]['travel_time']/100 for k in graph.edges]\n",
|
||||
" # print(edge_width)\n",
|
||||
" weights = [graph.edges[k]['occupation'] for k in graph.edges]\n",
|
||||
" norm = colors.Normalize(vmin=0, vmax=max(weights))\n",
|
||||
" color = plasma(norm(weights))\n",
|
||||
" # print(color)\n",
|
||||
" return dict(node_size=node_size, node_color=node_color, edge_linewidth=edge_width, edge_color=color)\n",
|
||||
"\n",
|
||||
"page = visualization.JupyterViz(\n",
|
||||
" markov_sim.CityEnv,\n",
|
||||
" model_params,\n",
|
||||
" measures=[\"NodeGini\", \"EdgeGini\", \"EdgeOccupation\"],\n",
|
||||
" name=\"City Environment\",\n",
|
||||
" space_drawer=GeoNetworkDrawer,\n",
|
||||
" agent_portrayal=network_portrayal,\n",
|
||||
" columns=3,\n",
|
||||
")\n",
|
||||
"# This is required to render the visualization in the Jupyter notebook\n",
|
||||
"page"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"id": "70da18d7-66bd-4710-89a6-aca14707c56e",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div>\n",
|
||||
"<style scoped>\n",
|
||||
" .dataframe tbody tr th:only-of-type {\n",
|
||||
" vertical-align: middle;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe tbody tr th {\n",
|
||||
" vertical-align: top;\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" .dataframe thead th {\n",
|
||||
" text-align: right;\n",
|
||||
" }\n",
|
||||
"</style>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>NodeGini</th>\n",
|
||||
" <th>EdgeGini</th>\n",
|
||||
" <th>EdgeOccupation</th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>0.866567</td>\n",
|
||||
" <td>0.927276</td>\n",
|
||||
" <td>0.087624</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>0.866567</td>\n",
|
||||
" <td>0.933494</td>\n",
|
||||
" <td>0.081301</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>0.863867</td>\n",
|
||||
" <td>0.933163</td>\n",
|
||||
" <td>0.078591</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>0.866567</td>\n",
|
||||
" <td>0.929943</td>\n",
|
||||
" <td>0.084914</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>0.869433</td>\n",
|
||||
" <td>0.934949</td>\n",
|
||||
" <td>0.076784</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>...</th>\n",
|
||||
" <td>...</td>\n",
|
||||
" <td>...</td>\n",
|
||||
" <td>...</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>127</th>\n",
|
||||
" <td>0.880367</td>\n",
|
||||
" <td>0.934185</td>\n",
|
||||
" <td>0.075881</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>128</th>\n",
|
||||
" <td>0.881400</td>\n",
|
||||
" <td>0.933038</td>\n",
|
||||
" <td>0.078591</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>129</th>\n",
|
||||
" <td>0.881400</td>\n",
|
||||
" <td>0.936299</td>\n",
|
||||
" <td>0.078591</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>130</th>\n",
|
||||
" <td>0.881400</td>\n",
|
||||
" <td>0.929784</td>\n",
|
||||
" <td>0.086721</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>131</th>\n",
|
||||
" <td>0.876733</td>\n",
|
||||
" <td>0.932746</td>\n",
|
||||
" <td>0.082204</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"<p>132 rows × 3 columns</p>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" NodeGini EdgeGini EdgeOccupation\n",
|
||||
"0 0.866567 0.927276 0.087624\n",
|
||||
"1 0.866567 0.933494 0.081301\n",
|
||||
"2 0.863867 0.933163 0.078591\n",
|
||||
"3 0.866567 0.929943 0.084914\n",
|
||||
"4 0.869433 0.934949 0.076784\n",
|
||||
".. ... ... ...\n",
|
||||
"127 0.880367 0.934185 0.075881\n",
|
||||
"128 0.881400 0.933038 0.078591\n",
|
||||
"129 0.881400 0.936299 0.078591\n",
|
||||
"130 0.881400 0.929784 0.086721\n",
|
||||
"131 0.876733 0.932746 0.082204\n",
|
||||
"\n",
|
||||
"[132 rows x 3 columns]"
|
||||
]
|
||||
},
|
||||
"execution_count": 39,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"page.controller.model.datacollector.get_model_vars_dataframe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d9a7d3c8-2f87-47d5-8d27-a7387ea3457d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
11
examples/markov_chains/app.py
Normal file
11
examples/markov_chains/app.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from flask import Flask
|
||||
import solara.server.flask
|
||||
|
||||
app = Flask(__name__)
|
||||
app.register_blueprint(solara.server.flask.blueprint, url_prefix="/solara/")
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def hello_world():
|
||||
return "<p>Hello, World!</p>"
|
||||
|
1
examples/markov_chains/cache/09a7a68a80018222f1664b90343892049e1aa11c.json
vendored
Normal file
1
examples/markov_chains/cache/09a7a68a80018222f1664b90343892049e1aa11c.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
examples/markov_chains/cache/197dbd44d019bd1193a35cd7a026cc804ebd1050.json
vendored
Normal file
1
examples/markov_chains/cache/197dbd44d019bd1193a35cd7a026cc804ebd1050.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
examples/markov_chains/cache/22d10b0cf32c036918f028c264b91bf130ec62f1.json
vendored
Normal file
1
examples/markov_chains/cache/22d10b0cf32c036918f028c264b91bf130ec62f1.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
examples/markov_chains/cache/b64244838e9beadda30d0d2a72a54353258b5c83.json
vendored
Normal file
1
examples/markov_chains/cache/b64244838e9beadda30d0d2a72a54353258b5c83.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
examples/markov_chains/cache/b83091b27a005b409e64054a3cad9807ecce636c.json
vendored
Normal file
1
examples/markov_chains/cache/b83091b27a005b409e64054a3cad9807ecce636c.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
examples/markov_chains/cache/cd74ca98335920ce3055676b8729521ca6f6767a.json
vendored
Normal file
1
examples/markov_chains/cache/cd74ca98335920ce3055676b8729521ca6f6767a.json
vendored
Normal file
File diff suppressed because one or more lines are too long
159
examples/markov_chains/markov_sim.py
Normal file
159
examples/markov_chains/markov_sim.py
Normal file
@@ -0,0 +1,159 @@
|
||||
'''
|
||||
This scenario has drivers driving around a city.
|
||||
In this model, drivers can only be at intersections, which are treated as nodes in the City Graph (grid).
|
||||
|
||||
At the start of the simulation, drivers are randomly positioned in the city grid.
|
||||
|
||||
The following models for agent behavior are included:
|
||||
|
||||
* DummyDriver: In each simulation step, this type of driver can instantly move to any of the neighboring nodes in the grid, or stay in its place.
|
||||
|
||||
'''
|
||||
|
||||
import networkx as nx
|
||||
from soil import Environment, BaseAgent, state, time
|
||||
from mesa.space import NetworkGrid
|
||||
import mesa
|
||||
import statistics
|
||||
|
||||
|
||||
class CityGrid(NetworkGrid):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for (u, v, d) in self.G.edges(data=True):
|
||||
d["occupation"] = 0
|
||||
# self.dijkstras = dict(nx.all_pairs_dijkstra(self.G, weight="length"))
|
||||
|
||||
# def eta(self, pos1, pos2):
|
||||
# return self.dijkstras[pos1][0][pos2]
|
||||
|
||||
def travel_time(self, pos1, pos2):
|
||||
return float(min(d["travel_time"] for d in self.G.adj[pos1][pos2].values()))
|
||||
|
||||
|
||||
def node_occupation(self):
|
||||
return {k: len(v.get("agent", [])) for (k, v) in self.G.nodes(data=True)}
|
||||
|
||||
def edge_occupation(self):
|
||||
return {(u,v): d.get('occupation', 1) for (u, v, d) in self.G.edges(data=True)}
|
||||
|
||||
|
||||
class Roamer(BaseAgent):
|
||||
waiting = False
|
||||
|
||||
def step(self):
|
||||
'''
|
||||
A simple driver that just moves to a neighboring cell in the city
|
||||
'''
|
||||
yield from self.move_to(None)
|
||||
return self.delay(0)
|
||||
|
||||
def choose_next(self):
|
||||
opts = self.model.grid.get_neighborhood(self.pos, include_center=False)
|
||||
pos = self.random.choice(opts)
|
||||
delay = self.model.grid.travel_time(self.pos, pos)
|
||||
return pos, delay
|
||||
|
||||
def move_to(self, pos=None):
|
||||
self.waiting = True
|
||||
if pos is None:
|
||||
pos, delay = self.choose_next()
|
||||
if self.model.gradual_move:
|
||||
# Calculate how long it will take, and wait for that long
|
||||
if pos != self.pos:
|
||||
self.model.grid.G.edges[self.pos,pos,0]["occupation"] += 1
|
||||
yield delay
|
||||
if self.model.gradual_move and pos != self.pos:
|
||||
w1 = self.model.grid.G.edges[self.pos,pos,0]["occupation"]
|
||||
oldpos = self.pos
|
||||
self.model.grid.G.edges[self.pos,pos,0]["occupation"] = w1 - 1
|
||||
assert self.model.grid.G.edges[self.pos,pos,0]["occupation"] == w1-1
|
||||
self.model.grid.move_agent(self, pos)
|
||||
self.waiting = False
|
||||
|
||||
|
||||
class LazyRoamer(Roamer):
|
||||
waiting = False
|
||||
def choose_next(self):
|
||||
opts = self.model.grid.get_neighborhood(self.pos, include_center=False)
|
||||
times = [self.model.grid.travel_time(self.pos, other) for other in opts]
|
||||
idx = self.random.choices(range(len(times)), k=1, weights=[1/time for time in times])[0]
|
||||
return opts[idx], times[idx]
|
||||
|
||||
|
||||
|
||||
def gini(values):
|
||||
s = sum(values)
|
||||
|
||||
N = len(values)
|
||||
if s == 0:
|
||||
return 0
|
||||
x = sorted(values)
|
||||
|
||||
B = sum(xi * (N - i) for i, xi in enumerate(x)) / (N * s)
|
||||
return 1 + (1 / N) - 2 * B
|
||||
|
||||
|
||||
class CityEnv(Environment):
|
||||
def __init__(self, *, G, side=20, n_assets=100, ratio_lazy=1, lockstep=True, gradual_move=True, max_weight=1, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
if lockstep:
|
||||
self.schedule = time.Lockstepper(self.schedule)
|
||||
self.n_assets = n_assets
|
||||
self.side = side
|
||||
self.max_weight = max_weight
|
||||
self.gradual_move = gradual_move
|
||||
self.grid = CityGrid(g=G)
|
||||
|
||||
n_lazy = round(self.n_assets * ratio_lazy)
|
||||
n_other = self.n_assets - n_lazy
|
||||
self.add_agents(Roamer, k=n_other)
|
||||
self.add_agents(LazyRoamer, k=n_lazy)
|
||||
|
||||
positions = list(self.grid.G.nodes)
|
||||
for agent in self.get_agents():
|
||||
pos = self.random.choice(positions)
|
||||
self.grid.place_agent(agent, pos)
|
||||
|
||||
self.datacollector = mesa.DataCollector(
|
||||
model_reporters={
|
||||
"NodeGini": lambda model: gini(model.grid.node_occupation().values()),
|
||||
"EdgeGini": lambda model: gini(model.grid.edge_occupation().values()),
|
||||
"EdgeOccupation": lambda model: statistics.mean(model.grid.edge_occupation().values()),
|
||||
}#, agent_reporters={"Wealth": "wealth"}
|
||||
)
|
||||
|
||||
class SquareCityEnv(CityEnv):
|
||||
def __init__(self, *, side=20, **kwargs):
|
||||
self.side = side
|
||||
G = nx.grid_graph(dim=[side, side])
|
||||
for (_, _, d) in G.edges(data=True):
|
||||
d["travel_time"] = self.random.randint(1, self.max_weight)
|
||||
|
||||
for (k, d) in G.nodes(data=True):
|
||||
d["pos"] = k
|
||||
super().__init__(**kwargs, G=G)
|
||||
|
||||
import osmnx as ox
|
||||
|
||||
|
||||
class NamedCityEnv(CityEnv):
|
||||
def __init__(self, *, location="Chamberi, Madrid", **kwargs):
|
||||
self.location = location
|
||||
super().__init__(**kwargs, G=load_city_graph(location))
|
||||
|
||||
|
||||
def load_city_graph(location='Chamberi, Madrid', **kwargs):
|
||||
G = ox.graph.graph_from_place(location, **kwargs)
|
||||
G = ox.add_edge_speeds(G)
|
||||
G = ox.add_edge_travel_times(G)
|
||||
largest = sorted(nx.strongly_connected_components(G), key=lambda x: len(x))[-1]
|
||||
G = G.subgraph(largest)
|
||||
return G
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
env = CityEnv()
|
||||
for i in range(100):
|
||||
env.step()
|
26
examples/markov_chains/sol.py
Normal file
26
examples/markov_chains/sol.py
Normal file
@@ -0,0 +1,26 @@
|
||||
import solara
|
||||
|
||||
@solara.component
|
||||
def MainPage(clicks):
|
||||
color = "green"
|
||||
if clicks.value >= 5:
|
||||
color = "red"
|
||||
|
||||
def increment():
|
||||
clicks.value += 1
|
||||
print("clicks", clicks) # noqa
|
||||
|
||||
solara.Button(label=f"Clicked: {clicks}", on_click=increment, color=color)
|
||||
|
||||
@solara.component
|
||||
def Page():
|
||||
v = Visualization()
|
||||
v.viz()
|
||||
|
||||
class Visualization:
|
||||
def __init__(self):
|
||||
self.clicks = solara.reactive(0)
|
||||
|
||||
def viz(self):
|
||||
from sol_lib import MainPage
|
||||
return MainPage(self.clicks)
|
13
examples/markov_chains/sol_lib.py
Normal file
13
examples/markov_chains/sol_lib.py
Normal file
@@ -0,0 +1,13 @@
|
||||
import solara
|
||||
|
||||
@solara.component
|
||||
def MainPage(clicks):
|
||||
color = "green"
|
||||
if clicks.value >= 5:
|
||||
color = "red"
|
||||
|
||||
def increment():
|
||||
clicks.value += 1
|
||||
print("clicks", clicks) # noqa
|
||||
|
||||
solara.Button(label=f"Clicked: {clicks}", on_click=increment, color=color)
|
Reference in New Issue
Block a user