AMICI-dev / AMICI

Advanced Multilanguage Interface to CVODES and IDAS
https://amici.readthedocs.io/
Other
108 stars 31 forks source link

ShapeError: Matrix size mismatch during import of SBML semantic case 01240 #2109

Closed dweindl closed 1 year ago

dweindl commented 1 year ago

tests/testSBMLSuite.py::test_sbml_testsuite_case[01240] fails with sympy.matrices.common.ShapeError: Matrix size mismatch when generating sensitivity code.

Probable issue: 0 states, or an Event without EventAssignment.

Details

```python pytest -s tests/testSBMLSuite.py::test_sbml_testsuite_case[01240] =============================================================================================== test session starts =============================================================================================== platform linux -- Python 3.11.3, pytest-7.3.1, pluggy-1.0.0 -- /home/dweindl/src/AMICI-devel/build/venv/bin/python cachedir: .pytest_cache rootdir: /home/dweindl/src/AMICI-devel configfile: pytest.ini plugins: xdist-3.2.1, anyio-3.6.2, rerunfailures-11.1.2, cov-4.0.0 collected 1 item tests/testSBMLSuite.py::test_sbml_testsuite_case[01240] FAILED ==================================================================================================== FAILURES ===================================================================================================== _________________________________________________________________________________________ test_sbml_testsuite_case[01240] _________________________________________________________________________________________ test_number = '01240', result_path = PosixPath('/home/dweindl/src/AMICI-devel/tests/amici-semantic-results') sbml_semantic_cases_dir = PosixPath('/home/dweindl/src/AMICI-devel/tests/sbml-test-suite/cases/semantic') def test_sbml_testsuite_case(test_number, result_path, sbml_semantic_cases_dir): test_id = format_test_id(test_number) model_dir = None if test_id == "01395": pytest.skip("NaNs in the Jacobian") # test cases for which sensitivities are to be checked # key: case ID; value: epsilon for finite differences sensitivity_check_cases = { # parameter-dependent conservation laws "00783": 1.5e-2, # initial events "00995": 1e-3, } try: current_test_path = sbml_semantic_cases_dir / test_id # parse expected results results_file = current_test_path / f"{test_id}-results.csv" results = pd.read_csv(results_file, delimiter=",") results.rename( columns={c: c.replace(" ", "") for c in results.columns}, inplace=True ) # TODO remove after https://github.com/AMICI-dev/AMICI/pull/2101 # and https://github.com/AMICI-dev/AMICI/issues/2106 # Don't attempt to generate sensitivity code for models with events+algebraic rules, which will fail sbml_file = find_model_file(current_test_path, test_id) sbml_document = sbml.SBMLReader().readSBMLFromFile(str(sbml_file)) sbml_model = sbml_document.getModel() has_events = sbml_model.getNumEvents() > 0 has_algebraic_rules = any( rule.getTypeCode() == sbml.SBML_ALGEBRAIC_RULE for rule in sbml_model.getListOfRules() ) generate_sensitivity_code = not (has_events and has_algebraic_rules) # ^^^^^^^^ # setup model model_dir = Path(__file__).parent / "SBMLTestModels" / test_id > model, solver, wrapper = compile_model( current_test_path, test_id, model_dir, generate_sensitivity_code=generate_sensitivity_code, ) tests/testSBMLSuite.py:91: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/testSBMLSuite.py:359: in compile_model sbml_importer.sbml2amici( python/sdist/amici/sbml_import.py:415: in sbml2amici exporter.generate_model_code() python/sdist/amici/logging.py:209: in wrapper_timer rval = func(*args, **kwargs) python/sdist/amici/de_export.py:2711: in generate_model_code self._generate_c_code() python/sdist/amici/de_export.py:2747: in _generate_c_code dec(self._write_function_file)(func_name) python/sdist/amici/logging.py:209: in wrapper_timer rval = func(*args, **kwargs) python/sdist/amici/de_export.py:2945: in _write_function_file equations = self.model.eq(function) python/sdist/amici/de_export.py:1366: in eq dec(self._compute_equation)(name) python/sdist/amici/logging.py:209: in wrapper_timer rval = func(*args, **kwargs) python/sdist/amici/de_export.py:2014: in _compute_equation tmp_dxdp = self.sym("sx") * sp.ones(1, self.num_par()) build/venv/lib/python3.11/site-packages/sympy/core/decorators.py:106: in binary_op_wrapper return func(self, other) build/venv/lib/python3.11/site-packages/sympy/matrices/common.py:2702: in __mul__ return self.multiply(other) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Matrix(0, 0, []), other = Matrix([[1]]), dotprodsimp = None def multiply(self, other, dotprodsimp=None): """Same as __mul__() but with optional simplification. Parameters ========== dotprodsimp : bool, optional Specifies whether intermediate term algebraic simplification is used during matrix multiplications to control expression blowup and thus speed up calculation. Default is off. """ isimpbool = _get_intermediate_simp_bool(False, dotprodsimp) other = _matrixify(other) # matrix-like objects can have shapes. This is # our first sanity check. Double check other is not explicitly not a Matrix. if (hasattr(other, 'shape') and len(other.shape) == 2 and (getattr(other, 'is_Matrix', True) or getattr(other, 'is_MatrixLike', True))): if self.shape[1] != other.shape[0]: > raise ShapeError("Matrix size mismatch: %s * %s." % ( self.shape, other.shape)) E sympy.matrices.common.ShapeError: Matrix size mismatch: (0, 0) * (1, 1). build/venv/lib/python3.11/site-packages/sympy/matrices/common.py:2724: ShapeError ============================================================================================= short test summary info ============================================================================================= FAILED tests/testSBMLSuite.py::test_sbml_testsuite_case[01240] - sympy.matrices.common.ShapeError: Matrix size mismatch: (0, 0) * (1, 1). ================================================================================================ 1 failed in 2.20s ================================================================================================ ```

FFroehlich commented 1 year ago

hmm, not sure whether #2112 this is actually the most appropriate fix here. The multiplication of sym('sx') probably needs to be replaced by sym('sx').row_join('sdx').

dweindl commented 1 year ago

hmm, not sure whether #2112 this is actually the most appropriate fix here. The multiplication of sym('sx') probably needs to be replaced by sym('sx').row_join('sdx').

That's possible, but it won't fix this issue. This model doesn't have any algebraic or differential states.

Maybe the event should have been ignored already earlier? Generally, we have to keep Events without EventAssignment for event observables, right?

FFroehlich commented 1 year ago

ah!

hmm, not sure whether #2112 this is actually the most appropriate fix here. The multiplication of sym('sx') probably needs to be replaced by sym('sx').row_join('sdx').

That's possible, but it won't fix this issue. This model doesn't have any algebraic or differential states.

ah, I see.

Maybe the event should have been ignored already earlier? Generally, we have to keep Events without EventAssignment for event observables, right?

Hmm, AMICI certainly isn't the most appropriate tool do consider these models but I guess we can allow such models.

Sounds like in that case the changes are appropriate.

dweindl commented 1 year ago

Hmm, AMICI certainly isn't the most appropriate tool do consider these models but I guess we can allow such models.

Agreed. It's just easier to support that than excluding the respective test cases...