A Python library for optimizing chemical reaction scheduling on automated synthesis platforms. This tool clusters reactions and optimizes temperature and duration parameters to minimize the number of experimental batches while respecting container and volume constraints.
- Reaction Clustering: Intelligently groups reactions based on chemical compatibility and resource constraints
- Parameter Optimization: Automatically selects optimal temperature and duration for each cluster
- Resource Management: Respects container capacity limits for substrates, solutions, solvents, and powders
- Volume Constraints: Handles maximum volume per slot for each container type
- Batch Minimization: Reduces the number of experimental runs needed
- Python 3.12 or higher
uvpackage manager (install uv)
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"git clone https://github.com/iktos/tactical-scheduling.git
cd tactical-scheduling# Create a virtual environment and install dependencies
uv syncThis command will:
- Create a virtual environment
- Install all project dependencies (pulp, pandas, numpy, ipykernel)
- Set up the package in development mode
The easiest way to use the scheduler is through the Streamlit web interface:
# Start the Streamlit app
uv run streamlit run app.pyThe app will open in your browser at http://localhost:8501. You can:
- Upload your reaction data as JSON
- Configure optimization parameters
- Run the optimization (may take 1-2 minutes for large datasets)
- View and export results
Note: The optimization uses an integer linear programming solver that can take several minutes to complete. The app will display a progress message while solving. The solver has a 5-minute timeout to prevent indefinite hanging.
The project includes a Jupyter notebook example demonstrating the scheduling optimization:
# Start Jupyter with the example notebook
uv run jupyter notebook example/test_tactical_schedule.ipynbfrom iktos.tactical_scheduling import run_tactical
# Prepare your reactions and configuration
reactions = [...] # List of reaction dictionaries
config = {
"containers": [...], # Container specifications
"config": {
"actions": {
"dispenseSolvent": {"extraVolume": 10},
"dispenseSolution": {"extraVolume": 5},
"dispensePowder": {"extraWeight": 0.1},
}
}
}
# Run the optimization
clusters = run_tactical(reactions, config)
# Process results
for (pair, cluster_id), reactions_in_cluster in clusters.items():
print(f"Pair {pair}, Cluster {cluster_id}: {len(reactions_in_cluster)} reactions")The config parameter should include:
-
containers: List of container specifications with:
type: Container type (SUBSTRATE, SOLUTION, SOLVENT, POWDER)slots: Number of available slotsmaxVolumePerSlot: Maximum volume per slot
-
config.actions: Extra volume/weight parameters for each dispense action
tactical-scheduling/
├── iktos/
│ └── tactical_scheduling/
│ ├── tactical_schedule.py # Main scheduling function
│ └── utils.py # Optimization utilities
├── example/
│ ├── test_tactical_schedule.ipynb # Example notebook
│ └── data/ # Example data files
├── pyproject.toml # Project configuration
└── README.md # This file
# Run the example notebook
uv run jupyter notebook example/test_tactical_schedule.ipynb- pulp: Linear programming solver for optimization
- pandas: Data manipulation and analysis
- numpy: Numerical computing
- ipykernel: Jupyter kernel for interactive notebooks
- streamlit: Web interface framework for interactive applications
If you use this project in your research, please cite it appropriately.
For issues, questions, or contributions, please contact the development team or open an issue in the repository.
This source code project is provided as an example for educational and illustrative purposes only. While efforts have been made to ensure the accuracy and reliability of the code, no guarantee is made regarding its suitability for any specific purpose.
By accessing and using this source code, you agree that:
- The code is provided "as is" without warranty of any kind, express or implied.
- You acknowledge that you are solely responsible for any consequences resulting from the use of this code.
- The author(s) and contributors of this code shall not be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) arising in any way out of the use of this code, even if advised of the possibility of such damage.
- Copyright © 2025 Iktos. All rights reserved.
This disclaimer does not limit or exclude any liability for death or personal injury resulting from negligence, fraud, or any other liability that cannot be excluded or limited under applicable law.
Use of this source code project implies acceptance of these terms.