> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender

### *final class* atoti.aggregate\_provider.aggregate\_provider\_recommender.AggregateProviderRecommender

Recommend [`AggregateProvider`](./atoti.aggregate_provider.aggregate_provider#atoti.AggregateProvider) s for a [`Cube`](./atoti.cube#atoti.Cube).

The recommender analyzes the queries executed against the cube while it is
[`recording`](./atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender.status#atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender.status) to recommend the most impactful aggregate providers.

### Example

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> df = pd.DataFrame(
...     {
...         "Country": ["France", "France", "Germany"],
...         "City": ["Paris", "Lyon", "Berlin"],
...         "Price": [2.5, 3.0, 4.0],
...     }
... )
>>> table = session.read_pandas(df, table_name="Sales")
>>> cube = session.create_cube(table)
```

By default, the recommender is idle:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> recommender = cube.aggregate_providers.recommender
>>> recommender.status
'idle'
```

Recommendations require a recorded query history, so none can be made while idle:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> recommender.recommend(cover_target=0.42)
Traceback (most recent call last):
    ...
RuntimeError: Cannot get recommendation when status is `idle`.
```

Starting to record queries:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> recommender.status = "recording"
>>> recommender.status
'recording'
```

Running some queries:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> l, m = cube.levels, cube.measures
>>> for level in [l["City"], l["Country"]]:
...     _ = cube.query(m["Price.SUM"], levels=[level])
```

Getting a recommendation:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> import pprint
>>> recommended = recommender.recommend(
...     cover_target=0.42,
...     excluded_levels={l["Country"]},
... )
>>> pprint.pp(recommended)
{'ai-optimizer-1': AggregateProvider(filter=None,
                                     key='bitmap',
                                     levels=frozenset({l['Sales', 'City', 'City']}),
                                     measures=frozenset({m['Price.SUM']}),
                                     partitioning=None)}
```

Excluding another level changes the recommendation:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> from datetime import timedelta
>>> recommended = recommender.recommend(
...     candidate_evaluation_time_limit=timedelta(seconds=92),
...     cover_target=0.42,
...     excluded_levels={l["City"]},
... )
>>> pprint.pp(recommended)
{'ai-optimizer-1': AggregateProvider(filter=None,
                                     key='bitmap',
                                     levels=frozenset({l['Sales', 'Country', 'Country']}),
                                     measures=frozenset({m['Price.SUM']}),
                                     partitioning=None)}
```

Once a suitable recommendation is made, the recommender can be made idle again:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> recommender.status = "idle"
>>> recommender.status
'idle'
```

The recommendation can be applied directly:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> cube.aggregate_providers.update(recommended)
```

Or it can be serialized and transferred from one environment to another:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> from pydantic import TypeAdapter
>>> type_adapter = TypeAdapter(dict[str, tt.AggregateProvider])
>>> path = tmp_path / "aggregate_providers.json"
>>> _ = path.write_bytes(type_adapter.dump_json(recommended))
```

In another process:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> transferred_aggregate_providers = type_adapter.validate_json(
...     path.read_bytes()
... )
>>> recommended == transferred_aggregate_providers
True
```

| [`recommend`](./atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender.recommend#atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender.recommend) | Return recommended aggregate providers keyed by name.                     |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| [`status`](./atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender.status#atoti.aggregate_provider.aggregate_provider_recommender.AggregateProviderRecommender.status)          | Whether the cube records incoming queries for the recommender to analyze. |
