Metadata-Version: 2.4
Name: OpenCtrl
Version: 1.0.16
Summary: A library for Optimal Control and System Dynamics
Home-page: https://github.com/shoham-roy31/OpenCtrl
Author: Shoham Roy
Author-email: shohamc3@gmail.com
Project-URL: Bug Tracker, https://github.com/shoham-roy31/OpenCtrl/issues
Project-URL: Source Code, https://github.com/shoham-roy31/OpenCtrl
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=2.3.0
Requires-Dist: matplotlib>=3.10.0
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: project-url
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

![OpenCtrl](https://github.com/shoham-roy31/OpenCtrl/blob/main/OpenCtrlLogo.png?raw=true)
OpenCtrl is an open source library for Control System Dynamics and Optimal Control Alogrithms.

The library facilitates:
 - System Objects
 - Multi-Horizon Optimization
 - Control Algorithms
 - Real-time visualization

## How to install
Run the flowing code using pip:
`pip install OpenCtrl`

For specific version *X* use:
`pip install OpenCtrl==X`

## Quick Guide

Version Check:
`python -c "import OpenCtrl print(OpenCtrl.__version__)"`

### Create a Linear System
To create Linear System:
```
import numpy as np
from OpenCtrl.SystemDynamicExample import LinearSystem
''' define your input space parameters '''
input_space = { '1' : {'discrete' : [0,512]},
                '2' : {'random' : ['uniform',-128,127]},
                '3' : {'continuous' : [-10,10]},
                '4' : {'continuous' : [512,1024]},
              }
''' Instantiate Linear System Object '''
linear_sys = LinearSystem(sys_dim = 4,
                          input_dim = 4,
                          input_space = input_space,
                          disturbance_type = 'uniform',
                          disturbance_scale = [-255, 255],
                          disturbance_params = None
                          )
''' Info : sys_dim equals input_dim since we considered we can control 4 degrees of freedom, if the case is different like we have 1 degree of freedom then input_space can only have { '1' : {'discrete' : [0,512] } } only. For disturbance_params some degree of freedom can have no impact by disturbance if only 1 degree is impacted the disturbance_params will be 1. '''
u_o = np.array([np.random.randint(0,512), 
              np.random.uniform(-128,127), 
              np.random.uniform(-10,10), 
              np.random.uniform(512,1024)]
            )
linear_sys.step(u_o)
print(linear_sys.x)
```
### Create an Optimizer
To create an optimizer object to optimize the system:
```
from OpenCtrl.optim import VanillaOptim
''' Let's create 3 different types of Optimizers '''
cost_func = 'quadratic'
horizon = 5
max_iteration = 50
tolerance_step = 10

def get_predictions(horizon):
    return [u_o for _ in range(horizon)]

def print_metrics(type,cost,u):
    print(f"For optimizer type {type} \nCost: {cost}\nOptimal Input : {u}")

''' Random Search '''
optimizer_random = VanillaOptim( system = linear_sys,
                                 horizon = horizon,
                                 cost_function = cost_func,
                                 optimizer_type = 'random',
                                 max_iterations = max_iteration,
                                 tolerance_step = tolerance_step
                                )
cost_random, u_random = optimizer_random.optimize( preds = get_predictions(horizon),
                                                    verbose = True
                                                  )
print_metrics('random',cost_random,u_random)     

''' Gradient Descent '''
optimizer_gradient = VanillaOptim( system = linear_sys,
                                   horizon = 5,
                                   cost_function = 'quadratic',
                                   optimizer_type = 'gradient',
                                   alpha = 1e-3,
                                   max_iterations = max_iteration,
                                   tolerance_step = tolerance_step
                                )
cost_gradient,u_gradient = optimizer_gradient.optimize(preds = get_predictions(horizon),
verbose = True )
print_metrics('gradient',cost_gradient,u_gradient)
''' Genetic Algorithm '''
optimizer_genetic = VanillaOptim( system = linear_sys,
                                  horiozn = horizon,
                                  cost_function = cost_func,
                                  optimizer_type = 'genetic',
                                  population_size = 1000,
                                  cross_over_rate = 0.42,
                                  mutation_rate = 0.23,
                                  cut_off_rate = 0.5,
                                  max_iterations = max_iteration,
                                  tolerance_step = tolerance_step
                                  )
cost_genetic,u_genetic = optimizer_genetic.optimize(pred = get_predictios(horizon),
verbose = True)
print_metrics('genetic',cost_genetic,u_genetic)
```
![OptimPlot](https://github.com/shoham-roy31/OpenCtrl/blob/main/optim_plot.gif?raw=true)
### Use Control Algorithm
To use a control algorith to tune the system:
```
from OpenCtrl.controls import LAC
control_horizon = 10
lac = LAC(system = linear_sys,
          optimizer = optimizer_gradient,
          horizon = horizon,
          nominal_disturbance = 'baseline'
          )
''' nominal_disturbance is a conventional method of predicting disturbance '''
for _ in range(control_horizon):
    preds = get_predictions(horizon)
    cost,u = lac.tune(preds = preds,
                      verbose = True,
                      base_line= _
                     )
    print_metrics('gradient',cost, u)

```
![ControlMetrics](https://github.com/shoham-roy31/OpenCtrl/blob/main/control_metrics.gif?raw=true)
## To Create Extension of Algos and System Dynamics
*** Developer Documentation in Progress ***
## To Contribute 
You can check out the dev repo of OpenCtrl:
[OpenCtrl](https://github.com/shoham-roy31/OpenCtrl)
