mirror of
https://github.com/logos-co/SimulationsFramework.git
synced 2025-02-22 18:58:18 +00:00
commit
48da9c5730
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.md
|
||||||
|
.venv
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
|||||||
.idea/
|
.idea/
|
||||||
|
.venv/
|
||||||
|
*__pycache__*
|
34
Dockerfile
Normal file
34
Dockerfile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# BUILD IMAGE --------------------------------------------------------
|
||||||
|
|
||||||
|
FROM rust as builder
|
||||||
|
|
||||||
|
# Update default packages
|
||||||
|
RUN apt-get update
|
||||||
|
|
||||||
|
# Get tools needed
|
||||||
|
RUN apt-get install -y git
|
||||||
|
|
||||||
|
# Get the simulation code
|
||||||
|
WORKDIR /rust-app
|
||||||
|
RUN git clone https://github.com/logos-co/consensus-research.git
|
||||||
|
|
||||||
|
# Compile it
|
||||||
|
WORKDIR /rust-app/consensus-research
|
||||||
|
RUN cargo build --profile release-opt --bin snow-family
|
||||||
|
|
||||||
|
|
||||||
|
# ACTUAL IMAGE ------------------------------------------------------
|
||||||
|
FROM python
|
||||||
|
|
||||||
|
COPY --from=builder /rust-app/consensus-research/target/release-opt/snow-family /usr/local/bin/snow-family
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
ENV PYTHONPATH "${PYTHONPATH}:src"
|
||||||
|
|
||||||
|
ENTRYPOINT ["python", "src/main.py"]
|
||||||
|
|
||||||
|
|
57
README.md
Executable file
57
README.md
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
# Simulations Framework
|
||||||
|
|
||||||
|
This framework is to run simulations, as well as being able to obtain plots from the results in an easy-one command manner.
|
||||||
|
|
||||||
|
Simulations supported:
|
||||||
|
- Snow family: https://github.com/logos-co/consensus-research (default)
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
In order to build the image, simply run:
|
||||||
|
|
||||||
|
`docker build -t desired_name_of_docker_image .`
|
||||||
|
|
||||||
|
In order to tell the container what to do, you need to specify the options in a configuration file, as json.
|
||||||
|
More information in:
|
||||||
|
|
||||||
|
|
||||||
|
Supported parameters:
|
||||||
|
- Run parameters `--run` or `-r`
|
||||||
|
- `both` (default) (to-do)
|
||||||
|
- `simulation`
|
||||||
|
- `plotter` (to-do)
|
||||||
|
- Simulation type `--protocol` or `-p` (to-do)
|
||||||
|
- `snow-family` (default, not changeable)
|
||||||
|
- Configuration file `--configuration-file` or `-cf`
|
||||||
|
- <configuration_file_name.json>
|
||||||
|
|
||||||
|
In order to receive the information, plots, and whatever is done inside the container, a shared folder is
|
||||||
|
provided inside this repository. Before running the container,
|
||||||
|
|
||||||
|
### Example of execution:
|
||||||
|
|
||||||
|
`docker run --rm -v </your/path/to/SimulationsFramework/shared>:/app/shared <desired_name_of_docker_image>
|
||||||
|
-r <simulation> -cf <configuration_file_name.json>`
|
||||||
|
|
||||||
|
The parameters inside `< >` can be changed. Where:
|
||||||
|
|
||||||
|
- `docker run --rm` will launch a docker container, and after it finishes, it will automatically destroy itself.
|
||||||
|
- `-v </your/path/to/SimulationsFramework/shared>:/app/shared` is the mount folder that will be used to share data
|
||||||
|
between the container and the host. In order to make things easier, the folder inside this repo can be used for that.
|
||||||
|
Still, any desired folder can be put here, as long as it is in absolute path. `/app/shared` is a internal framework
|
||||||
|
location, so this needs to remain unchanged.
|
||||||
|
- `<desired_name_of_docker_image>` is the docker image name previously created.
|
||||||
|
- `-r <simulation>` is the type of execution we want. It can be only simulation `simulation`, only plotting `plotter`,
|
||||||
|
or simulation and plot `both`. This last option is as default, so if this is the case, it is something that needs to
|
||||||
|
be specified.
|
||||||
|
- `-cf <configuration_file_name.json>` is the configuration file where we set up what we want to do in the execution.
|
||||||
|
This file needs to be in our shared host folder.
|
||||||
|
|
||||||
|
So, an example of a command would be:
|
||||||
|
|
||||||
|
`docker run --rm -v /mnt/d/Projects/SimulationsFramework/shared:/app/shared simulation-framework
|
||||||
|
-r simulation -cf config_example.json`
|
||||||
|
|
||||||
|
## Project structure
|
||||||
|
|
||||||
|
(to-do)
|
@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
"consensus_settings": {
|
|
||||||
"snow_ball": {
|
|
||||||
"quorum_size": 14,
|
|
||||||
"sample_size": 20,
|
|
||||||
"decision_threshold": 20
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"distribution": {
|
|
||||||
"yes": 0.6,
|
|
||||||
"no": 0.4,
|
|
||||||
"none": 0.0
|
|
||||||
},
|
|
||||||
"byzantine_settings": {
|
|
||||||
"total_size": 10000,
|
|
||||||
"distribution": {
|
|
||||||
"honest": 1.0,
|
|
||||||
"infantile": 0.0,
|
|
||||||
"random": 0.0,
|
|
||||||
"omniscient": 0.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wards": [
|
|
||||||
{
|
|
||||||
"time_to_finality": {
|
|
||||||
"ttf_threshold" : 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"network_modifiers": [
|
|
||||||
{
|
|
||||||
"random_drop": {
|
|
||||||
"drop_rate": 0.01
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"seed" : 18042022
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
# Python Imports
|
|
||||||
import typer
|
|
||||||
|
|
||||||
# Project Imports
|
|
||||||
from Utilities.Files.Json.simulation_config_parser import SimulationConfigParser
|
|
||||||
from runner import run_simulation
|
|
||||||
|
|
||||||
|
|
||||||
def main(
|
|
||||||
# todo put in output format possible names (-f --output-format)
|
|
||||||
output_format: str = typer.Option(..., "--output-format", "-f"),
|
|
||||||
input_settings: str = typer.Option(..., "--input-settings", "-i"),
|
|
||||||
output_file: str = typer.Option(..., "--output-file", "-o")
|
|
||||||
):
|
|
||||||
# Check config file
|
|
||||||
parser = SimulationConfigParser(input_settings)
|
|
||||||
parser.read_content()
|
|
||||||
# Calls simulation with configuration
|
|
||||||
run_simulation(output_format, input_settings, output_file)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
typer.run(main)
|
|
@ -1,9 +0,0 @@
|
|||||||
# Python Imports
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Project Imports
|
|
||||||
from Utilities.env_variables import binary_path
|
|
||||||
|
|
||||||
|
|
||||||
def run_simulation(output_format, input_settings, output_file):
|
|
||||||
os.system(binary_path + " -f " + output_format + " -i " + input_settings + " -o " + output_file)
|
|
@ -1,20 +0,0 @@
|
|||||||
from Utilities import env_variables
|
|
||||||
from Utilities.Files.Json.json_utils import read_json, validate_json
|
|
||||||
|
|
||||||
|
|
||||||
class SimulationConfigParser:
|
|
||||||
|
|
||||||
def __init__(self, file_path):
|
|
||||||
self._file_path = file_path
|
|
||||||
self._configuration = None
|
|
||||||
|
|
||||||
def read_content(self):
|
|
||||||
# Retrieve raw info
|
|
||||||
json_configuration = read_json(self._file_path)
|
|
||||||
|
|
||||||
# Retrieve valid schema
|
|
||||||
json_schema = read_json(env_variables.schema_path)
|
|
||||||
|
|
||||||
# Validate
|
|
||||||
validate_json(json_configuration, json_schema)
|
|
||||||
self._configuration = json_configuration
|
|
@ -1,4 +0,0 @@
|
|||||||
# Workaround while docker is not set up
|
|
||||||
|
|
||||||
binary_path = "C:/Users/Alberto/Desktop/Status/consensus-prototypes/target/release-opt/consensus-simulations.exe"
|
|
||||||
schema_path = "../Utilities/Files/Schemas/configuration_schema.json"
|
|
BIN
requirements.txt
Executable file
BIN
requirements.txt
Executable file
Binary file not shown.
44
shared/config_example.json
Normal file
44
shared/config_example.json
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"arguments": {"output-format": "csv", "output-file": "test"},
|
||||||
|
"simulation": {
|
||||||
|
"consensus_settings": {
|
||||||
|
"snow_ball": {
|
||||||
|
"quorum_size": 14,
|
||||||
|
"sample_size": 20,
|
||||||
|
"decision_threshold": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"distribution": {
|
||||||
|
"yes": 0.6,
|
||||||
|
"no": 0.4,
|
||||||
|
"none": 0.0
|
||||||
|
},
|
||||||
|
"byzantine_settings": {
|
||||||
|
"total_size": 10000,
|
||||||
|
"distribution": {
|
||||||
|
"honest": 1.0,
|
||||||
|
"infantile": 0.0,
|
||||||
|
"random": 0.0,
|
||||||
|
"omniscient": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wards": [
|
||||||
|
{
|
||||||
|
"time_to_finality": {
|
||||||
|
"ttf_threshold": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"network_modifiers": [
|
||||||
|
{
|
||||||
|
"random_drop": {
|
||||||
|
"drop_rate": 0.01
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"seed": 18042022
|
||||||
|
},
|
||||||
|
"plotting": {
|
||||||
|
"test": "test"
|
||||||
|
}
|
||||||
|
}
|
0
Plotter/__init__.py → src/__init__.py
Normal file → Executable file
0
Plotter/__init__.py → src/__init__.py
Normal file → Executable file
1
src/configuration_settings.json
Executable file
1
src/configuration_settings.json
Executable file
@ -0,0 +1 @@
|
|||||||
|
{"consensus_settings": {"snow_ball": {"quorum_size": 14, "sample_size": 20, "decision_threshold": 20}}, "distribution": {"yes": 0.6, "no": 0.4, "none": 0.0}, "byzantine_settings": {"total_size": 10000, "distribution": {"honest": 1.0, "infantile": 0.0, "random": 0.0, "omniscient": 0.0}}, "wards": [{"time_to_finality": {"ttf_threshold": 1}}], "network_modifiers": [{"random_drop": {"drop_rate": 0.01}}], "seed": 18042022}
|
27
src/main.py
Executable file
27
src/main.py
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
# Python Imports
|
||||||
|
import typer
|
||||||
|
|
||||||
|
# Project Imports
|
||||||
|
from src.simulation_runner.runner import run_simulation
|
||||||
|
from src.utilities.files.json.simulation_config_parser import SimulationConfigParser
|
||||||
|
|
||||||
|
|
||||||
|
def main(
|
||||||
|
run_type: str = typer.Option(..., "--run", "-r"),
|
||||||
|
configuration_file: str = typer.Option(..., "--configuration-file", "-cf")
|
||||||
|
):
|
||||||
|
parser = SimulationConfigParser(configuration_file)
|
||||||
|
arguments_config, simulation_config, plotter_config = parser.read_content()
|
||||||
|
# Calls depending on json config
|
||||||
|
if run_type == "simulation":
|
||||||
|
run_simulation(arguments_config, simulation_config)
|
||||||
|
elif run_type == "plotter":
|
||||||
|
# run_plotter()
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
run_simulation()
|
||||||
|
# run_plotter()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
typer.run(main)
|
18
src/simulation_runner/runner.py
Normal file
18
src/simulation_runner/runner.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Python Imports
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Project Imports
|
||||||
|
from src.utilities.env_variables import BINARY_PATH, CONFIGURATION_SETTINGS, SHARED_FOLDER
|
||||||
|
from src.utilities.files.json.json_utils import write_json
|
||||||
|
|
||||||
|
|
||||||
|
def run_simulation(arguments_config: dict, simulation_config: dict):
|
||||||
|
|
||||||
|
write_json(simulation_config, CONFIGURATION_SETTINGS)
|
||||||
|
|
||||||
|
os.system(BINARY_PATH
|
||||||
|
+ " -f " + arguments_config["output-format"]
|
||||||
|
+ " -i " + CONFIGURATION_SETTINGS + " -o "
|
||||||
|
+ arguments_config["output-file"])
|
||||||
|
|
||||||
|
os.system("mv " + arguments_config["output-file"] + "." + arguments_config["output-format"] + " " + SHARED_FOLDER)
|
11
src/utilities/env_variables.py
Normal file
11
src/utilities/env_variables.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
# Binary
|
||||||
|
BINARY_PATH = "snow-family"
|
||||||
|
CONFIGURATION_SETTINGS = "shared/configuration_settings.json"
|
||||||
|
|
||||||
|
# Schemas
|
||||||
|
ARGUMENTS_SCHEMA_PATH = "src/utilities/files/schemas/arguments_schema.json"
|
||||||
|
CONFIGURATION_SCHEMA_PATH = "src/utilities/files/schemas/snow_family_configuration_schema.json"
|
||||||
|
|
||||||
|
# Shared folder
|
||||||
|
SHARED_FOLDER = "shared/"
|
@ -3,13 +3,18 @@ import json
|
|||||||
import jsonschema
|
import jsonschema
|
||||||
|
|
||||||
|
|
||||||
def read_json(file_path):
|
def read_json(file_path: str) -> dict:
|
||||||
with open(file_path, "r") as file:
|
with open(file_path, "r") as file:
|
||||||
json_content = json.load(file)
|
json_content = json.load(file)
|
||||||
|
|
||||||
return json_content
|
return json_content
|
||||||
|
|
||||||
|
|
||||||
def validate_json(json_content, json_schema):
|
def write_json(info: dict, file_path: str):
|
||||||
|
with open(file_path, "w") as file:
|
||||||
|
json.dump(info, file)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_json(json_content: dict, json_schema: dict):
|
||||||
jsonschema.validate(instance=json_content, schema=json_schema)
|
jsonschema.validate(instance=json_content, schema=json_schema)
|
||||||
|
|
32
src/utilities/files/json/simulation_config_parser.py
Normal file
32
src/utilities/files/json/simulation_config_parser.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Project Imports
|
||||||
|
from src.utilities import env_variables
|
||||||
|
from src.utilities.files.json.json_utils import read_json, validate_json
|
||||||
|
|
||||||
|
|
||||||
|
class SimulationConfigParser:
|
||||||
|
_file_path: str
|
||||||
|
|
||||||
|
def __init__(self, file_path: str):
|
||||||
|
self._file_path = file_path
|
||||||
|
|
||||||
|
def read_content(self) -> tuple[dict, dict, dict]:
|
||||||
|
# Retrieve raw info
|
||||||
|
json_configuration = read_json(env_variables.SHARED_FOLDER + self._file_path)
|
||||||
|
|
||||||
|
# Split two parts
|
||||||
|
arguments_config = json_configuration["arguments"]
|
||||||
|
simulation_config = json_configuration["simulation"]
|
||||||
|
# plotter_config = json_configuration["plotter"]
|
||||||
|
|
||||||
|
# Retrieve valid schemas
|
||||||
|
arguments_json_schema = read_json(env_variables.ARGUMENTS_SCHEMA_PATH)
|
||||||
|
config_json_schema = read_json(env_variables.CONFIGURATION_SCHEMA_PATH)
|
||||||
|
# plotter_json_schema = read_json(env_variables.plotter_schema_path)
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
validate_json(arguments_config, arguments_json_schema)
|
||||||
|
validate_json(simulation_config, config_json_schema)
|
||||||
|
# validate_json(plotter_config, plotter_json_schema)
|
||||||
|
|
||||||
|
# return simulation_config, plotter_config
|
||||||
|
return arguments_config, simulation_config, {}
|
17
src/utilities/files/schemas/arguments_schema.json
Executable file
17
src/utilities/files/schemas/arguments_schema.json
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"output-format": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"parquet",
|
||||||
|
"csv",
|
||||||
|
"json"
|
||||||
|
],
|
||||||
|
"default": "parquet"
|
||||||
|
},
|
||||||
|
"output-file": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
0
src/utilities/files/schemas/plotter_schema.json
Executable file
0
src/utilities/files/schemas/plotter_schema.json
Executable file
@ -19,7 +19,7 @@
|
|||||||
},
|
},
|
||||||
"required": ["quorum_size", "sample_size", "decision_threshold"]
|
"required": ["quorum_size", "sample_size", "decision_threshold"]
|
||||||
},
|
},
|
||||||
"glacier": {
|
"claro": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"evidence_alpha": {"type": "number"},
|
"evidence_alpha": {"type": "number"},
|
@ -2,9 +2,9 @@
|
|||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
# Project Imports
|
# Project Imports
|
||||||
from Utilities.Files.SimulationDataTypes.JsonDataSimulationHandler import JsonDataSimulationHandler
|
from src.utilities.files.simulation_data_types.json_data_simulation_handler import JsonDataSimulationHandler
|
||||||
from Utilities.Files.SimulationDataTypes.CsvDataSimulationHandler import CsvDataSimulationHandler
|
from src.utilities.files.simulation_data_types.csv_data_simulation_handler import CsvDataSimulationHandler
|
||||||
from Utilities.Files.SimulationDataTypes.ParquetSimulationDataHandler import ParquetDataSimulationHandler
|
from src.utilities.files.simulation_data_types.parquet_simulation_data_handler import ParquetDataSimulationHandler
|
||||||
|
|
||||||
handlers = {'.csv': CsvDataSimulationHandler,
|
handlers = {'.csv': CsvDataSimulationHandler,
|
||||||
'.json': JsonDataSimulationHandler,
|
'.json': JsonDataSimulationHandler,
|
@ -1,4 +1,4 @@
|
|||||||
from Utilities.Files.SimulationDataTypes.BaseDataSimulationHandler import BaseDataSimulationHandler
|
from src.utilities.files.simulation_data_types.base_data_simulation_handler import BaseDataSimulationHandler
|
||||||
|
|
||||||
|
|
||||||
class CsvDataSimulationHandler(BaseDataSimulationHandler):
|
class CsvDataSimulationHandler(BaseDataSimulationHandler):
|
@ -1,4 +1,4 @@
|
|||||||
from Utilities.Files.SimulationDataTypes.BaseDataSimulationHandler import BaseDataSimulationHandler
|
from src.utilities.files.simulation_data_types.base_data_simulation_handler import BaseDataSimulationHandler
|
||||||
|
|
||||||
|
|
||||||
class JsonDataSimulationHandler(BaseDataSimulationHandler):
|
class JsonDataSimulationHandler(BaseDataSimulationHandler):
|
@ -1,4 +1,4 @@
|
|||||||
from Utilities.Files.SimulationDataTypes.BaseDataSimulationHandler import BaseDataSimulationHandler
|
from src.utilities.files.simulation_data_types.base_data_simulation_handler import BaseDataSimulationHandler
|
||||||
|
|
||||||
|
|
||||||
class ParquetDataSimulationHandler(BaseDataSimulationHandler):
|
class ParquetDataSimulationHandler(BaseDataSimulationHandler):
|
Loading…
x
Reference in New Issue
Block a user