This project is developed and tested with **Python 3.10.5** and **Ubuntu 20.04**

## Quick install
```
pip install -r requirements.txt
```

## Quick run (2 nodes for atomic commit)
### Training
```
cd MCTS
python main.py --players 2 --round 2 --protocol atomic_commit --model_type transformer --fix 1 --pre_train 10 --interval 5 --save_dir ../chkpt/ac_2n_2r_test
```
### Verification
#### Verify the model just trainied
```
cd MCTS
python eval.py --players 2 --round 2 --protocol atomic_commit --model_type transformer --load_dir ../chkpt/ac_2n_2r_test
```
#### Verify an existing model
```
cd MCTS
python eval.py --players 2 --round 2 --protocol atomic_commit --model_type transformer --load_dir ../chkpt/ac_2n_2r_v6 
```
Option: add *--verbose* to list all transitions


# Train a distributed protocol
## Steps
Give example to train a new protocol (Take atomic commit as an example)
1. Create a folder with the protocol name (e.g., atomic_commit)
2. Define necessary functions:
    1. AtomicCommitEnv.py: environment and reward functions
    2. AtomicCommit.py: customized reset and step function for multiple agents, and insert failure
3. Register new protocol in *import_functions.py*

## Z3 CPP Verifier (Not support in ICLR26 submission)
Implemented under cpp_verfier/
### Steps to build and run
1. Install [z3](https://github.com/Z3Prover/z3)
2. Build cpp verifier
    ```
    cd cpp_verifier
    mkdir build && cd build
    cmake -DZ3_HOME=~/z3-install ../ (specify your z3 installed path)
    make -j8
    ```
3. Run verifier
    ```
    ./run_verify -t ../../transition_lists/pb_3p.txt -r 2 -n 3 -p primary_backup
    ```

## Tests
### Unit Tests (More tests are coming)
All test files are located at `root/tests/`

Run all tests: 

`python MCTS/tests/test_environment.py`

or

`python -m unittest discover tests`

Run specific test file: 

`python -m unittest tests/test_PrimaryBackup.py`

## Resutls
### Raw results (Not included in ICLR26 submission due to size limit)
All raw results are stored in *chkpt/* and *logs/*. The naming rules are shown below:

`<protocol_name>_<#nodes>_<#rounds>_<model_type>_<method>_<version>`

If the *<model_type>* is not specified, then it's transformer by default. 
If the *<method>* is not specified, it's GGMS by default. 
