Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change behavior for adding Difference Metrics #102

Open
wants to merge 85 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
7c32af2
Improve ReferenceIO solution shape check
schmoelder Dec 5, 2023
cbd69ae
Check cstr volume only when flow rate is not None
schmoelder Dec 2, 2023
5e10679
Fix calculation of conversion rates for MSSMA model
Dec 7, 2023
b4bb2a1
Update CI
schmoelder Dec 9, 2023
00d72cc
Only evaluate objects registered in objective/constraint functions
schmoelder Oct 24, 2023
c5f71d3
Fix objective names
schmoelder Oct 24, 2023
438c542
Restructure OptimizationProblem metrics
schmoelder Oct 25, 2023
5b4dd04
Add `results` in example callback.
schmoelder Oct 27, 2023
9015404
move create_hopsy_problem to separate method
flo-schu Jul 13, 2023
f4b35b1
implement else action if shapes of rounded and unrounded problems do …
flo-schu Jul 26, 2023
580a84e
Add support for creating x0 with linear equality constraints
schmoelder Nov 30, 2023
0125189
Raise warning if x0 is smaller than popsize
schmoelder Jan 9, 2024
3e1898b
Fix behavior of comparisons to references with multiple components
Dec 7, 2023
70e9dfb
Add examples for SMA parameter determination using Yamamoto and inver…
Dec 15, 2023
dd851e7
Temporarily disable test_fit_column_parameters to avoid breaking CI
Jan 10, 2024
5287ec8
Fix jupytext formatting
schmoelder Jan 10, 2024
89ec75e
Add n_difference_metrics property
schmoelder Dec 9, 2023
394d08c
Improve figure styling
schmoelder Dec 9, 2023
6e49da1
Allow setting empty list for output_state for units without destination
schmoelder Dec 2, 2023
a9389d7
Untransform x when evaluating callbacks.
Jan 9, 2024
980dad7
Clarify that OptimizationProblem.transform expects independent space
Jan 10, 2024
23c04ce
Remove increased burn-in when using equality constraints
Jan 10, 2024
d451fbc
Assume x0 contains only independent variables
Jan 10, 2024
aa3f922
Return dependent variables for x0 by default
Jan 10, 2024
fd13a12
Move chebyshev center to own method
schmoelder Jan 10, 2024
895dfe8
Improve docstring
schmoelder Jan 10, 2024
b47cb30
Add check_individual method
schmoelder Jan 10, 2024
8dfde9a
Move validation of x0 to OptimizerBase
schmoelder Jan 10, 2024
8c07312
Small fix: adjust variable types in optimizer.check_x0
Jan 15, 2024
c5f20f8
Use original space for chebychev center
schmoelder Jan 16, 2024
a7229c8
Fix calculation of flow rates for single Cstr
schmoelder Feb 2, 2024
724dc24
Add adapter for LangmuirLDFLiquidPhase
jAniceto Oct 20, 2023
3151154
Add method to create individuals
schmoelder Feb 5, 2024
3ae11df
Update docstrings
schmoelder Feb 7, 2024
f271649
Fix typo
schmoelder Feb 7, 2024
1b7a108
Improve error message
schmoelder Feb 7, 2024
9e1c0b1
Use check_mod_value instead of check_size for modulated parameters
schmoelder Feb 7, 2024
281fdfe
Make characteristic_charge_breaks optional
schmoelder Feb 7, 2024
596032e
Add Cstr to __all__
schmoelder Feb 7, 2024
fed3edb
Add bindings and adapter for two HIC isotherms:
Feb 7, 2024
7fe21b3
Add default value to docstring
schmoelder Feb 9, 2024
53b9b39
Add flag for optimizers that only support single objective
schmoelder Feb 14, 2024
403dcee
Add AxInterface
schmoelder Jun 24, 2023
982bc8a
Add Ax documentation
schmoelder Jun 24, 2023
f84f8da
Add behaviour tests for optimizers
schmoelder Jun 24, 2023
b899751
Fix docstring
schmoelder Feb 14, 2024
3037d18
Add optional pre-processing step before setting optimization variable
schmoelder Feb 26, 2024
b422b32
Use floats for output_state
schmoelder Feb 26, 2024
ad5f390
Fix numpy/scipy deprecation warnings
schmoelder Mar 2, 2024
0e1cb9a
Add short_id to Individual
schmoelder Mar 9, 2024
5dc274c
Fix NormLogTransform if lb==0
schmoelder Mar 9, 2024
80b2053
Add string representation to SolutionBase
schmoelder Mar 9, 2024
1dd7805
Wrap FlowSheet methods for improved docstrings
schmoelder Mar 11, 2024
1f55438
Make some internal methods private
schmoelder Mar 11, 2024
3d78930
Pass feed/eluent/product information to FlowSheet
schmoelder Mar 12, 2024
867573b
Add plot method to TransformBase
schmoelder Feb 5, 2024
a9c86dd
Allow setting state for dependent events
ronald-jaepel Mar 1, 2024
c4d5128
Only use independent variables for hopsy
schmoelder Mar 1, 2024
c21ae41
Use independent variables for linear constraints in Ax
ronald-jaepel Mar 12, 2024
748f08b
Improve behavior for fractionation with empty fractions
schmoelder Mar 11, 2024
08cc01e
Remove waste fractions in initial values if start time coincides with…
schmoelder Mar 14, 2024
1c5977a
Cache more properties when locked
schmoelder Dec 5, 2023
a554703
Remove unnecessary code
schmoelder Dec 2, 2023
9ff3495
Unify post processing
schmoelder Jun 27, 2023
9a27d99
Use individuals from meta front for reporting (instead of pareto front)
schmoelder Mar 17, 2024
d6f9642
Unify updating results
schmoelder Jun 27, 2023
ad1cebb
Cache results for meta scores
schmoelder Mar 17, 2024
db18577
Improve caching
schmoelder Mar 17, 2024
65f0384
Rename typed Dict to Dictionary to avoid conflict with addict
schmoelder Mar 17, 2024
5348c43
Add sysinfo
schmoelder Mar 17, 2024
fd50aba
Store additional information in optimization results
schmoelder Mar 17, 2024
e1ff9f6
Improve final processing of optimization results
schmoelder Mar 17, 2024
f97b02c
Add `success` attribute to OptimizationResults and raise Exepction `i…
schmoelder Mar 22, 2024
9cccf3c
Fix plot for populations without (in)feasible subpopulations
schmoelder Mar 23, 2024
a2774ea
Show all individuals in Pareto plot
schmoelder Mar 21, 2024
4475526
Update FractionationOptimization options
schmoelder Mar 23, 2024
f26e7e2
Add n_total_metrics to optimization metrics
schmoelder Mar 20, 2024
540a0fc
Allow specifying objectives as maximization problems
schmoelder Mar 20, 2024
d2471be
Allow specifying nonlinear constraints with comparison operator
schmoelder Mar 20, 2024
7c59905
Allow specifying meta scores as maximization problems
schmoelder Mar 21, 2024
a8ad135
Add triangle theory for SMBs
schmoelder Mar 14, 2024
e6e182d
Expose zone inlet/outlet valve volume
schmoelder Mar 19, 2024
e832ac0
Fix non-linearity check during linear constraints
ronald-jaepel Mar 25, 2024
cd4c8ee
Return numpy arrays for individuals / results
schmoelder Mar 26, 2024
c2590bd
[WIP] Restructure Comparator
schmoelder Mar 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 63 additions & 35 deletions .github/workflows/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,77 @@ on:
branches:
- master
- dev
- test_ci
pull_request:

jobs:
test-job:
runs-on: ${{ matrix.os }}

defaults:
run:
shell: bash -l {0}

strategy:
matrix:
python-version: ["3.9", "3.10", "3.11"]
os: [ubuntu-latest, windows-latest]
os: [ubuntu-latest]
python-version: ["3.10", "3.11", "3.12"]
include:
- os: windows-latest
python-version: "3.12"
- os: macos-latest
python-version: "3.12"

env:
CONDA_FILE: environment.yml

steps:
- uses: actions/checkout@v3
- name: Cache conda
uses: actions/cache@v3
env:
# Increase this value to reset cache if etc/example-environment.yml has not changed
CACHE_NUMBER: 2
with:
path: ~/conda_pkgs_dir
key:
${{ matrix.os }}-python_${{ matrix.python-version }}-${{ env.CACHE_NUMBER }}-${{ hashFiles('etc/example-environment.yml') }}
- uses: conda-incubator/setup-miniconda@v2
with:
python-version: ${{ matrix.python-version }}
miniforge-variant: Mambaforge
use-mamba: true
auto-update-conda: true
channels: conda-forge,
- name: Install dependencies
run: |
mamba install cadet
pip install -e ./[testing]
- name: Test
run: |
python -m unittest discover -s tests
- name: Install pypa/build
run: |
python -m pip install build --user
- name: Build binary wheel and source tarball
run: |
python -m build --sdist --wheel --outdir dist/ .
- name: Test Wheel install and import
run: |
python -c "import CADETProcess; print(CADETProcess.__version__)"
- uses: actions/checkout@v4

- name: Get Date
id: get-date
run: echo "today=$(/bin/date -u '+%Y%m%d')" >> $GITHUB_OUTPUT
shell: bash

- name: Setup Conda Environment
uses: conda-incubator/setup-miniconda@v3
with:
miniforge-variant: Mambaforge
use-mamba: true
activate-environment: cadet-process
channels: conda-forge,

- name: Cache conda
uses: actions/cache@v3
env:
# Increase this value to reset cache if environment.yml has not changed
CACHE_NUMBER: 0
with:
path: ${{ env.CONDA }}/envs
key: ${{ matrix.os }}-python_${{ matrix.python-version }}-${{ steps.get-date.outputs.today }}-${{ hashFiles(env.CONDA_FILE) }}-${{ env.CACHE_NUMBER }}

- name: Update environment
run: |
mamba install python==${{ matrix.python-version }}
mamba env update -n cadet-process -f ${{ env.CONDA_FILE }}
if: steps.cache.outputs.cache-hit != 'true'

- name: Install
run: |
pip install -e ./[testing]

- name: Test
run: |
python -m unittest discover -s tests

- name: Install pypa/build
run: |
python -m pip install build --user

- name: Build binary wheel and source tarball
run: |
python -m build --sdist --wheel --outdir dist/ .

- name: Test Wheel install and import
run: |
python -c "import CADETProcess; print(CADETProcess.__version__)"
1 change: 1 addition & 0 deletions CADETProcess/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from .settings import Settings
settings = Settings()

from . import sysinfo
from . import dataStructure
from . import transform
from . import plotting
Expand Down
70 changes: 40 additions & 30 deletions CADETProcess/comparison/comparator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import copy
import importlib
import functools
import warnings

import numpy as np
import matplotlib.pyplot as plt
Expand Down Expand Up @@ -81,6 +82,11 @@ def metrics(self):
"""list: List of difference metrics."""
return self._metrics

@property
def n_diffference_metrics(self):
"""int: Number of difference metrics in the Comparator."""
return len(self.metrics)

@property
def n_metrics(self):
"""int: Number of metrics to be evaluated."""
Expand Down Expand Up @@ -116,20 +122,19 @@ def labels(self):

return labels

@functools.wraps(DifferenceBase.__init__)
def add_difference_metric(
self, difference_metric, reference, solution_path,
self, difference_metric, solution_path, reference,
*args, **kwargs):
"""Add a difference metric to the Comparator.

Parameters
----------
difference_metric : str
Name of the difference metric to be evaluated.
reference : str or SolutionBase
Name of the reference or reference itself.
difference_metric : DifferenceMetricBase
Difference metric to be evaluated.
solution_path : str
Path to the solution in SimulationResults.
reference : str or SolutionBase
Name of the reference or reference itself.
*args, **kwargs
Additional arguments and keyword arguments to be passed to the
difference metric constructor.
Expand All @@ -139,29 +144,36 @@ def add_difference_metric(
CADETProcessError
If the difference metric or reference is unknown.
"""
try:
module = importlib.import_module(
'CADETProcess.comparison.difference'
if isinstance(difference_metric, str):
warnings.warn(
'This method of adding difference metrics is deprecated. '
'Instead, pass an instance of the desired metric class.',
DeprecationWarning, stacklevel=2
)
cls_ = getattr(module, difference_metric)
except KeyError:
raise CADETProcessError("Unknown Metric Type.")
if isinstance(reference, SolutionBase):
reference = reference.name

if isinstance(reference, SolutionBase):
reference = reference.name
if reference not in self.references:
raise CADETProcessError("Unknown Reference.")

if reference not in self.references:
raise CADETProcessError("Unknown Reference.")

reference = self.references[reference]

metric = cls_(reference, *args, **kwargs)
reference = self.references[reference]
try:
module = importlib.import_module(
'CADETProcess.comparison.difference'
)
cls_ = getattr(module, difference_metric)
difference_metric = cls_(reference, *args, **kwargs)
except KeyError:
raise CADETProcessError("Unknown Difference Metric.")
else:
if not isinstance(difference_metric, DifferenceBase):
raise TypeError("Expected DifferenceBase.")

self.solution_paths[metric] = solution_path
self.solution_paths[difference_metric] = solution_path

self._metrics.append(metric)
self._metrics.append(difference_metric)

return metric
return difference_metric

def extract_solution(self, simulation_results, metric):
"""Extract the solution for a given metric from the SimulationResults object.
Expand Down Expand Up @@ -233,22 +245,20 @@ def setup_comparison_figure(self, plot_individual=False):
tuple
A tuple of the comparison figure(s) and axes object(s).
"""
n = len(self.metrics)

if n == 0:
if self.n_diffference_metrics == 0:
return (None, None)

comparison_fig_all, comparison_axs_all = plt.subplots(
nrows=n,
figsize=(8 + 4 + 2, n*8 + 2),
comparison_fig_all, comparison_axs_all = plotting.setup_figure(
n_rows=self.n_diffference_metrics,
squeeze=False
)

plt.close(comparison_fig_all)
comparison_axs_all = comparison_axs_all.reshape(-1)

comparison_fig_ind = []
comparison_axs_ind = []
for i in range(n):
for i in range(self.n_diffference_metrics):
fig, axs = plt.subplots()
comparison_fig_ind.append(fig)
comparison_axs_ind.append(axs)
Expand Down
14 changes: 7 additions & 7 deletions CADETProcess/comparison/difference.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from warnings import warn

import numpy as np
from scipy.integrate import simps
from scipy.integrate import simpson
from scipy.special import expit

from CADETProcess import CADETProcessError
Expand Down Expand Up @@ -177,7 +177,7 @@ def reference(self, reference):
self._reference.smooth_data()
reference = slice_solution(
self._reference,
None,
self.components,
self.use_total_concentration,
self.use_total_concentration_components,
coordinates={'time': (self.start, self.end)}
Expand Down Expand Up @@ -407,10 +407,10 @@ def _evaluate(self, solution):
Concentration profile of simulation.

"""
area_ref = simps(
area_ref = simpson(
self.reference.solution, self.reference.time, axis=0
)
area_sol = simps(solution.solution, solution.time, axis=0)
area_sol = simpson(solution.solution, solution.time, axis=0)

return abs(area_ref - area_sol)

Expand All @@ -427,10 +427,10 @@ def _evaluate(self, solution):
Concentration profile of simulation.

"""
area_ref = simps(
self.reference.solution, self.reference.time, axis=0
area_ref = simpson(
self.reference.solution, x=self.reference.time, axis=0
)
area_new = simps(solution.solution, solution.time, axis=0)
area_new = simpson(solution.solution, x=solution.time, axis=0)

return abs(area_ref - area_new)/area_ref

Expand Down
34 changes: 16 additions & 18 deletions CADETProcess/dataStructure/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ParameterBase(Descriptor):
Tuple
Float
String
Dict
Dictionary
"""

def __init__(
Expand Down Expand Up @@ -378,7 +378,7 @@ class Typed(ParameterBase):
Tuple
Float
String
Dict
Dictionary
"""

def __init__(self, *args, ty=None, **kwargs):
Expand Down Expand Up @@ -568,15 +568,8 @@ class List(Typed):
ty = list


class Dict(Typed):
"""
Parameter descriptor constrained to dictionary (`dict`) values.

Notes
-----
When integrating with libraries like `addict`, be cautious about potential
name collisions with `addict.Dict`.
"""
class Dictionary(Typed):
"""Parameter descriptor constrained to dictionary (`dict`) values."""

ty = dict

Expand Down Expand Up @@ -1036,10 +1029,10 @@ def check_size(self, instance, value):
return

size = self.get_size(value)
exptected_size = self.get_expected_size(instance)
expected_size = self.get_expected_size(instance)

if size != exptected_size:
raise ValueError(f"Expected size {exptected_size}")
if size != expected_size:
raise ValueError(f"Expected size {expected_size}")

def _prepare(self, instance, value, recursive=False):
"""
Expand Down Expand Up @@ -1529,7 +1522,7 @@ def fill_values(self, dims, value):
raise ValueError("Can only set single entry if n_entries == 1.")

if isinstance(value, np.ndarray) and value.size == 1:
value = float(value)
value = float(value.squeeze())

if isinstance(value, (int, float)):
value = n_entries * [value]
Expand Down Expand Up @@ -1650,12 +1643,17 @@ def check_mod_value(self, instance, value):
If the modulo condition of the size does not meet the expected criteria.
"""
size = self.get_size(value)
exptected_size = self.get_expected_size(instance)
expected_size = self.get_expected_size(instance)

size %= exptected_size
size %= expected_size

if size != 0:
raise ValueError("Size mod exptected size is not 0")
raise ValueError(
f"The size of the value modulo the expected size is not zero. "
f"Size: {size}, Expected Size: {expected_size}"
)

check_size = check_mod_value


class DependentlyModulatedUnsignedList(UnsignedList, SizedList, DependentlyModulated):
Expand Down
Loading
Loading