# interconnect

humancompatible.interconnect is an open-source toolkit for the modelling, simulations, and theorem proving within ergodicity of multi-agent systems.

## Functionality

---
Notably, the toolkit makes it possible to test contraction-on-average (sufficient and sometimes necessary) conditions for unique ergodicity via 
stochastic approximation, i.e., to check if unique invariant measure exists. This is a prerequisite for most definitions of fairness in repeated
uses of AI systems. The toolkit also makes it possible to estimate this unique invariant measure, if it does exist.

<div align="center">
    <img src="images/c_factor.png" alt="Contraction Factor approximation" width="550"/>
</div>

<div align="center">
    <img src="images/uid_est.png" alt="Unique Invariant Measure estimation" width="550"/>
</div>

## Using HumanCompatible.Interconnect

---
1. Approximation of the modulus of local Lipschitz continuity on average for an iterated function system:

```python
from tests.contractionTests.contraction_test import get_factor_from_list

C = get_factor_from_list(reference_signals=reference_signals,
                         agent_probs=np.array([[eps, 1-eps], [eps, 1-eps]]),
                         sim_class=Sim,
                         it=100,
                         trials=20,
                         weights="./weights/weights_basic_ReLU.pth",
                         node_outputs_plot="A1",
                         show_distributions_plot=True,
                         show_distributions_histograms_plot=False)
```

2. Approximating the unique invariant measure of the system:

```python
from humancompatible.interconnect.simulators.distribution import *
reference_signals = np.array([4, 5, 20, 25])

fig, ax = plt.subplots()
outputs = generate_outputs(sim_class=Sim,
                           weights="./weights/weights_basic_ReLU.pth",
                           reference_signals=reference_signals,
                           node="A1",
                           iterations=100,
                           samples=100)
distributions = get_distributions(x=outputs,
                                  h=1.9,
                                  labels=[f"reference_signal = {r}" for r in reference_signals],
                                  step=0.1,
                                  node="A1",
                                  show_plots=True,
                                  show_histograms=True,
                                  fig=fig,
                                  ax=ax)
```

### Examples

``examples/basic_simulation_ReLU`` - example notebook featuring the calls above.
Other example notebooks can be found in the same folder.
