diff --git a/.github/actions/linux-build/action.yml b/.github/actions/linux-build/action.yml index 418ace362a..20ccf5c8bc 100644 --- a/.github/actions/linux-build/action.yml +++ b/.github/actions/linux-build/action.yml @@ -41,6 +41,10 @@ inputs: description: "Enable Multithreading with OpenMP (ON or OFF, default OFF). If ON, adds `-omp` to the name of the artifact." required: false default: "OFF" + enable-optimization: + description: "Enable optimization with Ipopt (ON or OFF, default ON)" + required: false + default: "ON" runs: using: "composite" steps: @@ -89,7 +93,7 @@ runs: exit 1 fi mkdir -p build && cd build - cmake -DCMAKE_BUILD_TYPE=${{ inputs.config }} -DMEMILIO_BUILD_TESTS=${{ inputs.build-tests }} -DMEMILIO_BUILD_BENCHMARKS=${{ inputs.build-benchmarks }} -DMEMILIO_TEST_COVERAGE=${{ inputs.coverage }} -DMEMILIO_SANITIZE_ADDRESS=${{ inputs.sanitize-addr }} -DMEMILIO_SANITIZE_UNDEFINED=${{ inputs.sanitize-ub }} -DMEMILIO_USE_BUNDLED_JSONCPP=${{ inputs.optional-dependencies }} -DMEMILIO_ENABLE_OPENMP=${{ inputs.openmp }} .. + cmake -DCMAKE_BUILD_TYPE=${{ inputs.config }} -DMEMILIO_BUILD_TESTS=${{ inputs.build-tests }} -DMEMILIO_BUILD_BENCHMARKS=${{ inputs.build-benchmarks }} -DMEMILIO_ENABLE_IPOPT=${{ inputs.enable-optimization }} -DMEMILIO_TEST_COVERAGE=${{ inputs.coverage }} -DMEMILIO_SANITIZE_ADDRESS=${{ inputs.sanitize-addr }} -DMEMILIO_SANITIZE_UNDEFINED=${{ inputs.sanitize-ub }} -DMEMILIO_USE_BUNDLED_JSONCPP=${{ inputs.optional-dependencies }} -DMEMILIO_ENABLE_OPENMP=${{ inputs.openmp }} .. make -j4 - name: create build dir archive shell: bash diff --git a/.gitignore b/.gitignore index f4ff6a4b0f..3ce1467f8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,281 +1,281 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/.pnp -.pnp.js - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local -*.xls -*.xlsx -*.zip -*.tar.gz -*.csv - -# Created by https://www.gitignore.io/api/c++,node,python -# Edit at https://www.gitignore.io/?templates=c++,node,python - -### C++ ### -# Prerequisites -*.d - -# Compiled Object files -*.slo -*.lo -*.o -*.obj - -# Precompiled Headers -*.gch -*.pch - -# Compiled Dynamic libraries -*.so -*.dylib -*.dll - -# Fortran module files -*.mod -*.smod - -# Compiled Static libraries -*.lai -*.la -*.a -*.lib - -# Executables -*.exe -*.out -*.app - -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# next.js build output -.next - -# nuxt.js build output -.nuxt - -# rollup.js default build output -dist/ - -# Uncomment the public line if your project uses Gatsby -# https://nextjs.org/blog/next-9-1#public-directory-support -# https://create-react-app.dev/docs/using-the-public-folder/#docsNav -# public - -# Storybook build outputs -.out -.storybook-out - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# Temporary folders -tmp/ -temp/ - -### Python ### -# Pycharm -.idea - -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions - -# Distribution / packaging -.Python -build/ -develop-eggs/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST -_skbuild/ - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# Data output -pycode/epidemiology/**/*.json -pycode/epidemiology/**/*.h5 -pycode/epi_venv/ -pycode/build_pylint/ - -# Credentials for data download -pycode/memilio-epidata/memilio/epidata/CredentialsRegio.ini - -# Docs -docs/html -docs/xml - -# End of https://www.gitignore.io/api/c++,node,python \ No newline at end of file +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/.pnp +.pnp.js + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local +*.xls +*.xlsx +*.zip +*.tar.gz +*.csv + +# Created by https://www.gitignore.io/api/c++,node,python +# Edit at https://www.gitignore.io/?templates=c++,node,python + +### C++ ### +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# rollup.js default build output +dist/ + +# Uncomment the public line if your project uses Gatsby +# https://nextjs.org/blog/next-9-1#public-directory-support +# https://create-react-app.dev/docs/using-the-public-folder/#docsNav +# public + +# Storybook build outputs +.out +.storybook-out + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Temporary folders +tmp/ +temp/ + +### Python ### +# Pycharm +.idea + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions + +# Distribution / packaging +.Python +build/ +develop-eggs/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +_skbuild/ + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Data output +pycode/epidemiology/**/*.json +pycode/epidemiology/**/*.h5 +pycode/epi_venv/ +pycode/build_pylint/ + +# Credentials for data download +pycode/memilio-epidata/memilio/epidata/CredentialsRegio.ini + +# Docs +docs/html +docs/xml + +# End of https://www.gitignore.io/api/c++,node,python diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index e7a3306c24..405b7cd17d 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -17,6 +17,7 @@ option(MEMILIO_BUILD_SHARED_LIBS "Build memilio as a shared library." ON) option(MEMILIO_BUILD_STATIC_LIBS "Build memilio as a static library." ON) option(MEMILIO_ENABLE_MPI "Build memilio with MPI." OFF) option(MEMILIO_ENABLE_OPENMP "Enable Multithreading with OpenMP." OFF) +option(MEMILIO_ENABLE_IPOPT "Enable numerical optimization with Ipopt, requires a Fortran compiler" OFF) mark_as_advanced(MEMILIO_USE_BUNDLED_SPDLOG MEMILIO_SANITIZE_ADDRESS MEMILIO_SANITIZE_UNDEFINED) @@ -75,7 +76,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG") setup_target_for_coverage_lcov( NAME coverage EXECUTABLE memilio-test - EXCLUDE "${CMAKE_SOURCE_DIR}/tests*" "${CMAKE_SOURCE_DIR}/simulations*" "${CMAKE_SOURCE_DIR}/examples*" "${CMAKE_BINARY_DIR}/*" "/usr*" + EXCLUDE "${CMAKE_SOURCE_DIR}/tests*" "${CMAKE_SOURCE_DIR}/simulations*" "${CMAKE_SOURCE_DIR}/examples*" + "${CMAKE_SOURCE_DIR}/memilio/ad*" "${CMAKE_BINARY_DIR}/*" "/usr*" "${CMAKE_SOURCE_DIR}/*.F" ) endif() endif() @@ -113,6 +115,7 @@ endif() # add parts of the project include(thirdparty/CMakeLists.txt) +add_subdirectory(memilio/ad) add_subdirectory(memilio) if(MEMILIO_BUILD_MODELS) @@ -123,6 +126,7 @@ if(MEMILIO_BUILD_MODELS) add_subdirectory(models/ide_secir) add_subdirectory(models/ide_seir) add_subdirectory(models/ode_seir) + add_subdirectory(models/ode_seair) add_subdirectory(models/ode_sir) add_subdirectory(models/sde_sir) add_subdirectory(models/sde_sirs) diff --git a/cpp/benchmarks/flow_simulation_ode_secirvvs.cpp b/cpp/benchmarks/flow_simulation_ode_secirvvs.cpp index 71b721d140..f1f091e933 100644 --- a/cpp/benchmarks/flow_simulation_ode_secirvvs.cpp +++ b/cpp/benchmarks/flow_simulation_ode_secirvvs.cpp @@ -38,13 +38,13 @@ void flowless_sim(::benchmark::State& state) Model model(cfg.num_agegroups); mio::benchmark::setup_model(model); // create simulation - std::shared_ptr I = - std::make_shared>( + std::shared_ptr> I = + std::make_shared>( cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); // run benchmark for (auto _ : state) { // This code gets timed - mio::benchmark::Simulation> sim(model, cfg.t0, cfg.dt); + mio::benchmark::Simulation> sim(model, cfg.t0, cfg.dt); sim.set_integrator(I); // run sim sim.advance(cfg.t_max); @@ -63,13 +63,13 @@ void flow_sim_comp_only(::benchmark::State& state) Model model(cfg.num_agegroups); mio::benchmark::setup_model(model); // create simulation - std::shared_ptr I = - std::make_shared>( + std::shared_ptr> I = + std::make_shared>( cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); // run benchmark for (auto _ : state) { // This code gets timed - mio::osecirvvs::Simulation> sim(model, cfg.t0, cfg.dt); + mio::osecirvvs::Simulation> sim(model, cfg.t0, cfg.dt); sim.set_integrator(I); // run sim sim.advance(cfg.t_max); @@ -88,13 +88,13 @@ void flow_sim(::benchmark::State& state) Model model(cfg.num_agegroups); mio::benchmark::setup_model(model); // create simulation - std::shared_ptr I = - std::make_shared>( + std::shared_ptr> I = + std::make_shared>( cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); // run benchmark for (auto _ : state) { // This code gets timed - mio::osecirvvs::Simulation> sim(model, cfg.t0, cfg.dt); + mio::osecirvvs::Simulation> sim(model, cfg.t0, cfg.dt); sim.set_integrator(I); // run sim sim.advance(cfg.t_max); diff --git a/cpp/benchmarks/flow_simulation_ode_secirvvs.h b/cpp/benchmarks/flow_simulation_ode_secirvvs.h index 13d65e480d..cd529a8b93 100644 --- a/cpp/benchmarks/flow_simulation_ode_secirvvs.h +++ b/cpp/benchmarks/flow_simulation_ode_secirvvs.h @@ -25,7 +25,7 @@ namespace mio namespace benchmark { -using FlowModel = osecirvvs::Model; +using FlowModel = osecirvvs::Model<>; // For comparison benchmarks, an old model version that does not provide computation of flows has been reimplemented here. // For more details see the original implementation in: @@ -34,12 +34,14 @@ using FlowModel = osecirvvs::Model; // - Apply_variant function has been adjusted to be more generic // - Fixed a bug where the transmission probability was always set to zero. -class FlowlessModel : public CompartmentalModel, osecirvvs::Parameters> +class FlowlessModel : public CompartmentalModel, + osecirvvs::Parameters> { using InfectionState = osecirvvs::InfectionState; - using Parameters = osecirvvs::Parameters; - using Base = CompartmentalModel, Parameters>; + using Base = CompartmentalModel, + osecirvvs::Parameters>; public: FlowlessModel(const Populations& pop, const ParameterSet& params) @@ -59,14 +61,14 @@ class FlowlessModel : public CompartmentalModelparameters; AgeGroup n_agegroups = params.get_num_groups(); - ContactMatrixGroup const& contact_matrix = params.get(); + ContactMatrixGroup const& contact_matrix = params.get>(); auto icu_occupancy = 0.0; auto test_and_trace_required = 0.0; for (auto i = AgeGroup(0); i < n_agegroups; ++i) { test_and_trace_required += - (1 - params.get()[i]) / - params.get()[i] * + (1 - params.get>()[i]) / + params.get>()[i] * (this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsNaive}) + this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsPartialImmunity}) + this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsImprovedImmunity}) + @@ -127,29 +129,29 @@ class FlowlessModel : public CompartmentalModel()[i]; - double reducExposedImprovedImmunity = params.get()[i]; + double reducExposedPartialImmunity = params.get>()[i]; + double reducExposedImprovedImmunity = params.get>()[i]; double reducInfectedSymptomsPartialImmunity = - params.get()[i]; + params.get>()[i]; double reducInfectedSymptomsImprovedImmunity = - params.get()[i]; + params.get>()[i]; double reducInfectedSevereCriticalDeadPartialImmunity = - params.get()[i]; + params.get>()[i]; double reducInfectedSevereCriticalDeadImprovedImmunity = - params.get()[i]; - double reducTimeInfectedMild = params.get()[i]; + params.get>()[i]; + double reducTimeInfectedMild = params.get>()[i]; //symptomatic are less well quarantined when testing and tracing is overwhelmed so they infect more people auto riskFromInfectedSymptomatic = - smoother_cosine(test_and_trace_required, params.get(), - params.get() * 15, - params.get()[i], - params.get()[i]); + smoother_cosine(test_and_trace_required, params.get>(), + params.get>() * 15, + params.get>()[i], + params.get>()[i]); auto riskFromInfectedNoSymptoms = - smoother_cosine(test_and_trace_required, params.get(), - params.get() * 2, - params.get()[i], 1.0); + smoother_cosine(test_and_trace_required, params.get>(), + params.get>() * 2, + params.get>()[i], 1.0); for (auto j = AgeGroup(0); j < n_agegroups; j++) { size_t SNj = this->populations.get_flat_index({j, InfectionState::SusceptibleNaive}); @@ -190,9 +192,8 @@ class FlowlessModel : public CompartmentalModel() * - sin(3.141592653589793 * - (std::fmod((params.get() + t), 365.0) / 182.5 + 0.5))); + (1 + params.get>() * + sin(3.141592653589793 * ((params.get() + t) / 182.5 + 0.5))); double cont_freq_eff = season_val * contact_matrix.get_matrix_at(t)(static_cast((size_t)i), static_cast((size_t)j)); @@ -206,7 +207,7 @@ class FlowlessModel : public CompartmentalModel()[(AgeGroup)i] * + params.template get>()[(AgeGroup)i] * (riskFromInfectedNoSymptoms * (pop[INSNj] + pop[INSPIj] + pop[INSIIj]) + riskFromInfectedSymptomatic * (pop[ISyNj] + pop[ISyPIj] + pop[ISyIIj])); @@ -231,151 +232,168 @@ class FlowlessModel : public CompartmentalModel(), - params.get(), params.get()[i], 0); + smoother_cosine(icu_occupancy, 0.90 * params.get>(), + params.get>(), + params.get>()[i], 0); - double deathsPerSevereAdjusted = params.get()[i] - criticalPerSevereAdjusted; + double deathsPerSevereAdjusted = + params.get>()[i] - criticalPerSevereAdjusted; /**** path of immune-naive ***/ dydt[ENi] -= - y[ENi] / params.get()[i]; // only exchange of E and InfectedNoSymptoms done here - dydt[INSNi] = y[ENi] / params.get()[i] - - y[INSNi] / params.get()[i]; - dydt[INSNCi] = -y[INSNCi] / params.get()[i]; - - dydt[ISyNi] = (1 - params.get()[i]) / - params.get()[i] * y[INSNi] - - (y[ISyNi] / params.get()[i]); - dydt[ISyNCi] = (1 - params.get()[i]) / - params.get()[i] * y[INSNCi] - - (y[ISyNCi] / params.get()[i]); - - dydt[ISevNi] = params.get()[i] / - params.get()[i] * (y[ISyNi] + y[ISyNCi]) - - (1 / params.get()[i]) * y[ISevNi]; - dydt[ICrNi] = -y[ICrNi] / params.get()[i]; + y[ENi] / + params.get< + osecirvvs::TimeExposed>()[i]; // only exchange of E and InfectedNoSymptoms done here + dydt[INSNi] = y[ENi] / params.get>()[i] - + y[INSNi] / params.get>()[i]; + dydt[INSNCi] = -y[INSNCi] / params.get>()[i]; + + dydt[ISyNi] = (1 - params.get>()[i]) / + params.get>()[i] * y[INSNi] - + (y[ISyNi] / params.get>()[i]); + dydt[ISyNCi] = (1 - params.get>()[i]) / + params.get>()[i] * y[INSNCi] - + (y[ISyNCi] / params.get>()[i]); + + dydt[ISevNi] = params.get>()[i] / + params.get>()[i] * (y[ISyNi] + y[ISyNCi]) - + (1 / params.get>()[i]) * y[ISevNi]; + dydt[ICrNi] = -y[ICrNi] / params.get>()[i]; // add flow from hosp to icu according to potentially adjusted probability due to ICU limits - dydt[ICrNi] += criticalPerSevereAdjusted / params.get()[i] * y[ISevNi]; + dydt[ICrNi] += + criticalPerSevereAdjusted / params.get>()[i] * y[ISevNi]; /**** path of partially immune (e.g., one dose of vaccination) ***/ dydt[EPIi] -= y[EPIi] / - params.get()[i]; // only exchange of E and InfectedNoSymptoms done here - dydt[INSPIi] = y[EPIi] / params.get()[i] - - y[INSPIi] / (params.get()[i] * reducTimeInfectedMild); - dydt[INSPICi] = -y[INSPICi] / (params.get()[i] * reducTimeInfectedMild); - dydt[ISyPIi] = (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) * - (1 - params.get()[i]) * y[INSPIi] / - (params.get()[i] * reducTimeInfectedMild) - - (y[ISyPIi] / (params.get()[i] * reducTimeInfectedMild)); - dydt[ISyPICi] = (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) * - (1 - params.get()[i]) / - (params.get()[i] * reducTimeInfectedMild) * - y[INSPICi] - - (y[ISyPICi] / (params.get()[i] * reducTimeInfectedMild)); + params.get< + osecirvvs::TimeExposed>()[i]; // only exchange of E and InfectedNoSymptoms done here + dydt[INSPIi] = + y[EPIi] / params.get>()[i] - + y[INSPIi] / (params.get>()[i] * reducTimeInfectedMild); + dydt[INSPICi] = + -y[INSPICi] / (params.get>()[i] * reducTimeInfectedMild); + dydt[ISyPIi] = + (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) * + (1 - params.get>()[i]) * y[INSPIi] / + (params.get>()[i] * reducTimeInfectedMild) - + (y[ISyPIi] / (params.get>()[i] * reducTimeInfectedMild)); + dydt[ISyPICi] = + (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) * + (1 - params.get>()[i]) / + (params.get>()[i] * reducTimeInfectedMild) * + y[INSPICi] - + (y[ISyPICi] / (params.get>()[i] * reducTimeInfectedMild)); dydt[ISevPIi] = reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSymptomsPartialImmunity * - params.get()[i] / - (params.get()[i] * reducTimeInfectedMild) * + params.get>()[i] / + (params.get>()[i] * reducTimeInfectedMild) * (y[ISyPIi] + y[ISyPICi]) - - (1 / params.get()[i]) * y[ISevPIi]; - dydt[ICrPIi] = -(1 / params.get()[i]) * y[ICrPIi]; + (1 / params.get>()[i]) * y[ISevPIi]; + dydt[ICrPIi] = -(1 / params.get>()[i]) * y[ICrPIi]; // add flow from hosp to icu according to potentially adjusted probability due to ICU limits dydt[ICrPIi] += reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity * criticalPerSevereAdjusted / - params.get()[i] * y[ISevPIi]; + params.get>()[i] * y[ISevPIi]; /**** path of twice vaccinated, here called immune although reinfection is possible now ***/ - dydt[EIIi] -= y[EIIi] / params.get()[i]; // only exchange of E and C done here + dydt[EIIi] -= + y[EIIi] / params.get>()[i]; // only exchange of E and C done here - dydt[INSIIi] = y[EIIi] / params.get()[i] - - y[INSIIi] / (params.get()[i] * reducTimeInfectedMild); - dydt[INSIICi] = -y[INSIICi] / (params.get()[i] * reducTimeInfectedMild); + dydt[INSIIi] = + y[EIIi] / params.get>()[i] - + y[INSIIi] / (params.get>()[i] * reducTimeInfectedMild); + dydt[INSIICi] = + -y[INSIICi] / (params.get>()[i] * reducTimeInfectedMild); - dydt[ISyIIi] = (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) * - (1 - params.get()[i]) * y[INSIIi] / - (params.get()[i] * reducTimeInfectedMild) - - (1 / (params.get()[i] * reducTimeInfectedMild)) * y[ISyIIi]; + dydt[ISyIIi] = + (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) * + (1 - params.get>()[i]) * y[INSIIi] / + (params.get>()[i] * reducTimeInfectedMild) - + (1 / (params.get>()[i] * reducTimeInfectedMild)) * + y[ISyIIi]; dydt[ISyIICi] = (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) * - (1 - params.get()[i]) * y[INSIICi] / - (params.get()[i] * reducTimeInfectedMild) - - (1 / (params.get()[i] * reducTimeInfectedMild)) * y[ISyIICi]; + (1 - params.get>()[i]) * y[INSIICi] / + (params.get>()[i] * reducTimeInfectedMild) - + (1 / (params.get>()[i] * reducTimeInfectedMild)) * + y[ISyIICi]; dydt[ISevIIi] = reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSymptomsImprovedImmunity * - params.get()[i] / - (params.get()[i] * reducTimeInfectedMild) * + params.get>()[i] / + (params.get>()[i] * reducTimeInfectedMild) * (y[ISyIIi] + y[ISyIICi]) - - (1 / params.get()[i]) * y[ISevIIi]; - dydt[ICrIIi] = -(1 / params.get()[i]) * y[ICrIIi]; + (1 / params.get>()[i]) * y[ISevIIi]; + dydt[ICrIIi] = -(1 / params.get>()[i]) * y[ICrIIi]; // add flow from hosp to icu according to potentially adjusted probability due to ICU limits dydt[ICrIIi] += reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity * criticalPerSevereAdjusted / - params.get()[i] * y[ISevIIi]; + params.get>()[i] * y[ISevIIi]; // recovered and deaths from all paths - dydt[SIIi] += params.get()[i] / - params.get()[i] * (y[INSNi] + y[INSNCi]) + - (1 - params.get()[i]) / - params.get()[i] * (y[ISyNi] + y[ISyNCi]) + - (1 - params.get()[i]) / - params.get()[i] * y[ISevNi] + - (1 - params.get()[i]) / - params.get()[i] * y[ICrNi]; + dydt[SIIi] += params.get>()[i] / + params.get>()[i] * (y[INSNi] + y[INSNCi]) + + (1 - params.get>()[i]) / + params.get>()[i] * (y[ISyNi] + y[ISyNCi]) + + (1 - params.get>()[i]) / + params.get>()[i] * y[ISevNi] + + (1 - params.get>()[i]) / + params.get>()[i] * y[ICrNi]; dydt[SIIi] += (1 - (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) * - (1 - params.get()[i])) / - (params.get()[i] * reducTimeInfectedMild) * + (1 - params.get>()[i])) / + (params.get>()[i] * reducTimeInfectedMild) * (y[INSPIi] + y[INSPICi]) + (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSymptomsPartialImmunity) * - params.get()[i]) / - (params.get()[i] * reducTimeInfectedMild) * + params.get>()[i]) / + (params.get>()[i] * reducTimeInfectedMild) * (y[ISyPIi] + y[ISyPICi]) + (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) * - params.get()[i]) / - params.get()[i] * y[ISevPIi] + + params.get>()[i]) / + params.get>()[i] * y[ISevPIi] + (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) * - params.get()[i]) / - params.get()[i] * y[ICrPIi]; + params.get>()[i]) / + params.get>()[i] * y[ICrPIi]; dydt[SIIi] += (1 - (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) * - (1 - params.get()[i])) * - (params.get()[i] * reducTimeInfectedMild) * + (1 - params.get>()[i])) * + (params.get>()[i] * reducTimeInfectedMild) * (y[INSIIi] + y[INSIICi]) + (1 - (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSymptomsImprovedImmunity) * - params.get()[i]) / - (params.get()[i] * reducTimeInfectedMild) * + params.get>()[i]) / + (params.get>()[i] * reducTimeInfectedMild) * (y[ISyIIi] + y[ISyIICi]) + (1 - (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) * - params.get()[i]) / - params.get()[i] * y[ISevIIi] + + params.get>()[i]) / + params.get>()[i] * y[ISevIIi] + (1 - (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) * - params.get()[i]) / - params.get()[i] * y[ICrIIi]; + params.get>()[i]) / + params.get>()[i] * y[ICrIIi]; - dydt[DNi] = params.get()[i] / - params.get()[i] * y[ICrNi]; + dydt[DNi] = params.get>()[i] / + params.get>()[i] * y[ICrNi]; dydt[DPIi] = reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity * - params.get()[i] / - params.get()[i] * y[ICrPIi]; + params.get>()[i] / + params.get>()[i] * y[ICrPIi]; dydt[DIIi] = reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity * - params.get()[i] / - params.get()[i] * y[ICrIIi]; + params.get>()[i] / + params.get>()[i] * y[ICrIIi]; // add potential, additional deaths due to ICU overflow - dydt[DNi] += deathsPerSevereAdjusted / params.get()[i] * y[ISevNi]; + dydt[DNi] += + deathsPerSevereAdjusted / params.get>()[i] * y[ISevNi]; dydt[DPIi] += (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) * - deathsPerSevereAdjusted / params.get()[i] * y[ISevPIi]; + deathsPerSevereAdjusted / params.get>()[i] * y[ISevPIi]; dydt[DIIi] += (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) * - deathsPerSevereAdjusted / params.get()[i] * y[ISevIIi]; + deathsPerSevereAdjusted / params.get>()[i] * y[ISevIIi]; } } @@ -410,8 +428,9 @@ class FlowlessModel : public CompartmentalModel> -double get_infections_relative(const Simulation& model, double t, const Eigen::Ref& y); +template > +double get_infections_relative(const Simulation& model, double t, + const Eigen::Ref& y); template class Simulation : public Base @@ -429,7 +448,7 @@ class Simulation : public Base { } - void apply_variant(const double t, const CustomIndexArray base_infectiousness) + void apply_variant(const double t, const CustomIndexArray, AgeGroup> base_infectiousness) { auto start_day = this->get_model().parameters.template get(); auto start_day_new_variant = this->get_model().parameters.template get(); @@ -442,8 +461,9 @@ class Simulation : public Base double new_transmission = (1 - share_new_variant) * base_infectiousness[i] + share_new_variant * base_infectiousness[i] * - this->get_model().parameters.template get()[i]; - this->get_model().parameters.template get()[i] = + this->get_model().parameters.template get>()[i]; + this->get_model() + .parameters.template get>()[i] = new_transmission; } } @@ -466,16 +486,16 @@ class Simulation : public Base double first_vacc; double full_vacc; if (t_idx == SimulationDay(0)) { - first_vacc = params.template get()[{(AgeGroup)i, t_idx}]; - full_vacc = params.template get()[{(AgeGroup)i, t_idx}]; + first_vacc = params.template get>()[{(AgeGroup)i, t_idx}]; + full_vacc = params.template get>()[{(AgeGroup)i, t_idx}]; } else { - first_vacc = - params.template get()[{(AgeGroup)i, t_idx}] - - params.template get()[{(AgeGroup)i, t_idx - SimulationDay(1)}]; - full_vacc = - params.template get()[{(AgeGroup)i, t_idx}] - - params.template get()[{(AgeGroup)i, t_idx - SimulationDay(1)}]; + first_vacc = params.template get>()[{(AgeGroup)i, t_idx}] - + params.template get>()[{ + (AgeGroup)i, t_idx - SimulationDay(1)}]; + full_vacc = params.template get>()[{(AgeGroup)i, t_idx}] - + params.template get>()[{ + (AgeGroup)i, t_idx - SimulationDay(1)}]; } if (last_value(count * i + S) - first_vacc < 0) { @@ -509,13 +529,14 @@ class Simulation : public Base */ Eigen::Ref advance(double tmax) { - auto& t_end_dyn_npis = this->get_model().parameters.get_end_dynamic_npis(); - auto& dyn_npis = this->get_model().parameters.template get(); - auto& contact_patterns = this->get_model().parameters.template get(); + auto& t_end_dyn_npis = this->get_model().parameters.get_end_dynamic_npis(); + auto& dyn_npis = + this->get_model().parameters.template get>(); + auto& contact_patterns = this->get_model().parameters.template get>(); const size_t num_groups = (size_t)this->get_model().parameters.get_num_groups(); auto base_infectiousness = - this->get_model().parameters.template get(); + this->get_model().parameters.template get>(); double delay_lockdown; auto t = Base::get_result().get_last_time(); @@ -574,7 +595,8 @@ class Simulation : public Base } } - this->get_model().parameters.template get() = base_infectiousness; + this->get_model().parameters.template get>() = + base_infectiousness; return this->get_result().get_last_value(); } @@ -641,50 +663,52 @@ void setup_model(Model& model) {i, osecirvvs::InfectionState::SusceptibleNaive}, 1000); } - model.parameters.template get() = 100; - model.parameters.template get() = 0.0143; - model.parameters.template get().resize(SimulationDay(size_t(1000))); - model.parameters.template get().array().setConstant(5); - model.parameters.template get().resize(SimulationDay(size_t(1000))); - model.parameters.template get().array().setConstant(3); + model.parameters.template get>() = 100; + model.parameters.template get>() = 0.0143; + model.parameters.template get>().resize(SimulationDay(size_t(1000))); + model.parameters.template get>().array().setConstant(5); + model.parameters.template get>().resize(SimulationDay(size_t(1000))); + model.parameters.template get>().array().setConstant(3); - auto& contacts = model.parameters.template get(); + auto& contacts = model.parameters.template get>(); auto& contact_matrix = contacts.get_cont_freq_mat(); contact_matrix[0].get_baseline().setConstant(0.5); contact_matrix[0].get_baseline().diagonal().setConstant(5.0); contact_matrix[0].add_damping(0.3, SimulationTime(5.0)); //times - model.parameters.template get()[AgeGroup(0)] = 3.33; - model.parameters.template get()[AgeGroup(0)] = 1.87; - model.parameters.template get()[AgeGroup(0)] = 7; - model.parameters.template get()[AgeGroup(0)] = 6; - model.parameters.template get()[AgeGroup(0)] = 7; + model.parameters.template get>()[AgeGroup(0)] = 3.33; + model.parameters.template get>()[AgeGroup(0)] = 1.87; + model.parameters.template get>()[AgeGroup(0)] = 7; + model.parameters.template get>()[AgeGroup(0)] = 6; + model.parameters.template get>()[AgeGroup(0)] = 7; //probabilities - model.parameters.template get()[AgeGroup(0)] = 0.15; - model.parameters.template get()[AgeGroup(0)] = 0.5; + model.parameters.template get>()[AgeGroup(0)] = 0.15; + model.parameters.template get>()[AgeGroup(0)] = 0.5; // The precise value between Risk* (situation under control) and MaxRisk* (situation not under control) // depends on incidence and test and trace capacity - model.parameters.template get()[AgeGroup(0)] = 0.0; - model.parameters.template get()[AgeGroup(0)] = 0.4; - model.parameters.template get()[AgeGroup(0)] = 0.2; - model.parameters.template get()[AgeGroup(0)] = 0.1; - model.parameters.template get()[AgeGroup(0)] = 0.1; - model.parameters.template get()[AgeGroup(0)] = 0.1; - - model.parameters.template get()[AgeGroup(0)] = 0.8; - model.parameters.template get()[AgeGroup(0)] = 0.331; - model.parameters.template get()[AgeGroup(0)] = 0.65; - model.parameters.template get()[AgeGroup(0)] = 0.243; - model.parameters.template get()[AgeGroup(0)] = 0.1; - model.parameters.template get()[AgeGroup(0)] = 0.091; - model.parameters.template get()[AgeGroup(0)] = 0.9; - - model.parameters.template get() = 0.2; + model.parameters.template get>()[AgeGroup(0)] = 0.0; + model.parameters.template get>()[AgeGroup(0)] = 0.4; + model.parameters.template get>()[AgeGroup(0)] = 0.2; + model.parameters.template get>()[AgeGroup(0)] = 0.1; + model.parameters.template get>()[AgeGroup(0)] = 0.1; + model.parameters.template get>()[AgeGroup(0)] = 0.1; + + model.parameters.template get>()[AgeGroup(0)] = 0.8; + model.parameters.template get>()[AgeGroup(0)] = 0.331; + model.parameters.template get>()[AgeGroup(0)] = 0.65; + model.parameters.template get>()[AgeGroup(0)] = 0.243; + model.parameters + .template get>()[AgeGroup(0)] = 0.1; + model.parameters + .template get>()[AgeGroup(0)] = 0.091; + model.parameters.template get>()[AgeGroup(0)] = 0.9; + + model.parameters.template get>() = 0.2; model.apply_constraints(); } } // namespace benchmark -} // namespace mio \ No newline at end of file +} // namespace mio diff --git a/cpp/benchmarks/flow_simulation_ode_seir.cpp b/cpp/benchmarks/flow_simulation_ode_seir.cpp index be19fcbec2..6cf7a586cd 100644 --- a/cpp/benchmarks/flow_simulation_ode_seir.cpp +++ b/cpp/benchmarks/flow_simulation_ode_seir.cpp @@ -32,61 +32,82 @@ namespace mio namespace benchmark { -using FlowModel = ::mio::oseir::Model; +using FlowModel = ::mio::oseir::Model; using namespace oseir; -// For comparison benchmarks, an old model version that does not provide computation of flows has been reimplemented here. -// For more details see the original implementation in: -// https://github.com/SciCompMod/memilio/blob/13555a6b23177d2d4633c393903461a27ce5762b/cpp/models/ode_seir/model.h -class FlowlessModel : public CompartmentalModel, Parameters> +// For comparison benchmarks, the ODE-SEIR model has been adapted into +// a compartmental model that does not rely on flows. +class FlowlessModel + : public CompartmentalModel, oseir::Parameters> { - using Base = CompartmentalModel, Parameters>; + using Base = CompartmentalModel, + oseir::Parameters>; public: - FlowlessModel() - : Base(Populations({InfectionState::Count}, 0.), ParameterSet()) + FlowlessModel(int num_agegroups) + : Base(Populations({AgeGroup(num_agegroups), InfectionState::Count}), ParameterSet(AgeGroup(num_agegroups))) { } void get_derivatives(Eigen::Ref pop, Eigen::Ref y, double t, Eigen::Ref dydt) const override { - auto& params = this->parameters; - double coeffStoE = params.get().get_matrix_at(t)(0, 0) * - params.get() / populations.get_total(); - - dydt[(size_t)InfectionState::Susceptible] = - -coeffStoE * y[(size_t)InfectionState::Susceptible] * pop[(size_t)InfectionState::Infected]; - dydt[(size_t)InfectionState::Exposed] = - coeffStoE * y[(size_t)InfectionState::Susceptible] * pop[(size_t)InfectionState::Infected] - - (1.0 / params.get()) * y[(size_t)InfectionState::Exposed]; - dydt[(size_t)InfectionState::Infected] = - (1.0 / params.get()) * y[(size_t)InfectionState::Exposed] - - (1.0 / params.get()) * y[(size_t)InfectionState::Infected]; - dydt[(size_t)InfectionState::Recovered] = - (1.0 / params.get()) * y[(size_t)InfectionState::Infected]; + auto& params = this->parameters; + const Index age_groups = reduce_index>(this->populations.size()); + + for (auto i : mio::make_index_range(age_groups)) { + size_t Si = this->populations.get_flat_index({i, InfectionState::Susceptible}); + size_t Ei = this->populations.get_flat_index({i, InfectionState::Exposed}); + size_t Ii = this->populations.get_flat_index({i, InfectionState::Infected}); + size_t Ri = this->populations.get_flat_index({i, InfectionState::Recovered}); + + for (auto j : make_index_range(age_groups)) { + + size_t Sj = this->populations.get_flat_index({j, InfectionState::Susceptible}); + size_t Ej = this->populations.get_flat_index({j, InfectionState::Exposed}); + size_t Ij = this->populations.get_flat_index({j, InfectionState::Infected}); + size_t Rj = this->populations.get_flat_index({j, InfectionState::Recovered}); + + const double Nj_inv = 1.0 / (pop[Sj] + pop[Ej] + pop[Ij] + pop[Rj]); + const double coeffStoE = + params.template get>().get_cont_freq_mat().get_matrix_at(t)(i.get(), + j.get()) * + params.template get>()[i] * Nj_inv; + + dydt[Si] -= y[Si] * pop[Ij] * coeffStoE; + dydt[Ei] += y[Si] * pop[Ij] * coeffStoE; + } + + dydt[Ii] += (1.0 / params.get>()[i]) * y[Ei]; + dydt[Ii] -= (1.0 / params.get>()[i]) * y[Ii]; + dydt[Ri] = (1.0 / params.get>()[i]) * y[Ii]; + } } }; template void setup_model(Model& model) { - double total_population = 10000; - model.populations[{mio::Index(mio::oseir::InfectionState::Exposed)}] = 100; - model.populations[{mio::Index(mio::oseir::InfectionState::Infected)}] = 100; - model.populations[{mio::Index(mio::oseir::InfectionState::Recovered)}] = 100; - model.populations[{mio::Index(mio::oseir::InfectionState::Susceptible)}] = - total_population - - model.populations[{mio::Index(mio::oseir::InfectionState::Exposed)}] - - model.populations[{mio::Index(mio::oseir::InfectionState::Infected)}] - - model.populations[{mio::Index(mio::oseir::InfectionState::Recovered)}]; - // suscetible now set with every other update - // params.nb_sus_t0 = params.nb_total_t0 - params.nb_exp_t0 - params.nb_inf_t0 - params.nb_rec_t0; - model.parameters.template set(5.2); - model.parameters.template set(6); - model.parameters.template set(0.04); - model.parameters.template get().get_baseline()(0, 0) = 10; + const double total_population = 10000.0; + const auto num_groups = model.parameters.get_num_groups(); + for (AgeGroup i = 0; i < num_groups; i++) { + model.populations[{i, oseir::InfectionState::Exposed}] = 100.0 / static_cast(num_groups); + model.populations[{i, oseir::InfectionState::Infected}] = 100.0 / static_cast(num_groups); + model.populations[{i, oseir::InfectionState::Recovered}] = 100.0 / static_cast(num_groups); + model.populations[{i, oseir::InfectionState::Susceptible}] = + total_population / static_cast(num_groups) - + model.populations[{i, oseir::InfectionState::Exposed}] - + model.populations[{i, oseir::InfectionState::Infected}] - + model.populations[{i, oseir::InfectionState::Recovered}]; + } + model.parameters.template set>(5.2); + model.parameters.template set>(6); + model.parameters.template set>(0.04); + mio::ContactMatrixGroup& contact_matrix = model.parameters.template get>(); + contact_matrix[0].get_baseline().setConstant(10.); } } // namespace benchmark @@ -101,11 +122,11 @@ void flowless_sim(::benchmark::State& state) // load config auto cfg = mio::benchmark::SimulationConfig::initialize(config_path); // create model - Model model; + Model model(cfg.num_agegroups); mio::benchmark::setup_model(model); // create simulation - std::shared_ptr I = - std::make_shared>( + std::shared_ptr> I = + std::make_shared>( cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); mio::TimeSeries results(static_cast(Model::Compartments::Count)); // run benchmark @@ -124,11 +145,11 @@ void flow_sim_comp_only(::benchmark::State& state) // load config auto cfg = mio::benchmark::SimulationConfig::initialize(config_path); // create model - Model model; + Model model(cfg.num_agegroups); mio::benchmark::setup_model(model); // create simulation - std::shared_ptr I = - std::make_shared>( + std::shared_ptr> I = + std::make_shared>( cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); mio::TimeSeries results(static_cast(Model::Compartments::Count)); // run benchmark @@ -147,11 +168,11 @@ void flow_sim(::benchmark::State& state) // load config auto cfg = mio::benchmark::SimulationConfig::initialize(config_path); // create model - Model model; + Model model(cfg.num_agegroups); mio::benchmark::setup_model(model); // create simulation - std::shared_ptr I = - std::make_shared>( + std::shared_ptr> I = + std::make_shared>( cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); mio::TimeSeries results(static_cast(Model::Compartments::Count)); // run benchmark diff --git a/cpp/benchmarks/graph_simulation.cpp b/cpp/benchmarks/graph_simulation.cpp index 752f3f5173..02b3c56dcc 100644 --- a/cpp/benchmarks/graph_simulation.cpp +++ b/cpp/benchmarks/graph_simulation.cpp @@ -22,13 +22,14 @@ #include "memilio/mobility/metapopulation_mobility_instant.h" #include "benchmark/benchmark.h" #include "ode_secirvvs/model.h" +#include "memilio/math/adapt_rk.h" #include const std::string config_path = "../../benchmarks/graph_simulation.config"; -mio::osecirvvs::Model create_model(size_t num_agegroups, const ScalarType tmax) +mio::osecirvvs::Model create_model(size_t num_agegroups, const ScalarType tmax) { - mio::osecirvvs::Model model(num_agegroups); + mio::osecirvvs::Model model(num_agegroups); const size_t pop_total = 10000; const size_t init_val = 20; for (mio::AgeGroup i = 0; i < (mio::AgeGroup)num_agegroups; i++) { @@ -64,16 +65,16 @@ mio::osecirvvs::Model create_model(size_t num_agegroups, const ScalarType tmax) {i, mio::osecirvvs::InfectionState::SusceptibleNaive}, pop_total); } - const size_t vacc_first = 5; - const size_t vacc_full = 5; - model.parameters.get() = 100; - model.parameters.get() = 0.0143; - model.parameters.get().resize(mio::SimulationDay(tmax)); - model.parameters.get().array().setConstant(vacc_first); - model.parameters.get().resize(mio::SimulationDay(tmax)); - model.parameters.get().array().setConstant(vacc_full); + const size_t vacc_first = 5; + const size_t vacc_full = 5; + model.parameters.get>() = 100; + model.parameters.get>() = 0.0143; + model.parameters.get>().resize(mio::SimulationDay(tmax)); + model.parameters.get>().array().setConstant(vacc_first); + model.parameters.get>().resize(mio::SimulationDay(tmax)); + model.parameters.get>().array().setConstant(vacc_full); - auto& contacts = model.parameters.get(); + auto& contacts = model.parameters.get>(); auto& contact_matrix = contacts.get_cont_freq_mat(); contact_matrix[0].get_baseline().setConstant(0.5); contact_matrix[0].get_baseline().diagonal().setConstant(5.0); @@ -81,31 +82,31 @@ mio::osecirvvs::Model create_model(size_t num_agegroups, const ScalarType tmax) for (mio::AgeGroup i = 0; i < (mio::AgeGroup)num_agegroups; i++) { //times - model.parameters.get()[i] = 3.33; - model.parameters.get()[i] = 1.87; - model.parameters.get()[i] = 7; - model.parameters.get()[i] = 6; - model.parameters.get()[i] = 7; + model.parameters.get>()[i] = 3.33; + model.parameters.get>()[i] = 1.87; + model.parameters.get>()[i] = 7; + model.parameters.get>()[i] = 6; + model.parameters.get>()[i] = 7; //probabilities - model.parameters.get()[i] = 0.15; - model.parameters.get()[i] = 0.5; - model.parameters.get()[i] = 0.0; - model.parameters.get()[i] = 0.4; - model.parameters.get()[i] = 0.2; - model.parameters.get()[i] = 0.1; - model.parameters.get()[i] = 0.1; - model.parameters.get()[i] = 0.1; - - model.parameters.get()[i] = 0.8; - model.parameters.get()[i] = 0.331; - model.parameters.get()[i] = 0.65; - model.parameters.get()[i] = 0.243; - model.parameters.get()[i] = 0.1; - model.parameters.get()[i] = 0.091; - model.parameters.get()[i] = 0.9; + model.parameters.get>()[i] = 0.15; + model.parameters.get>()[i] = 0.5; + model.parameters.get>()[i] = 0.0; + model.parameters.get>()[i] = 0.4; + model.parameters.get>()[i] = 0.2; + model.parameters.get>()[i] = 0.1; + model.parameters.get>()[i] = 0.1; + model.parameters.get>()[i] = 0.1; + + model.parameters.get>()[i] = 0.8; + model.parameters.get>()[i] = 0.331; + model.parameters.get>()[i] = 0.65; + model.parameters.get>()[i] = 0.243; + model.parameters.get>()[i] = 0.1; + model.parameters.get>()[i] = 0.091; + model.parameters.get>()[i] = 0.9; } - model.parameters.get() = 0.2; + model.parameters.get>() = 0.2; return model; } @@ -116,7 +117,9 @@ auto create_simulation() mio::osecirvvs::Model model = create_model(cfg.num_agegroups, cfg.t_max); - mio::Graph>, mio::MigrationEdge> g; + mio::Graph>>, + mio::MigrationEdge> + g; for (size_t county_id = 0; county_id < cfg.num_regions; county_id++) { g.add_node(county_id, model, cfg.t0); g.nodes()[county_id].property.get_simulation().set_integrator(std::make_shared()); @@ -160,18 +163,21 @@ void graph_sim_secirvvs(::benchmark::State& state) // register functions as a benchmarks and set a name // mitigate influence of cpu scaling -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Dummy 1/3"); -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Dummy 2/3"); -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Dummy 3/3"); +BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Dummy 1/3"); +BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Dummy 2/3"); +BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Dummy 3/3"); // register functions as a benchmarks and set a name -BENCHMARK_TEMPLATE(init_benchmark, mio::RKIntegratorCore)->Name("Initialize Graph without simulation"); -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::EulerIntegratorCore)->Name("Graph Simulation - simple explicit euler"); -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Graph Simulation - adapt_rk"); -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) +BENCHMARK_TEMPLATE(init_benchmark, mio::RKIntegratorCore)->Name("Initialize Graph without simulation"); +BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::EulerIntegratorCore) + ->Name("Graph Simulation - simple explicit euler"); +BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::RKIntegratorCore)->Name("Graph Simulation - adapt_rk"); +BENCHMARK_TEMPLATE(graph_sim_secirvvs, + mio::ControlledStepperWrapper) ->Name("Graph Simulation - rk_ck54 (boost)"); // BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) // ->Name("Graph Simulation - rk_dopri5 (boost)"); // TODO: reenable once boost bug is fixed -BENCHMARK_TEMPLATE(graph_sim_secirvvs, mio::ControlledStepperWrapper) +BENCHMARK_TEMPLATE(graph_sim_secirvvs, + mio::ControlledStepperWrapper) ->Name("Graph Simulation - rkf78 (boost)"); // run all benchmarks BENCHMARK_MAIN(); diff --git a/cpp/benchmarks/integrator_step.cpp b/cpp/benchmarks/integrator_step.cpp index edccd893fd..9159c15810 100644 --- a/cpp/benchmarks/integrator_step.cpp +++ b/cpp/benchmarks/integrator_step.cpp @@ -36,7 +36,8 @@ void integrator_step(::benchmark::State& state) //auto cfg = mio::benchmark::IntegratorStepConfig::initialize(); auto model = mio::benchmark::model::SecirAgeres(cfg.num_agegroups); // set deriv function and integrator - mio::DerivFunction f = [model](Eigen::Ref x, double s, Eigen::Ref dxds) { + mio::DerivFunction f = [model](Eigen::Ref x, double s, + Eigen::Ref dxds) { model.eval_right_hand_side(x, x, s, dxds); }; auto I = Integrator(cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); @@ -51,16 +52,18 @@ void integrator_step(::benchmark::State& state) } // dummy runs to avoid large effects of cpu scaling on times of actual benchmarks -BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 1/3"); -BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 2/3"); -BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 3/3"); +BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 1/3"); +BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 2/3"); +BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("Dummy 3/3"); // register functions as a benchmarks and set a name -BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("simulate SecirModel adapt_rk"); -BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) +BENCHMARK_TEMPLATE(integrator_step, mio::RKIntegratorCore)->Name("simulate SecirModel adapt_rk"); +BENCHMARK_TEMPLATE(integrator_step, + mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rk_ck54"); // BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) // ->Name("simulate SecirModel boost rk_dopri5"); // TODO: reenable once boost bug is fixed -BENCHMARK_TEMPLATE(integrator_step, mio::ControlledStepperWrapper) +BENCHMARK_TEMPLATE(integrator_step, + mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rkf78"); // run all benchmarks BENCHMARK_MAIN(); diff --git a/cpp/benchmarks/secir_ageres_setups.h b/cpp/benchmarks/secir_ageres_setups.h index d56e3593b9..a374b8c56a 100644 --- a/cpp/benchmarks/secir_ageres_setups.h +++ b/cpp/benchmarks/secir_ageres_setups.h @@ -35,7 +35,7 @@ namespace detail /** * @brief Helper function to create a secir model with consistent setup for use in benchmarking. */ -mio::osecir::Model make_model(int num) +mio::osecir::Model make_model(int num) { double cont_freq = 10; // see Polymod study @@ -49,16 +49,16 @@ mio::osecir::Model make_model(int num) auto& params = model.parameters; - params.set(std::numeric_limits::max()); + params.set>(std::numeric_limits::max()); params.set(0); - params.set(0); + params.set>(0); for (auto i = mio::AgeGroup(0); i < nb_groups; i++) { - params.get()[i] = 3.2; - params.get()[i] = 2.; - params.get()[i] = 6.; - params.get()[i] = 12; - params.get()[i] = 8; + params.get>()[i] = 3.2; + params.get>()[i] = 2.; + params.get>()[i] = 6.; + params.get>()[i] = 12; + params.get>()[i] = 8; model.populations[{i, mio::osecir::InfectionState::Exposed}] = fact * nb_exp_t0; model.populations[{i, mio::osecir::InfectionState::InfectedNoSymptoms}] = fact * nb_car_t0; @@ -70,16 +70,16 @@ mio::osecir::Model make_model(int num) model.populations.set_difference_from_group_total({i, mio::osecir::InfectionState::Susceptible}, fact * nb_total_t0); - params.get()[i] = 0.05; - params.get()[i] = 0.67; - params.get()[i] = 0.09; - params.get()[i] = 0.25; - params.get()[i] = 0.2; - params.get()[i] = 0.25; - params.get()[i] = 0.3; + params.get>()[i] = 0.05; + params.get>()[i] = 0.67; + params.get>()[i] = 0.09; + params.get>()[i] = 0.25; + params.get>()[i] = 0.2; + params.get>()[i] = 0.25; + params.get>()[i] = 0.3; } - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); contact_matrix.add_damping(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, 0.7), @@ -96,13 +96,13 @@ namespace model /** * @brief Secir model with consistent setup for use in benchmarking. */ -mio::osecir::Model SecirAgeres(size_t num_agegroups) +mio::osecir::Model SecirAgeres(size_t num_agegroups) { - mio::osecir::Model model = mio::benchmark::detail::make_model(num_agegroups); + mio::osecir::Model model = mio::benchmark::detail::make_model(num_agegroups); auto nb_groups = model.parameters.get_num_groups(); double cont_freq = 10, fact = 1.0 / (double)(size_t)nb_groups; - mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); @@ -114,13 +114,13 @@ mio::osecir::Model SecirAgeres(size_t num_agegroups) /** * @brief Secir model with consistent setup for use in benchmarking with added dampings. */ -mio::osecir::Model SecirAgeresDampings(size_t num_agegroups) +mio::osecir::Model SecirAgeresDampings(size_t num_agegroups) { - mio::osecir::Model model = mio::benchmark::detail::make_model(num_agegroups); + mio::osecir::Model model = mio::benchmark::detail::make_model(num_agegroups); auto nb_groups = model.parameters.get_num_groups(); double cont_freq = 10, fact = 1.0 / (double)(size_t)nb_groups; - mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); @@ -141,13 +141,13 @@ mio::osecir::Model SecirAgeresDampings(size_t num_agegroups) * @brief Secir model with consistent setup for use in benchmarking with added dampings. * Dampings are set up to challenge the integrator, not to be realistic. */ -mio::osecir::Model SecirAgeresAbsurdDampings(size_t num_agegroups) +mio::osecir::Model SecirAgeresAbsurdDampings(size_t num_agegroups) { - mio::osecir::Model model = mio::benchmark::detail::make_model(num_agegroups); + mio::osecir::Model model = mio::benchmark::detail::make_model(num_agegroups); auto nb_groups = model.parameters.get_num_groups(); double cont_freq = 10, fact = 1.0 / (double)(size_t)nb_groups; - mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); diff --git a/cpp/benchmarks/simulation.cpp b/cpp/benchmarks/simulation.cpp index 988a0df1b6..1b84e751d6 100644 --- a/cpp/benchmarks/simulation.cpp +++ b/cpp/benchmarks/simulation.cpp @@ -35,23 +35,25 @@ void simulation(::benchmark::State& state) for (auto _ : state) { // This code gets timed - std::shared_ptr I = + std::shared_ptr> I = std::make_shared(cfg.abs_tol, cfg.rel_tol, cfg.dt_min, cfg.dt_max); simulate(cfg.t0, cfg.t_max, cfg.dt, model, I); } } // dummy runs to avoid large effects of cpu scaling on times of actual benchmarks -BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 1/3"); -BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 2/3"); -BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 3/3"); +BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 1/3"); +BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 2/3"); +BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("Dummy 3/3"); // register functions as a benchmarks and set a name -BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("simulate SecirModel adapt_rk"); -BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) +BENCHMARK_TEMPLATE(simulation, mio::RKIntegratorCore)->Name("simulate SecirModel adapt_rk"); +BENCHMARK_TEMPLATE(simulation, + mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rk_ck54"); // BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) // ->Name("simulate SecirModel boost rk_dopri5"); // TODO: reenable once boost bug is fixed -BENCHMARK_TEMPLATE(simulation, mio::ControlledStepperWrapper) +BENCHMARK_TEMPLATE(simulation, + mio::ControlledStepperWrapper) ->Name("simulate SecirModel boost rkf78"); // run all benchmarks BENCHMARK_MAIN(); diff --git a/cpp/examples/CMakeLists.txt b/cpp/examples/CMakeLists.txt index 586d5cc19a..0d3b703ffe 100644 --- a/cpp/examples/CMakeLists.txt +++ b/cpp/examples/CMakeLists.txt @@ -34,6 +34,24 @@ add_executable(sde_sirs_example sde_sirs.cpp) target_link_libraries(sde_sirs_example PRIVATE memilio sde_sirs) target_compile_options(sde_sirs_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) +add_executable(ode_seair_example ode_seair.cpp) +target_link_libraries(ode_seair_example PRIVATE memilio ode_seair AD::AD) +target_compile_options(ode_seair_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + +if(MEMILIO_ENABLE_IPOPT) + add_executable(ode_seair_optimization ode_seair_optimization.cpp) + target_link_libraries(ode_seair_optimization PRIVATE memilio ode_seair AD::AD Ipopt::Ipopt) + target_compile_options(ode_seair_optimization PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) +endif() + +add_executable(ad_square_example ad_square_example.cpp) +target_link_libraries(ad_square_example PRIVATE memilio AD::AD) +target_compile_options(ad_square_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + +add_executable(ad_odeint_example ad_odeint_example.cpp) +target_link_libraries(ad_odeint_example PRIVATE memilio AD::AD Boost::boost) +target_compile_options(ad_odeint_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + add_executable(ode_sir_ageres_example ode_sir_ageres.cpp) target_link_libraries(ode_sir_ageres_example PRIVATE memilio ode_sir) target_compile_options(ode_sir_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) @@ -95,38 +113,38 @@ target_link_libraries(history_example PRIVATE memilio) target_compile_options(history_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) if(MEMILIO_HAS_JSONCPP) - add_executable(ode_secir_read_graph_example ode_secir_read_graph.cpp) - target_link_libraries(ode_secir_read_graph_example PRIVATE memilio ode_secir) - target_include_directories(ode_secir_read_graph_example PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # configured headers - target_compile_options(ode_secir_read_graph_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + add_executable(ode_secir_read_graph_example ode_secir_read_graph.cpp) + target_link_libraries(ode_secir_read_graph_example PRIVATE memilio ode_secir) + target_include_directories(ode_secir_read_graph_example PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # configured headers + target_compile_options(ode_secir_read_graph_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() if(MEMILIO_HAS_HDF5 AND MEMILIO_HAS_JSONCPP) - add_executable(ode_secir_parameter_study_example ode_secir_parameter_study.cpp) - target_link_libraries(ode_secir_parameter_study_example PRIVATE memilio ode_secir) - target_compile_options(ode_secir_parameter_study_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + add_executable(ode_secir_parameter_study_example ode_secir_parameter_study.cpp) + target_link_libraries(ode_secir_parameter_study_example PRIVATE memilio ode_secir) + target_compile_options(ode_secir_parameter_study_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() if(MEMILIO_HAS_JSONCPP) - add_executable(cli_example cli.cpp) - target_link_libraries(cli_example PRIVATE memilio) - target_compile_options(cli_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + add_executable(cli_example cli.cpp) + target_link_libraries(cli_example PRIVATE memilio) + target_compile_options(cli_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() if(MEMILIO_HAS_JSONCPP) - add_executable(serialize_example serialize.cpp) - target_link_libraries(serialize_example PRIVATE memilio) - target_compile_options(serialize_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + add_executable(serialize_example serialize.cpp) + target_link_libraries(serialize_example PRIVATE memilio) + target_compile_options(serialize_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() if(MEMILIO_HAS_HDF5) - add_executable(ode_secir_save_results_example ode_secir_save_results.cpp) - target_link_libraries(ode_secir_save_results_example PRIVATE memilio ode_secir) - target_compile_options(ode_secir_save_results_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + add_executable(ode_secir_save_results_example ode_secir_save_results.cpp) + target_link_libraries(ode_secir_save_results_example PRIVATE memilio ode_secir) + target_compile_options(ode_secir_save_results_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() if(MEMILIO_HAS_JSONCPP) add_executable(ide_initialization_example ide_initialization.cpp) target_link_libraries(ide_initialization_example PRIVATE memilio ide_secir) target_compile_options(ide_initialization_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) -endif() \ No newline at end of file +endif() diff --git a/cpp/examples/ad_odeint_example.cpp b/cpp/examples/ad_odeint_example.cpp new file mode 100644 index 0000000000..760d2af6ab --- /dev/null +++ b/cpp/examples/ad_odeint_example.cpp @@ -0,0 +1,87 @@ +/* +* Copyright (C) 2020-2024 MEmilio +* +* Authors: Ralf Hannemann-Tamas +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "ad/ad.hpp" +#include "boost/numeric/odeint.hpp" +#include + +// This program shows that boost::numeric::odeint::runge_kutta_cash_karp54 can be fully +// algorithmically diffentiated using the algorithmic differentiation (AD) data types of ad/ad.hpp. + +using ad_forward_type = typename ad::gt1s::type; // AD data type for scalar forward mode + +using value_type = ad_forward_type; +using time_type = value_type; + +// The type of container used to hold the state vector +const size_t dimension = 2; // dimension of ODE +using state_type = std::array; // 2-dimensional vector + +double damping = 0.15; + +/** The rhs of x' = f(x). This ODE describes a damped harmonic oscillator. */ +void harmonic_oscillator(const state_type& x, state_type& dxdt, const time_type /* t */) +{ + dxdt[0] = x[1]; + dxdt[1] = -x[0] - damping * x[1]; +} + +// We use a an adaptive step size control +using error_stepper_type = + boost::numeric::odeint::runge_kutta_cash_karp54; +using controlled_stepper_type = boost::numeric::odeint::controlled_runge_kutta; + +using boost::numeric::odeint::make_controlled; + +int main() +{ + state_type x; + x[0] = 1.0; // start at x=1.0, p=0.0 + x[1] = 0.0; + ad::derivative(x[0]) = 1.0; // compute derivative with respect to x[0] (scalar tangent-linear mode) + + auto t0 = time_type(0.0); // initial time + auto t_end = time_type(10.0); // stop time + auto dt = time_type(0.01); // hint for initial step size + + const double abs_tol = 1e-6; // absolute tolerance for error-controlled integration + const double rel_tol = 1e-6; // relative tolerance for error-controlled integration + + controlled_stepper_type controlled_stepper; + boost::numeric::odeint::integrate_adaptive(make_controlled(abs_tol, rel_tol), + harmonic_oscillator, x, t0, t_end, dt); + std::cout << "ad derivative of x is (" << ad::derivative(x[0]) << ", " << ad::derivative(x[1]) << ")\n"; + + // We want to compare AD derivatives with difference quotient + // To this end, we simulate again with a perturbation of the initial value of x[0] + const double h = 1e-3; // pertubation for finite differences + std::array y = {ad::value(x[0]), ad::value(x[1])}; + x[0] = 1.0 + h; // add perturbation to initial value of x[0] + x[1] = 0.0; + + // integrate perturbed system + boost::numeric::odeint::integrate_adaptive(make_controlled(abs_tol, rel_tol), + harmonic_oscillator, x, t0, t_end, dt); + + std::cout << "finite differences derivative of x is (" << (ad::value(x[0]) - y[0]) / h << ", " + << (ad::value(x[1]) - y[1]) / h << ")\n"; + + return 0; +} diff --git a/cpp/examples/ad_square_example.cpp b/cpp/examples/ad_square_example.cpp new file mode 100644 index 0000000000..551d002337 --- /dev/null +++ b/cpp/examples/ad_square_example.cpp @@ -0,0 +1,103 @@ +/* +* Copyright (C) 2020-2024 MEmilio +* +* Authors: Ralf Hannemann-Tamas +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "ad/ad.hpp" +#include + +/* This example computes the derivative of f(x) = x^2 in two different ways: + * 1. Using the forward mode of algorithmic differentiation (AD) + * 2. Using the reverse mode of algorithmic differentiation + * + * Assume, a subroutine is given that computes y = f(x), where x is an n-dimenstional input vector + * and y is an m-dimensional output vector. + * + * Forward mode AD (also known as tangent-linear mode) + * computes Jacobian-vector products of f(x). I.e., if J(x) denotes the Jacobian of f(x) and + * v is an n-dimensional seed vector, the forward mode computes the matrix-vector product + * J(x) * v. To this end, The data type of x is set to a forward mode AD data type that additionally to the + * original value, also stores derivative information. The original value is accessed by the command + * ad::value(x). The derivative information is accessed by ad::derivative(x) which is accordingly + * used to set the seed vector v, i.e., ad::derivative(x) = v. + * After the conmputation the Jacobian-vector product is accessed by the command ad::derivative(y). + * + * Reverse mode (also known as adjoint mode, or back progpagation) computes vector-Jacobian products of f(x). + * I.e, if J(x) denotes the Jacobian of f(x) and + * w is an m-dimensional seed vector (which is a row vector), the reverse mode computes the vector-matrix product + * w * J(x). The data type of x is set to a reverse mode AD data type that additionally to the + * original value, also stores derivative information. The original value is accessed by the command + * ad::value(x). The derivative information is accessed by ad::derivative(x). + * While the forward mode computes derivatives in one sweep, the reverse mode computes is divided + * into two sweeps. A forward sweep for the computation, where intermediate results are stored on a temporary + * memory location called tape. After + * the forward sweep, the seed of the computation is set by the command ad::derivative(y) = w. + * And a reverse sweep, where the actual derivative computation takes place, has to be performed. The derivative information of + * x has to be initalized to zero (ad::derivative(x) = 0), before the tape can be interpreted backwards. Then, + * the tape can interpreted backwards + * and the vector-Jacobian product can be accessed the command ad::derivative(x). + * + * For a concise introduction to AD we recommend the article: + * Verma, Arun. "An introduction to automatic differentiation." Current Science (2000): 804-807. + */ + +/** + * @brief square computes the square of the input parameter + * @param x input parameter + * @return the square of x. + */ +template +FP square(FP x) +{ + return x * x; +} + +int main() +{ + /**** 1. Forward AD ****/ + std::cout << "Forward AD" << std::endl; + ad::gt1s::type t1_x; // tangent-linear AD type + ad::value(t1_x) = 3.0; // set value (this corresponds to the non-AD part) + ad::derivative(t1_x) = 1.0; // set tangent-linear derivative seed + ad::gt1s::type t1_y = square(t1_x); + std::cout << "value of square(" << ad::value(t1_x) << ") is " << ad::value(t1_y) << std::endl; + std::cout << "forward derivative of square(" << ad::value(t1_x) << ") is " << ad::derivative(t1_y) << std::endl; + + /**** 2. Reverse AD ****/ + std::cout << "Reverse AD" << std::endl; + // create tape (allocation) + if (!ad::ga1s::global_tape) + ad::ga1s::global_tape = ad::ga1s::tape_t::create(); + // clear tape + ad::ga1s::global_tape->reset(); + + ad::ga1s::type a1_x; // reverse-mode AD type + ad::value(a1_x) = 3.0; // set value (this corresponds to the non-AD part) + ad::derivative(a1_x) = 0.0; // for reverse-mode the seed has to be set to zero + ad::ga1s::global_tape->register_variable(a1_x); // register input variable + ad::ga1s::type a1_y = square(a1_x); + std::cout << "value of square(" << ad::value(a1_x) << ") is " << ad::value(a1_y) << std::endl; + ad::ga1s::global_tape->register_output_variable(a1_y); + ad::derivative(a1_y) = 1.0; + ad::ga1s::global_tape + ->interpret_adjoint(); // compute reverse-mode derivatives by evaluatin the tape backwards + std::cout << "adjoint derivative is " << ad::derivative(a1_x) << std::endl; // access reverse-derivatives + ad::ga1s::tape_t::remove(ad::ga1s::global_tape); // deallocate tape + + return 0; +} diff --git a/cpp/examples/adapt_rk_test.cpp b/cpp/examples/adapt_rk_test.cpp index 6e906f6c10..5f1bcd512f 100644 --- a/cpp/examples/adapt_rk_test.cpp +++ b/cpp/examples/adapt_rk_test.cpp @@ -40,7 +40,7 @@ void integration_test(std::vector& y, std::vector rkf45; rkf45.set_abs_tolerance(1e-7); rkf45.set_rel_tolerance(1e-7); rkf45.set_dt_min(1e-3); diff --git a/cpp/examples/graph.cpp b/cpp/examples/graph.cpp index 6ecbf8a5d3..ecd5100882 100644 --- a/cpp/examples/graph.cpp +++ b/cpp/examples/graph.cpp @@ -23,25 +23,23 @@ #include "memilio/mobility/metapopulation_mobility_instant.h" #include "memilio/compartments/simulation.h" -#include - int main() { const auto t0 = 0.; const auto tmax = 10.; const auto dt = 0.5; //time step of migration, daily migration every second step - mio::oseir::Model model(1); + mio::oseir::Model<> model(1); // set population model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Susceptible}] = 10000; // set transition times - model.parameters.set(1); - model.parameters.set(1); + model.parameters.set>(1); + model.parameters.set>(1); // set contact matrix - mio::ContactMatrixGroup& contact_matrix = model.parameters.get().get_cont_freq_mat(); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>().get_cont_freq_mat(); contact_matrix[0].get_baseline().setConstant(2.7); //two mostly identical groups @@ -49,14 +47,15 @@ int main() auto model_group2 = model; //some contact restrictions in group 1 - mio::ContactMatrixGroup& contact_matrix1 = model_group1.parameters.get().get_cont_freq_mat(); + mio::ContactMatrixGroup& contact_matrix1 = + model_group1.parameters.get>().get_cont_freq_mat(); contact_matrix1[0].add_damping(0.5, mio::SimulationTime(5)); - + //infection starts in group 1 model_group1.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Susceptible}] = 9990; model_group1.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Exposed}] = 10; - mio::Graph>, mio::MigrationEdge> g; + mio::Graph>>, mio::MigrationEdge<>> g; g.add_node(1001, model_group1, t0); g.add_node(1002, model_group2, t0); g.add_edge(0, 1, Eigen::VectorXd::Constant((size_t)mio::oseir::InfectionState::Count, 0.01)); diff --git a/cpp/examples/graph_stochastic_mobility.cpp b/cpp/examples/graph_stochastic_mobility.cpp index c67802bd89..1c97df1e41 100644 --- a/cpp/examples/graph_stochastic_mobility.cpp +++ b/cpp/examples/graph_stochastic_mobility.cpp @@ -38,7 +38,7 @@ int main(int /*argc*/, char** /*argv*/) num_dead = 0; //model with 3 age groups - mio::osecir::Model model(3); + mio::osecir::Model model(3); auto& params = model.parameters; @@ -47,11 +47,11 @@ int main(int /*argc*/, char** /*argv*/) //set initialization and model parameters for (auto i = mio::AgeGroup(0); i < num_age_groups; i++) { - params.get()[i] = 3.2; - params.get()[i] = 2.; - params.get()[i] = 6.; - params.get()[i] = 12.; - params.get()[i] = 8.; + params.get>()[i] = 3.2; + params.get>()[i] = 2.; + params.get>()[i] = 6.; + params.get>()[i] = 12.; + params.get>()[i] = 8.; //initial populations is equally distributed among age groups model.populations[{i, mio::osecir::InfectionState::Exposed}] = fact * num_exp; @@ -64,17 +64,17 @@ int main(int /*argc*/, char** /*argv*/) model.populations.set_difference_from_group_total({i, mio::osecir::InfectionState::Susceptible}, fact * num_total); - params.get()[i] = 0.05; - params.get()[i] = 0.67; - params.get()[i] = 0.09; - params.get()[i] = 0.25; - params.get()[i] = 0.2; - params.get()[i] = 0.25; - params.get()[i] = 0.3; + params.get>()[i] = 0.05; + params.get>()[i] = 0.67; + params.get>()[i] = 0.09; + params.get>()[i] = 0.25; + params.get>()[i] = 0.2; + params.get>()[i] = 0.25; + params.get>()[i] = 0.3; } //add contact pattern and contact damping - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)num_age_groups, (size_t)num_age_groups, fact * 10)); contact_matrix.add_damping(Eigen::MatrixXd::Constant((size_t)num_age_groups, (size_t)num_age_groups, 0.6), @@ -94,7 +94,8 @@ int main(int /*argc*/, char** /*argv*/) fact * num_total); } - mio::Graph>, mio::MigrationEdgeStochastic> graph; + mio::Graph>>, mio::MigrationEdgeStochastic> + graph; graph.add_node(1001, model, t0); graph.add_node(1002, model2, t0); diff --git a/cpp/examples/history.cpp b/cpp/examples/history.cpp index 5a53d96d9b..141717b580 100644 --- a/cpp/examples/history.cpp +++ b/cpp/examples/history.cpp @@ -19,13 +19,13 @@ int main() // For example purposes we "log" the numbers 0-9. As we multiply it by 2 in the logger, the History stores 0,2,4,... . for (int i = 0; i < 10; ++i) { - history.log(i); + history.log(i); } - // If we want to to access the logged data we can use the get_log() function. - // As the History object stores a std::vector in a std::tuple for + // If we want to to access the logged data we can use the get_log() function. + // As the History object stores a std::vector in a std::tuple for // each logger, we have to use std::get<0>(history.get_log()) to access the data of the first (and only) logger which contains the records of MyLogger. - std::vector logData = std::get<0>(history.get_log()); + std::vector logData = std::get<0>(history.get_log()); // Finally we can print the logged data. std::cout << "Logged data from MyLogger:" << std::endl; diff --git a/cpp/examples/ide_seir.cpp b/cpp/examples/ide_seir.cpp index 6bc24bac13..7091c4092a 100644 --- a/cpp/examples/ide_seir.cpp +++ b/cpp/examples/ide_seir.cpp @@ -19,7 +19,6 @@ */ #include "ide_seir/model.h" -#include "memilio/math/eigen.h" #include "memilio/utils/time_series.h" #include "memilio/epidemiology/uncertain_matrix.h" @@ -50,7 +49,7 @@ int main() } // Initialize model. - mio::iseir::Model model(std::move(init), dt, N); + mio::iseir::Model model(std::move(init), dt, N); // Set working parameters. model.parameters.set(3.3); @@ -60,7 +59,7 @@ int main() contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10.)); // Add damping. contact_matrix[0].add_damping(0.7, mio::SimulationTime(10.)); - model.parameters.get() = mio::UncertainContactMatrix(contact_matrix); + model.parameters.get>() = mio::UncertainContactMatrix(contact_matrix); // Carry out simulation. model.simulate(tmax); diff --git a/cpp/examples/ode_seair.cpp b/cpp/examples/ode_seair.cpp new file mode 100644 index 0000000000..ea57588239 --- /dev/null +++ b/cpp/examples/ode_seair.cpp @@ -0,0 +1,108 @@ +/* +* Copyright (C) 2020-2024 MEmilio +* +* Authors: Ralf Hannemann-Tamas +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// This model is a extented SEIR type model of the COVID-19 pandemic in the US +// that als includes asymptomatic and dead people. +// A detailed description of the model can be found in the publication +// Tsay et al. (2020), Modeling, state estimation, and optimal control for the US COVID-19 outbreak. + +#include "ad/ad.hpp" + +#include "ode_seair/model.h" +#include "ode_seair/infection_state.h" +#include "memilio/compartments/simulation.h" +#include "memilio/utils/logging.h" +#include "memilio/utils/time_series.h" + +/** + * @brief set_initial_values sets the initial value of the mio::oseair::Model model according to + * the publication of Tsay et al. (2020): Modeling, state estimation, and optimal control for the US COVID-19 outbreak. + * Note that the total population, i.e., the sum of all compartments, is normalized to one. + * @tparam FP floating point type, e.g., double + * @param model an instance of the mio::oseair::Model which is a compartmental model. + */ +template +void set_initial_values(mio::oseair::Model& model) +{ + const double N = 327167434; // total population of the United States + + model.populations[{mio::Index(mio::oseair::InfectionState::Susceptible)}] = + 0.9977558755803503 * N; + model.populations[{mio::Index(mio::oseair::InfectionState::Exposed)}] = + 0.0003451395725394549 * N; + model.populations[{mio::Index(mio::oseair::InfectionState::Asymptomatic)}] = + 0.00037846880968213874 * N; + model.populations[{mio::Index(mio::oseair::InfectionState::Infected)}] = 337072.0; + model.populations[{mio::Index(mio::oseair::InfectionState::Recovered)}] = 17448.0; + model.populations[{mio::Index(mio::oseair::InfectionState::Dead)}] = 9619.0; +} + +int main() +{ + + mio::set_log_level(mio::LogLevel::debug); + + using FP = typename ad::gt1s::type; // algorithmic differentiation data type: scalar tangent-linear mode + + FP t0 = 0; + FP tmax = 10; + FP dt = 0.3; + + mio::log_info("Simulating SEAIR; t={} ... {} with dt = {}.", ad::value(t0), ad::value(tmax), ad::value(dt)); + + // Compute derivative of the final states of the model with respect to the initial value of the suscetible population + mio::oseair::Model model1; + set_initial_values(model1); + FP value = model1.populations[{mio::Index(mio::oseair::InfectionState::Susceptible)}]; + ad::derivative(value) = 1.0; + model1.populations[{mio::Index(mio::oseair::InfectionState::Susceptible)}] = value; + model1.check_constraints(); + auto seair1 = mio::simulate>(t0, tmax, dt, model1); + + // We want to compare the derivatives computed ba algorithmic differention with difference quotient. + // To this end we perturbe the corresponding initial value of the by an increment h and simulate again. + mio::oseair::Model model2; + set_initial_values(model2); + double h = 1e-4; + model2.populations[{mio::Index(mio::oseair::InfectionState::Susceptible)}] += h; + model2.check_constraints(); + mio::TimeSeries seair2 = + mio::simulate>(ad::value(t0), ad::value(tmax), ad::value(dt), model2); + + const std::string file_name = "seair-compare.csv"; + std::ofstream file(file_name); + std::cout << "Writing output to " << file_name << std::endl; + seair1.print_table({}, 21, 10, file); + file.close(); + + auto last1 = seair1.get_last_value(); + auto last2 = seair2.get_last_value(); + + std::cout << "Last value is" << std::endl; + std::cout << last2 << std::endl; + + std::cout << "Compare algorithmic differentiation (AD) with finite differences (FD)" << std::endl; + for (Eigen::Index i = 0; i < last1.size(); ++i) { + std::cout << "AD: " << ad::derivative(last1[i]) << " FD: " << (1. / h) * (last2[i] - ad::value(last1[i])) + << std::endl; + } + + return 0; +} diff --git a/cpp/examples/ode_seair_optimization.cpp b/cpp/examples/ode_seair_optimization.cpp new file mode 100644 index 0000000000..caffdb8b23 --- /dev/null +++ b/cpp/examples/ode_seair_optimization.cpp @@ -0,0 +1,649 @@ +/* +* Copyright (C) 2020-2024 MEmilio +* +* Authors: Ralf Hannemann-Tamas +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* The documentation of the Ipopt::TNLP member functions in Seair_NLP +* is extracted from the Ipopt documentation +*/ + +#include "ad/ad.hpp" + +#include "memilio/utils/compiler_diagnostics.h" +#include "ode_seair/model.h" +#include "ode_seair/infection_state.h" +#include "ode_seair/parameters.h" +#include "memilio/compartments/simulation.h" +#include "memilio/utils/logging.h" +#include "memilio/utils/time_series.h" +#include "IpTNLP.hpp" +#include "IpIpoptApplication.hpp" +#include + +// This program implements direct single shooting for the optimal control of +// nonpharmazeutical intervation in pandemic ordinary differential equation (ODE) models. +// The socioeconomic costs are to be minmized using an objective functional which is the +// weighted integral of the nonpharmazeutical interventions and testing costs. +// In direct single shooting (also known as control vector parameterization) the +// continuous control variables are paremeterized using a discretization such that +// continuous optimal contorl prblem is transcribed into a finite dimensional nonlinear +// program which is then solved by the interior point method IPOPT. Here, we use +// a piecewise constant discretization. + +class Seair_NLP : public Ipopt::TNLP +{ +public: + static constexpr double N = 327167434; // total US population + Seair_NLP() = default; + Seair_NLP(const Seair_NLP&) = delete; + Seair_NLP(Seair_NLP&&) = delete; + Seair_NLP& operator=(const Seair_NLP&) = delete; + Seair_NLP& operator=(Seair_NLP&&) = delete; + ~Seair_NLP() = default; + + /** Method to request the initial information about the problem. + * + * %Ipopt uses this information when allocating the arrays + * that it will later ask you to fill with values. Be careful in this + * method since incorrect values will cause memory bugs which may be very + * difficult to find. + * + * @param n (out) Storage for the number of variables \f$x\f$ + * @param m (out) Storage for the number of constraints \f$g(x)\f$ + * @param nnz_jac_g (out) Storage for the number of nonzero entries in the Jacobian + * @param nnz_h_lag (out) Storage for the number of nonzero entries in the Hessian + * @param index_style (out) Storage for the index style, + * the numbering style used for row/col entries in the sparse matrix format + * (TNLP::C_STYLE: 0-based, TNLP::FORTRAN_STYLE: 1-based; see also \ref TRIPLET) + */ + bool get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g, Ipopt::Index& nnz_h_lag, + IndexStyleEnum& index_style) override; + + /** Method to request bounds on the variables and constraints. + * + * @param n (in) the number of variables \f$x\f$ in the problem + * @param x_l (out) the lower bounds \f$x^L\f$ for the variables \f$x\f$ + * @param x_u (out) the upper bounds \f$x^U\f$ for the variables \f$x\f$ + * @param m (in) the number of constraints \f$g(x)\f$ in the problem + * @param g_l (out) the lower bounds \f$g^L\f$ for the constraints \f$g(x)\f$ + * @param g_u (out) the upper bounds \f$g^U\f$ for the constraints \f$g(x)\f$ + * + * @return true if success, false otherwise. + * + * The values of `n` and `m` that were specified in TNLP::get_nlp_info are passed + * here for debug checking. Setting a lower bound to a value less than or + * equal to the value of the option \ref OPT_nlp_lower_bound_inf "nlp_lower_bound_inf" + * will cause %Ipopt to assume no lower bound. Likewise, specifying the upper bound above or + * equal to the value of the option \ref OPT_nlp_upper_bound_inf "nlp_upper_bound_inf" + * will cause %Ipopt to assume no upper bound. These options are set to -1019 and + * 1019, respectively, by default, but may be modified by changing these + * options. + */ + bool get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u, Ipopt::Index m, Ipopt::Number* g_l, + Ipopt::Number* g_u) override; + + /** Method to request the starting point before iterating. + * + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param init_x (in) if true, this method must provide an initial value for \f$x\f$ + * @param x (out) the initial values for the primal variables \f$x\f$ + * @param init_z (in) if true, this method must provide an initial value for the bound multipliers \f$z^L\f$ and \f$z^U\f$ + * @param z_L (out) the initial values for the bound multipliers \f$z^L\f$ + * @param z_U (out) the initial values for the bound multipliers \f$z^U\f$ + * @param m (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param init_lambda (in) if true, this method must provide an initial value for the constraint multipliers \f$\lambda\f$ + * @param lambda (out) the initial values for the constraint multipliers, \f$\lambda\f$ + * + * @return true if success, false otherwise. + */ + bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x, bool init_z, Ipopt::Number* z_L, + Ipopt::Number* z_U, Ipopt::Index m, bool init_lambda, Ipopt::Number* lambda) override; + + /** Method to request the value of the objective function. + * + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param x (in) the values for the primal variables \f$x\f$ at which the objective function \f$f(x)\f$ is to be evaluated + * @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise. + * This can be helpful when users have efficient implementations that calculate multiple outputs at once. + * %Ipopt internally caches results from the TNLP and generally, this flag can be ignored. + * @param obj_value (out) storage for the value of the objective function \f$f(x)\f$ + * + * @return true if success, false otherwise. + */ + virtual bool eval_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number& obj_value) override; + + /** Method to request the gradient of the objective function. + * + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param x (in) the values for the primal variables \f$x\f$ at which the gradient \f$\nabla f(x)\f$ is to be evaluated + * @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f + * @param grad_f (out) array to store values of the gradient of the objective function \f$\nabla f(x)\f$. + * The gradient array is in the same order as the \f$x\f$ variables + * (i.e., the gradient of the objective with respect to `x[2]` should be put in `grad_f[2]`). + * + * @return true if success, false otherwise. + */ + virtual bool eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number* grad_f) override; + + /** Method to request the constraint values. + * + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param x (in) the values for the primal variables \f$x\f$ at which the constraint functions \f$g(x)\f$ are to be evaluated + * @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f + * @param m (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param g (out) array to store constraint function values \f$g(x)\f$, do not add or subtract the bound values \f$g^L\f$ or \f$g^U\f$. + * + * @return true if success, false otherwise. + */ + virtual bool eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Number* g) override; + + /** Method to request either the sparsity structure or the values of the Jacobian of the constraints. + * + * The Jacobian is the matrix of derivatives where the derivative of + * constraint function \f$g_i\f$ with respect to variable \f$x_j\f$ is placed in row + * \f$i\f$ and column \f$j\f$. + * See \ref TRIPLET for a discussion of the sparse matrix format used in this method. + * + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param x (in) first call: NULL; later calls: the values for the primal variables \f$x\f$ at which the constraint Jacobian \f$\nabla g(x)^T\f$ is to be evaluated + * @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f + * @param m (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param nele_jac (in) the number of nonzero elements in the Jacobian; it will have the same value that was specified in TNLP::get_nlp_info + * @param iRow (out) first call: array of length nele_jac to store the row indices of entries in the Jacobian of the constraints; later calls: NULL + * @param jCol (out) first call: array of length nele_jac to store the column indices of entries in the Jacobian of the constraints; later calls: NULL + * @param values (out) first call: NULL; later calls: array of length nele_jac to store the values of the entries in the Jacobian of the constraints + * + * @return true if success, false otherwise. + * */ + virtual bool eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Index nele_jac, + Ipopt::Index* iRow, Ipopt::Index* jCol, Ipopt::Number* values) override; + + /** Method to request either the sparsity structure or the values of the Hessian of the Lagrangian. + * + * The Hessian matrix that %Ipopt uses is + * \f[ \sigma_f \nabla^2 f(x_k) + \sum_{i=1}^m\lambda_i\nabla^2 g_i(x_k) \f] + * for the given values for \f$x\f$, \f$\sigma_f\f$, and \f$\lambda\f$. + * See \ref TRIPLET for a discussion of the sparse matrix format used in this method. + * + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param x (in) first call: NULL; later calls: the values for the primal variables \f$x\f$ at which the Hessian is to be evaluated + * @param new_x (in) false if any evaluation method (`eval_*`) was previously called with the same values in x, true otherwise; see also TNLP::eval_f + * @param obj_factor (in) factor \f$\sigma_f\f$ in front of the objective term in the Hessian + * @param m (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param lambda (in) the values for the constraint multipliers \f$\lambda\f$ at which the Hessian is to be evaluated + * @param new_lambda (in) false if any evaluation method was previously called with the same values in lambda, true otherwise + * @param nele_hess (in) the number of nonzero elements in the Hessian; it will have the same value that was specified in TNLP::get_nlp_info + * @param iRow (out) first call: array of length nele_hess to store the row indices of entries in the Hessian; later calls: NULL + * @param jCol (out) first call: array of length nele_hess to store the column indices of entries in the Hessian; later calls: NULL + * @param values (out) first call: NULL; later calls: array of length nele_hess to store the values of the entries in the Hessian + * + * @return true if success, false otherwise. + */ + virtual bool eval_h(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number obj_factor, Ipopt::Index m, + const Ipopt::Number* lambda, bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index* iRow, + Ipopt::Index* jCol, Ipopt::Number* values) override; + + /** This method is called when the algorithm has finished (successfully or not) so the TNLP can digest the outcome, e.g., store/write the solution, if any. + * + * @param status @parblock (in) gives the status of the algorithm + * - SUCCESS: Algorithm terminated successfully at a locally optimal + * point, satisfying the convergence tolerances (can be specified + * by options). + * - MAXITER_EXCEEDED: Maximum number of iterations exceeded (can be specified by an option). + * - CPUTIME_EXCEEDED: Maximum number of CPU seconds exceeded (can be specified by an option). + * - STOP_AT_TINY_STEP: Algorithm proceeds with very little progress. + * - STOP_AT_ACCEPTABLE_POINT: Algorithm stopped at a point that was converged, not to "desired" tolerances, but to "acceptable" tolerances (see the acceptable-... options). + * - LOCAL_INFEASIBILITY: Algorithm converged to a point of local infeasibility. Problem may be infeasible. + * - USER_REQUESTED_STOP: The user call-back function TNLP::intermediate_callback returned false, i.e., the user code requested a premature termination of the optimization. + * - DIVERGING_ITERATES: It seems that the iterates diverge. + * - RESTORATION_FAILURE: Restoration phase failed, algorithm doesn't know how to proceed. + * - ERROR_IN_STEP_COMPUTATION: An unrecoverable error occurred while %Ipopt tried to compute the search direction. + * - INVALID_NUMBER_DETECTED: Algorithm received an invalid number (such as NaN or Inf) from the NLP; see also option check_derivatives_for_nan_inf). + * - INTERNAL_ERROR: An unknown internal error occurred. + * @endparblock + * @param n (in) the number of variables \f$x\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param x (in) the final values for the primal variables + * @param z_L (in) the final values for the lower bound multipliers + * @param z_U (in) the final values for the upper bound multipliers + * @param m (in) the number of constraints \f$g(x)\f$ in the problem; it will have the same value that was specified in TNLP::get_nlp_info + * @param g (in) the final values of the constraint functions + * @param lambda (in) the final values of the constraint multipliers + * @param obj_value (in) the final value of the objective function + * @param ip_data (in) provided for expert users + * @param ip_cq (in) provided for expert users + */ + virtual void finalize_solution(Ipopt::SolverReturn status, Ipopt::Index n, const Ipopt::Number* x, + const Ipopt::Number* z_L, const Ipopt::Number* z_U, Ipopt::Index m, + const Ipopt::Number* g, const Ipopt::Number* lambda, Ipopt::Number obj_value, + const Ipopt::IpoptData* ip_data, Ipopt::IpoptCalculatedQuantities* ip_cq) override; + + /** Intermediate Callback method for the user. + * + * This method is called once per iteration (during the convergence check), + * and can be used to obtain information about the optimization status while + * %Ipopt solves the problem, and also to request a premature termination. + * + * The information provided by the entities in the argument list correspond + * to what %Ipopt prints in the iteration summary (see also \ref OUTPUT), + * except for inf_pr, which by default corresponds to the original problem + * in the log but to the scaled internal problem in this callback. + * Further information can be obtained from the ip_data and ip_cq objects. + * The current iterate and violations of feasibility and optimality can be + * accessed via the methods Ipopt::TNLP::get_curr_iterate() and + * Ipopt::TNLP::get_curr_violations(). + * These methods translate values for the *internal representation* of + * the problem from `ip_data` and `ip_cq` objects into the TNLP representation. + * + * @return If this method returns false, %Ipopt will terminate with the + * User_Requested_Stop status. + * + * It is not required to implement (overload) this method. + * The default implementation always returns true. + */ + bool intermediate_callback(Ipopt::AlgorithmMode mode, Ipopt::Index iter, Ipopt::Number obj_value, + Ipopt::Number inf_pr, Ipopt::Number inf_du, Ipopt::Number DeathRate, + Ipopt::Number d_norm, Ipopt::Number regularization_size, Ipopt::Number alpha_du, + Ipopt::Number alpha_pr, Ipopt::Index ls_trials, const Ipopt::IpoptData* ip_data, + Ipopt::IpoptCalculatedQuantities* ip_cq) override; + + /** + * @brief Seair_NLP::eval_objective_constraints evaluates the objective and the constraints of the NLP + * @param x optimization variables of the NLP + * @param constraints are the constraints of the NLP + * @param objective is the objectie of the NLP + */ + template + void eval_objective_constraints(const std::vector& x, std::vector& constraints, FP& objective); + +public: + int getN() + { + return n_; + } + int getM() + { + return m_; + } + +private: + const int numControlIntervals_ = + 20; // number of piecewise constants interval for controls (same for all control variables) + const int numControls_ = 3; // number of control variables + const int numPathConstraints_ = 1; // number of path constraints + const int pcresolution_ = + 5; // the resultion of path constraints is by this factor higher than the control discretization + const int numIntervals_ = pcresolution_ * numControlIntervals_; // number of integration intervals + const int n_ = numControlIntervals_ * numControls_; // number of optimization variables in the NLP + const int m_ = numIntervals_ * numPathConstraints_; // number of constraints in the NLP +}; +/** + * @brief set_initial_values sets the initial values of the pandemic ODE + * @param model an instance of the pandemic model + */ +template +void set_initial_values(mio::oseair::Model& model) +{ + const double N = Seair_NLP::N; // total population of the United States + + model.populations[{mio::Index(mio::oseair::InfectionState::Susceptible)}] = + 0.9977558755803503 * N; + model.populations[{mio::Index(mio::oseair::InfectionState::Exposed)}] = + 0.0003451395725394549 * N; + model.populations[{mio::Index(mio::oseair::InfectionState::Asymptomatic)}] = + + 0.00037846880968213874 * N; + model.populations[{mio::Index(mio::oseair::InfectionState::Infected)}] = 337072.0; + model.populations[{mio::Index(mio::oseair::InfectionState::Recovered)}] = 17448.0; + model.populations[{mio::Index(mio::oseair::InfectionState::Dead)}] = 9619.0; +} + +template +void Seair_NLP::eval_objective_constraints(const std::vector& x, std::vector& constraints, FP& objective) +{ + + FP t0 = 0; // initial time + FP tmax = 100; // stop time + FP dt = 0.2; // hint for initial step size for the integrator + std::vector grid(numIntervals_ + 1); + for (int i = 0; i < numIntervals_ + 1; ++i) { + grid[i] = (tmax / numIntervals_) * i + (t0 / numIntervals_) * (numIntervals_ - i); + } + mio::oseair::Model model; + + set_initial_values(model); + int gridindex = 0; + objective = 0.0; + for (int controlIndex = 0; controlIndex < numControlIntervals_; ++controlIndex) { + model.parameters.template get>() = x[controlIndex]; + model.parameters.template get>() = x[controlIndex + numControlIntervals_]; + model.parameters.template get>() = x[controlIndex + 2 * numControlIntervals_]; + // the objective is the weighted integral of the controls, since we use a piecewise constant dicretization + // we just can add the values + objective += pcresolution_ * (-x[controlIndex] - x[controlIndex + numControlIntervals_] + + 0.1 * x[controlIndex + 2 * numControlIntervals_]); + + for (int i = 0; i < pcresolution_; ++i, ++gridindex) { + + auto result = mio::simulate>(grid[gridindex], grid[gridindex + 1], dt, model); + + for (int j = 0; j < (int)mio::oseair::InfectionState::Count; ++j) { + model.populations[mio::oseair::InfectionState(j)] = result.get_last_value()[j]; + } + constraints[gridindex] = result.get_last_value()[(int)mio::oseair::InfectionState::Infected]; + } + } + + return; +} + +bool Seair_NLP::get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g, Ipopt::Index& nnz_h_lag, + IndexStyleEnum& index_style) +{ + n = n_; + + m = m_; + + // in this example the jacobian is dense and contains 8 nonzeros + nnz_jac_g = m_ * n_; + + // the Hessian is also dense and has 16 total nonzeros, but we + // only need the lower left corner (since it is symmetric) + nnz_h_lag = n_ * n_; + + // use the C style indexing (0-based) + index_style = Ipopt::TNLP::C_STYLE; + + return true; +} + +bool Seair_NLP::get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u, Ipopt::Index m, + Ipopt::Number* g_l, Ipopt::Number* g_u) +{ + mio::unused(n, m); + // controls order: 1. SocialDistancing, 2. Quarantined, 3. TestingRate + for (int i = 0; i < numControlIntervals_; ++i) { + x_l[i] = 0.05; // lower bound of SocialDistancing + x_u[i] = 0.5; // upper bound of SocialDistancing + x_l[i + numControlIntervals_] = 0.01; // lower bound of Quarantined + x_u[i + numControlIntervals_] = 0.3; // upper bound of Quarantined + x_l[i + 2 * numControlIntervals_] = 0.15; // lower bound of TestingRate + x_u[i + 2 * numControlIntervals_] = 0.3; // upper bound of TestingRate + } + + // path constraints + for (int i = 0; i < m_; ++i) { + g_l[i] = 0.0; + g_u[i] = 1e6; + } + return true; +} + +bool Seair_NLP::get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x, bool init_z, Ipopt::Number* z_L, + Ipopt::Number* z_U, Ipopt::Index m, bool init_lambda, Ipopt::Number* lambda) +{ + mio::unused(init_x, init_z, z_L, z_U, m, init_lambda, lambda); + assert(init_z == false); + assert(init_lambda == false); + + for (int i = 0; i < n; ++i) { + x[i] = 0.2; + } + return true; +} + +bool Seair_NLP::eval_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number& obj_value) +{ + mio::unused(new_x); + std::vector xx(getN()); + std::vector constraints(getM()); + for (int i = 0; i < n; ++i) + xx[i] = x[i]; + eval_objective_constraints(xx, constraints, obj_value); + return true; +} + +bool Seair_NLP::eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number* grad_f) +{ + mio::unused(new_x); + using FP = ad::gt1s::type; + std::vector xx(getN()); + std::vector constraints(getM()); + FP objective; + for (int i = 0; i < n; ++i) + ad::value(xx[i]) = x[i]; + for (int i = 0; i < n; ++i) { + ad::derivative(xx[i]) = 1.0; + eval_objective_constraints(xx, constraints, objective); + grad_f[i] = ad::derivative(objective); + ad::derivative(xx[i]) = 0.0; + } + return true; +} + +bool Seair_NLP::eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Number* g) +{ + mio::unused(new_x); + std::vector xx(getN()); + std::vector constraints(getM()); + double obj_value = 0; + for (int i = 0; i < n; ++i) + xx[i] = x[i]; + eval_objective_constraints(xx, constraints, obj_value); + for (int i = 0; i < m; ++i) + g[i] = constraints[i]; + return true; +} + +bool Seair_NLP::eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Index nele_jac, + Ipopt::Index* iRow, Ipopt::Index* jCol, Ipopt::Number* values) +{ + mio::unused(new_x, nele_jac); + if (values == nullptr) { + int jac_index = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < m; ++j) { + iRow[jac_index] = j; + jCol[jac_index] = i; + ++jac_index; + } + } + } + else { + using FP = ad::gt1s::type; + std::vector xx(getN()); + std::vector constraints(getM()); + FP objective; + int jac_index = 0; + for (int i = 0; i < n; ++i) + ad::value(xx[i]) = x[i]; + for (int i = 0; i < n; ++i) { + ad::derivative(xx[i]) = 1.0; + eval_objective_constraints(xx, constraints, objective); + for (int j = 0; j < m; ++j) { + values[jac_index] = ad::derivative(constraints[j]); + ++jac_index; + } + ad::derivative(xx[i]) = 0.0; + } + } + return true; +} + +bool Seair_NLP::eval_h(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number obj_factor, Ipopt::Index m, + const Ipopt::Number* lambda, bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index* iRow, + Ipopt::Index* jCol, Ipopt::Number* values) +{ + mio::unused(n, x, new_x, obj_factor, m, lambda, new_lambda, new_lambda, nele_hess, iRow, jCol, values); + return true; +} + +void Seair_NLP::finalize_solution(Ipopt::SolverReturn status, Ipopt::Index n, const Ipopt::Number* x, + const Ipopt::Number* z_L, const Ipopt::Number* z_U, Ipopt::Index m, + const Ipopt::Number* g, const Ipopt::Number* lambda, Ipopt::Number obj_value, + const Ipopt::IpoptData* ip_data, Ipopt::IpoptCalculatedQuantities* ip_cq) +{ + mio::unused(status, n, z_L, z_U, m, g, lambda, obj_value, ip_data, ip_cq); + std::cout << "optimal solution is\n"; + std::cout << "Writing output to text files" << std::endl; + using FP = double; + using IS = mio::oseair::InfectionState; + using Idx = mio::Index; + + FP t0 = 0; + FP tmax = 100; + FP dt = 0.2; + std::vector grid(numIntervals_ + 1); + for (int i = 0; i < numIntervals_ + 1; ++i) { + grid[i] = (tmax / numIntervals_) * i + (t0 / numIntervals_) * (numIntervals_ - i); + } + mio::oseair::Model model; + + //open files for parameter output + std::ofstream outFileSocialDistancing("SocialDistancing.txt"); + std::ofstream outFileQuarantined("Quarantined.txt"); + std::ofstream outFileTestingRate("TestingRate.txt"); + + //open files for state output + std::ofstream outFileSusceptible("Susceptible.txt"); + std::ofstream outFileExposed("Exposed.txt"); + std::ofstream outFileAsymptomatic("Asymptomatic.txt"); + std::ofstream outFileInfected("Infected.txt"); + std::ofstream outFileRecovered("Recovered.txt"); + std::ofstream outFileDead("Dead.txt"); + + set_initial_values(model); + int gridindex = 0; + for (int controlIndex = 0; controlIndex < numControlIntervals_; ++controlIndex) { + model.parameters.template get>() = x[controlIndex]; + model.parameters.template get>() = x[controlIndex + numControlIntervals_]; + model.parameters.template get>() = x[controlIndex + 2 * numControlIntervals_]; + + outFileSocialDistancing << grid[gridindex] << " " + << model.parameters.template get>() << "\n"; + outFileQuarantined << grid[gridindex] << " " << model.parameters.template get>() + << "\n"; + outFileTestingRate << grid[gridindex] << " " << model.parameters.template get>() + << "\n"; + + outFileSusceptible << grid[gridindex] << " " << model.populations[{Idx(IS::Susceptible)}] * N / 1000.0 << "\n"; + outFileExposed << grid[gridindex] << " " << model.populations[{Idx(IS::Exposed)}] * N / 1000.0 << "\n"; + outFileAsymptomatic << grid[gridindex] << " " << model.populations[{Idx(IS::Asymptomatic)}] * N / 1000.0 + << "\n"; + outFileInfected << grid[gridindex] << " " << model.populations[{Idx(IS::Infected)}] * N / 1000.0 << "\n"; + outFileRecovered << grid[gridindex] << " " << model.populations[{Idx(IS::Recovered)}] * N / 1000.0 << "\n"; + outFileDead << grid[gridindex] << " " << model.populations[{Idx(IS::Dead)}] * N / 1000.0 << "\n"; + + for (int i = 0; i < pcresolution_; ++i, ++gridindex) { + + auto result = mio::simulate>(grid[gridindex], grid[gridindex + 1], dt, model); + + for (int j = 0; j < (int)mio::oseair::InfectionState::Count; ++j) { + model.populations[mio::oseair::InfectionState(j)] = result.get_last_value()[j]; + } + outFileSusceptible << grid[gridindex + 1] << " " << model.populations[{Idx(IS::Susceptible)}] * N / 1000.0 + << "\n"; + outFileExposed << grid[gridindex + 1] << " " << model.populations[{Idx(IS::Exposed)}] * N / 1000.0 << "\n"; + outFileAsymptomatic << grid[gridindex + 1] << " " << model.populations[{Idx(IS::Asymptomatic)}] * N / 1000.0 + << "\n"; + outFileInfected << grid[gridindex + 1] << " " << model.populations[{Idx(IS::Infected)}] * N / 1000.0 + << "\n"; + outFileRecovered << grid[gridindex + 1] << " " << model.populations[{Idx(IS::Recovered)}] * N / 1000.0 + << "\n"; + outFileDead << grid[gridindex + 1] << " " << model.populations[{Idx(IS::Dead)}] * N / 1000.0 << "\n"; + } + + outFileSocialDistancing << grid[gridindex] << " " + << model.parameters.template get>() << "\n"; + outFileQuarantined << grid[gridindex] << " " << model.parameters.template get>() + << "\n"; + outFileTestingRate << grid[gridindex] << " " << model.parameters.template get>() + << "\n"; + } + + //close files + outFileSocialDistancing.close(); + outFileQuarantined.close(); + outFileTestingRate.close(); + outFileSusceptible.close(); + outFileExposed.close(); + outFileAsymptomatic.close(); + outFileInfected.close(); + outFileRecovered.close(); + outFileDead.close(); + + return; +} + +bool Seair_NLP::intermediate_callback(Ipopt::AlgorithmMode mode, Ipopt::Index iter, Ipopt::Number obj_value, + Ipopt::Number inf_pr, Ipopt::Number inf_du, Ipopt::Number DeathRate, + Ipopt::Number d_norm, Ipopt::Number regularization_size, Ipopt::Number alpha_du, + Ipopt::Number alpha_pr, Ipopt::Index ls_trials, const Ipopt::IpoptData* ip_data, + Ipopt::IpoptCalculatedQuantities* ip_cq) +{ + mio::unused(mode, iter, obj_value, inf_pr, inf_du, DeathRate, d_norm, regularization_size, alpha_du, alpha_pr, + ls_trials, ip_data, ip_cq); + return true; +} + +int main() +{ + //switch of logging for mio + mio::set_log_level(mio::LogLevel::off); + + // Create a new instance of your nlp + // (use a SmartPtr, not raw) + Ipopt::SmartPtr mynlp = new Seair_NLP(); + + // Create a new instance of IpoptApplication + // (use a SmartPtr, not raw) + // We are using the factory, since this allows us to compile this + // example with an Ipopt Windows DLL + Ipopt::SmartPtr app = IpoptApplicationFactory(); + + // Change some options + // Note: The following choices are only examples, they might not be + // suitable for your optimization problem. + app->Options()->SetNumericValue("tol", 1e-6); + app->Options()->SetStringValue("mu_strategy", "adaptive"); + app->Options()->SetStringValue("output_file", "ipopt.out"); + app->Options()->SetStringValue("hessian_approximation", "limited-memory"); + app->Options()->SetStringValue("limited_memory_update_type", "bfgs"); + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = app->Initialize(); + if (status != Ipopt::Solve_Succeeded) { + std::cout << std::endl << std::endl << "*** Error during initialization!" << std::endl; + return (int)status; + } + + // Ask Ipopt to solve the problem + status = app->OptimizeTNLP(mynlp); + + if (status == Ipopt::Solve_Succeeded) { + std::cout << std::endl << std::endl << "*** The problem solved!" << std::endl; + } + else { + std::cout << std::endl << std::endl << "*** The problem FAILED!" << std::endl; + } + + // As the SmartPtrs go out of scope, the reference count + // will be decremented and the objects will automatically + // be deleted. + + return (int)status; +} diff --git a/cpp/examples/ode_secir.cpp b/cpp/examples/ode_secir.cpp index d7db19b9ca..89fa02a539 100644 --- a/cpp/examples/ode_secir.cpp +++ b/cpp/examples/ode_secir.cpp @@ -36,18 +36,18 @@ int main() double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_car_t0 = 50, nb_hosp_t0 = 20, nb_icu_t0 = 10, nb_rec_t0 = 10, nb_dead_t0 = 0; - mio::osecir::Model model(1); + mio::osecir::Model model(1); - model.parameters.set(60); - model.parameters.set(0.2); + model.parameters.template set(60); + model.parameters.set>(0.2); - model.parameters.get() = 3.2; - model.parameters.get() = 2.0; - model.parameters.get() = 5.8; - model.parameters.get() = 9.5; - model.parameters.get() = 7.1; + model.parameters.get>() = 3.2; + model.parameters.get>() = 2.0; + model.parameters.get>() = 5.8; + model.parameters.get>() = 9.5; + model.parameters.get>() = 7.1; - mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, cont_freq)); contact_matrix[0].add_damping(0.7, mio::SimulationTime(30.)); @@ -64,15 +64,15 @@ int main() model.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, nb_total_t0); - model.parameters.get() = 0.05; - model.parameters.get() = 0.7; - model.parameters.get() = 0.09; - model.parameters.get() = 0.25; - model.parameters.get() = 0.45; - model.parameters.get() = 35; - model.parameters.get() = 0.2; - model.parameters.get() = 0.25; - model.parameters.get() = 0.3; + model.parameters.get>() = 0.05; + model.parameters.get>() = 0.7; + model.parameters.get>() = 0.09; + model.parameters.get>() = 0.25; + model.parameters.get>() = 0.45; + model.parameters.get>() = 35; + model.parameters.get>() = 0.2; + model.parameters.get>() = 0.25; + model.parameters.get>() = 0.3; model.apply_constraints(); diff --git a/cpp/examples/ode_secir_ageres.cpp b/cpp/examples/ode_secir_ageres.cpp index b10f0fbca7..0d9293212c 100644 --- a/cpp/examples/ode_secir_ageres.cpp +++ b/cpp/examples/ode_secir_ageres.cpp @@ -44,22 +44,22 @@ int main() // theta = theta_in; // icu per hospitalized // delta = delta_in; // deaths per ICUs - mio::osecir::Model model(3); + mio::osecir::Model model(3); auto nb_groups = model.parameters.get_num_groups(); double fact = 1.0 / (double)(size_t)nb_groups; auto& params = model.parameters; params.set(60); - params.set(0.2); - params.get() = 35; + params.set>(0.2); + params.get>() = 35; for (auto i = mio::AgeGroup(0); i < nb_groups; i++) { - params.get()[i] = 3.2; - params.get()[i] = 2.; - params.get()[i] = 5.8; - params.get()[i] = 9.5; - params.get()[i] = 7.1; + params.get>()[i] = 3.2; + params.get>()[i] = 2.; + params.get>()[i] = 5.8; + params.get>()[i] = 9.5; + params.get>()[i] = 7.1; model.populations[{i, mio::osecir::InfectionState::Exposed}] = fact * nb_exp_t0; model.populations[{i, mio::osecir::InfectionState::InfectedNoSymptoms}] = fact * nb_car_t0; @@ -73,27 +73,26 @@ int main() model.populations.set_difference_from_group_total({i, mio::osecir::InfectionState::Susceptible}, fact * nb_total_t0); - params.get()[i] = 0.05; - params.get()[i] = 0.7; - params.get()[i] = 0.09; - params.get()[i] = 0.25; - params.get()[i] = 0.45; - params.get()[i] = 0.2; - params.get()[i] = 0.25; - params.get()[i] = 0.3; + params.get>()[i] = 0.05; + params.get>()[i] = 0.7; + params.get>()[i] = 0.09; + params.get>()[i] = 0.25; + params.get>()[i] = 0.45; + params.get>()[i] = 0.2; + params.get>()[i] = 0.25; + params.get>()[i] = 0.3; } model.apply_constraints(); - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); contact_matrix.add_damping(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, 0.7), mio::SimulationTime(30.)); - mio::TimeSeries secir = simulate(t0, tmax, dt, model); - - bool print_to_terminal = true; + mio::TimeSeries secir = mio::simulate>(t0, tmax, dt, model); + bool print_to_terminal = true; if (print_to_terminal) { diff --git a/cpp/examples/ode_secir_contact_changes.cpp b/cpp/examples/ode_secir_contact_changes.cpp index b883158889..f05c72d11e 100644 --- a/cpp/examples/ode_secir_contact_changes.cpp +++ b/cpp/examples/ode_secir_contact_changes.cpp @@ -40,7 +40,7 @@ int main() double nb_total_t0 = 1000, nb_inf_t0 = 10; - auto integrator = std::make_shared(); + auto integrator = std::make_shared>(); // default model run to be compared against mio::osecir::Model model_a(1); @@ -51,12 +51,12 @@ int main() model_a.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_a.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, nb_total_t0); - mio::ContactMatrixGroup& contact_matrix_a = model_a.parameters.get(); + mio::ContactMatrixGroup& contact_matrix_a = model_a.parameters.get>(); contact_matrix_a[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, cont_freq)); // set probability of transmission and risk of infection to 1. - model_a.parameters.get() = 1.0; - model_a.parameters.get() = 1.0; - auto result_a = simulate_flows(t0, tmax, dt, model_a, integrator); + model_a.parameters.get>() = 1.0; + model_a.parameters.get>() = 1.0; + auto result_a = mio::simulate_flows(t0, tmax, dt, model_a, integrator); result_a[1].print_table({"S->E", "E->I_NS", "I_NS->I_Sy", "I_NS->R", "I_NSC->I_SyC", "I_NSC->R", "I_Sy->I_Sev", "I_Sy->R", "I_SyC->I_Sev", "I_SyC->R", "I_Sev->I_Crit", "I_Sev->R", "I_Sev->D", "I_Crit->D", "I_Crit->R"}, @@ -70,10 +70,10 @@ int main() model_b.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_b.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, nb_total_t0); - mio::ContactMatrixGroup& contact_matrix_b = model_b.parameters.get(); + mio::ContactMatrixGroup& contact_matrix_b = model_b.parameters.get>(); contact_matrix_b[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, cont_freq)); contact_matrix_b[0].add_damping(0.5, mio::SimulationTime(0.)); // contact reduction happens here! - auto result_b = simulate_flows(t0, tmax, dt, model_b, integrator); + auto result_b = mio::simulate_flows(t0, tmax, dt, model_b, integrator); result_b[1].print_table({"S->E", "E->I_NS", "I_NS->I_Sy", "I_NS->R", "I_NSC->I_SyC", "I_NSC->R", "I_Sy->I_Sev", "I_Sy->R", "I_SyC->I_Sev", "I_SyC->R", "I_Sev->I_Crit", "I_Sev->R", "I_Sev->D", "I_Crit->D", "I_Crit->R"}, @@ -88,10 +88,10 @@ int main() model_c.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_c.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, nb_total_t0); - mio::ContactMatrixGroup& contact_matrix_c = model_c.parameters.get(); + mio::ContactMatrixGroup& contact_matrix_c = model_c.parameters.get>(); contact_matrix_c[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, cont_freq)); contact_matrix_c[0].add_damping(1., mio::SimulationTime(0.)); // contact reduction happens here! - auto result_c = simulate_flows(t0, tmax, dt, model_c, integrator); + auto result_c = mio::simulate_flows(t0, tmax, dt, model_c, integrator); result_c[1].print_table({"S->E", "E->I_NS", "I_NS->I_Sy", "I_NS->R", "I_NSC->I_SyC", "I_NSC->R", "I_Sy->I_Sev", "I_Sy->R", "I_SyC->I_Sev", "I_SyC->R", "I_Sev->I_Crit", "I_Sev->R", "I_Sev->D", "I_Crit->D", "I_Crit->R"}, @@ -106,10 +106,10 @@ int main() model_d.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_d.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, nb_total_t0); - mio::ContactMatrixGroup& contact_matrix_d = model_d.parameters.get(); + mio::ContactMatrixGroup& contact_matrix_d = model_d.parameters.get>(); contact_matrix_d[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, cont_freq)); contact_matrix_d[0].add_damping(-1., mio::SimulationTime(0.)); // contact increase happens here! - auto result_d = simulate_flows(t0, tmax, dt, model_d, integrator); + auto result_d = mio::simulate_flows(t0, tmax, dt, model_d, integrator); result_d[1].print_table({"S->E", "E->I_NS", "I_NS->I_Sy", "I_NS->R", "I_NSC->I_SyC", "I_NSC->R", "I_Sy->I_Sev", "I_Sy->R", "I_SyC->I_Sev", "I_SyC->R", "I_Sev->I_Crit", "I_Sev->R", "I_Sev->D", "I_Crit->D", "I_Crit->R"}, diff --git a/cpp/examples/ode_secir_parameter_sampling.cpp b/cpp/examples/ode_secir_parameter_sampling.cpp index 5bbf7231d2..2ee75b74bd 100644 --- a/cpp/examples/ode_secir_parameter_sampling.cpp +++ b/cpp/examples/ode_secir_parameter_sampling.cpp @@ -73,28 +73,28 @@ int main() /* * Contact frequency and dampings variable element */ - mio::osecir::Model model(3); + mio::osecir::Model model(3); auto& params = model.parameters; mio::AgeGroup nb_groups = params.get_num_groups(); mio::ContactMatrixGroup cm_group{ mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, 0.5))}; - params.get() = cm_group; + params.get>() = cm_group; - params.get().get_dampings().push_back(mio::DampingSampling( - mio::UncertainValue(0.5), mio::DampingLevel(0), mio::DampingType(0), mio::SimulationTime(30.), + params.get>().get_dampings().push_back(mio::DampingSampling( + mio::UncertainValue(0.5), mio::DampingLevel(0), mio::DampingType(0), mio::SimulationTime(30.), std::vector(1, size_t(0)), Eigen::VectorXd::Constant(Eigen::Index(nb_groups.get()), 1.0))); - params.get().get_dampings()[0].get_value().set_distribution( + params.get>().get_dampings()[0].get_value().set_distribution( mio::ParameterDistributionNormal(0.0, 1.0, 0.5, 0.2)); - params.get().get_dampings().push_back(mio::DampingSampling( - mio::UncertainValue(0.3), mio::DampingLevel(1), mio::DampingType(0), mio::SimulationTime(10.), + params.get>().get_dampings().push_back(mio::DampingSampling( + mio::UncertainValue(0.3), mio::DampingLevel(1), mio::DampingType(0), mio::SimulationTime(10.), std::vector(1, size_t(0)), Eigen::VectorXd::Constant(Eigen::Index(nb_groups.get()), 1.0))); - params.get().get_dampings()[0].get_value().set_distribution( + params.get>().get_dampings()[0].get_value().set_distribution( mio::ParameterDistributionNormal(0.0, 1.0, 0.4, 0.05)); draw_sample(model); - auto& cfmat_sample = params.get().get_cont_freq_mat(); + auto& cfmat_sample = params.get>().get_cont_freq_mat(); printf("\n\n Number of dampings: %zu\n", cfmat_sample[0].get_dampings().size()); diff --git a/cpp/examples/ode_secir_parameter_study.cpp b/cpp/examples/ode_secir_parameter_study.cpp index 9538801db5..640ef30380 100644 --- a/cpp/examples/ode_secir_parameter_study.cpp +++ b/cpp/examples/ode_secir_parameter_study.cpp @@ -30,9 +30,9 @@ * @param t0 starting point of simulation * @param tmax end point of simulation */ -mio::IOResult -write_single_run_result(const size_t run, - const mio::Graph>, mio::MigrationEdge>& graph) +mio::IOResult write_single_run_result( + const size_t run, + const mio::Graph>, mio::MigrationEdge>& graph) { std::string abs_path; BOOST_OUTCOME_TRY(auto&& created, mio::create_directory("results", abs_path)); @@ -88,22 +88,22 @@ int main() double num_total_t0 = 10000, num_exp_t0 = 100, num_inf_t0 = 50, num_car_t0 = 50, num_hosp_t0 = 20, num_icu_t0 = 10, num_rec_t0 = 10, num_dead_t0 = 0; - mio::osecir::Model model(1); + mio::osecir::Model model(1); mio::AgeGroup num_groups = model.parameters.get_num_groups(); double fact = 1.0 / (double)(size_t)num_groups; auto& params = model.parameters; - params.set(std::numeric_limits::max()); + params.set>(std::numeric_limits::max()); params.set(0); - params.set(0); + params.set>(0); for (auto i = mio::AgeGroup(0); i < num_groups; i++) { - params.get()[i] = 3.2; - params.get()[i] = 2.; - params.get()[i] = 6.; - params.get()[i] = 12; - params.get()[i] = 8; + params.get>()[i] = 3.2; + params.get>()[i] = 2.; + params.get>()[i] = 6.; + params.get>()[i] = 12; + params.get>()[i] = 8; model.populations[{i, mio::osecir::InfectionState::Exposed}] = fact * num_exp_t0; model.populations[{i, mio::osecir::InfectionState::InfectedNoSymptoms}] = fact * num_car_t0; @@ -115,18 +115,18 @@ int main() model.populations.set_difference_from_group_total({i, mio::osecir::InfectionState::Susceptible}, fact * num_total_t0); - params.get()[i] = 0.05; - params.get()[i] = 0.67; - params.get()[i] = 0.09; - params.get()[i] = 0.25; - params.get()[i] = 0.2; - params.get()[i] = 0.25; - params.get()[i] = 0.3; + params.get>()[i] = 0.05; + params.get>()[i] = 0.67; + params.get>()[i] = 0.09; + params.get>()[i] = 0.25; + params.get>()[i] = 0.2; + params.get>()[i] = 0.25; + params.get>()[i] = 0.3; } params.apply_constraints(); - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)num_groups, (size_t)num_groups, fact * cont_freq)); diff --git a/cpp/examples/ode_secir_read_graph.cpp b/cpp/examples/ode_secir_read_graph.cpp index fc675352f4..20052706e2 100644 --- a/cpp/examples/ode_secir_read_graph.cpp +++ b/cpp/examples/ode_secir_read_graph.cpp @@ -55,28 +55,29 @@ int main(int argc, char** argv) const auto t0 = 0.; const auto tmax = 10.; + using FP = double; double cont_freq = 10; // see Polymod study double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_car_t0 = 50, nb_hosp_t0 = 20, nb_icu_t0 = 10, nb_rec_t0 = 10, nb_dead_t0 = 0; - mio::osecir::Model model(1); + mio::osecir::Model model(1); mio::AgeGroup nb_groups = model.parameters.get_num_groups(); double fact = 1.0 / (double)(size_t)nb_groups; auto& params = model.parameters; - params.set(std::numeric_limits::max()); + params.set>(std::numeric_limits::max()); params.set(0); - params.set(0); + params.set>(0); for (auto i = mio::AgeGroup(0); i < nb_groups; i++) { - params.get()[i] = 3.2; - params.get()[i] = 2.0; - params.get()[i] = 6.; - params.get()[i] = 12; - params.get()[i] = 8; + params.get>()[i] = 3.2; + params.get>()[i] = 2.0; + params.get>()[i] = 6.; + params.get>()[i] = 12; + params.get>()[i] = 8; model.populations[{i, mio::osecir::InfectionState::Exposed}] = fact * nb_exp_t0; model.populations[{i, mio::osecir::InfectionState::InfectedNoSymptoms}] = fact * nb_car_t0; @@ -90,18 +91,18 @@ int main(int argc, char** argv) model.populations.set_difference_from_group_total({i, mio::osecir::InfectionState::Susceptible}, fact * nb_total_t0); - params.get()[i] = 0.05; - params.get()[i] = 0.67; - params.get()[i] = 0.09; - params.get()[i] = 0.25; - params.get()[i] = 0.2; - params.get()[i] = 0.25; - params.get()[i] = 0.3; + params.get>()[i] = 0.05; + params.get>()[i] = 0.67; + params.get>()[i] = 0.09; + params.get>()[i] = 0.25; + params.get>()[i] = 0.2; + params.get>()[i] = 0.25; + params.get>()[i] = 0.3; } params.apply_constraints(); - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); @@ -117,7 +118,7 @@ int main(int argc, char** argv) std::cout << "Done" << std::endl; std::cout << "Intializing Graph..." << std::flush; - mio::Graph graph; + mio::Graph, mio::MigrationParameters> graph; for (int node = 0; node < twitter_migration_2018.rows(); node++) { graph.add_node(node, model); } @@ -139,7 +140,7 @@ int main(int argc, char** argv) std::cout << "Done" << std::endl; std::cout << "Reading Json Files..." << std::flush; - auto graph_read_result = mio::read_graph("graph_parameters"); + auto graph_read_result = mio::read_graph>("graph_parameters"); if (!graph_read_result) { std::cout << "Error: " << graph_read_result.error().formatted_message(); diff --git a/cpp/examples/ode_secir_save_results.cpp b/cpp/examples/ode_secir_save_results.cpp index b3b5833d7d..51089bd4e4 100644 --- a/cpp/examples/ode_secir_save_results.cpp +++ b/cpp/examples/ode_secir_save_results.cpp @@ -34,22 +34,22 @@ int main() double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_car_t0 = 50, nb_hosp_t0 = 20, nb_icu_t0 = 10, nb_rec_t0 = 10, nb_dead_t0 = 0; - mio::osecir::Model model(1); + mio::osecir::Model model(1); mio::AgeGroup nb_groups = model.parameters.get_num_groups(); double fact = 1.0 / (double)(size_t)nb_groups; auto& params = model.parameters; - params.set(std::numeric_limits::max()); + params.set>(std::numeric_limits::max()); params.set(0); - params.set(0); + params.set>(0); for (auto i = mio::AgeGroup(0); i < nb_groups; i++) { - params.get()[i] = 3.2; - params.get()[i] = 2.0; - params.get()[i] = 6.; - params.get()[i] = 12; - params.get()[i] = 8; + params.get>()[i] = 3.2; + params.get>()[i] = 2.0; + params.get>()[i] = 6.; + params.get>()[i] = 12; + params.get>()[i] = 8; model.populations[{i, mio::osecir::InfectionState::Exposed}] = fact * nb_exp_t0; model.populations[{i, mio::osecir::InfectionState::InfectedNoSymptoms}] = fact * nb_car_t0; @@ -63,23 +63,23 @@ int main() model.populations.set_difference_from_group_total({i, mio::osecir::InfectionState::Susceptible}, fact * nb_total_t0); - params.get()[i] = 0.05; - params.get()[i] = 0.67; - params.get()[i] = 0.09; - params.get()[i] = 0.25; - params.get()[i] = 0.2; - params.get()[i] = 0.25; - params.get()[i] = 0.3; + params.get>()[i] = 0.05; + params.get>()[i] = 0.67; + params.get>()[i] = 0.09; + params.get>()[i] = 0.25; + params.get>()[i] = 0.2; + params.get>()[i] = 0.25; + params.get>()[i] = 0.3; } params.apply_constraints(); - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant((size_t)nb_groups, (size_t)nb_groups, fact * cont_freq)); contact_matrix.add_damping(0.3, mio::SimulationTime(30.)); - auto result_from_sim = simulate(t0, tmax, dt, model); + auto result_from_sim = mio::osecir::simulate(t0, tmax, dt, model); std::vector> results_from_sim = {result_from_sim, result_from_sim}; std::vector ids = {1, 2}; diff --git a/cpp/examples/ode_secirvvs.cpp b/cpp/examples/ode_secirvvs.cpp index e7eaed0cbf..cddbfee849 100644 --- a/cpp/examples/ode_secirvvs.cpp +++ b/cpp/examples/ode_secirvvs.cpp @@ -31,7 +31,7 @@ int main() mio::log_info("Simulating SECIRVVS; t={} ... {} with dt = {}.", t0, tmax, dt); - mio::osecirvvs::Model model(1); + mio::osecirvvs::Model model(1); for (mio::AgeGroup i = 0; i < model.parameters.get_num_groups(); i++) { model.populations[{i, mio::osecirvvs::InfectionState::ExposedNaive}] = 10; @@ -64,52 +64,56 @@ int main() {i, mio::osecirvvs::InfectionState::SusceptibleNaive}, 1000); } - model.parameters.get() = 100; - model.parameters.get() = 0.0143; + model.parameters.get>() = 100; + model.parameters.get>() = 0.0143; const size_t daily_vaccinations = 10; - model.parameters.get().resize(mio::SimulationDay((size_t)tmax + 1)); - model.parameters.get().resize(mio::SimulationDay((size_t)tmax + 1)); + model.parameters.get>().resize(mio::SimulationDay((size_t)tmax + 1)); + model.parameters.get>().resize(mio::SimulationDay((size_t)tmax + 1)); for (size_t i = 0; i < tmax + 1; ++i) { auto num_vaccinations = static_cast(i * daily_vaccinations); - model.parameters.get()[{(mio::AgeGroup)0, mio::SimulationDay(i)}] = + model.parameters + .get>()[{(mio::AgeGroup)0, mio::SimulationDay(i)}] = num_vaccinations; - model.parameters.get()[{(mio::AgeGroup)0, mio::SimulationDay(i)}] = + model.parameters + .get>()[{(mio::AgeGroup)0, mio::SimulationDay(i)}] = num_vaccinations; } - auto& contacts = model.parameters.get(); + auto& contacts = model.parameters.get>(); auto& contact_matrix = contacts.get_cont_freq_mat(); contact_matrix[0].get_baseline().setConstant(0.5); contact_matrix[0].get_baseline().diagonal().setConstant(5.0); contact_matrix[0].add_damping(0.3, mio::SimulationTime(5.0)); //times - model.parameters.get()[mio::AgeGroup(0)] = 3.33; - model.parameters.get()[mio::AgeGroup(0)] = 1.87; - model.parameters.get()[mio::AgeGroup(0)] = 7; - model.parameters.get()[mio::AgeGroup(0)] = 6; - model.parameters.get()[mio::AgeGroup(0)] = 7; + model.parameters.get>()[mio::AgeGroup(0)] = 3.33; + model.parameters.get>()[mio::AgeGroup(0)] = 1.87; + model.parameters.get>()[mio::AgeGroup(0)] = 7; + model.parameters.get>()[mio::AgeGroup(0)] = 6; + model.parameters.get>()[mio::AgeGroup(0)] = 7; //probabilities - model.parameters.get()[mio::AgeGroup(0)] = 0.15; - model.parameters.get()[mio::AgeGroup(0)] = 0.5; + model.parameters.get>()[mio::AgeGroup(0)] = 0.15; + model.parameters.get>()[mio::AgeGroup(0)] = 0.5; // The precise value between Risk* (situation under control) and MaxRisk* (situation not under control) // depends on incidence and test and trace capacity - model.parameters.get()[mio::AgeGroup(0)] = 0.0; - model.parameters.get()[mio::AgeGroup(0)] = 0.4; - model.parameters.get()[mio::AgeGroup(0)] = 0.2; - model.parameters.get()[mio::AgeGroup(0)] = 0.1; - model.parameters.get()[mio::AgeGroup(0)] = 0.1; - model.parameters.get()[mio::AgeGroup(0)] = 0.1; + model.parameters.get>()[mio::AgeGroup(0)] = 0.0; + model.parameters.get>()[mio::AgeGroup(0)] = 0.4; + model.parameters.get>()[mio::AgeGroup(0)] = 0.2; + model.parameters.get>()[mio::AgeGroup(0)] = 0.1; + model.parameters.get>()[mio::AgeGroup(0)] = 0.1; + model.parameters.get>()[mio::AgeGroup(0)] = 0.1; - model.parameters.get()[mio::AgeGroup(0)] = 0.8; - model.parameters.get()[mio::AgeGroup(0)] = 0.331; - model.parameters.get()[mio::AgeGroup(0)] = 0.65; - model.parameters.get()[mio::AgeGroup(0)] = 0.243; - model.parameters.get()[mio::AgeGroup(0)] = 0.1; - model.parameters.get()[mio::AgeGroup(0)] = 0.091; - model.parameters.get()[mio::AgeGroup(0)] = 0.9; + model.parameters.get>()[mio::AgeGroup(0)] = 0.8; + model.parameters.get>()[mio::AgeGroup(0)] = 0.331; + model.parameters.get>()[mio::AgeGroup(0)] = 0.65; + model.parameters.get>()[mio::AgeGroup(0)] = 0.243; + model.parameters.get>()[mio::AgeGroup(0)] = + 0.1; + model.parameters.get>()[mio::AgeGroup(0)] = + 0.091; + model.parameters.get>()[mio::AgeGroup(0)] = 0.9; - model.parameters.get() = 0.2; + model.parameters.get>() = 0.2; model.apply_constraints(); @@ -122,7 +126,7 @@ int main() // mio::TimeSeries secir = simulate(t0, tmax, dt, model, integrator); // use default Cash-Karp adaptive integrator - mio::TimeSeries result = simulate(t0, tmax, dt, model); + mio::TimeSeries result = mio::simulate>(t0, tmax, dt, model); bool print_to_terminal = true; diff --git a/cpp/examples/ode_seir.cpp b/cpp/examples/ode_seir.cpp index ad21bc76fb..875372959e 100644 --- a/cpp/examples/ode_seir.cpp +++ b/cpp/examples/ode_seir.cpp @@ -22,6 +22,7 @@ #include "ode_seir/parameters.h" #include "memilio/compartments/simulation.h" #include "memilio/utils/logging.h" +#include "memilio/utils/time_series.h" #include "memilio/utils/time_series.h" @@ -29,15 +30,15 @@ int main() { mio::set_log_level(mio::LogLevel::debug); - double t0 = 0; - double tmax = 50.; - double dt = 1.0; + ScalarType t0 = 0; + ScalarType tmax = 50.; + ScalarType dt = 1.0; mio::log_info("Simulating ODE SEIR; t={} ... {} with dt = {}.", t0, tmax, dt); - mio::oseir::Model model(1); + mio::oseir::Model model(1); - double total_population = 10000; + ScalarType total_population = 10000; model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Exposed}] = 100; model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Infected}] = 100; model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Recovered}] = 100; @@ -46,25 +47,18 @@ int main() model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Infected}] - model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Recovered}]; - model.parameters.set(5.2); - model.parameters.set(6); - model.parameters.set(0.1); + model.parameters.set>(5.2); + model.parameters.set>(6); + model.parameters.set>(0.1); - mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); contact_matrix[0].get_baseline().setConstant(2.7); contact_matrix[0].add_damping(0.7, mio::SimulationTime(30.)); - model.check_constraints(); - mio::TimeSeries seir = simulate(t0, tmax, dt, model); - - bool print_to_terminal = true; - - if (print_to_terminal) { - seir.print_table({"S", "E", "I", "R"}); + auto seir = simulate(t0, tmax, dt, model); - Eigen::VectorXd res_j = seir.get_last_value(); - printf("\nnumber total: %f\n", res_j[0] + res_j[1] + res_j[2] + res_j[3]); - } + seir.print_table({"S", "E", "I", "R"}); + std::cout << "\nnumber total: " << seir.get_last_value().sum() << "\n"; } diff --git a/cpp/examples/ode_seir_ageres.cpp b/cpp/examples/ode_seir_ageres.cpp index 03925413e5..10c1df58ce 100644 --- a/cpp/examples/ode_seir_ageres.cpp +++ b/cpp/examples/ode_seir_ageres.cpp @@ -19,7 +19,7 @@ int main() double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_rec_t0 = 10; const size_t num_groups = 3; - mio::oseir::Model model(num_groups); + mio::oseir::Model model(num_groups); double fact = 1.0 / num_groups; auto& params = model.parameters; @@ -31,18 +31,18 @@ int main() model.populations.set_difference_from_group_total({i, mio::oseir::InfectionState::Susceptible}, fact * nb_total_t0); - model.parameters.get()[i] = 5.2; - model.parameters.get()[i] = 6; - model.parameters.get()[i] = 0.04; + model.parameters.get>()[i] = 5.2; + model.parameters.get>()[i] = 6; + model.parameters.get>()[i] = 0.04; } - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(num_groups, num_groups, fact * cont_freq)); contact_matrix.add_damping(Eigen::MatrixXd::Constant(num_groups, num_groups, 0.7), mio::SimulationTime(30.)); model.apply_constraints(); - mio::TimeSeries seir = simulate(t0, tmax, dt, model); + auto seir = simulate(t0, tmax, dt, model); std::vector vars = {"S", "E", "I", "R"}; printf("Number of time points :%d\n", static_cast(seir.get_num_time_points())); @@ -57,6 +57,6 @@ int main() dummy += seir.get_last_value()[k + (size_t)mio::oseir::InfectionState::Count * (int)i]; } - printf("\t %s_otal: %.0f\n", vars[k].c_str(), dummy); + printf("\t %s_Total: %.0f\n", vars[k].c_str(), dummy); } } diff --git a/cpp/examples/ode_seir_flows.cpp b/cpp/examples/ode_seir_flows.cpp index 9e3adf5a28..233b98b392 100644 --- a/cpp/examples/ode_seir_flows.cpp +++ b/cpp/examples/ode_seir_flows.cpp @@ -17,15 +17,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "memilio/config.h" -#include "memilio/utils/time_series.h" + #include "ode_seir/model.h" #include "ode_seir/infection_state.h" #include "ode_seir/parameters.h" #include "memilio/compartments/flow_simulation.h" #include "memilio/utils/logging.h" -#include #include int main() @@ -38,7 +36,7 @@ int main() mio::log_info("Simulating SEIR; t={} ... {} with dt = {}.", t0, tmax, dt); - mio::oseir::Model model(1); + mio::oseir::Model model(1); constexpr double total_population = 10000; model.populations[{mio::AgeGroup(0), mio::oseir::InfectionState::Exposed}] = 100; @@ -47,11 +45,12 @@ int main() model.populations.set_difference_from_group_total( {mio::AgeGroup(0), mio::oseir::InfectionState::Susceptible}, total_population); - model.parameters.set(5.2); - model.parameters.set(6); - model.parameters.set(0.04); + model.parameters.set>(5.2); + model.parameters.set>(6); + model.parameters.set>(0.04); - mio::ContactMatrixGroup& contact_matrix = model.parameters.get().get_cont_freq_mat(); + mio::ContactMatrixGroup& contact_matrix = + model.parameters.get>().get_cont_freq_mat(); contact_matrix[0].get_baseline().setConstant(10); model.check_constraints(); diff --git a/cpp/examples/ode_sir.cpp b/cpp/examples/ode_sir.cpp index 4b6769c5a5..e4f0df32bb 100644 --- a/cpp/examples/ode_sir.cpp +++ b/cpp/examples/ode_sir.cpp @@ -19,63 +19,47 @@ */ #include "memilio/compartments/simulation.h" +#include "memilio/config.h" #include "memilio/math/euler.h" +#include "memilio/math/integrator.h" #include "memilio/utils/logging.h" #include "ode_sir/infection_state.h" #include "ode_sir/model.h" #include "ode_sir/parameters.h" -#include -#include +#include int main() { mio::set_log_level(mio::LogLevel::debug); - double t0 = 0.; - double tmax = 50.; - double dt = 0.1; + ScalarType t0 = 0.; + ScalarType tmax = 50.; + ScalarType dt = 0.1; - double total_population = 1061000; + ScalarType total_population = 1061000; mio::log_info("Simulating SIR; t={} ... {} with dt = {}.", t0, tmax, dt); - mio::osir::Model model(1); + mio::osir::Model model(1); model.populations[{mio::AgeGroup(0), mio::osir::InfectionState::Infected}] = 1000; model.populations[{mio::AgeGroup(0), mio::osir::InfectionState::Recovered}] = 1000; model.populations[{mio::AgeGroup(0), mio::osir::InfectionState::Susceptible}] = total_population - model.populations[{mio::AgeGroup(0), mio::osir::InfectionState::Infected}] - model.populations[{mio::AgeGroup(0), mio::osir::InfectionState::Recovered}]; - model.parameters.set(2); - model.parameters.set(0.5); + model.parameters.set>(2); + model.parameters.set>(0.5); - mio::ContactMatrixGroup& contact_matrix = model.parameters.get().get_cont_freq_mat(); + mio::ContactMatrixGroup& contact_matrix = + model.parameters.get>().get_cont_freq_mat(); contact_matrix[0].get_baseline().setConstant(2.7); contact_matrix[0].add_damping(0.6, mio::SimulationTime(12.5)); model.check_constraints(); - auto integrator = std::make_shared(); - auto sir = simulate(t0, tmax, dt, model, integrator); + std::shared_ptr> integrator = + std::make_shared>(); + auto sir = simulate(t0, tmax, dt, model, integrator); - bool print_to_terminal = true; - - if (print_to_terminal) { - std::vector vars = {"S", "I", "R"}; - printf("\n # t"); - for (size_t k = 0; k < (size_t)mio::osir::InfectionState::Count; k++) { - printf(" %s", vars[k].c_str()); - } - - auto num_points = static_cast(sir.get_num_time_points()); - for (size_t i = 0; i < num_points; i++) { - printf("\n%.14f ", sir.get_time(i)); - Eigen::VectorXd res_j = sir.get_value(i); - for (size_t j = 0; j < (size_t)mio::osir::InfectionState::Count; j++) { - printf(" %.14f", res_j[j]); - } - } - - Eigen::VectorXd res_j = sir.get_last_value(); - printf("number total: %f", res_j[0] + res_j[1] + res_j[2]); - } + sir.print_table({"S", "I", "R"}); + std::cout << "\nnumber total: " << sir.get_last_value().sum() << "\n"; } diff --git a/cpp/examples/ode_sir_ageres.cpp b/cpp/examples/ode_sir_ageres.cpp index 60e6b88e24..b84126261a 100644 --- a/cpp/examples/ode_sir_ageres.cpp +++ b/cpp/examples/ode_sir_ageres.cpp @@ -31,17 +31,17 @@ int main() model.populations.set_difference_from_group_total({i, mio::osir::InfectionState::Susceptible}, fact * nb_total_t0); - model.parameters.get()[i] = 2.0; - model.parameters.get()[i] = 0.3; + model.parameters.get>()[i] = 2.0; + model.parameters.get>()[i] = 0.3; } - mio::ContactMatrixGroup& contact_matrix = params.get(); + mio::ContactMatrixGroup& contact_matrix = params.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(num_groups, num_groups, fact * cont_freq)); contact_matrix.add_damping(Eigen::MatrixXd::Constant(num_groups, num_groups, 0.7), mio::SimulationTime(30.)); model.apply_constraints(); - mio::TimeSeries sir = simulate(t0, tmax, dt, model); + auto sir = simulate(t0, tmax, dt, model); std::vector vars = {"S", "I", "R"}; printf("Number of time points :%d\n", static_cast(sir.get_num_time_points())); @@ -56,6 +56,6 @@ int main() dummy += sir.get_last_value()[k + (size_t)mio::osir::InfectionState::Count * (int)i]; } - printf("\t %s_otal: %.0f\n", vars[k].c_str(), dummy); + printf("\t %s_Total: %.0f\n", vars[k].c_str(), dummy); } } \ No newline at end of file diff --git a/cpp/memilio/CMakeLists.txt b/cpp/memilio/CMakeLists.txt index 0bb0f81a88..fd24f11e8e 100644 --- a/cpp/memilio/CMakeLists.txt +++ b/cpp/memilio/CMakeLists.txt @@ -98,7 +98,7 @@ target_include_directories(memilio PUBLIC ) target_compile_features(memilio PUBLIC cxx_std_17) -target_link_libraries(memilio PUBLIC spdlog::spdlog Eigen3::Eigen Boost::boost Boost::filesystem Boost::disable_autolinking Random123) +target_link_libraries(memilio PUBLIC spdlog::spdlog Eigen3::Eigen Boost::boost Boost::filesystem Boost::disable_autolinking Random123 AD::AD) target_compile_options(memilio PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS} diff --git a/cpp/memilio/ad/CMakeLists.txt b/cpp/memilio/ad/CMakeLists.txt new file mode 100644 index 0000000000..e260bdcc7f --- /dev/null +++ b/cpp/memilio/ad/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.5) +project(AD CXX) + +add_library(AD INTERFACE) +add_library(AD::AD ALIAS AD) + +target_include_directories(AD INTERFACE + $ + $) + +target_link_libraries(AD INTERFACE spdlog::spdlog) + +### installation related stuff #### + + install(TARGETS AD + EXPORT ADConfig + LIBRARY DESTINATION lib COMPONENT AD + ARCHIVE DESTINATION lib COMPONENT AD + RUNTIME DESTINATION bin COMPONENT AD + INCLUDES DESTINATION include) + + install(EXPORT ADConfig + FILE ADConfig.cmake + NAMESPACE AD:: + DESTINATION lib/cmake/ADConfig + COMPONENT AD) + + + install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" + DESTINATION "include" + COMPONENT AD + ) + \ No newline at end of file diff --git a/cpp/memilio/ad/README.md b/cpp/memilio/ad/README.md new file mode 100644 index 0000000000..f4bffbe4b4 --- /dev/null +++ b/cpp/memilio/ad/README.md @@ -0,0 +1,3 @@ +# AD + +Algorithmic differentiation library by Uwe Naumann's group. See the book "The Art of Differentiating Computer Programs" by Uwe Naumann. diff --git a/cpp/memilio/ad/include/ad/ad.hpp b/cpp/memilio/ad/include/ad/ad.hpp new file mode 100644 index 0000000000..1492151261 --- /dev/null +++ b/cpp/memilio/ad/include/ad/ad.hpp @@ -0,0 +1,4165 @@ +/*---------------------------------------------------------------------------*\ + * Algorithmic Differentiation by Overloading in C++ + Copyright (C) 2021 Software and Tools for Computational Engineering (STCE) + RWTH Aachen University www.stce.rwth-aachen.de +\*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*\ +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#pragma once + +#ifndef AD_HPP +#define AD_HPP + +#define AD_VERSION_SHORT "AD v1.0" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#if !defined(_WIN32) +#include +#include +#include +#endif + +#if !defined(AD_DOXYGEN) & defined(_WIN32) + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include +#include + +#endif + +// for stce::timer + +#include +#include + +// define all DEPRECATED, to generate compiler-warnings, +// if a marked function is instantiated +// (only implemented for gnu compiler and visual C++) +#ifdef __GNUC__ +#define DEPRECATED __attribute__((deprecated)) +#else +// #pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define DEPRECATED +#endif + +#ifndef AD_DEFAULT_TAPE_SIZE +#define AD_DEFAULT_TAPE_SIZE 1024*1024*10 +#endif + +#define ADi_INLINEDEF inline + +typedef long int AD_TAPE_INT; +#define ADi_BASE_TYPE double + +#ifdef AD_DEBUG +# ifndef AD_TAPE_BOUNDS_CHECK +# define AD_TAPE_BOUNDS_CHECK +# endif +# define CHECK_OVERFLOW(x, a) assert(x < static_cast(std::numeric_limits::max()-a)) +#else +# define CHECK_OVERFLOW(x, a) +#endif + +// this macro enables a constructor to the type passed as argument +namespace ad { +template + struct ad_type_constructable_from { const static bool value = false; }; +} + +#define AD_ENABLE_TYPE_CONSTRUCTION_FROM(T) \ + namespace ad { \ + template \ + struct ad_type_constructable_from { \ + const static bool value = true; \ + typedef T2 type; \ + }; \ + } + +typedef long int AD_TAPE_INT; +namespace ad { + namespace operations { + templatestruct ad_add_aa { + templatestatic inline const AD_TAPE_REAL eval (const T1 &arg1, const T2 &arg2) { + return arg1._value() + arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return 1.0; + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return 1.0; + } + }; + templatestruct ad_sub_aa { + templatestatic inline const AD_TAPE_REAL eval (const T1 &arg1, const T2 &arg2) { + return arg1._value() - arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return 1.0; + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return -1.0; + } + }; + templatestruct ad_mul_aa { + templatestatic inline const AD_TAPE_REAL eval (const T1 &arg1, const T2 &arg2) { + return arg1._value() * arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return arg1._value(); + } + }; + templatestruct ad_div_aa { + templatestatic inline const AD_TAPE_REAL eval (const T1 &arg1, const T2 &arg2) { + return arg1._value() / arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return 1.0 / arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const T1 &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return -_value / arg2._value(); + } + }; + templatestruct ad_add_ap { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const AD_TAPE_REAL &arg2) { + return arg1._value() + arg2; + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const AD_TAPE_REAL &arg2 ) { + (void)_value; + (void)arg1; + (void)arg2; + return 1.0; + } + }; + templatestruct ad_add_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T2 &arg2) { + return arg1 + arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const AD_TAPE_REAL &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return 1.0; + } + }; + templatestruct ad_sub_ap { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const AD_TAPE_REAL &arg2) { + return arg1._value() - arg2; + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const AD_TAPE_REAL &arg2 ) { + (void)_value; + (void)arg1; + (void)arg2; + return 1.0; + } + }; + templatestruct ad_sub_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T2 &arg2) { + return arg1 - arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const AD_TAPE_REAL &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return -1.0; + } + }; + templatestruct ad_mul_ap { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const AD_TAPE_REAL &arg2) { + return arg1._value() * arg2; + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const AD_TAPE_REAL &arg2 ) { + (void)_value; + (void)arg1; + (void)arg2; + return arg2; + } + }; + templatestruct ad_mul_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T2 &arg2) { + return arg1 * arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const AD_TAPE_REAL &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return arg1; + } + }; + templatestruct ad_div_ap { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const AD_TAPE_REAL &arg2) { + return arg1._value() / arg2; + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL &_value, const T1 &arg1, const AD_TAPE_REAL &arg2 ) { + (void)_value; + (void)arg1; + (void)arg2; + return 1.0 / arg2; + } + }; + templatestruct ad_div_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T2 &arg2) { + return arg1 / arg2._value(); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL &_value, const AD_TAPE_REAL &arg1, const T2 &arg2 ) { + (void) _value; + (void)arg1; + (void)arg2; + return -_value / arg2._value(); + } + }; + using std::sin; + templatestruct ad_sin { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return sin(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (cos(x._value())); + } + }; + using std::cos; + templatestruct ad_cos { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return cos(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (-sin(x._value())); + } + }; + using std::tan; + templatestruct ad_tan { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return tan(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return ((1.0 + (tan(x._value())*tan(x._value())))); + } + }; + using std::cosh; + templatestruct ad_cosh { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return cosh(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (sinh(x._value())); + } + }; + using std::sinh; + templatestruct ad_sinh { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return sinh(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (cosh(x._value())); + } + }; + using std::asin; + templatestruct ad_asin { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return asin(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1 / sqrt(1.0 - x._value()*x._value())); + } + }; + using std::acos; + templatestruct ad_acos { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return acos(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (-1 / sqrt(1.0 - x._value()*x._value())); + } + }; + using std::exp; + templatestruct ad_exp { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return exp(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (exp(x._value())); + } + }; + using std::atan; + templatestruct ad_atan { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return atan(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1.0 / (1.0 + x._value()*x._value())); + } + }; + using std::tanh; + templatestruct ad_tanh { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return tanh(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1.0 - tanh(x._value())*tanh(x._value())); + } + }; + using std::sqrt; + templatestruct ad_sqrt { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return sqrt(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1.0/(2.0*sqrt(x._value() + (x._value() > 0 ? 0.0 : 1e-8)))); + } + }; + using std::log; + templatestruct ad_log { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return log(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1.0 / x._value()); + } + }; + using ::erf; + templatestruct ad_erf { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return erf(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (2.0 / sqrt(3.14159265358979323846264338327950288) * exp(-x._value() * x._value())); + } + }; + using ::erfc; + templatestruct ad_erfc { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return erfc(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (-2.0 / sqrt(3.14159265358979323846264338327950288) * exp(-x._value() * x._value())); + } + }; + using ::asinh; + templatestruct ad_asinh { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return asinh(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1. / sqrt(1. + (x._value()*x._value()))); + } + }; + using ::acosh; + templatestruct ad_acosh { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return acosh(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1. / sqrt((x._value()*x._value()) - 1.)); + } + }; + using ::expm1; + templatestruct ad_expm1 { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return expm1(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (exp(x._value())); + } + }; + using ::atanh; + templatestruct ad_atanh { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return atanh(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1. / (1. - (x._value()*x._value()))); + } + }; + using ::log1p; + templatestruct ad_log1p { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return log1p(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1.0 / (x._value() + 1)); + } + }; + using ::log10; + templatestruct ad_log10 { + templatestatic inline const AD_TAPE_REAL eval(const T &arg) { + return log10(arg._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &x) { + (void)_value; + return (1.0 / (x._value()*log(10))); + } + }; + templatestruct ad_minus { + templatestatic inline const AD_TAPE_REAL eval(const T &arg1) { + return -arg1._value(); + } + templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &arg1 ) { + (void)_value; + (void)arg1; + return -1.0; + } + }; + templatestruct ad_plus { + templatestatic inline const AD_TAPE_REAL eval(const T &arg1) { + return arg1._value(); + } + templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &arg1 ) { + (void)_value; + (void)arg1; + return 1.0; + } + }; + using ::fabs; + templatestruct ad_fabs { + templatestatic inline const AD_TAPE_REAL eval(const T &arg1) { + return fabs(arg1._value()); + } + templatestatic inline const AD_TAPE_REAL calc_partial(const AD_TAPE_REAL &_value, const T &arg1 ) { + (void) _value; + if (arg1._value() < 0) return -1.0; + else return 1.0; + } + }; + templatestruct ad_atan2_aa { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const T2 &arg2) { + (void) arg1; + (void) arg2; + return atan2(arg1._value(),arg2._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL _value, const T1 &arg1, const T2 &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return arg2._value() / (arg2._value() * arg2._value() + arg1._value() * arg1._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL _value, const T1 &arg1, const T2 &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return -arg1._value() / (arg2._value() * arg2._value() + arg1._value() * arg1._value()); + } + }; + templatestruct ad_atan2_ap { + templatestatic inline const AD_TAPE_REAL eval(const T &arg1, const AD_TAPE_REAL &arg2) { + (void) arg1; + (void) arg2; + return atan2(arg1._value(),arg2); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL _value, const T &arg1, const AD_TAPE_REAL &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return arg2 / (arg2 * arg2 + arg1._value() * arg1._value()); + } + }; + templatestruct ad_atan2_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T &arg2) { + (void) arg1; + (void) arg2; + return atan2(arg1,arg2._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL _value, const AD_TAPE_REAL &arg1, const T &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return -arg1 / (arg2._value() * arg2._value() + arg1 *arg1); + } + }; + template + struct ad_pow_aa { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const T2 &arg2) { + return pow(arg1._value(), arg2._value()); + } + templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL _value, const T1 &arg1, const T2 &arg2) { + (void)_value; + return arg2._value() * pow(arg1._value(), arg2._value() - 1.0); + } + templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL _value, const T1 &arg1, const T2 &arg2) { + (void) _value; + if (arg1 <= 0) + return 0; + else + return log(arg1._value()) * pow(arg1._value(), arg2._value()); + } + }; + template + struct ad_pow_ap { + templatestatic inline const AD_TAPE_REAL eval(const T &arg1, const AD_TAPE_REAL &arg2) { + return pow(arg1._value(), arg2); + } + templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL _value, const T &arg1, const AD_TAPE_REAL &arg2) { + (void) _value; + return arg2 * pow(arg1._value(), arg2 - 1.0); + } + }; + template + struct ad_pow_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T &arg2) { + return pow(arg1, arg2._value()); + } + templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL _value, const AD_TAPE_REAL &arg1, const T &arg2) { + (void) _value; + return log(arg1) * pow(arg1, arg2._value()); + } + }; + templatestruct ad_hypot_aa { + templatestatic inline const AD_TAPE_REAL eval(const T1 &arg1, const T2 &arg2) { + (void) arg1; + (void) arg2; + return hypot(arg1._value(),arg2._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL _value, const T1 &arg1, const T2 &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return arg1._value() / _value; + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL _value, const T1 &arg1, const T2 &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return arg2._value() / _value; + } + }; + templatestruct ad_hypot_ap { + templatestatic inline const AD_TAPE_REAL eval(const T &arg1, const AD_TAPE_REAL &arg2) { + (void) arg1; + (void) arg2; + return hypot(arg1._value(),arg2); + } templatestatic inline const AD_TAPE_REAL calc_partial1(const AD_TAPE_REAL _value, const T &arg1, const AD_TAPE_REAL &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return arg1._value() / _value; + } + }; + templatestruct ad_hypot_pa { + templatestatic inline const AD_TAPE_REAL eval(const AD_TAPE_REAL &arg1, const T &arg2) { + (void) arg1; + (void) arg2; + return hypot(arg1,arg2._value()); + } templatestatic inline const AD_TAPE_REAL calc_partial2(const AD_TAPE_REAL _value, const AD_TAPE_REAL &arg1, const T &arg2) { + (void) _value; + (void) arg1; + (void) arg2; + return arg2._value() / _value; + } + }; + } +} +namespace ad { + namespace helper { + template + struct type_identity { + typedef T type; + }; + } +} +namespace ad { + template + class reference_constructor_wrapper { + const TYPE &T; + public: + reference_constructor_wrapper(const TYPE &T_) : T(T_) {} + template + TO_CREATE *create() const { + return new TO_CREATE(T); + } + }; + template<> + class reference_constructor_wrapper { + public: + reference_constructor_wrapper(void *v) { + (void) v; + } + template + TO_CREATE *create() const { + return new TO_CREATE(); + } + }; +} +namespace ad { + namespace internal { + template struct unary_intermediate { + const AD_TAPE_REAL _value_; + const AD_ARG &_arg; + typedef AD_TAPE_REAL VALUE_TYPE; + typedef typename AD_ARG::DATA_TYPE DATA_TYPE; + explicit unary_intermediate(const AD_ARG &arg) : _value_(AD_OPERATION::eval(arg)), _arg(arg) { + } + inline const AD_TAPE_REAL &_value() const { + return _value_; + } + inline const AD_TAPE_REAL pval() const { + return AD_OPERATION::calc_partial(_value(), _arg); + } + }; + template struct binary_intermediate_aa { + AD_TAPE_REAL _value_; + const AD_ARG1 &_arg1; + const AD_ARG2 &_arg2; + typedef AD_TAPE_REAL VALUE_TYPE; + typedef typename AD_ARG1::DATA_TYPE DATA_TYPE; + binary_intermediate_aa(const AD_ARG1 &arg1, const AD_ARG2 &arg2) : + _value_(AD_OPERATION::eval(arg1, arg2)), + _arg1(arg1), + _arg2(arg2) { + } + inline const AD_TAPE_REAL pval1() const { + return AD_OPERATION::calc_partial1(_value(), _arg1, _arg2); + } + inline const AD_TAPE_REAL pval2() const { + return AD_OPERATION::calc_partial2(_value(), _arg1, _arg2); + } + inline const AD_TAPE_REAL &_value() const { + return _value_; + } + }; + template struct binary_intermediate_ap { + const AD_TAPE_REAL _value_; + const AD_ARG1 &_arg1; + const AD_TAPE_REAL _arg2; + typedef AD_TAPE_REAL VALUE_TYPE; + typedef typename AD_ARG1::DATA_TYPE DATA_TYPE; + binary_intermediate_ap(const AD_ARG1 &arg1, const AD_TAPE_REAL &arg2) : + _value_(AD_OPERATION::eval(arg1, arg2)), _arg1(arg1), _arg2(arg2) {} + inline const AD_TAPE_REAL &_value() const { + return _value_; + } + inline const AD_TAPE_REAL pval1() const { + return AD_OPERATION::calc_partial1(_value_, _arg1, _arg2); + } + }; + template struct binary_intermediate_pa { + const AD_TAPE_REAL _value_; + const AD_TAPE_REAL _arg1; + const AD_ARG2 &_arg2; + typedef AD_TAPE_REAL VALUE_TYPE; + typedef typename AD_ARG2::DATA_TYPE DATA_TYPE; + binary_intermediate_pa(const AD_TAPE_REAL &arg1, const AD_ARG2 &arg2) : + _value_(AD_OPERATION::eval(arg1, arg2)), _arg1(arg1), _arg2(arg2) {} + inline const AD_TAPE_REAL &_value() const { + return _value_; + } + inline const AD_TAPE_REAL pval2() const { + return AD_OPERATION::calc_partial2(_value_, _arg1, _arg2); + } + }; + template + struct passive_value_type_of { + typedef T TYPE; + }; + template struct active_type { + private: + AD_TAPE_REAL _value_; + DATA_HANDLER _data_; + public: + typedef AD_TAPE_REAL VALUE_TYPE; + typedef DATA_HANDLER DATA_TYPE; + typedef typename passive_value_type_of::TYPE PASSIVE_VALUE_TYPE; + inline const AD_TAPE_REAL &_value() const { + return _value_; + } + inline AD_TAPE_REAL &_value() { + return _value_; + } + inline const DATA_HANDLER &_data() const { + return _data_; + } + inline DATA_HANDLER &_data() { + return _data_; + } + inline void _clear() { + _data_.clear(); + } + + inline active_type(const active_type&) = default; + template::type> + inline active_type& operator=(const TYPE &val) { + _value_ = val; + _data_.clear(); + return *this; + } + template::type> + inline active_type(const TYPE &val) : + _value_(val) {} + + inline active_type() : _value_(static_cast(0.0)) {} + template + inline active_type(const active_type &val) : _value_(val) {} + inline active_type(const PASSIVE_VALUE_TYPE &val) : _value_(val) {} + inline active_type &operator = (const active_type &x) { + this->_value_ = x._value_; + this->_data_ = x._data_; + return *this; + } + inline active_type &operator =(const PASSIVE_VALUE_TYPE &vneu) { + this->_value_ = vneu; + this->_data_.clear(); + return *this; + } + template + inline active_type &operator =(const active_type &vneu) { + this->_value_ = vneu; + this->_data_.clear(); + return *this; + } + private: + template inline void build_from(const ad::internal::binary_intermediate_aa &x) { + DATA_HANDLER::handle(x, *this); + this->_value_ = x._value_; + } public: + template active_type(const ad::internal::binary_intermediate_aa &x) { + build_from(x); + } template inline active_type& operator=(const ad::internal::binary_intermediate_aa &x) { + build_from(x); + return *this; + } + private: + template inline void build_from(const ad::internal::binary_intermediate_ap &x) { + DATA_HANDLER::handle(x, *this); + this->_value_ = x._value_; + } public: + template active_type(const ad::internal::binary_intermediate_ap &x) { + build_from(x); + } template inline active_type& operator=(const ad::internal::binary_intermediate_ap &x) { + build_from(x); + return *this; + } + private: + template inline void build_from(const ad::internal::binary_intermediate_pa &x) { + DATA_HANDLER::handle(x, *this); + this->_value_ = x._value_; + } public: + template active_type(const ad::internal::binary_intermediate_pa &x) { + build_from(x); + } template inline active_type& operator=(const ad::internal::binary_intermediate_pa &x) { + build_from(x); + return *this; + } + private: + template inline void build_from(const ad::internal::unary_intermediate &x) { + DATA_HANDLER::handle(x, *this); + this->_value_ = x._value_; + } public: + template active_type(const ad::internal::unary_intermediate &x) { + build_from(x); + } template inline active_type& operator=(const ad::internal::unary_intermediate &x) { + build_from(x); + return *this; + } + template inline active_type& operator += (const active_type &x) { + *this = *this + x; + return *this; + } template inline active_type& operator += (const ad::internal::binary_intermediate_aa &x) { + *this = *this + x; + return *this; + } template inline active_type& operator += (const ad::internal::binary_intermediate_ap &x) { + *this = *this + x; + return *this; + } template inline active_type& operator += (const ad::internal::binary_intermediate_pa &x) { + *this = *this + x; + return *this; + } template inline active_type& operator += (const ad::internal::unary_intermediate &x) { + *this = *this + x; + return *this; + } inline active_type& operator += (const AD_TAPE_REAL &x) { + this->_value() += x; + return *this; + } + template inline active_type& operator -= (const active_type &x) { + *this = *this - x; + return *this; + } template inline active_type& operator -= (const ad::internal::binary_intermediate_aa &x) { + *this = *this - x; + return *this; + } template inline active_type& operator -= (const ad::internal::binary_intermediate_ap &x) { + *this = *this - x; + return *this; + } template inline active_type& operator -= (const ad::internal::binary_intermediate_pa &x) { + *this = *this - x; + return *this; + } template inline active_type& operator -= (const ad::internal::unary_intermediate &x) { + *this = *this - x; + return *this; + } inline active_type& operator -= (const AD_TAPE_REAL &x) { + this->_value() -= x; + return *this; + } + template inline active_type& operator *= (const active_type &x) { + *this = *this * x; + return *this; + } template inline active_type& operator *= (const ad::internal::binary_intermediate_aa &x) { + *this = *this * x; + return *this; + } template inline active_type& operator *= (const ad::internal::binary_intermediate_ap &x) { + *this = *this * x; + return *this; + } template inline active_type& operator *= (const ad::internal::binary_intermediate_pa &x) { + *this = *this * x; + return *this; + } template inline active_type& operator *= (const ad::internal::unary_intermediate &x) { + *this = *this * x; + return *this; + } inline active_type& operator *= (const AD_TAPE_REAL &x) { + *this = *this * x; + return *this; + } + template inline active_type& operator /= (const active_type &x) { + *this = *this / x; + return *this; + } template inline active_type& operator /= (const ad::internal::binary_intermediate_aa &x) { + *this = *this / x; + return *this; + } template inline active_type& operator /= (const ad::internal::binary_intermediate_ap &x) { + *this = *this / x; + return *this; + } template inline active_type& operator /= (const ad::internal::binary_intermediate_pa &x) { + *this = *this / x; + return *this; + } template inline active_type& operator /= (const ad::internal::unary_intermediate &x) { + *this = *this / x; + return *this; + } inline active_type& operator /= (const AD_TAPE_REAL &x) { + *this = *this / x; + return *this; + } + inline active_type &operator ++() { + ++this->_value_; + return *this; + } + inline active_type &operator --() { + --this->_value_; + return *this; + } + inline active_type operator ++(int) { + active_type ret(*this); + ++this->_value_; + return ret; + } + inline active_type operator --(int) { + active_type ret(*this); + --this->_value_; + return ret; + } + }; + template + struct passive_value_type_of > { + typedef typename passive_value_type_of::TYPE TYPE; + }; + + template ad::internal::unary_intermediate, ad::operations::ad_minus > operator -( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_minus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_minus > operator -( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_minus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_minus > operator -( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_minus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_minus > operator -( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_minus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_minus > operator -( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_minus >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_plus > operator +( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_plus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_plus > operator +( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_plus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_plus > operator +( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_plus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_plus > operator +( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_plus >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_plus > operator +( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_plus >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_sin > sin( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sin > sin( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sin > sin( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sin > sin( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sin > sin( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sin >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_cos > cos( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cos > cos( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cos > cos( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cos > cos( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cos > cos( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cos >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_tan > tan( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tan > tan( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tan > tan( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tan > tan( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tan > tan( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tan >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_cosh > cosh( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cosh > cosh( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cosh > cosh( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cosh > cosh( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_cosh > cosh( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_cosh >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_sinh > sinh( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sinh > sinh( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sinh > sinh( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sinh > sinh( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sinh > sinh( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sinh >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_asin > asin( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asin > asin( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asin > asin( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asin > asin( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asin >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asin > asin( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asin >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_acos > acos( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acos > acos( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acos > acos( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acos > acos( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acos >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acos > acos( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acos >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_exp > exp( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_exp >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_exp > exp( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_exp >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_exp > exp( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_exp >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_exp > exp( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_exp >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_exp > exp( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_exp >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_atan > atan( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atan > atan( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atan > atan( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atan > atan( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atan >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atan > atan( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atan >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_tanh > tanh( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tanh > tanh( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tanh > tanh( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tanh > tanh( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_tanh > tanh( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_tanh >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_sqrt > sqrt( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sqrt >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sqrt > sqrt( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sqrt >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sqrt > sqrt( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sqrt >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sqrt > sqrt( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sqrt >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_sqrt > sqrt( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_sqrt >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_log > log( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log > log( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log > log( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log > log( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log > log( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_erf > erf( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erf >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erf > erf( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erf >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erf > erf( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erf >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erf > erf( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erf >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erf > erf( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erf >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_erfc > erfc( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erfc >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erfc > erfc( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erfc >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erfc > erfc( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erfc >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erfc > erfc( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erfc >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_erfc > erfc( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_erfc >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_expm1 > expm1( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_expm1 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_expm1 > expm1( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_expm1 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_expm1 > expm1( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_expm1 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_expm1 > expm1( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_expm1 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_expm1 > expm1( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_expm1 >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_asinh > asinh( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asinh > asinh( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asinh > asinh( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asinh > asinh( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asinh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_asinh > asinh( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_asinh >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_acosh > acosh( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acosh > acosh( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acosh > acosh( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acosh > acosh( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acosh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_acosh > acosh( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_acosh >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_atanh > atanh( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atanh > atanh( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atanh > atanh( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atanh > atanh( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atanh >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_atanh > atanh( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_atanh >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_log1p > log1p( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log1p >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log1p > log1p( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log1p >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log1p > log1p( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log1p >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log1p > log1p( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log1p >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log1p > log1p( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log1p >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_log10 > log10( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log10 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log10 > log10( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log10 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log10 > log10( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log10 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log10 > log10( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log10 >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_log10 > log10( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_log10 >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_fabs > fabs( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > fabs( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > fabs( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > fabs( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > fabs( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } + template ad::internal::unary_intermediate, ad::operations::ad_fabs > abs( const ad::internal::active_type &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > abs( const ad::internal::binary_intermediate_aa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > abs( const ad::internal::binary_intermediate_ap &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > abs( const ad::internal::binary_intermediate_pa &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } template ad::internal::unary_intermediate, ad::operations::ad_fabs > abs( const ad::internal::unary_intermediate &x1) { + return ad::internal::unary_intermediate,ad::operations::ad_fabs >(x1); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_add_aa > operator + (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_add_aa > operator + (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa > operator + (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa > operator + (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa > operator + (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_add_aa > operator + (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_add_aa > operator + (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa > operator + (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa > operator + (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa > operator + (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa > operator + (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_add_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > operator + (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > >::type operator + (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > operator + (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > >::type operator + (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > operator + (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > >::type operator + (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > operator + (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > >::type operator + (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > operator + (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > >::type operator + (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > operator + (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > >::type operator + (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > operator + (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > >::type operator + (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > operator + (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > >::type operator + (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > operator + (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap > >::type operator + (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_add_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > operator + (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa > >::type operator + (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_add_pa >(x1,x2); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_sub_aa > operator - (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_sub_aa > operator - (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa > operator - (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa > operator - (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa > operator - (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_sub_aa > operator - (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_sub_aa > operator - (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa > operator - (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa > operator - (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa > operator - (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa > operator - (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_sub_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > operator - (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > >::type operator - (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > operator - (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > >::type operator - (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > operator - (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > >::type operator - (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > operator - (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > >::type operator - (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > operator - (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > >::type operator - (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > operator - (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > >::type operator - (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > operator - (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > >::type operator - (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > operator - (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > >::type operator - (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > operator - (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap > >::type operator - (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_sub_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > operator - (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa > >::type operator - (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_sub_pa >(x1,x2); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_mul_aa > operator * (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_mul_aa > operator * (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa > operator * (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa > operator * (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa > operator * (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_mul_aa > operator * (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_mul_aa > operator * (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa > operator * (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa > operator * (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa > operator * (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa > operator * (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_mul_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > operator * (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > >::type operator * (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > operator * (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > >::type operator * (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > operator * (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > >::type operator * (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > operator * (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > >::type operator * (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > operator * (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > >::type operator * (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > operator * (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > >::type operator * (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > operator * (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > >::type operator * (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > operator * (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > >::type operator * (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > operator * (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap > >::type operator * (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_mul_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > operator * (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa > >::type operator * (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_mul_pa >(x1,x2); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_div_aa > operator / (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_div_aa > operator / (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa > operator / (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa > operator / (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa > operator / (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_div_aa > operator / (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_div_aa > operator / (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa > operator / (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa > operator / (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa > operator / (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa > operator / (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_div_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > operator / (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > >::type operator / (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > operator / (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > >::type operator / (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > operator / (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > >::type operator / (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > operator / (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > >::type operator / (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > operator / (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > >::type operator / (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > operator / (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > >::type operator / (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > operator / (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > >::type operator / (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > operator / (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > >::type operator / (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > operator / (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap > >::type operator / (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_div_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > operator / (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa > >::type operator / (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_div_pa >(x1,x2); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_atan2_aa > atan2 (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_atan2_aa > atan2 (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa > atan2 (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_atan2_aa > atan2 (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_atan2_aa > atan2 (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa > atan2 (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa > atan2 (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > atan2 (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > >::type atan2 (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > atan2 (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > >::type atan2 (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > atan2 (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > >::type atan2 (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > atan2 (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > >::type atan2 (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > atan2 (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > >::type atan2 (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > atan2 (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > >::type atan2 (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > atan2 (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > >::type atan2 (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > atan2 (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > >::type atan2 (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > atan2 (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap > >::type atan2 (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_atan2_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > atan2 (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa > >::type atan2 (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_atan2_pa >(x1,x2); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_pow_aa > pow (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_pow_aa > pow (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa > pow (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa > pow (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa > pow (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_pow_aa > pow (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_pow_aa > pow (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa > pow (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa > pow (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa > pow (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa > pow (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_pow_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > pow (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > >::type pow (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > pow (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > >::type pow (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > pow (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > >::type pow (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > pow (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > >::type pow (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > pow (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > >::type pow (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > pow (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > >::type pow (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > pow (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > >::type pow (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > pow (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > >::type pow (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > pow (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap > >::type pow (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_pow_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > pow (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa > >::type pow (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_pow_pa >(x1,x2); + } + template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_hypot_aa > hypot (const ad::internal::active_type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_hypot_aa > hypot (const ad::internal::active_type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa > hypot (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa > hypot (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa > hypot (const ad::internal::active_type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_hypot_aa > hypot (const ad::internal::unary_intermediate &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_hypot_aa > hypot (const ad::internal::unary_intermediate &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa > hypot (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa > hypot (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa > hypot (const ad::internal::unary_intermediate &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_aa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_aa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_aa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_ap &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_ap &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_ap &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::active_type, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_pa &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::active_type, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::unary_intermediate, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_pa &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::unary_intermediate, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_aa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_aa, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa > hypot (const ad::internal::binary_intermediate_pa &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_aa,ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_aa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > hypot (const ad::internal::active_type &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > >::type hypot (const ad::internal::active_type &x1, const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > hypot (const typename ad::helper::type_identity::type &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::active_type::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > >::type hypot (const typename ad::internal::active_type::PASSIVE_VALUE_TYPE &x1, const ad::internal::active_type &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > hypot (const ad::internal::unary_intermediate &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > >::type hypot (const ad::internal::unary_intermediate &x1, const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > hypot (const typename ad::helper::type_identity::type &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > >::type hypot (const typename ad::internal::unary_intermediate::PASSIVE_VALUE_TYPE &x1, const ad::internal::unary_intermediate &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > hypot (const ad::internal::binary_intermediate_aa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > >::type hypot (const ad::internal::binary_intermediate_aa &x1, const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > hypot (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > >::type hypot (const typename ad::internal::binary_intermediate_aa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_aa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > hypot (const ad::internal::binary_intermediate_ap &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > >::type hypot (const ad::internal::binary_intermediate_ap &x1, const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > hypot (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > >::type hypot (const typename ad::internal::binary_intermediate_ap::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_ap &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > hypot (const ad::internal::binary_intermediate_pa &x1, const typename ad::helper::type_identity::type &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap > >::type hypot (const ad::internal::binary_intermediate_pa &x1, const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x2) { + return ad::internal::binary_intermediate_ap, ad::operations::ad_hypot_ap >(x1,x2); + } template ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > hypot (const typename ad::helper::type_identity::type &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } template typename std::enable_if::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE>::value, ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa > >::type hypot (const typename ad::internal::binary_intermediate_pa::PASSIVE_VALUE_TYPE &x1, const ad::internal::binary_intermediate_pa &x2) { + return ad::internal::binary_intermediate_pa, ad::operations::ad_hypot_pa >(x1,x2); + } + template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::active_type& x2) ; + template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::active_type& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator == (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) ; + template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator == (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() == x2._value(); + } template static inline bool operator == (const ad::internal::active_type& x1, const double& x2); + template static inline bool operator == (const ad::internal::active_type& x1, const double& x2) { + return x1._value() == x2; + } template static inline bool operator == (const double& x1, const ad::internal::active_type& x2); + template static inline bool operator == (const double& x1, const ad::internal::active_type& x2) { + return x1 == x2._value(); + } template static inline bool operator == (const ad::internal::unary_intermediate& x1, const double& x2); + template static inline bool operator == (const ad::internal::unary_intermediate& x1, const double& x2) { + return x1._value() == x2; + } template static inline bool operator == (const double& x1, const ad::internal::unary_intermediate& x2); + template static inline bool operator == (const double& x1, const ad::internal::unary_intermediate& x2) { + return x1 == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const double& x2); + template static inline bool operator == (const ad::internal::binary_intermediate_aa& x1, const double& x2) { + return x1._value() == x2; + } template static inline bool operator == (const double& x1, const ad::internal::binary_intermediate_aa& x2); + template static inline bool operator == (const double& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1 == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const double& x2); + template static inline bool operator == (const ad::internal::binary_intermediate_ap& x1, const double& x2) { + return x1._value() == x2; + } template static inline bool operator == (const double& x1, const ad::internal::binary_intermediate_ap& x2); + template static inline bool operator == (const double& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1 == x2._value(); + } template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const double& x2); + template static inline bool operator == (const ad::internal::binary_intermediate_pa& x1, const double& x2) { + return x1._value() == x2; + } template static inline bool operator == (const double& x1, const ad::internal::binary_intermediate_pa& x2); + template static inline bool operator == (const double& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1 == x2._value(); + } + template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::active_type& x2) ; + template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::active_type& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator != (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) ; + template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator != (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() != x2._value(); + } template static inline bool operator != (const ad::internal::active_type& x1, const double& x2); + template static inline bool operator != (const ad::internal::active_type& x1, const double& x2) { + return x1._value() != x2; + } template static inline bool operator != (const double& x1, const ad::internal::active_type& x2); + template static inline bool operator != (const double& x1, const ad::internal::active_type& x2) { + return x1 != x2._value(); + } template static inline bool operator != (const ad::internal::unary_intermediate& x1, const double& x2); + template static inline bool operator != (const ad::internal::unary_intermediate& x1, const double& x2) { + return x1._value() != x2; + } template static inline bool operator != (const double& x1, const ad::internal::unary_intermediate& x2); + template static inline bool operator != (const double& x1, const ad::internal::unary_intermediate& x2) { + return x1 != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const double& x2); + template static inline bool operator != (const ad::internal::binary_intermediate_aa& x1, const double& x2) { + return x1._value() != x2; + } template static inline bool operator != (const double& x1, const ad::internal::binary_intermediate_aa& x2); + template static inline bool operator != (const double& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1 != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const double& x2); + template static inline bool operator != (const ad::internal::binary_intermediate_ap& x1, const double& x2) { + return x1._value() != x2; + } template static inline bool operator != (const double& x1, const ad::internal::binary_intermediate_ap& x2); + template static inline bool operator != (const double& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1 != x2._value(); + } template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const double& x2); + template static inline bool operator != (const ad::internal::binary_intermediate_pa& x1, const double& x2) { + return x1._value() != x2; + } template static inline bool operator != (const double& x1, const ad::internal::binary_intermediate_pa& x2); + template static inline bool operator != (const double& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1 != x2._value(); + } + template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::active_type& x2) ; + template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::active_type& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator < (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) ; + template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator < (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() < x2._value(); + } template static inline bool operator < (const ad::internal::active_type& x1, const double& x2); + template static inline bool operator < (const ad::internal::active_type& x1, const double& x2) { + return x1._value() < x2; + } template static inline bool operator < (const double& x1, const ad::internal::active_type& x2); + template static inline bool operator < (const double& x1, const ad::internal::active_type& x2) { + return x1 < x2._value(); + } template static inline bool operator < (const ad::internal::unary_intermediate& x1, const double& x2); + template static inline bool operator < (const ad::internal::unary_intermediate& x1, const double& x2) { + return x1._value() < x2; + } template static inline bool operator < (const double& x1, const ad::internal::unary_intermediate& x2); + template static inline bool operator < (const double& x1, const ad::internal::unary_intermediate& x2) { + return x1 < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const double& x2); + template static inline bool operator < (const ad::internal::binary_intermediate_aa& x1, const double& x2) { + return x1._value() < x2; + } template static inline bool operator < (const double& x1, const ad::internal::binary_intermediate_aa& x2); + template static inline bool operator < (const double& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1 < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const double& x2); + template static inline bool operator < (const ad::internal::binary_intermediate_ap& x1, const double& x2) { + return x1._value() < x2; + } template static inline bool operator < (const double& x1, const ad::internal::binary_intermediate_ap& x2); + template static inline bool operator < (const double& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1 < x2._value(); + } template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const double& x2); + template static inline bool operator < (const ad::internal::binary_intermediate_pa& x1, const double& x2) { + return x1._value() < x2; + } template static inline bool operator < (const double& x1, const ad::internal::binary_intermediate_pa& x2); + template static inline bool operator < (const double& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1 < x2._value(); + } + template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::active_type& x2) ; + template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::active_type& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator <= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) ; + template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() <= x2._value(); + } template static inline bool operator <= (const ad::internal::active_type& x1, const double& x2); + template static inline bool operator <= (const ad::internal::active_type& x1, const double& x2) { + return x1._value() <= x2; + } template static inline bool operator <= (const double& x1, const ad::internal::active_type& x2); + template static inline bool operator <= (const double& x1, const ad::internal::active_type& x2) { + return x1 <= x2._value(); + } template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const double& x2); + template static inline bool operator <= (const ad::internal::unary_intermediate& x1, const double& x2) { + return x1._value() <= x2; + } template static inline bool operator <= (const double& x1, const ad::internal::unary_intermediate& x2); + template static inline bool operator <= (const double& x1, const ad::internal::unary_intermediate& x2) { + return x1 <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const double& x2); + template static inline bool operator <= (const ad::internal::binary_intermediate_aa& x1, const double& x2) { + return x1._value() <= x2; + } template static inline bool operator <= (const double& x1, const ad::internal::binary_intermediate_aa& x2); + template static inline bool operator <= (const double& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1 <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const double& x2); + template static inline bool operator <= (const ad::internal::binary_intermediate_ap& x1, const double& x2) { + return x1._value() <= x2; + } template static inline bool operator <= (const double& x1, const ad::internal::binary_intermediate_ap& x2); + template static inline bool operator <= (const double& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1 <= x2._value(); + } template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const double& x2); + template static inline bool operator <= (const ad::internal::binary_intermediate_pa& x1, const double& x2) { + return x1._value() <= x2; + } template static inline bool operator <= (const double& x1, const ad::internal::binary_intermediate_pa& x2); + template static inline bool operator <= (const double& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1 <= x2._value(); + } + template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::active_type& x2) ; + template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::active_type& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator > (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) ; + template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator > (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() > x2._value(); + } template static inline bool operator > (const ad::internal::active_type& x1, const double& x2); + template static inline bool operator > (const ad::internal::active_type& x1, const double& x2) { + return x1._value() > x2; + } template static inline bool operator > (const double& x1, const ad::internal::active_type& x2); + template static inline bool operator > (const double& x1, const ad::internal::active_type& x2) { + return x1 > x2._value(); + } template static inline bool operator > (const ad::internal::unary_intermediate& x1, const double& x2); + template static inline bool operator > (const ad::internal::unary_intermediate& x1, const double& x2) { + return x1._value() > x2; + } template static inline bool operator > (const double& x1, const ad::internal::unary_intermediate& x2); + template static inline bool operator > (const double& x1, const ad::internal::unary_intermediate& x2) { + return x1 > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const double& x2); + template static inline bool operator > (const ad::internal::binary_intermediate_aa& x1, const double& x2) { + return x1._value() > x2; + } template static inline bool operator > (const double& x1, const ad::internal::binary_intermediate_aa& x2); + template static inline bool operator > (const double& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1 > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const double& x2); + template static inline bool operator > (const ad::internal::binary_intermediate_ap& x1, const double& x2) { + return x1._value() > x2; + } template static inline bool operator > (const double& x1, const ad::internal::binary_intermediate_ap& x2); + template static inline bool operator > (const double& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1 > x2._value(); + } template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const double& x2); + template static inline bool operator > (const ad::internal::binary_intermediate_pa& x1, const double& x2) { + return x1._value() > x2; + } template static inline bool operator > (const double& x1, const ad::internal::binary_intermediate_pa& x2); + template static inline bool operator > (const double& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1 > x2._value(); + } + template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::active_type& x2) ; + template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::active_type& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator >= (const ad::internal::active_type& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) ; + template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::active_type& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::active_type& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::active_type& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::active_type& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::unary_intermediate& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) ; + template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1._value() >= x2._value(); + } template static inline bool operator >= (const ad::internal::active_type& x1, const double& x2); + template static inline bool operator >= (const ad::internal::active_type& x1, const double& x2) { + return x1._value() >= x2; + } template static inline bool operator >= (const double& x1, const ad::internal::active_type& x2); + template static inline bool operator >= (const double& x1, const ad::internal::active_type& x2) { + return x1 >= x2._value(); + } template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const double& x2); + template static inline bool operator >= (const ad::internal::unary_intermediate& x1, const double& x2) { + return x1._value() >= x2; + } template static inline bool operator >= (const double& x1, const ad::internal::unary_intermediate& x2); + template static inline bool operator >= (const double& x1, const ad::internal::unary_intermediate& x2) { + return x1 >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const double& x2); + template static inline bool operator >= (const ad::internal::binary_intermediate_aa& x1, const double& x2) { + return x1._value() >= x2; + } template static inline bool operator >= (const double& x1, const ad::internal::binary_intermediate_aa& x2); + template static inline bool operator >= (const double& x1, const ad::internal::binary_intermediate_aa& x2) { + return x1 >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const double& x2); + template static inline bool operator >= (const ad::internal::binary_intermediate_ap& x1, const double& x2) { + return x1._value() >= x2; + } template static inline bool operator >= (const double& x1, const ad::internal::binary_intermediate_ap& x2); + template static inline bool operator >= (const double& x1, const ad::internal::binary_intermediate_ap& x2) { + return x1 >= x2._value(); + } template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const double& x2); + template static inline bool operator >= (const ad::internal::binary_intermediate_pa& x1, const double& x2) { + return x1._value() >= x2; + } template static inline bool operator >= (const double& x1, const ad::internal::binary_intermediate_pa& x2); + template static inline bool operator >= (const double& x1, const ad::internal::binary_intermediate_pa& x2) { + return x1 >= x2._value(); + } + template + static inline void reset_variable(ad::internal::active_type &x) { + double tmp = 0; + get(x, tmp); + x = tmp; + } + template + static inline std::istream &operator >> (std::istream &in, const ad::internal::active_type &x) { + AD_TAPE_REAL &tmp = const_cast(x._value()); + in >> tmp; + return in; + } + using std::ceil; + using std::floor; + using std::isfinite; + using std::isnan; + using std::isinf; + template static inline bool isnan(const ad::internal::active_type& x) { + return isnan(x._value()); + } template static inline bool isinf(const ad::internal::active_type& x) { + return isinf(x._value()); + } template static inline double ceil(const ad::internal::active_type& x) { + return ceil(x._value()); + } template static inline double floor(const ad::internal::active_type& x) { + return floor(x._value()); + } template static inline bool isfinite(const ad::internal::active_type& x) { + return isfinite(x._value()); + } + using std::ceil; + using std::floor; + using std::isfinite; + using std::isnan; + using std::isinf; + template static inline bool isnan(const ad::internal::binary_intermediate_aa& x) { + return isnan(x._value()); + } template static inline bool isinf(const ad::internal::binary_intermediate_aa& x) { + return isinf(x._value()); + } template static inline double ceil(const ad::internal::binary_intermediate_aa& x) { + return ceil(x._value()); + } template static inline double floor(const ad::internal::binary_intermediate_aa& x) { + return floor(x._value()); + } template static inline bool isfinite(const ad::internal::binary_intermediate_aa& x) { + return isfinite(x._value()); + } + using std::ceil; + using std::floor; + using std::isfinite; + using std::isnan; + using std::isinf; + template static inline bool isnan(const ad::internal::binary_intermediate_ap& x) { + return isnan(x._value()); + } template static inline bool isinf(const ad::internal::binary_intermediate_ap& x) { + return isinf(x._value()); + } template static inline double ceil(const ad::internal::binary_intermediate_ap& x) { + return ceil(x._value()); + } template static inline double floor(const ad::internal::binary_intermediate_ap& x) { + return floor(x._value()); + } template static inline bool isfinite(const ad::internal::binary_intermediate_ap& x) { + return isfinite(x._value()); + } + using std::ceil; + using std::floor; + using std::isfinite; + using std::isnan; + using std::isinf; + template static inline bool isnan(const ad::internal::binary_intermediate_pa& x) { + return isnan(x._value()); + } template static inline bool isinf(const ad::internal::binary_intermediate_pa& x) { + return isinf(x._value()); + } template static inline double ceil(const ad::internal::binary_intermediate_pa& x) { + return ceil(x._value()); + } template static inline double floor(const ad::internal::binary_intermediate_pa& x) { + return floor(x._value()); + } template static inline bool isfinite(const ad::internal::binary_intermediate_pa& x) { + return isfinite(x._value()); + } + using std::ceil; + using std::floor; + using std::isfinite; + using std::isnan; + using std::isinf; + template static inline bool isnan(const ad::internal::unary_intermediate& x) { + return isnan(x._value()); + } template static inline bool isinf(const ad::internal::unary_intermediate& x) { + return isinf(x._value()); + } template static inline double ceil(const ad::internal::unary_intermediate& x) { + return ceil(x._value()); + } template static inline double floor(const ad::internal::unary_intermediate& x) { + return floor(x._value()); + } template static inline bool isfinite(const ad::internal::unary_intermediate& x) { + return isfinite(x._value()); + } + template static inline std::ostream& operator << (std::ostream& out, const ad::internal::active_type& x) { + out << x._value(); + return out; + } + template static inline std::ostream& operator << (std::ostream& out, const ad::internal::binary_intermediate_aa& x) { + out << x._value(); + return out; + } + template static inline std::ostream& operator << (std::ostream& out, const ad::internal::binary_intermediate_ap& x) { + out << x._value(); + return out; + } + template static inline std::ostream& operator << (std::ostream& out, const ad::internal::binary_intermediate_pa& x) { + out << x._value(); + return out; + } + template static inline std::ostream& operator << (std::ostream& out, const ad::internal::unary_intermediate& x) { + out << x._value(); + return out; + } + } +} +namespace ad { + namespace internal { + template struct is_not_ad_type { + const static bool RET = true; + }; + template struct is_not_ad_type > { + const static bool RET=false; + }; + template struct is_not_ad_type > { + const static bool RET=false; + }; + template struct is_not_ad_type > { + const static bool RET=false; + }; + template struct is_not_ad_type > { + const static bool RET=false; + }; + template struct is_not_ad_type > { + const static bool RET=false; + }; + template + struct IF { + typedef Then RET; + }; + template + struct IF { + typedef Else RET; + }; + template struct + active_type_of { + typedef T RET; + }; + template struct active_type_of > { + typedef ad::internal::active_type< typename ad::internal::active_type::VALUE_TYPE, typename ad::internal::active_type::DATA_TYPE> RET; + }; + template struct active_type_of > { + typedef ad::internal::active_type< typename ad::internal::unary_intermediate::VALUE_TYPE, typename ad::internal::unary_intermediate::DATA_TYPE> RET; + }; + template struct active_type_of > { + typedef ad::internal::active_type< typename ad::internal::binary_intermediate_aa::VALUE_TYPE, typename ad::internal::binary_intermediate_aa::DATA_TYPE> RET; + }; + template struct active_type_of > { + typedef ad::internal::active_type< typename ad::internal::binary_intermediate_ap::VALUE_TYPE, typename ad::internal::binary_intermediate_ap::DATA_TYPE> RET; + }; + template struct active_type_of > { + typedef ad::internal::active_type< typename ad::internal::binary_intermediate_pa::VALUE_TYPE, typename ad::internal::binary_intermediate_pa::DATA_TYPE> RET; + }; + template + struct min_max_return_type { + typedef typename IF::RET, AD_ARG1, typename active_type_of::RET >::RET tmp_type; + typedef typename IF::RET, AD_ARG2, typename active_type_of::RET >::RET tmp_type2; + typedef typename IF::RET, tmp_type2, tmp_type>::RET ret_type1; + typedef typename IF::RET, AD_ARG1, ret_type1>::RET type; + }; + template static inline typename min_max_return_type, ad::internal::active_type >::type max(const ad::internal::active_type &a, const ad::internal::active_type &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::active_type >::type min(const ad::internal::active_type &a, const ad::internal::active_type &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type max(const ad::internal::active_type &a, const ad::internal::unary_intermediate &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type min(const ad::internal::active_type &a, const ad::internal::unary_intermediate &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type max(const ad::internal::active_type &a, const ad::internal::binary_intermediate_aa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type min(const ad::internal::active_type &a, const ad::internal::binary_intermediate_aa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type max(const ad::internal::active_type &a, const ad::internal::binary_intermediate_ap &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type min(const ad::internal::active_type &a, const ad::internal::binary_intermediate_ap &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type max(const ad::internal::active_type &a, const ad::internal::binary_intermediate_pa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type min(const ad::internal::active_type &a, const ad::internal::binary_intermediate_pa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::active_type >::type max(const ad::internal::unary_intermediate &a, const ad::internal::active_type &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::active_type >::type min(const ad::internal::unary_intermediate &a, const ad::internal::active_type &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type max(const ad::internal::unary_intermediate &a, const ad::internal::unary_intermediate &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type min(const ad::internal::unary_intermediate &a, const ad::internal::unary_intermediate &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type max(const ad::internal::unary_intermediate &a, const ad::internal::binary_intermediate_aa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type min(const ad::internal::unary_intermediate &a, const ad::internal::binary_intermediate_aa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type max(const ad::internal::unary_intermediate &a, const ad::internal::binary_intermediate_ap &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type min(const ad::internal::unary_intermediate &a, const ad::internal::binary_intermediate_ap &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type max(const ad::internal::unary_intermediate &a, const ad::internal::binary_intermediate_pa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type min(const ad::internal::unary_intermediate &a, const ad::internal::binary_intermediate_pa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::active_type >::type max(const ad::internal::binary_intermediate_aa &a, const ad::internal::active_type &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::active_type >::type min(const ad::internal::binary_intermediate_aa &a, const ad::internal::active_type &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type max(const ad::internal::binary_intermediate_aa &a, const ad::internal::unary_intermediate &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type min(const ad::internal::binary_intermediate_aa &a, const ad::internal::unary_intermediate &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type max(const ad::internal::binary_intermediate_aa &a, const ad::internal::binary_intermediate_aa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type min(const ad::internal::binary_intermediate_aa &a, const ad::internal::binary_intermediate_aa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type max(const ad::internal::binary_intermediate_aa &a, const ad::internal::binary_intermediate_ap &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type min(const ad::internal::binary_intermediate_aa &a, const ad::internal::binary_intermediate_ap &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type max(const ad::internal::binary_intermediate_aa &a, const ad::internal::binary_intermediate_pa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type min(const ad::internal::binary_intermediate_aa &a, const ad::internal::binary_intermediate_pa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::active_type >::type max(const ad::internal::binary_intermediate_ap &a, const ad::internal::active_type &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::active_type >::type min(const ad::internal::binary_intermediate_ap &a, const ad::internal::active_type &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type max(const ad::internal::binary_intermediate_ap &a, const ad::internal::unary_intermediate &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type min(const ad::internal::binary_intermediate_ap &a, const ad::internal::unary_intermediate &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type max(const ad::internal::binary_intermediate_ap &a, const ad::internal::binary_intermediate_aa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type min(const ad::internal::binary_intermediate_ap &a, const ad::internal::binary_intermediate_aa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type max(const ad::internal::binary_intermediate_ap &a, const ad::internal::binary_intermediate_ap &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type min(const ad::internal::binary_intermediate_ap &a, const ad::internal::binary_intermediate_ap &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type max(const ad::internal::binary_intermediate_ap &a, const ad::internal::binary_intermediate_pa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type min(const ad::internal::binary_intermediate_ap &a, const ad::internal::binary_intermediate_pa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::active_type >::type max(const ad::internal::binary_intermediate_pa &a, const ad::internal::active_type &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::active_type >::type min(const ad::internal::binary_intermediate_pa &a, const ad::internal::active_type &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type max(const ad::internal::binary_intermediate_pa &a, const ad::internal::unary_intermediate &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::unary_intermediate >::type min(const ad::internal::binary_intermediate_pa &a, const ad::internal::unary_intermediate &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type max(const ad::internal::binary_intermediate_pa &a, const ad::internal::binary_intermediate_aa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_aa >::type min(const ad::internal::binary_intermediate_pa &a, const ad::internal::binary_intermediate_aa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type max(const ad::internal::binary_intermediate_pa &a, const ad::internal::binary_intermediate_ap &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_ap >::type min(const ad::internal::binary_intermediate_pa &a, const ad::internal::binary_intermediate_ap &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type max(const ad::internal::binary_intermediate_pa &a, const ad::internal::binary_intermediate_pa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, ad::internal::binary_intermediate_pa >::type min(const ad::internal::binary_intermediate_pa &a, const ad::internal::binary_intermediate_pa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, AD_TAPE_REAL>::type max(const ad::internal::active_type &a, const AD_TAPE_REAL &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, AD_TAPE_REAL>::type min(const ad::internal::active_type &a, const AD_TAPE_REAL &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, AD_TAPE_REAL>::type max(const ad::internal::unary_intermediate &a, const AD_TAPE_REAL &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, AD_TAPE_REAL>::type min(const ad::internal::unary_intermediate &a, const AD_TAPE_REAL &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, AD_TAPE_REAL>::type max(const ad::internal::binary_intermediate_aa &a, const AD_TAPE_REAL &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, AD_TAPE_REAL>::type min(const ad::internal::binary_intermediate_aa &a, const AD_TAPE_REAL &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, AD_TAPE_REAL>::type max(const ad::internal::binary_intermediate_ap &a, const AD_TAPE_REAL &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, AD_TAPE_REAL>::type min(const ad::internal::binary_intermediate_ap &a, const AD_TAPE_REAL &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type, AD_TAPE_REAL>::type max(const ad::internal::binary_intermediate_pa &a, const AD_TAPE_REAL &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type, AD_TAPE_REAL>::type min(const ad::internal::binary_intermediate_pa &a, const AD_TAPE_REAL &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type >::type max(const AD_TAPE_REAL &a, const ad::internal::active_type &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type >::type min(const AD_TAPE_REAL &a, const ad::internal::active_type &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type >::type max(const AD_TAPE_REAL &a, const ad::internal::unary_intermediate &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type >::type min(const AD_TAPE_REAL &a, const ad::internal::unary_intermediate &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type >::type max(const AD_TAPE_REAL &a, const ad::internal::binary_intermediate_aa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type >::type min(const AD_TAPE_REAL &a, const ad::internal::binary_intermediate_aa &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type >::type max(const AD_TAPE_REAL &a, const ad::internal::binary_intermediate_ap &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type >::type min(const AD_TAPE_REAL &a, const ad::internal::binary_intermediate_ap &b) { + if (a < b) return a; + else return b; + } + template static inline typename min_max_return_type >::type max(const AD_TAPE_REAL &a, const ad::internal::binary_intermediate_pa &b) { + if (a > b) return a; + else return b; + } template static inline typename min_max_return_type >::type min(const AD_TAPE_REAL &a, const ad::internal::binary_intermediate_pa &b) { + if (a < b) return a; + else return b; + } + } + + +} + + +namespace ad { + namespace internal { + template + struct ts_data { + typedef AD_TAPE_REAL DERIVATIVE_T; + AD_TAPE_REAL tlm; + ts_data() : tlm(0) {} + ts_data &operator = (const ts_data &b) { + tlm = b.tlm; + return *this; + } + inline void clear() { + tlm = 0; + } + inline const AD_TAPE_REAL &_derivative() const + { + (void) "adgt1v"; + return tlm; + } + inline AD_TAPE_REAL &_derivative() + { + (void) "adgt1v"; + return tlm; + } + template + static inline void handle(const AD_INTERMEDIATE &vneu, AD_ACTIVE_TYPE &target) { + ts_data &data = const_cast(target._data()); + data.tlm = get_tlm(vneu, 1.0); + } + template + static inline AD_TAPE_REAL get_tlm(const ad::internal::active_type &x, const AD_TAPE_REAL &pval) { + return x._data().tlm * pval; + } + template + static inline AD_TAPE_REAL get_tlm(const ad::internal::binary_intermediate_aa &x, const AD_TAPE_REAL &pval) { + return get_tlm(x._arg1, x.pval1() * pval) + get_tlm(x._arg2, x.pval2() * pval); + } + template + static inline AD_TAPE_REAL get_tlm(const ad::internal::unary_intermediate &x, const AD_TAPE_REAL &pval) { + return get_tlm(x._arg, x.pval() * pval); + } + template + static inline AD_TAPE_REAL get_tlm(const ad::internal::binary_intermediate_ap &x, const AD_TAPE_REAL &pval) { + return get_tlm(x._arg1, x.pval1() * pval); + } + template + static inline AD_TAPE_REAL get_tlm(const ad::internal::binary_intermediate_pa &x, const AD_TAPE_REAL &pval) { + return get_tlm(x._arg2, x.pval2() * pval); + } + typedef void DATA_TAPE_TYPE; + typedef AD_TAPE_INT TAPE_INDEX_TYPE; + inline void *_tape() const { + return NULL; + } + inline AD_TAPE_INT _tape_index() const { + return 0; + } + }; + } +} +namespace ad { + namespace internal { + class tape_options { + private: + AD_TAPE_INT _tapesize; + public: + tape_options() : _tapesize(AD_DEFAULT_TAPE_SIZE) { } + inline AD_TAPE_INT &tapesize() { + return _tapesize; + } + inline const AD_TAPE_INT &tapesize() const { + return _tapesize; + } + }; + } +} +namespace ad { + class exception { + public: + template static std_exception create(std::string error, std::string file = "", int line = 0) { + std::stringstream S; + S << "--- ad/c++ --- " << error; + if (file != "") S << " --- " << file << ":" << line << "."; + std::cout << "EXCEPTION thrown: " << S.str() << std::endl; + return std_exception(S.str()); + } + }; +} +namespace ad { + namespace internal { + template struct blob_tape; + } +/* + namespace helper { + template + class callback_object_base { + template friend struct ad::internal::blob_tape; + protected: + inline virtual ~callback_object_base() { + } + AD_TAPE *registered_tape; + public: + inline void set_tape(AD_TAPE *t) { + if (registered_tape != 0) return; + else registered_tape = t; + } + inline AD_TAPE *get_tape() { + return registered_tape; + } + inline callback_object_base() : registered_tape(0) { } + inline virtual double get_memory_size() { + return sizeof(AD_TAPE); + } + }; + } +} +*/ + + + namespace helper { + template + class callback_object_base { + template friend struct ad::internal::blob_tape; + protected: + inline virtual ~callback_object_base() { + } + AD_TAPE *registered_tape; + public: + inline void set_tape(AD_TAPE *t) { + if (registered_tape != 0) return; + else registered_tape = t; + } + inline AD_TAPE *get_tape() { + return registered_tape; + } + inline callback_object_base() : registered_tape(0) { } + inline virtual double get_memory_size() { + return sizeof(AD_TAPE); + } + }; + template + class userdata_object_base : public callback_object_base { + private: + class template_base_class { + public: + virtual ~template_base_class() {}; + virtual double size() = 0; + }; + template + class templated_base_class : public template_base_class { + public: + const X _data; + templated_base_class(const X &d) : _data(d) {} + const X &get_data() const { + return _data; + } + }; + template + class template_class : public templated_base_class { + public: + template_class(X data) : templated_base_class(data) {} + virtual ~template_class() { } + virtual double size() { + return sizeof(X); + } + }; + template + class template_vector_class : public templated_base_class { + public: + const int _n; + template_vector_class(const X *data, int n) : templated_base_class(new X[n]), _n(n) { + for (int i = 0; i < n; ++i) + this->_data[i] = data[i]; + } + template_vector_class(const X *data, const int inc, const int n) : templated_base_class(new X[n]), _n(n) { + for (int i = 0, idx = 0; i < n; ++i, idx += inc) + this->_data[i] = data[idx]; + } + virtual ~template_vector_class() { + delete [] this->_data; + } + virtual double size() { + return _n * sizeof(X); + } + }; + unsigned int cp_count; + std::vector checkpoint; + protected: + virtual ~userdata_object_base() { + for (unsigned int i = 0; i < checkpoint.size(); i++) + delete checkpoint[i]; + checkpoint.clear(); + } + public: + userdata_object_base(): callback_object_base(), cp_count(0) {} + inline virtual double get_memory_size() { + double S = callback_object_base::get_memory_size(); + for (unsigned int i = 0; i < checkpoint.size(); i++) + S += checkpoint[i]->size(); + return S; + } + template + inline void write_data(const X &cp) { + checkpoint.push_back(new template_class(cp)); + } + template + inline void write_data(const X *const cp, const int n) { + checkpoint.push_back(new template_vector_class(cp, n)); + } + template + inline void write_data(const X *const &cp, const int inc, const int n) { + checkpoint.push_back(new template_vector_class(cp, inc, n)); + } + template + inline const X &read_data() { + const X &cp = static_cast* >(checkpoint[cp_count])->get_data(); + ++cp_count; + if (static_cast(cp_count) == checkpoint.size()) cp_count = 0; + return cp; + } + }; + template + class external_adjoint_object_base : public userdata_object_base { + protected: + std::vector inputs; + std::vector outputs; + AD_TAPE_INT inputs_count; + AD_TAPE_INT outputs_count; + public: + inline size_t get_number_of_registered_inputs() { + return inputs.size(); + } + inline size_t get_number_of_registered_outputs() { + return outputs.size(); + } + public: + inline void check_tape(const AD_TYPE &x) { + if ((x._data()._tape() != 0) && (this->registered_tape != x._data()._tape())) + throw ad::exception::create("impossible binding tape - wrong tape in variable!"); + } + protected: + ~external_adjoint_object_base() { } + public: + external_adjoint_object_base(const std::pair &a): userdata_object_base(), + inputs_count(0), + outputs_count(0) { + inputs.reserve(a.first); + outputs.reserve(a.second); + } + external_adjoint_object_base(): userdata_object_base(), inputs_count(0), outputs_count(0) { + } + inline typename AD_TYPE::VALUE_TYPE register_input(const AD_TYPE &x) { + check_tape(x); + inputs.push_back(x._data()._tape_index()); + return x._value(); + } + inline void register_input(const AD_TYPE *const x, typename AD_TYPE::VALUE_TYPE *values, const int n) { + AD_TAPE_INT oldsize = inputs.size(); + inputs.resize(oldsize + n); + AD_TAPE_INT *pos = &inputs[oldsize]; + int i; + for (i = 0; i < n; ++i) { + check_tape(x[i]); + pos[i] = x[i]._data()._tape_index(); + values[i] = x[i]._value(); + } + } + inline void register_input(const std::vector &x, std::vector &values) { + assert(x.size() == values.size()); + register_input(&(x[0]), &(values[0]), x.size()); + } + inline std::vector register_input(const std::vector &x) { + std::vector values(x.size()); + register_input(x, values); + return values; + } + inline void register_output(AD_TYPE *actives, const size_t n) { + if (this->registered_tape == NULL) { + throw ad::exception::create("impossible binding output - no tape available"); + } else { + AD_TAPE_INT oldsize = outputs.size(); + outputs.resize(oldsize + n); + AD_TAPE_INT *outs = &outputs[ oldsize ]; + size_t startindex = 0; + typename AD_TAPE::TAPE_ENTRY *ins = this->registered_tape->_get_insert_ptr_range(n, startindex); + for (size_t i = 0; i < n; ++i) { + ins[i].arg = 0; + typename AD_TYPE::DATA_TYPE &data = actives[i]._data(); + data.register_variable(startindex + i, this->registered_tape); + outs[i] = static_cast(startindex + i); + } + } + } + inline void register_output(const typename AD_TYPE::VALUE_TYPE *const pvalues, AD_TYPE *actives, const size_t n) { + if (this->registered_tape == NULL) { + throw ad::exception::create("impossible binding output - no tape available"); + } else { + AD_TAPE_INT oldsize = outputs.size(); + outputs.resize(oldsize + n); + AD_TAPE_INT *outs = &outputs[ oldsize ]; + size_t startindex = 0; + typename AD_TAPE::TAPE_ENTRY *ins = this->registered_tape->_get_insert_ptr_range(n, startindex); + for (size_t i = 0; i < n; ++i) { + ins[i].arg = 0; + actives[i] = pvalues[i]; + typename AD_TYPE::DATA_TYPE &data = const_cast(actives[i]._data()); + data.register_variable(startindex + i, this->registered_tape); + outs[i] = static_cast(startindex + i); + } + } + } + inline void register_output(const std::vector &pvalues, std::vector &actives) { + assert(pvalues.size() == actives.size()); + register_output(&(pvalues[0]), &(actives[0]), pvalues.size()); + } + inline std::vector register_output(const std::vector &pvalues) { + std::vector actives(pvalues.size()); + register_output(pvalues, actives); + return actives; + } + inline void register_output(std::vector &actives) { + register_output(&(actives[0]), actives.size()); + } + inline AD_TYPE register_output(const typename AD_TYPE::VALUE_TYPE &py, AD_TAPE *tape = NULL) { + AD_TYPE y; + if (tape != NULL) { + if (this->registered_tape != NULL && this->registered_tape != tape) { + throw ad::exception::create("impossible binding output in external function (register_output) - tape of inputs and outputs differ!"); + } + this->registered_tape = tape; + } + if (this->registered_tape != NULL) { + y = py; + this->registered_tape->register_variable(y); + } else + throw ad::exception::create("impossible binding output in external function - no tape available"); + outputs.push_back(y._data()._tape_index()); + return y; + } + inline typename AD_TYPE::VALUE_TYPE get_output_adjoint() { + AD_TAPE_INT idx = outputs_count; + outputs_count++; + if (static_cast(outputs_count) == outputs.size()) + outputs_count = 0; + typename AD_TYPE::VALUE_TYPE back = 0; + back = this->registered_tape->_adjointEx(outputs[static_cast(idx)]); + return back; + } + inline void get_output_adjoint(typename AD_TYPE::VALUE_TYPE *buffer, const size_t n) { + AD_TAPE_INT idx = outputs_count; + for (size_t i = 0; i < n; ++i) { + buffer[i] = this->registered_tape->_adjoint(outputs[idx]); + idx++; + } + outputs_count += n; + if (static_cast(outputs_count) == outputs.size()) + outputs_count = 0; + } + inline void get_output_adjoint(std::vector &buffer) { + assert(buffer.size()); + get_output_adjoint(&(buffer[0]), buffer.size()); + } + inline void increment_input_adjoint(const typename AD_TYPE::VALUE_TYPE *const adj, const int n) { + for (int i = 0; i < n; ++i) { + this->registered_tape->_adjoint(inputs[inputs_count + i]) += adj[i]; + } + inputs_count += n; + if (static_cast(inputs_count) == inputs.size()) + inputs_count = 0; + } + inline void increment_input_adjoint(const std::vector &adj) { + assert(adj.size() != 0); + increment_input_adjoint(&(adj[0]), adj.size()); + } + inline bool all_adjoints_written() { + if (inputs_count == 0) return true; + else return false; + } + inline bool all_adjoints_read() { + if (outputs_count == 0) return true; + else return false; + } + inline void increment_input_adjoint(const typename AD_TYPE::VALUE_TYPE &adj) { + AD_TAPE_INT idx = inputs_count; + inputs_count++; + if (static_cast(inputs_count) == inputs.size()) + inputs_count = 0; + this->registered_tape->_adjointEx(inputs[static_cast(idx)]) += adj; + } + }; + } +} + +namespace ad { + template< typename T > struct trait_value { + typedef T RETURN_TYPE; + static inline RETURN_TYPE &value(T &value) { + return value; + } + }; + template struct trait_value > { + typedef typename ad::internal::active_type::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::active_type &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef const typename ad::internal::active_type::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::active_type &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef typename ad::internal::unary_intermediate::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::unary_intermediate &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef const typename ad::internal::unary_intermediate::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::unary_intermediate &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef typename ad::internal::binary_intermediate_aa::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::binary_intermediate_aa &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef const typename ad::internal::binary_intermediate_aa::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::binary_intermediate_aa &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef typename ad::internal::binary_intermediate_ap::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::binary_intermediate_ap &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef const typename ad::internal::binary_intermediate_ap::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::binary_intermediate_ap &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef typename ad::internal::binary_intermediate_pa::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::binary_intermediate_pa &value) { + return value._value(); + } + }; + template struct trait_value > { + typedef const typename ad::internal::binary_intermediate_pa::VALUE_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::binary_intermediate_pa &value) { + return value._value(); + } + }; + template + inline typename trait_value::RETURN_TYPE &value(T &x) { + return trait_value::value(x); + } + template + inline typename trait_value::RETURN_TYPE &value(const T &x) { + return trait_value::value(x); + } + template< typename T > struct trait_passive_value : trait_value {}; + template struct trait_passive_value > { + typedef typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::active_type &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef const typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::active_type &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::unary_intermediate &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef const typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::unary_intermediate &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::binary_intermediate_aa &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef const typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::binary_intermediate_aa &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::binary_intermediate_ap &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef const typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::binary_intermediate_ap &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(ad::internal::binary_intermediate_pa &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template struct trait_passive_value > { + typedef const typename trait_passive_value::VALUE_TYPE>::RETURN_TYPE RETURN_TYPE; + static inline RETURN_TYPE& value(const ad::internal::binary_intermediate_pa &x) { + return trait_passive_value::VALUE_TYPE>::value(ad::value(x)); + } + }; + template + inline typename trait_passive_value::RETURN_TYPE &passive_value(T &x) { + return trait_passive_value::value(x); + } + template + inline const typename trait_passive_value::RETURN_TYPE &passive_value(const T &x) { + return trait_passive_value::value(x); + } + template< typename T > struct trait_derivative { + typedef T RETURN_TYPE; + static inline RETURN_TYPE value(const T &vvalue) { + (void) vvalue; + return RETURN_TYPE(); + } + }; + template struct trait_derivative > { + typedef typename ad::internal::active_type::DATA_TYPE::DERIVATIVE_T& RETURN_TYPE; + static inline RETURN_TYPE value(ad::internal::active_type &value) { + return value._data()._derivative(); + } + }; + template struct trait_derivative > { + typedef typename ad::internal::active_type::DATA_TYPE::DERIVATIVE_T& RETURN_TYPE; + static inline RETURN_TYPE value(const ad::internal::active_type &value) { + return const_cast(value._data()._derivative()); + } + }; + template struct trait_derivative >; + template struct trait_derivative >; + template struct trait_derivative >; + template struct trait_derivative >; + template struct trait_derivative >; + template struct trait_derivative >; + template struct trait_derivative >; + template struct trait_derivative >; + template + inline typename trait_derivative::RETURN_TYPE derivative(T &x) { + return trait_derivative::value(x); + } + template + inline typename trait_derivative::RETURN_TYPE derivative(const T &x) { + return trait_derivative::value(x); + } + template< typename T > struct trait_tape_index { + typedef AD_TAPE_INT RETURN_TYPE; + static inline RETURN_TYPE value(const T &vvalue) { + (void) vvalue; + return 0; + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::active_type::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(ad::internal::active_type &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::active_type::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(const ad::internal::active_type &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::unary_intermediate::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(ad::internal::unary_intermediate &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::unary_intermediate::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(const ad::internal::unary_intermediate &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::binary_intermediate_aa::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(ad::internal::binary_intermediate_aa &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::binary_intermediate_aa::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(const ad::internal::binary_intermediate_aa &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::binary_intermediate_ap::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(ad::internal::binary_intermediate_ap &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::binary_intermediate_ap::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(const ad::internal::binary_intermediate_ap &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::binary_intermediate_pa::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(ad::internal::binary_intermediate_pa &value) { + return value._data()._tape_index(); + } + }; + template struct trait_tape_index > { + typedef typename ad::internal::binary_intermediate_pa::DATA_TYPE::TAPE_INDEX_TYPE RETURN_TYPE; + static inline RETURN_TYPE value(const ad::internal::binary_intermediate_pa &value) { + return value._data()._tape_index(); + } + }; + template + inline typename trait_tape_index::RETURN_TYPE tape_index(T &x) { + return trait_tape_index::value(x); + } + template + inline typename trait_tape_index::RETURN_TYPE tape_index(const T &x) { + return trait_tape_index::value(x); + } +} +namespace ad { + namespace internal { + template + struct blob_tape { + public: + struct TAPE_ENTRY { + AD_TAPE_INT arg; + AD_TAPE_REAL pval; + }; + struct position_t { + friend struct blob_tape; + private: + AD_TAPE_INT stackcounter; + AD_TAPE_INT progvarcounter; + position_t(const AD_TAPE_INT nstackcounter, const AD_TAPE_INT nprogvarcounter) : stackcounter(nstackcounter), progvarcounter(nprogvarcounter) {} + public: + position_t() : stackcounter(0), progvarcounter(0) {} + inline const AD_TAPE_INT &_stackcounter() const { + return stackcounter; + } + inline const AD_TAPE_INT &_progvarcounter() const { + return progvarcounter; + } + inline bool operator== (const position_t &other) const { + return _stackcounter() == other._stackcounter(); + } + inline bool operator> (const position_t &other) const { + return _stackcounter() > other._stackcounter(); + } + inline bool operator< (const position_t &other) const { + return _stackcounter() < other._stackcounter(); + } + }; + private: + TAPE_ENTRY *_topOfStack; + AD_TAPE_INT _progvarcounter; + AD_ADJOINT_REAL *_adjoints; + TAPE_ENTRY *_stack; + AD_TAPE_INT _stack_size; + AD_TAPE_INT _adjoint_size; + bool _isdead; + bool _isactive; + int _vecidx; + private: + ~blob_tape() { + reset(); + delete [] _stack; + delete [] _adjoints; + } + public: + blob_tape() : _topOfStack(0), _progvarcounter(0), _adjoints(0), _stack(0), _stack_size(0), _adjoint_size(0), _isdead(false), _isactive(false), _vecidx(0) { + } + public: + inline void _finish_current_insert_ptr(TAPE_ENTRY *const end) { + _topOfStack = end + 1; + } + inline TAPE_ENTRY *_get_insert_ptr(const int num_entries2fill, AD_TAPE_INT &new_tape_index) { + ; + _progvarcounter++; + new_tape_index = _progvarcounter; + TAPE_ENTRY *ret = _topOfStack; + _topOfStack += num_entries2fill; + return ret; + } + inline TAPE_ENTRY *_get_insert_ptr_range(const int num_entries2fill, AD_TAPE_INT &new_tape_index) { + new_tape_index = _progvarcounter + 1; + ; + _progvarcounter += num_entries2fill; + TAPE_ENTRY *ret = _topOfStack; + _topOfStack += num_entries2fill; + return ret; + } + public: + struct interpretation_settings; + private: + void _interpret_chunk(TAPE_ENTRY *start, TAPE_ENTRY *end, AD_TAPE_INT &progvaridx, const interpretation_settings &settings) { + TAPE_ENTRY *cur = start; + if (settings.zeroadjoints) { + while (cur != end) { + cur--; + AD_ADJOINT_REAL &adj = _adjoints[progvaridx]; + --progvaridx; + const int &edgecount = cur->arg; + for (int i = 0; i < edgecount; ++i) { + cur--; + _adjoints[cur->arg] += adj * cur->pval; + } + adj = 0; + } + } else { + while (cur != end) { + cur--; + AD_ADJOINT_REAL &adj = _adjoints[progvaridx]; + --progvaridx; + const int &edgecount = cur->arg; + for (int i = 0; i < edgecount; ++i) { + cur--; + _adjoints[cur->arg] += adj * cur->pval; + } + } + } + } + inline void _interpret_adjoint_internal_plain(const position_t &from, const position_t &to, const interpretation_settings &settings) { + AD_TAPE_INT progvaridx = from._progvarcounter(); + TAPE_ENTRY *start = _stack + from._stackcounter(); + TAPE_ENTRY *end = _stack + to._stackcounter(); + _interpret_chunk(start, end, progvaridx, settings); + } + inline void _zero_adjoints_internal(const position_t &from, const position_t &to) { + if (_adjoints == 0) return; + for (AD_TAPE_INT i = from._progvarcounter(); i > to._progvarcounter(); --i) { + _adjoints[i] = 0; + } + } + inline void _reset_to_internal(const position_t &to) { + _zero_adjoints_internal(get_position(), to); + _topOfStack = _stack + to._stackcounter(); + _progvarcounter = to._progvarcounter(); + } + public: + template + inline void _register_variables_internal(AD_ACTIVE *actives, const typename AD_ACTIVE::VALUE_TYPE *values, int *outs, const int n) { + TAPE_ENTRY *entries = _topOfStack; + ; + AD_TAPE_INT startidx = _progvarcounter + 1; + AD_TAPE_INT i; + typedef typename AD_ACTIVE::DATA_TYPE AD_DATA; + for (i = 0; i < n; ++i) { + entries[i].arg = 0; + if (values) actives[i] = values[i]; + if (outs) outs[i] = startidx + i; + AD_DATA &data = const_cast(actives[i]._data()); + data.register_variable(startidx + i, this); + } + _topOfStack += n; + ; + _progvarcounter += n; + } + inline position_t get_position() const { + return position_t(static_cast(_topOfStack - _stack), _progvarcounter); + } + inline AD_TAPE_REAL &_adjointEx(const size_t tape_index) { + AD_ADJOINT_REAL &adj = _adjoint(tape_index); + AD_TAPE_REAL *adjvec; + adjvec = reinterpret_cast(&adj); + return adjvec[_vecidx]; + } + inline AD_ADJOINT_REAL &_adjoint(const size_t tape_index) { + return _adjoints[tape_index]; + } + inline double get_checkpoint_memory_size() { + double checkpoint_size = 0; + for (AD_TAPE_INT i = 0; i < tape_callbacks.size(); i++) + checkpoint_size += tape_callbacks[i].userdata->get_memory_size(); + return checkpoint_size / 1024.0 / 1024.0; + } + inline size_t get_tape_memory_size() const { + return (get_position()._progvarcounter() * sizeof(AD_TAPE_REAL) + get_position()._stackcounter() * sizeof(TAPE_ENTRY)); + } + inline double get_allocated_tape_memory_size() const { + return ((_adjoint_size / 1024.0 / 1024.0) * sizeof(AD_TAPE_REAL) + (_stack_size / 1024.0 / 1024.0) * sizeof(TAPE_ENTRY)); + } + inline size_t _get_tape_memory() const { + return (((get_position()._progvarcounter()) * sizeof(AD_TAPE_REAL)) + ((get_position()._stackcounter()) * sizeof(TAPE_ENTRY))); + } + static blob_tape *create(tape_options options = tape_options()) { + return create(options.tapesize()); + } + static blob_tape *create(AD_TAPE_INT size, AD_TAPE_INT progvarcounter = 0) { + if (progvarcounter == 0) progvarcounter = size / 2; + blob_tape *ret = new blob_tape(); + ret->_stack = new TAPE_ENTRY[size + 1]; + ret->_topOfStack = ret->_stack; + ret->_adjoints = new AD_ADJOINT_REAL[progvarcounter + 1]; + for (AD_TAPE_INT i = 0; i <= progvarcounter; i++) + ret->_adjoints[i] = 0; + ret->_stack_size = size; + ret->_adjoint_size = progvarcounter; + ret->_isactive = true; + for (AD_TAPE_INT i = 0; i <= size; ++i) { + ret->_stack[i].arg = 0; + ret->_stack[i].pval = 0; + } + return ret; + } + static void remove(blob_tape *&tape) { + if (tape == 0) return; + delete tape; + tape = 0; + } + typedef ad::internal::blob_tape AD_TAPE_CLASS; + public: + struct interpretation_settings { + bool reset; + bool zeroadjoints; + interpretation_settings() : reset(false), zeroadjoints(false) {} + }; + typedef ad::helper::callback_object_base callback_object_t; + + template + class CALLBACK_DATA_POINTER { + public: + typedef void (*TAPE_CALLBACK_w_all_base)(AD_TAPE_CLASS &caller, const interpretation_settings &s, EXT_DATA *userdata); + typedef void (*TAPE_CALLBACK_w_tape_base)(AD_TAPE_CLASS &caller, EXT_DATA *userdata); + typedef void (*TAPE_CALLBACK_plain_base)(EXT_DATA *userdata); + }; + class CALLBACK_FCN_HANDLER_BASE { + public: + virtual void run_callback(AD_TAPE_CLASS &caller, const interpretation_settings &s, callback_object_t *userdata) = 0; + virtual ~CALLBACK_FCN_HANDLER_BASE() {}; + }; + template + class CALLBACK_FCN_HANDLER : public CALLBACK_FCN_HANDLER_BASE { + private: + union { + typename CALLBACK_DATA_POINTER::TAPE_CALLBACK_plain_base fcn; + typename CALLBACK_DATA_POINTER::TAPE_CALLBACK_w_tape_base fcn_w_tape; + typename CALLBACK_DATA_POINTER::TAPE_CALLBACK_w_all_base fcn_w_all; + } fcn; + int fcn_type_id; + public: + CALLBACK_FCN_HANDLER(typename CALLBACK_DATA_POINTER::TAPE_CALLBACK_plain_base fcn_) : fcn_type_id(0) { + fcn.fcn = fcn_; + } + CALLBACK_FCN_HANDLER(typename CALLBACK_DATA_POINTER::TAPE_CALLBACK_w_tape_base fcn_) : fcn_type_id(1) { + fcn.fcn_w_tape = fcn_; + } + CALLBACK_FCN_HANDLER(typename CALLBACK_DATA_POINTER::TAPE_CALLBACK_w_all_base fcn_) : fcn_type_id(2) { + fcn.fcn_w_all = fcn_; + } + void run_callback(AD_TAPE_CLASS &caller, const interpretation_settings &s, callback_object_t *userdata) { + EXT_DATA *casted_userdata = static_cast(userdata); + switch (fcn_type_id) { + case 0: + fcn.fcn(casted_userdata); + break; + case 1: + fcn.fcn_w_tape(caller, casted_userdata); + break; + case 2: + fcn.fcn_w_all(caller, s, casted_userdata); + break; + default: + throw ad::exception::create("unknown callback to run."); + break; + } + } + ~CALLBACK_FCN_HANDLER() {} + }; + class tape_callback { + callback_object_t *userdata; + CALLBACK_FCN_HANDLER_BASE *callback_handler; + position_t position; + public: + tape_callback() : userdata(0), + callback_handler(0) { } + template + void set_callback(FCN_CALLBACK fcn_) { + if (callback_handler) + throw ad::exception::create("currently not supported to insert external_adjoint_object_bases twice."); + callback_handler = new CALLBACK_FCN_HANDLER(fcn_); + } + callback_object_t *&_userdata() { + return userdata; + } + void free_userdata() { + delete userdata; + if (callback_handler) + delete callback_handler; + } + position_t &_position() { + return position; + } + void run_callback(AD_TAPE_CLASS &caller, const interpretation_settings &s) { + if (callback_handler) + callback_handler->run_callback(caller, s, userdata); + } + }; + std::vector tape_callbacks; + template + inline ext_fcn_data_type *create_callback_object(const FCN_PARAMETERS ¶meters) { + const reference_constructor_wrapper ref_wrapper(parameters); + tape_callback external_fcn; + tape_callbacks.push_back(external_fcn); + tape_callbacks.back()._position() = get_position(); + ext_fcn_data_type *userdata = ref_wrapper.template create(); + tape_callbacks.back()._userdata() = userdata; + userdata->set_tape(this); + return userdata; + } + template + inline ext_fcn_data_type *create_callback_object() { + void *dummy; + return create_callback_object(dummy); + } + template + inline void insert_callback(FCN_CALLBACK callback_handler, ext_fcn_data_type *D) { + if (tape_callbacks.back()._userdata() == D) { + tape_callbacks.back().template set_callback(callback_handler); + tape_callbacks.back()._position() = get_position(); + AD_TAPE_INT tmp = 0; + _get_insert_ptr(1, tmp)->arg = 0; + } else { + throw ad::exception::create("please always insert most recently created external function object."); + } + } + private: + inline void _reset_tape_callbacks_to(const position_t &to) { + for (int i = static_cast(tape_callbacks.size()) - 1; i >= 0; i--) { + size_t offset = static_cast(i); + if (tape_callbacks[offset]._position()._progvarcounter() > to._progvarcounter()) { + tape_callbacks[offset].free_userdata(); + tape_callbacks.pop_back(); + } else { + break; + } + } + } + private: + inline void _interpret_adjoint_internal(const position_t &from, const position_t &to, const interpretation_settings &settings) + { + if (from > get_position()) + throw ad::exception::create("you try to use a tape position outside of the current tape. error."); + _adjoint(static_cast(from._progvarcounter())); + int external_first = -1; + int external_count = 0; + for (int i = static_cast(tape_callbacks.size()) - 1; i >= 0; --i) { + size_t offset = static_cast(i); + if ((tape_callbacks[offset]._position()._progvarcounter() <= from._progvarcounter()) && + (tape_callbacks[offset]._position()._progvarcounter() >= to._progvarcounter())) { + if (external_first == -1) external_first = i; + ++external_count; + } + } + position_t myfrom = from; + position_t myto; + for (int i = external_first; external_count > 0; --external_count) { + size_t offset = static_cast(i); + myto = tape_callbacks[offset]._position(); + _interpret_adjoint_internal_plain(myfrom, myto, settings); + if (settings.reset) { + _reset_to_internal(myto); + AD_TAPE_INT nti; + TAPE_ENTRY *cur = _get_insert_ptr(1, nti); + (void) cur; + } + tape_callbacks[offset].run_callback(*this, settings); + if (settings.reset) { + _reset_to_internal(myto); + tape_callbacks[offset].free_userdata(); + tape_callbacks.pop_back(); + } + myfrom = myto; + --i; + } + _interpret_adjoint_internal_plain(myfrom, to, settings); + } + public: + inline bool is_active() { + return _isactive; + } + inline void switch_to_active() { + if (!_isactive) _isactive = true; + } + inline void switch_to_passive() { + if (_isactive) _isactive = false; + } + template + inline void register_variable(ad::internal::active_type &x) { + AD_TAPE_INT new_tape_index; + TAPE_ENTRY *cur = _get_insert_ptr(1, new_tape_index); + (void) cur; + cur->arg = 0; + DATA_HANDLER_1 &data = const_cast(x._data()); + data.register_variable(new_tape_index, this); + } + template + inline void register_variable(ad::internal::active_type &x, const typename ad::internal::active_type::VALUE_TYPE &v) { + x = v; + register_variable(x); + } + template + inline void register_variable(std::vector > &x) { + for (size_t i = 0; i < x.size(); i++) + register_variable(x[i]); + } + template + inline void register_variable(ad::internal::active_type *x, const int n, const typename ad::internal::active_type::VALUE_TYPE *const v) { + if (n == 0) return; + for (int i = 0; i < n; ++i) + register_variable(x[i], v[i]); + } + template + inline void register_variable(ad::internal::active_type *x, const size_t n) { + if (n == 0) return; + for (size_t i = 0; i < n; ++i) + register_variable(x[i]); + } + template + inline void register_output_variable(ad::internal::active_type &x) { + x = static_cast >(1.0) * x; + } + template + inline void register_output_variable(ad::internal::active_type *x, const size_t n) { + if (n == 0) return; + for (size_t i = 0; i < n; ++i) + x[i] = static_cast >(1.0) * x[i]; + } + template + inline void register_output_variable(std::vector > &x) { + for (size_t i = 0; i < x.size(); i++) + register_output_variable(x[i]); + } + inline void reset_to(const position_t &to) { + _reset_to_internal(to); + _reset_tape_callbacks_to(to); + } + inline void reset() { + reset_to(position_t()); + } + inline void interpret_adjoint() { + position_t to; + interpretation_settings settings; + _interpret_adjoint_internal(get_position(), to, settings); + } + inline void interpret_adjoint_to(const position_t &to) { + interpretation_settings settings; + if (to > get_position()) + throw ad::exception::create("adjoint interpretation: from < to.", "../build_files//../src/ad//ad_tape_interface_inc.hpp", 241); + else + _interpret_adjoint_internal(get_position(), to, settings); + } + inline void interpret_adjoint_from(const position_t &from) { + position_t to; + assert(!(from < to)); + interpretation_settings settings; + _interpret_adjoint_internal(from, to, settings); + } + inline void interpret_adjoint_from_to(const position_t &from, const position_t &to) { + interpretation_settings settings; + if (to > from) + throw ad::exception::create("adjoint interpretation: from < to.", "../build_files//../src/ad//ad_tape_interface_inc.hpp", 264); + else + _interpret_adjoint_internal(from, to, settings); + } + inline void interpret_adjoint_and_reset_to(const position_t &to) { + position_t from(get_position()); + interpretation_settings settings; + settings.reset = true; + settings.zeroadjoints = true; + _interpret_adjoint_internal(from, to, settings); + _reset_to_internal(to); + _reset_tape_callbacks_to(to); + } + inline void interpret_adjoint_and_zero_adjoints_to(const position_t &to) { + position_t from(get_position()); + interpretation_settings settings; + settings.reset = false; + settings.zeroadjoints = true; + _interpret_adjoint_internal(from, to, settings); + } + inline void interpret_adjoint_and_zero_adjoints_from_to(const position_t &from, const position_t &to) { + interpretation_settings settings; + settings.reset = false; + settings.zeroadjoints = true; + _interpret_adjoint_internal(from, to, settings); + } + inline void zero_adjoints() { + position_t to; + _zero_adjoints_internal(get_position(), to); + } + inline void zero_adjoints_to(const position_t &to) { + _zero_adjoints_internal(get_position(), to); + } + inline void zero_adjoints_from(const position_t &from) { + position_t to; + _zero_adjoints_internal(from, to); + } + inline void zero_adjoints_from_to(const position_t &from, const position_t &to) { + _zero_adjoints_internal(from, to); + } + struct handler_base { + protected: + template + static inline int _get_edge_count(const ad::internal::active_type &x) { + return x._data()._edgecount(); + } + template + static inline int _get_edge_count(const ad::internal::binary_intermediate_aa &x) { + return _get_edge_count(x._arg1) + _get_edge_count(x._arg2); + } + template + static inline int _get_edge_count(const ad::internal::unary_intermediate &x) { + return _get_edge_count(x._arg); + } + template + static inline int _get_edge_count(const ad::internal::binary_intermediate_ap &x) { + return _get_edge_count(x._arg1); + } + template + static inline int _get_edge_count(const ad::internal::binary_intermediate_pa &x) { + return _get_edge_count(x._arg2); + } + struct tapehandler { + TAPE_ENTRY *_ins_ptr; + template + tapehandler(TAPE_ENTRY *ins_ptr, const int edgecount, AD_INTERMEDIATE vneu) : _ins_ptr(ins_ptr) { + interpret(vneu, 1.0); + _ins_ptr->arg = edgecount; + } + template + inline void interpret(const ad::internal::active_type &x, const AD_TAPE_REAL &pval) { + if (x._data()._tape_index() != 0) { + _ins_ptr->arg = x._data()._tape_index(); + _ins_ptr->pval = pval; + ++_ins_ptr; + } + } + template + inline void interpret(const ad::internal::binary_intermediate_aa &x, const AD_TAPE_REAL &pval) { + this->interpret(x._arg1, x.pval1()*pval); + this->interpret(x._arg2, x.pval2()*pval); + } + template + inline void interpret(const ad::internal::unary_intermediate &x, const AD_TAPE_REAL &pval) { + this->interpret(x._arg, x.pval() * pval); + } + template + inline void interpret(const ad::internal::binary_intermediate_ap &x, const AD_TAPE_REAL &pval) { + this->interpret(x._arg1, x.pval1()*pval); + } + template + inline void interpret(const ad::internal::binary_intermediate_pa &x, const AD_TAPE_REAL &pval) { + this->interpret(x._arg2, x.pval2()*pval); + } + }; + }; + template + struct single_tape_data : handler_base { + typedef AD_TAPE_CLASS DATA_TAPE_TYPE; + typedef const AD_TAPE_INT &TAPE_INDEX_TYPE; + typedef AD_ADJOINT_REAL DERIVATIVE_T; + AD_TAPE_INT _tape_index_; + public: + single_tape_data() : _tape_index_(0) {} + inline void clear() { + _tape_index_ = 0; + } + inline const AD_ADJOINT_REAL &_derivative() const { + return _adjoint(); + } + inline AD_ADJOINT_REAL &_derivative() { + return _adjoint(); + } + inline AD_ADJOINT_REAL &_adjoint() const { + return global_tape->_adjoint(_tape_index_); + } + inline bool _is_registered() const { + return _tape_index_ == 0 ? false : true; + } + inline AD_TAPE_INT &_tape_index() { + return _tape_index_; + } + inline const AD_TAPE_INT &_tape_index() const { + return _tape_index_; + } + inline int _edgecount() const { + return _tape_index_ == 0 ? 0 : 1; + } + inline void register_variable(AD_TAPE_INT new_tape_index, AD_TAPE_CLASS *tape) { + (void) tape; + _tape_index_ = new_tape_index; + } + template + static inline void handle(const AD_INTERMEDIATE &vneu, AD_ACTIVE_TYPE &target) { + int edgecount = handler_base::_get_edge_count(vneu); + if (edgecount > 0) { + if (NULL != global_tape && !global_tape->is_active()) { + single_tape_data &data = const_cast(target._data()); + data.clear(); + return; + } + AD_TAPE_INT newTapeIndex; + typename AD_TAPE_CLASS::TAPE_ENTRY *ins_ptr = global_tape->_get_insert_ptr(edgecount + 1, newTapeIndex); + if (ins_ptr != 0) { + typename handler_base::tapehandler tmp(ins_ptr, edgecount, vneu); + } + single_tape_data &data = const_cast(target._data()); + data._tape_index_ = newTapeIndex; + } else { + single_tape_data &data = const_cast(target._data()); + data.clear(); + } + } + static inline AD_TAPE_CLASS *_tape() { + return global_tape; + } + inline void _set_tape(AD_TAPE_CLASS *T) { + (void) T; + } + }; + }; + } +} +namespace ad { + template + class gvalue { + public: + typedef VALUE_T value_t; + typedef VALUE_T active_t; + typedef VALUE_T passive_t; + typedef VALUE_T type; + typedef void derivative_t; + typedef void tape_t; + static const bool is_ad_type = false; + static const bool is_adjoint_type = false; + static const bool is_tangent_type = false; + static const int order = 0; + }; + template + struct mode : public ad::gvalue {}; + + template + class gt1s { + public: + typedef T value_t; + typedef T derivative_t; + typedef typename mode::passive_t passive_t; + typedef ad::internal::ts_data _data; + typedef ad::internal::active_type type; + typedef void tape_t; + static const bool is_ad_type = true; + static const bool is_adjoint_type = false; + static const bool is_tangent_type = true; + static const int order = ad::mode::order + 1; + }; + template + class ga1s { + public: + typedef T value_t; + typedef T derivative_t; + typedef typename mode::passive_t passive_t; + typedef ad::internal::blob_tape tape_t; + static tape_t *global_tape; + typedef typename tape_t::template single_tape_data _data; + typedef ad::internal::active_type type; + typedef ad::internal::tape_options tape_options_t; + typedef ad::helper::callback_object_base callback_object_t; + typedef ad::helper::userdata_object_base userdata_object_t; + typedef ad::helper::external_adjoint_object_base external_adjoint_object_t; + typedef external_adjoint_object_t efo_t; + static const bool is_ad_type = true; + static const bool is_adjoint_type = true; + static const bool is_tangent_type = false; + static const int order = ad::mode::order + 1; + }; + template typename ga1s::tape_t *ga1s::global_tape; +} +namespace ad { + template + static size_t size_of(const tape_t *tape) { + return tape->_get_tape_memory(); + } + template + struct mode::_data> > : public ad::gt1s {}; + template + struct mode::_data> > : public ad::ga1s {}; +} + +#endif + diff --git a/cpp/memilio/compartments/compartmentalmodel.h b/cpp/memilio/compartments/compartmentalmodel.h index fe5853cebe..33388a2a45 100644 --- a/cpp/memilio/compartments/compartmentalmodel.h +++ b/cpp/memilio/compartments/compartmentalmodel.h @@ -61,6 +61,7 @@ using has_apply_constraints_member_function = is_expression_valid +template struct CompartmentalModel { public: using Compartments = Comp; using Populations = Pop; using ParameterSet = Params; - /** * @brief CompartmentalModel default constructor */ @@ -95,8 +95,9 @@ struct CompartmentalModel { virtual ~CompartmentalModel() = default; //REMARK: Not pure virtual for easier java/python bindings - virtual void get_derivatives(Eigen::Ref, Eigen::Ref /*y*/, - double /*t*/, Eigen::Ref /*dydt*/) const {}; + virtual void get_derivatives(Eigen::Ref>, Eigen::Ref> /*y*/, FP /*t*/, + Eigen::Ref> /*dydt*/) const {}; + /** * @brief eval_right_hand_side evaulates the right-hand-side f of the ODE dydt = f(y, t) * @@ -117,8 +118,8 @@ struct CompartmentalModel { * @param t the current time * @param dydt a reference to the calculated output */ - void eval_right_hand_side(Eigen::Ref pop, Eigen::Ref y, double t, - Eigen::Ref dydt) const + void eval_right_hand_side(Eigen::Ref> pop, Eigen::Ref> y, FP t, + Eigen::Ref> dydt) const { dydt.setZero(); this->get_derivatives(pop, y, t, dydt); @@ -129,7 +130,7 @@ struct CompartmentalModel { * This can be used as initial conditions in an ODE solver * @return the initial populatoins */ - Eigen::VectorXd get_initial_values() const + Vector get_initial_values() const { return populations.get_compartments(); } @@ -159,34 +160,38 @@ struct CompartmentalModel { * If the eval_right_hand_side member function exists in the type M, this template when instatiated * will be equal to the return type of the function. * Otherwise the template is invalid. + * @tparam FP, floating point type, e.g., double. * @tparam M a type that has a eval_right_hand_side member function, e.g. a compartment model type. */ -template -using eval_right_hand_side_expr_t = decltype(std::declval().eval_right_hand_side( - std::declval>(), std::declval>(), - std::declval(), std::declval>())); +template +using eval_right_hand_side_expr_t = + decltype(std::declval().eval_right_hand_side(std::declval>>(), + std::declval>>(), + std::declval(), std::declval>>())); /** * detect the get_initial_values member function of a compartment model. * If the detect_initial_values member function exists in the type M, this template when instatiated * will be equal to the return type of the function. * Otherwise the template is invalid. + * @tparam FP, floating point type, e.g., double. * @tparam M a type that has a get_initial_values member function, e.g. a compartment model type. */ -template -using get_initial_values_expr_t = - decltype(std::declval() = std::declval().get_initial_values()); +template +using get_initial_values_expr_t = decltype(std::declval&>() = std::declval().get_initial_values()); /** * Template meta function to check if a type is a valid compartment model. * Defines a static constant of name `value`. * The constant `value` will be equal to true if M is a valid compartment model type. * Otherwise, `value` will be equal to false. - * @tparam Sim a type that may or may not be a compartment model. + * @tparam FP, floating point type, e.g., double. + * @tparam M a type that may or may not be a compartment model. */ -template -using is_compartment_model = std::integral_constant::value && - is_expression_valid::value)>; +template +using is_compartment_model = + std::integral_constant::value && + is_expression_valid::value)>; } // namespace mio diff --git a/cpp/memilio/compartments/flow_model.h b/cpp/memilio/compartments/flow_model.h index c625aced80..41581633cd 100644 --- a/cpp/memilio/compartments/flow_model.h +++ b/cpp/memilio/compartments/flow_model.h @@ -55,8 +55,8 @@ using filtered_tuple_t = decltype(filter_tuple(std::declval() // Remove all occurrences of OmittedTag from the types in an Index = IndexTemplate. template class IndexTemplate, class Index> -using filtered_index_t = decltype( - as_index(std::declval()))>>())); +using filtered_index_t = decltype(as_index( + std::declval()))>>())); } //namespace details @@ -69,8 +69,8 @@ using filtered_index_t = decltype( * Flows is expected to be a TypeList containing types Flow, where A and B are compartments from the enum Comp. * Some examples can be found in the cpp/models/ directory, within the model.h files. */ -template -class FlowModel : public CompartmentalModel +template +class FlowModel : public CompartmentalModel { using PopIndex = typename Pop::Index; // FlowIndex is the same as PopIndex without the category Comp. It is used as argument type for @@ -84,21 +84,21 @@ class FlowModel : public CompartmentalModel static_assert(FlowIndex::size == PopIndex::size - 1, "Compartments must be used exactly once as population index."); public: - using Base = CompartmentalModel; + using Base = CompartmentalModel; /** * @brief Default constructor, forwarding args to Base constructor. */ template FlowModel(Args... args) - : CompartmentalModel(args...) + : CompartmentalModel(args...) , m_flow_values((this->populations.numel() / static_cast(Comp::Count)) * Flows::size()) { } // Note: use get_flat_flow_index when accessing flows // Note: by convention, we compute incoming flows, thus entries in flows must be non-negative - virtual void get_flows(Eigen::Ref /*pop*/, Eigen::Ref /*y*/, - double /*t*/, Eigen::Ref /*flows*/) const = 0; + virtual void get_flows(Eigen::Ref> /*pop*/, Eigen::Ref> /*y*/, FP /*t*/, + Eigen::Ref> /*flows*/) const = 0; /** * @brief Compute the right-hand-side of the ODE dydt = f(y, t) from flow values. @@ -108,7 +108,7 @@ class FlowModel : public CompartmentalModel * @param[in] flows The current flow values (as calculated by get_flows) as a flat array. * @param[out] dydt A reference to the calculated output. */ - void get_derivatives(Eigen::Ref flows, Eigen::Ref dydt) const + void get_derivatives(Eigen::Ref> flows, Eigen::Ref> dydt) const { // set dydt to 0, then iteratively add all flow contributions dydt.setZero(); @@ -134,8 +134,8 @@ class FlowModel : public CompartmentalModel * @param[in] t The current time. * @param[out] dydt A reference to the calculated output. */ - void get_derivatives(Eigen::Ref pop, Eigen::Ref y, double t, - Eigen::Ref dydt) const override final + void get_derivatives(Eigen::Ref> pop, Eigen::Ref> y, FP t, + Eigen::Ref> dydt) const override final { m_flow_values.setZero(); get_flows(pop, y, t, m_flow_values); @@ -147,9 +147,9 @@ class FlowModel : public CompartmentalModel * This can be used as initial conditions in an ODE solver. By default, this is a zero vector. * @return The initial flows. */ - Eigen::VectorXd get_initial_flows() const + Vector get_initial_flows() const { - return Eigen::VectorXd::Zero((this->populations.numel() / static_cast(Comp::Count)) * Flows::size()); + return Vector::Zero((this->populations.numel() / static_cast(Comp::Count)) * Flows::size()); } /** @@ -204,7 +204,7 @@ class FlowModel : public CompartmentalModel } private: - mutable Eigen::VectorXd m_flow_values; ///< Cache to avoid allocation in get_derivatives (using get_flows). + mutable Vector m_flow_values; ///< Cache to avoid allocation in get_derivatives (using get_flows). /** * @brief Compute the derivatives of the compartments. @@ -216,7 +216,7 @@ class FlowModel : public CompartmentalModel * @tparam I The index of a flow in FlowChart. */ template - inline void get_rhs_impl(Eigen::Ref flows, Eigen::Ref rhs, + inline void get_rhs_impl(Eigen::Ref> flows, Eigen::Ref> rhs, const FlowIndex& index) const { using Flow = type_at_index_t; @@ -238,22 +238,22 @@ class FlowModel : public CompartmentalModel * Detect whether certain member functions (the name before '_expr_t') exist. * If the member function exists in the type M, this template when instatiated * will be equal to the return type of the function. Otherwise the template is invalid. + * @tparam FP floating point type, e.g. double. * @tparam M Any class, e.g. FlowModel. * @{ */ -template +template using get_derivatives_expr_t = decltype(std::declval().get_derivatives( - std::declval>(), std::declval>())); + std::declval>>(), std::declval>>())); -template +template using get_flows_expr_t = - decltype(std::declval().get_flows(std::declval>(), - std::declval>(), - std::declval(), std::declval>())); + decltype(std::declval().get_flows(std::declval>>(), + std::declval>>(), std::declval(), + std::declval>>())); -template -using get_initial_flows_expr_t = - decltype(std::declval() = std::declval().get_initial_flows()); +template +using get_initial_flows_expr_t = decltype(std::declval>() = std::declval().get_initial_flows()); /** @} */ /** @@ -261,14 +261,15 @@ using get_initial_flows_expr_t = * Defines a static constant of name `value`. * The constant `value` will be equal to true if M is a valid flow model type. * Otherwise, `value` will be equal to false. + * @tparam FP floating point type, e.g. double. * @tparam Model A type that may or may not be a flow model. */ -template -using is_flow_model = std::integral_constant::value && - is_expression_valid::value && - is_expression_valid::value && - is_compartment_model::value)>; +template +using is_flow_model = std::integral_constant::value && + is_expression_valid::value && + is_expression_valid::value && + is_compartment_model::value)>; } // namespace mio -#endif // MIO_FLOW_MODEL_H_ \ No newline at end of file +#endif // MIO_FLOW_MODEL_H_ diff --git a/cpp/memilio/compartments/flow_simulation.h b/cpp/memilio/compartments/flow_simulation.h index c6bc60ac01..4c44395a55 100644 --- a/cpp/memilio/compartments/flow_simulation.h +++ b/cpp/memilio/compartments/flow_simulation.h @@ -26,14 +26,19 @@ namespace mio { -template -class FlowSimulation : public Simulation +/** + * @brief A class for the simulation of a flow model. + * @tparam FP A floating point type, e.g., double. + * @tparam M A FlowModel implementation. + */ +template +class FlowSimulation : public Simulation { - static_assert(is_flow_model::value, "Template parameter must be a flow model."); + static_assert(is_flow_model::value, "Template parameter must be a flow model."); public: using Model = M; - using Base = Simulation; + using Base = Simulation; /** * @brief Set up the simulation with an ODE solver. @@ -41,7 +46,7 @@ class FlowSimulation : public Simulation * @param[in] t0 Start time. * @param[in] dt Initial step size of integration. */ - FlowSimulation(Model const& model, double t0 = 0., double dt = 0.1) + FlowSimulation(Model const& model, FP t0 = 0., FP dt = 0.1) : Base(model, t0, dt) , m_pop(model.get_initial_values().size()) , m_flow_result(t0, model.get_initial_flows()) @@ -53,7 +58,7 @@ class FlowSimulation : public Simulation * tmax must be greater than get_result().get_last_time_point(). * @param[in] tmax Next stopping time of the simulation. */ - Eigen::Ref advance(double tmax) + Eigen::Ref> advance(FP tmax) { // the derivfunktion (i.e. the lambda passed to m_integrator.advance below) requires that there are at least // as many entries in m_flow_result as in Base::m_result @@ -94,12 +99,12 @@ class FlowSimulation : public Simulation * For each simulated time step, the TimeSeries contains the value of each flow. * @{ */ - TimeSeries& get_flows() + TimeSeries& get_flows() { return m_flow_result; } - const TimeSeries& get_flows() const + const TimeSeries& get_flows() const { return m_flow_result; } @@ -127,10 +132,10 @@ class FlowSimulation : public Simulation } } - Eigen::VectorXd m_pop; ///< pre-allocated temporary, used in right_hand_side() + Vector m_pop; ///< pre-allocated temporary, used in right_hand_side() private: - mio::TimeSeries m_flow_result; ///< flow result of the simulation + mio::TimeSeries m_flow_result; ///< flow result of the simulation }; /** @@ -142,12 +147,13 @@ class FlowSimulation : public Simulation * @param[in] integrator Optionally override the IntegratorCore used by the FlowSimulation. * @return The simulation result as two TimeSeries. The first describes the compartments at each time point, * the second gives the corresponding flows that lead from t0 to each time point. + * @tparam FP a floating point type, e.g., double * @tparam Model The particular Model derived from FlowModel to simulate. * @tparam Sim A FlowSimulation that can simulate the model. */ -template > -std::vector> simulate_flows(double t0, double tmax, double dt, Model const& model, - std::shared_ptr integrator = nullptr) +template > +std::vector> simulate_flows(FP t0, FP tmax, FP dt, Model const& model, + std::shared_ptr> integrator = nullptr) { model.check_constraints(); Sim sim(model, t0, dt); diff --git a/cpp/memilio/compartments/parameter_studies.h b/cpp/memilio/compartments/parameter_studies.h index 73ec8fa461..e364657bc8 100644 --- a/cpp/memilio/compartments/parameter_studies.h +++ b/cpp/memilio/compartments/parameter_studies.h @@ -55,12 +55,12 @@ class ParameterStudy * The Graph type that stores the parametes of the simulation. * This is the input of ParameterStudies. */ - using ParametersGraph = mio::Graph; + using ParametersGraph = mio::Graph>; /** * The Graph type that stores simulations and their results of each run. * This is the output of ParameterStudies for each run. */ - using SimulationGraph = mio::Graph, mio::MigrationEdge>; + using SimulationGraph = mio::Graph, mio::MigrationEdge>; /** * create study for graph of compartment models. @@ -140,8 +140,8 @@ class ParameterStudy #else num_procs = 1; rank = 0; -#endif - +#endif + //The ParameterDistributions used for sampling parameters use thread_local_rng() //So we set our own RNG to be used. //Assume that sampling uses the thread_local_rng() and isn't multithreaded @@ -149,7 +149,8 @@ class ParameterStudy thread_local_rng() = m_rng; auto run_distribution = distribute_runs(m_num_runs, num_procs); - auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); + auto start_run_idx = + std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; std::vector> ensemble_result; @@ -167,7 +168,8 @@ class ParameterStudy //sample auto sim = create_sampled_simulation(sample_graph); - log(LogLevel::info, "ParameterStudies: Generated {} random numbers.", (thread_local_rng().get_counter() - run_rng_counter).get()); + log(LogLevel::info, "ParameterStudies: Generated {} random numbers.", + (thread_local_rng().get_counter() - run_rng_counter).get()); //perform run sim.advance(m_tmax); @@ -328,7 +330,8 @@ class ParameterStudy } /** @} */ - RandomNumberGenerator& get_rng() { + RandomNumberGenerator& get_rng() + { return m_rng; } @@ -355,7 +358,7 @@ class ParameterStudy //evenly distribute runs //lower processes do one more run if runs are not evenly distributable auto num_runs_local = num_runs / num_procs; //integer division! - auto remainder = num_runs % num_procs; + auto remainder = num_runs % num_procs; std::vector run_distribution(num_procs); std::fill(run_distribution.begin(), run_distribution.begin() + remainder, num_runs_local + 1); diff --git a/cpp/memilio/compartments/simulation.h b/cpp/memilio/compartments/simulation.h index 65a3a242f5..8b3307f87f 100644 --- a/cpp/memilio/compartments/simulation.h +++ b/cpp/memilio/compartments/simulation.h @@ -29,16 +29,18 @@ namespace mio { -using DefaultIntegratorCore = mio::ControlledStepperWrapper; +template +using DefaultIntegratorCore = mio::ControlledStepperWrapper; /** - * @brief A class for the simulation of a compartment model. + * @brief A class for the simulation of a compartment model + * @tparam FP floating point type, e.g., double * @tparam M a CompartmentModel type */ -template +template class Simulation { - static_assert(is_compartment_model::value, "Template parameter must be a compartment model."); + static_assert(is_compartment_model::value, "Template parameter must be a compartment model."); public: using Model = M; @@ -49,8 +51,8 @@ class Simulation * @param[in] t0 Start time. * @param[in] dt Initial step size of integration */ - Simulation(Model const& model, double t0 = 0., double dt = 0.1) - : m_integratorCore(std::make_shared()) + Simulation(Model const& model, FP t0 = 0., FP dt = 0.1) + : m_integratorCore(std::make_shared>()) , m_model(std::make_unique(model)) , m_integrator(m_integratorCore) , m_result(t0, m_model->get_initial_values()) @@ -62,7 +64,7 @@ class Simulation * @brief Set the integrator core used in the simulation. * @param[in] integrator A shared pointer to an object derived from IntegratorCore. */ - void set_integrator(std::shared_ptr integrator) + void set_integrator(std::shared_ptr> integrator) { m_integratorCore = std::move(integrator); m_integrator.set_integrator(m_integratorCore); @@ -73,12 +75,16 @@ class Simulation * @return A reference to the integrator core used in the simulation * @{ */ - IntegratorCore& get_integrator() + IntegratorCore& get_integrator() { return *m_integratorCore; } - IntegratorCore const& get_integrator() const + /** + * @brief get_integrator + * @return reference to the core integrator used in the simulation + */ + IntegratorCore const& get_integrator() const { return *m_integratorCore; } @@ -89,7 +95,7 @@ class Simulation * tmax must be greater than get_result().get_last_time_point() * @param tmax next stopping point of simulation */ - Eigen::Ref advance(double tmax) + Eigen::Ref> advance(FP tmax) { return m_integrator.advance( [this](auto&& y, auto&& t, auto&& dydt) { @@ -108,12 +114,16 @@ class Simulation * For each simulated time step, the TimeSeries contains the population size in each compartment. * @{ */ - TimeSeries& get_result() + TimeSeries& get_result() { return m_result; } - const TimeSeries& get_result() const + /** + * @brief get_result returns the final simulation result + * @return a TimeSeries to represent the final simulation result + */ + const TimeSeries& get_result() const { return m_result; } @@ -141,12 +151,12 @@ class Simulation * next step size in this value. * @{ */ - double& get_dt() + FP& get_dt() { return m_dt; } - const double& get_dt() const + const FP& get_dt() const { return m_dt; } @@ -154,38 +164,41 @@ class Simulation protected: /// @brief Get a reference to the integrater. Can be used to overwrite advance. - OdeIntegrator& get_ode_integrator() + OdeIntegrator& get_ode_integrator() { return m_integrator; } private: - std::shared_ptr m_integratorCore; ///< Defines the integration scheme via its step function. + std::shared_ptr> m_integratorCore; ///< Defines the integration scheme via its step function. std::unique_ptr m_model; ///< The model defining the ODE system and initial conditions. - OdeIntegrator m_integrator; ///< Integrates the DerivFunction (see advance) and stores resutls in m_result. - TimeSeries m_result; ///< The simulation results. - ScalarType m_dt; ///< The time step used (and possibly set) by m_integratorCore::step. + OdeIntegrator m_integrator; ///< Integrates the DerivFunction (see advance) and stores resutls in m_result. + TimeSeries m_result; ///< The simulation results. + FP m_dt; ///< The time step used (and possibly set) by m_integratorCore::step. }; /** * Defines the return type of the `advance` member function of a type. * Template is invalid if this member function does not exist. + * + * @tparam FP floating point type, e.g., double * @tparam Sim a compartment model simulation type. */ -template -using advance_expr_t = decltype(std::declval().advance(std::declval())); +template +using advance_expr_t = decltype(std::declval().advance(std::declval())); /** * Template meta function to check if a type is a compartment model simulation. * Defines a static constant of name `value`. * The constant `value` will be equal to true if Sim is a valid compartment simulation type. * Otherwise, `value` will be equal to false. + * @tparam FP floating point type, e.g., double * @tparam Sim a type that may or may not be a compartment model simulation. */ -template +template using is_compartment_model_simulation = - std::integral_constant::value && - is_compartment_model::value)>; + std::integral_constant::value && + is_compartment_model::value)>; /** * @brief Run a Simulation of a CompartmentalModel. @@ -195,12 +208,13 @@ using is_compartment_model_simulation = * @param[in] model An instance of a CompartmentalModel. * @param[in] integrator Optionally override the IntegratorCore used by the Simulation. * @return A TimeSeries to represent the final Simulation result + * @tparam FP floating point type, e.g., double * @tparam Model The particular Model derived from CompartmentModel to simulate. * @tparam Sim A Simulation that can simulate the model. */ -template > -TimeSeries simulate(double t0, double tmax, double dt, Model const& model, - std::shared_ptr integrator = nullptr) +template > +TimeSeries simulate(FP t0, FP tmax, FP dt, Model const& model, + std::shared_ptr> integrator = nullptr) { model.check_constraints(); Sim sim(model, t0, dt); diff --git a/cpp/memilio/data/analyze_result.h b/cpp/memilio/data/analyze_result.h index ecb501247a..226ef11224 100644 --- a/cpp/memilio/data/analyze_result.h +++ b/cpp/memilio/data/analyze_result.h @@ -107,9 +107,9 @@ std::vector> ensemble_percentile(const std::vector +template std::vector> -interpolate_simulation_result(const Graph, MigrationEdge>& graph_result) +interpolate_simulation_result(const Graph, MigrationEdge>& graph_result) { std::vector> interpolated; interpolated.reserve(graph_result.nodes().size()); diff --git a/cpp/memilio/epidemiology/contact_matrix.h b/cpp/memilio/epidemiology/contact_matrix.h index bb96c92e0b..ccfb52e116 100644 --- a/cpp/memilio/epidemiology/contact_matrix.h +++ b/cpp/memilio/epidemiology/contact_matrix.h @@ -20,13 +20,12 @@ #ifndef EPI_ODE_CONTACT_FREQUENCY_MATRIX_H #define EPI_ODE_CONTACT_FREQUENCY_MATRIX_H -#include "memilio/math/eigen.h" #include "memilio/epidemiology/damping.h" #include "memilio/utils/stl_util.h" -#include #include #include +#include namespace mio { diff --git a/cpp/memilio/epidemiology/damping_sampling.h b/cpp/memilio/epidemiology/damping_sampling.h index c465866f30..d7203a87a8 100644 --- a/cpp/memilio/epidemiology/damping_sampling.h +++ b/cpp/memilio/epidemiology/damping_sampling.h @@ -34,6 +34,7 @@ namespace mio * The damping value is weighted by group (e.g. age) to be able to e.g. construct dampings that only * apply to specific groups. */ +template class DampingSampling { public: @@ -47,7 +48,7 @@ class DampingSampling * @param groups weights of age groups. */ template - DampingSampling(const UncertainValue& value, DampingLevel level, DampingType type, SimulationTime time, + DampingSampling(const UncertainValue& value, DampingLevel level, DampingType type, SimulationTime time, const std::vector matrices, const Eigen::MatrixBase& groups) : m_value(value) , m_level(level) @@ -63,11 +64,11 @@ class DampingSampling * @return the random value. * @{ */ - const UncertainValue& get_value() const + const UncertainValue& get_value() const { return m_value; } - UncertainValue& get_value() + UncertainValue& get_value() { return m_value; } @@ -77,7 +78,7 @@ class DampingSampling * Set the random value. * @param v random value. */ - void set_value(const UncertainValue& v) + void set_value(const UncertainValue& v) { m_value = v; } @@ -225,7 +226,7 @@ class DampingSampling auto ti = obj.expect_element("Time", Tag{}); auto ty = obj.expect_element("Type", Tag{}); auto l = obj.expect_element("Level", Tag{}); - auto v = obj.expect_element("Value", Tag{}); + auto v = obj.expect_element("Value", Tag>{}); auto m = obj.expect_list("MatrixIndices", Tag{}); auto g = obj.expect_element("GroupWeights", Tag{}); return apply( @@ -237,7 +238,7 @@ class DampingSampling } private: - UncertainValue m_value; + UncertainValue m_value; DampingLevel m_level; DampingType m_type; SimulationTime m_time; diff --git a/cpp/memilio/epidemiology/dynamic_npis.h b/cpp/memilio/epidemiology/dynamic_npis.h index b42fdb1859..90bb3a49f7 100644 --- a/cpp/memilio/epidemiology/dynamic_npis.h +++ b/cpp/memilio/epidemiology/dynamic_npis.h @@ -32,6 +32,7 @@ namespace mio * represents non-pharmaceutical interventions (NPI) that are activated during the simulation if * some value (e.g. infections) exceeds specified thresholds. */ +template class DynamicNPIs { public: @@ -40,7 +41,7 @@ class DynamicNPIs * @param threshold the threshold that may be exceeded. * @param dampings the NPIs */ - void set_threshold(double threshold, const std::vector& dampings) + void set_threshold(double threshold, const std::vector>& dampings) { insert_sorted_replace(m_thresholds, std::make_pair(threshold, dampings), [](auto& t1, auto& t2) { return t1.first > t2.first; @@ -173,7 +174,7 @@ class DynamicNPIs static IOResult deserialize(IOContext& io) { auto obj = io.expect_object("DynamicNPIs"); - auto t = obj.expect_list("Thresholds", Tag>>{}); + auto t = obj.expect_list("Thresholds", Tag>>>{}); auto d = obj.expect_element("Duration", Tag{}); auto i = obj.expect_element("Interval", Tag{}); auto b = obj.expect_element("BaseValue", Tag{}); @@ -193,7 +194,7 @@ class DynamicNPIs } private: - std::vector>> m_thresholds; + std::vector>>> m_thresholds; SimulationTime m_duration{14.0}; SimulationTime m_interval{3.0}; double m_base{1.0}; @@ -277,8 +278,8 @@ Eigen::Ref get_active_damping(const DampingE * @param end end of the time span that the NPIs will be active for. * @param make_matrix function to make a matrix of the same shape as the damping expression, see e.g. make_contact_damping_matrix */ -template -void implement_dynamic_npis(DampingExprGroup& damping_expr_group, const std::vector& npis, +template +void implement_dynamic_npis(DampingExprGroup& damping_expr_group, const std::vector>& npis, SimulationTime begin, SimulationTime end, MakeMatrix&& make_matrix) { for (auto& npi : npis) { diff --git a/cpp/memilio/epidemiology/populations.h b/cpp/memilio/epidemiology/populations.h index abf10bbc29..3554a463ed 100644 --- a/cpp/memilio/epidemiology/populations.h +++ b/cpp/memilio/epidemiology/populations.h @@ -25,8 +25,6 @@ #include "memilio/utils/custom_index_array.h" #include "memilio/math/eigen.h" -#include -#include #include namespace mio @@ -50,14 +48,15 @@ namespace mio * */ -template -class Populations : public CustomIndexArray +template +class Populations : public CustomIndexArray, Categories...> { public: - using Base = CustomIndexArray; + using Base = CustomIndexArray, Categories...>; using Index = typename Base::Index; - template ::value>* = nullptr> + template , Ts...>::value>* = nullptr> explicit Populations(Index const& sizes, Ts... args) : Base(sizes, args...) { @@ -80,9 +79,9 @@ class Populations : public CustomIndexArray * as initial conditions for the ODE solver * @return Eigen::VectorXd of populations */ - inline Eigen::VectorXd get_compartments() const + inline Vector get_compartments() const { - return this->array().template cast(); + return this->array().template cast(); } /** @@ -253,8 +252,9 @@ class Populations : public CustomIndexArray void check_constraints() const { for (int i = 0; i < this->array().size(); i++) { - if (this->array()[i] < 0) { - log_error("Constraint check: Compartment size {:d} is {:.4f} and smaller {:d}", i, this->array()[i], 0); + FP value = this->array()[i]; + if (value < 0.) { + log_error("Constraint check: Compartment size {} is {} and smaller {}", i, value, 0); } } } diff --git a/cpp/memilio/epidemiology/uncertain_matrix.cpp b/cpp/memilio/epidemiology/uncertain_matrix.cpp index 4cbe4b1089..b07cabd5fa 100644 --- a/cpp/memilio/epidemiology/uncertain_matrix.cpp +++ b/cpp/memilio/epidemiology/uncertain_matrix.cpp @@ -18,87 +18,3 @@ * limitations under the License. */ #include "memilio/epidemiology/uncertain_matrix.h" - -namespace mio -{ -UncertainContactMatrix::UncertainContactMatrix(size_t num_matrices, Eigen::Index num_groups) - : UncertainContactMatrix(ContactMatrixGroup(num_matrices, num_groups)) -{ -} - -UncertainContactMatrix::UncertainContactMatrix(const ContactMatrixGroup& cont_freq) - : m_cont_freq(cont_freq) - , m_dampings() - , m_school_holiday_damping(0.0, mio::DampingLevel(0), mio::DampingType(0), mio::SimulationTime(0), {}, - Eigen::VectorXd::Zero(cont_freq.get_num_groups())) - , m_school_holidays() -{ -} - -UncertainContactMatrix::operator ContactMatrixGroup const &() const -{ - return m_cont_freq; -} - -UncertainContactMatrix::operator ContactMatrixGroup&() -{ - return m_cont_freq; -} - -UncertainContactMatrix& UncertainContactMatrix::operator=(const ContactMatrixGroup& cont_freq) -{ - m_cont_freq = cont_freq; - return *this; -} - -ContactMatrixGroup& UncertainContactMatrix::get_cont_freq_mat() -{ - return m_cont_freq; -} - -ContactMatrixGroup const& UncertainContactMatrix::get_cont_freq_mat() const -{ - return m_cont_freq; -} - -ContactMatrixGroup UncertainContactMatrix::draw_sample(bool accum) -{ - draw_sample_dampings(); - return make_matrix(accum); -} - -void UncertainContactMatrix::draw_sample_dampings() -{ - for (auto& d : m_dampings) { - d.draw_sample(); - } - m_school_holiday_damping.draw_sample(); -} - -ContactMatrixGroup UncertainContactMatrix::make_matrix(bool accum) -{ - if (!accum) { - m_cont_freq.clear_dampings(); - } - - auto make_matrix = [](auto&& v) { - return mio::make_contact_damping_matrix(v); - }; - mio::apply_dampings(m_cont_freq, m_dampings, make_matrix); - - for (auto h : m_school_holidays) { - //enable damping at the start of the period - auto damping = m_school_holiday_damping; - damping.set_time(h.first); - mio::apply_dampings(m_cont_freq, make_range(&damping, &damping + 1), make_matrix); - - //disable damping at the end of the period - damping.get_value() = 0.0; - damping.set_time(h.second); - mio::apply_dampings(m_cont_freq, make_range(&damping, &damping + 1), make_matrix); - } - - return m_cont_freq; -} - -} // namespace mio diff --git a/cpp/memilio/epidemiology/uncertain_matrix.h b/cpp/memilio/epidemiology/uncertain_matrix.h index 04ed327de9..02e554b624 100644 --- a/cpp/memilio/epidemiology/uncertain_matrix.h +++ b/cpp/memilio/epidemiology/uncertain_matrix.h @@ -39,53 +39,80 @@ namespace mio * that are sampled to modify the contacts at some points in time. * @see UncertainValue */ +template class UncertainContactMatrix { public: - UncertainContactMatrix(size_t num_matrices = 1, Eigen::Index num_groups = 1); + UncertainContactMatrix(size_t num_matrices = 1, Eigen::Index num_groups = 1) + : UncertainContactMatrix(ContactMatrixGroup(num_matrices, num_groups)) + { + } - UncertainContactMatrix(const ContactMatrixGroup& cont_freq); + UncertainContactMatrix(const ContactMatrixGroup& cont_freq) + : m_cont_freq(cont_freq) + , m_dampings() + , m_school_holiday_damping(0.0, mio::DampingLevel(0), mio::DampingType(0), mio::SimulationTime(0), {}, + Eigen::VectorXd::Zero(cont_freq.get_num_groups())) + , m_school_holidays() + { + } /** * @brief Conversion to const ContactMatrix reference by returning the * ContactMatrix contained in UncertainContactMatrix */ - operator ContactMatrixGroup const &() const; + operator ContactMatrixGroup const &() const + { + return m_cont_freq; + } /** * @brief Conversion to ContactMatrix reference by returning the * ContactMatrix contained in UncertainContactMatrix */ - operator ContactMatrixGroup&(); + operator ContactMatrixGroup&() + { + return m_cont_freq; + } /** * @brief Set an UncertainContactMatrix from a ContactMatrix, * all distributions remain unchanged. */ - UncertainContactMatrix& operator=(const ContactMatrixGroup& cont_freq); + UncertainContactMatrix& operator=(const ContactMatrixGroup& cont_freq) + { + m_cont_freq = cont_freq; + return *this; + } /** * @brief Returns the ContactMatrix reference * of the UncertainContactMatrix object */ - ContactMatrixGroup& get_cont_freq_mat(); + ContactMatrixGroup& get_cont_freq_mat() + { + return m_cont_freq; + } /** * @brief Returns the const ContactMatrix reference * of the UncertainContactMatrix object */ - ContactMatrixGroup const& get_cont_freq_mat() const; + ContactMatrixGroup const& get_cont_freq_mat() const + { + return m_cont_freq; + } /** * @brief Get a list of uncertain Dampings that are sampled and added to the contact matrix. * @return list of damping samplings. * @{ */ - const std::vector& get_dampings() const + const std::vector>& get_dampings() const { return m_dampings; } - std::vector& get_dampings() + std::vector>& get_dampings() { return m_dampings; } @@ -96,11 +123,11 @@ class UncertainContactMatrix * time is ignored and taken from holidays instead. * @{ */ - const DampingSampling& get_school_holiday_damping() const + const DampingSampling& get_school_holiday_damping() const { return m_school_holiday_damping; } - DampingSampling& get_school_holiday_damping() + DampingSampling& get_school_holiday_damping() { return m_school_holiday_damping; } @@ -126,19 +153,53 @@ class UncertainContactMatrix * @param accum accumulating current and newly sampled dampings if true; * default: false; removing all previously set dampings */ - ContactMatrixGroup draw_sample(bool accum = false); + ContactMatrixGroup draw_sample(bool accum = false) + { + draw_sample_dampings(); + return make_matrix(accum); + } /** * draw sample of all dampings. */ - void draw_sample_dampings(); + void draw_sample_dampings() + { + for (auto& d : m_dampings) { + d.draw_sample(); + } + m_school_holiday_damping.draw_sample(); + } /** * create the contact matrix using the sampled dampings. * @param accum accumulating current and newly dampings if true; * default: false; removing all previously set dampings */ - ContactMatrixGroup make_matrix(bool accum = false); + ContactMatrixGroup make_matrix(bool accum = false) + { + if (!accum) { + m_cont_freq.clear_dampings(); + } + + auto make_matrix = [](auto&& v) { + return mio::make_contact_damping_matrix(v); + }; + mio::apply_dampings(m_cont_freq, m_dampings, make_matrix); + + for (auto h : m_school_holidays) { + //enable damping at the start of the period + auto damping = m_school_holiday_damping; + damping.set_time(h.first); + mio::apply_dampings(m_cont_freq, make_range(&damping, &damping + 1), make_matrix); + + //disable damping at the end of the period + damping.get_value() = 0.0; + damping.set_time(h.second); + mio::apply_dampings(m_cont_freq, make_range(&damping, &damping + 1), make_matrix); + } + + return m_cont_freq; + } /** * serialize this. @@ -166,16 +227,16 @@ class UncertainContactMatrix auto obj = io.expect_object("UncertainContactMatrix"); if (!(io.flags() & IOF_OmitDistributions)) { auto c = obj.expect_element("ContactMatrix", Tag{}); - auto e = obj.expect_element("SchoolHolidayDamping", Tag{}); + auto e = obj.expect_element("SchoolHolidayDamping", Tag>{}); auto f = obj.expect_list("SchoolHolidays", Tag>{}); - auto d = obj.expect_list("Dampings", Tag{}); + auto d = obj.expect_list("Dampings", Tag>{}); return apply( io, [](auto&& c_, auto&& d_, auto&& e_, auto&& f_) { - auto m = UncertainContactMatrix{c_}; - m.get_dampings() = d_; + auto m = UncertainContactMatrix{c_}; + m.get_dampings() = d_; m.get_school_holiday_damping() = e_; - m.get_school_holidays() = f_; + m.get_school_holidays() = f_; return m; }, c, d, e, f); @@ -193,8 +254,8 @@ class UncertainContactMatrix private: ContactMatrixGroup m_cont_freq; - std::vector m_dampings; - DampingSampling m_school_holiday_damping; + std::vector> m_dampings; + DampingSampling m_school_holiday_damping; std::vector> m_school_holidays; }; diff --git a/cpp/memilio/io/mobility_io.h b/cpp/memilio/io/mobility_io.h index 607ed72103..c30f923d4c 100644 --- a/cpp/memilio/io/mobility_io.h +++ b/cpp/memilio/io/mobility_io.h @@ -20,15 +20,9 @@ #ifndef READ_TWITTER_H #define READ_TWITTER_H -#include "memilio/config.h" -#include "memilio/math/eigen.h" #include "memilio/io/json_serializer.h" #include "memilio/mobility/graph.h" #include "memilio/mobility/metapopulation_mobility_instant.h" -#include -#include -#include -#include namespace mio { @@ -72,8 +66,8 @@ IOResult read_mobility_plain(const std::string& filename); * @param directory directory where files should be stored * @param ioflags flags that set the behavior of serialization; see mio::IOFlags */ -template -IOResult write_graph(const Graph& graph, const std::string& directory, +template +IOResult write_graph(const Graph>& graph, const std::string& directory, int ioflags = IOF_None) { assert(graph.nodes().size() > 0 && "Graph Nodes are empty"); @@ -132,9 +126,9 @@ IOResult write_graph(const Graph& graph, const * @param ioflags flags that set the behavior of serialization; see mio::IOFlags * @param read_edges boolean value that decides whether the edges of the graph should also be read in. */ -template -IOResult> read_graph(const std::string& directory, int ioflags = IOF_None, - bool read_edges = true) +template +IOResult>> read_graph(const std::string& directory, int ioflags = IOF_None, + bool read_edges = true) { std::string abs_path; if (!file_exists(directory, abs_path)) { @@ -142,7 +136,7 @@ IOResult> read_graph(const std::string& direct return failure(StatusCode::FileNotFound, directory); } - auto graph = Graph{}; + auto graph = Graph>{}; //read nodes, as many as files are available for (auto inode = 0;; ++inode) { @@ -181,7 +175,7 @@ IOResult> read_graph(const std::string& direct edge_filename + ", EndNodeIndex not in range of number of graph nodes."); } BOOST_OUTCOME_TRY(auto&& parameters, - deserialize_json(e["Parameters"], Tag{}, ioflags)); + deserialize_json(e["Parameters"], Tag>{}, ioflags)); graph.add_edge(start_node_idx, end_node_idx, parameters); } } diff --git a/cpp/memilio/io/result_io.h b/cpp/memilio/io/result_io.h index 8de5ec6461..81a08d6291 100644 --- a/cpp/memilio/io/result_io.h +++ b/cpp/memilio/io/result_io.h @@ -116,7 +116,7 @@ IOResult save_result_with_params(const std::vector>& re BOOST_OUTCOME_TRY(create_directory(result_dir_run.string())); BOOST_OUTCOME_TRY(save_result(result, county_ids, (int)(size_t)params[0].parameters.get_num_groups(), (result_dir_run / "Result.h5").string())); - BOOST_OUTCOME_TRY(write_graph(create_graph_without_edges(params, county_ids), + BOOST_OUTCOME_TRY(write_graph(create_graph_without_edges>(params, county_ids), result_dir_run.string(), IOF_OmitDistributions)); return success(); } @@ -211,7 +211,7 @@ IOResult save_results(const std::vector>>& auto ensemble_params_p95 = ensemble_params_percentile(ensemble_params, 0.95); auto make_graph = [&county_ids](auto&& params) { - return create_graph_without_edges(params, county_ids); + return create_graph_without_edges>(params, county_ids); }; BOOST_OUTCOME_TRY( write_graph(make_graph(ensemble_params_p05), result_dir_p05.string(), IOF_OmitDistributions)); diff --git a/cpp/memilio/math/adapt_rk.cpp b/cpp/memilio/math/adapt_rk.cpp index 88af7a25b3..407402efcc 100644 --- a/cpp/memilio/math/adapt_rk.cpp +++ b/cpp/memilio/math/adapt_rk.cpp @@ -18,136 +18,3 @@ * limitations under the License. */ #include "memilio/math/adapt_rk.h" -#include "memilio/utils/logging.h" - -namespace mio -{ - -TableauFinal::TableauFinal() -{ - entries_low.resize(6); - entries_high.resize(6); - - entries_low[0] = 25 / 216.0; - entries_low[1] = 0.0; - entries_low[2] = 1408 / 2565.0; - entries_low[3] = 2197 / 4104.0; - entries_low[4] = -0.2; - entries_low[5] = 0.0; - entries_high[0] = 16 / 135.0; - entries_high[1] = 0.0; - entries_high[2] = 6656 / 12825.0; - entries_high[3] = 28561 / 56430.0; - entries_high[4] = -9 / 50.0; - entries_high[5] = 2 / 55.0; -} - -Tableau::Tableau() -{ - entries.resize(5); - for (size_t i = 0; i < entries.size(); i++) { - entries.at(i).resize(i + 2); - } - - entries[0][0] = 0.25; - entries[0][1] = 0.25; - entries[1][0] = 3 / 8.0; - entries[1][1] = 3 / 32.0; - entries[1][2] = 9 / 32.0; - entries[2][0] = 12 / 13.0; - entries[2][1] = 1932 / 2197.0; - entries[2][2] = -7200 / 2197.0; - entries[2][3] = 7296 / 2197.0; - entries[3][0] = 1.0; - entries[3][1] = 439 / 216.0; - entries[3][2] = -8.0; - entries[3][3] = 3680 / 513.0; - entries[3][4] = -845 / 4104.0; - entries[4][0] = 0.5; - entries[4][1] = -8 / 27.0; - entries[4][2] = 2.0; - entries[4][3] = -3544 / 2565.0; - entries[4][4] = 1859 / 4104.0; - entries[4][5] = -11 / 40.0; -} - -bool RKIntegratorCore::step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, - Eigen::Ref ytp1) const -{ - assert(0 <= m_dt_min); - assert(m_dt_min <= m_dt_max); - - if (dt < m_dt_min || dt > m_dt_max) { - mio::log_warning("IntegratorCore: Restricting given step size dt = {} to [{}, {}].", dt, m_dt_min, m_dt_max); - } - - dt = std::min(dt, m_dt_max); - - double t_eval; // shifted time for evaluating yt - double dt_new; // updated dt - - bool converged = false; // carry for convergence criterion - bool dt_is_invalid = false; - - if (m_yt_eval.size() != yt.size()) { - m_yt_eval.resize(yt.size()); - m_kt_values.resize(yt.size(), m_tab_final.entries_low.size()); - } - - m_yt_eval = yt; - - while (!converged && !dt_is_invalid) { - if (dt < m_dt_min) { - dt_is_invalid = true; - dt = m_dt_min; - } - // compute first column of kt, i.e. kt_0 for each y in yt_eval - f(m_yt_eval, t, m_kt_values.col(0)); - - for (Eigen::Index i = 1; i < m_kt_values.cols(); i++) { - // we first compute k_n1 for each y_j, then k_n2 for each y_j, etc. - t_eval = t; - t_eval += m_tab.entries[i - 1][0] * - dt; // t_eval = t + c_i * h // note: line zero of Butcher tableau not stored in array - // use ytp1 as temporary storage for evaluating m_kt_values[i] - ytp1 = m_yt_eval; - for (Eigen::VectorXd::Index k = 1; k < m_tab.entries[i - 1].size(); k++) { - ytp1 += (dt * m_tab.entries[i - 1][k]) * m_kt_values.col(k - 1); - } - // get the derivatives, i.e., compute kt_i for all y in ytp1: kt_i = f(t_eval, ytp1_low) - f(ytp1, t_eval, m_kt_values.col(i)); - } - // calculate low order estimate - ytp1 = m_yt_eval; - ytp1 += (dt * (m_kt_values * m_tab_final.entries_low)); - // truncation error estimate: yt_low - yt_high = O(h^(p+1)) where p = order of convergence - m_error_estimate = dt * (m_kt_values * (m_tab_final.entries_high - m_tab_final.entries_low)).array().abs(); - // calculate mixed tolerance - m_eps = m_abs_tol + ytp1.array().abs() * m_rel_tol; - - converged = (m_error_estimate <= m_eps).all(); // convergence criterion - - if (converged || dt_is_invalid) { - // if sufficiently exact, return ytp1, which currently contains the lower order approximation - // (higher order is not always higher accuracy) - t += dt; // this is the t where ytp1 belongs to - } - // else: repeat the calculation above (with updated dt) - - // compute new value for dt - // converged implies eps/error_estimate >= 1, so dt will be increased for the next step - // hence !converged implies 0 < eps/error_estimate < 1, strictly decreasing dt - dt_new = dt * std::pow((m_eps / m_error_estimate).minCoeff(), (1. / (m_tab_final.entries_low.size() - 1))); - // safety factor for more conservative step increases, - // and to avoid dt_new -> dt for step decreases when |error_estimate - eps| -> 0 - dt_new *= 0.9; - // check if updated dt stays within desired bounds and update dt for next step - dt = std::min(dt_new, m_dt_max); - } - dt = std::max(dt, m_dt_min); - // return 'converged' in favor of '!dt_is_invalid', as these values only differ if step sizing failed, - // but the step with size dt_min was accepted. - return converged; -} - -} // namespace mio diff --git a/cpp/memilio/math/adapt_rk.h b/cpp/memilio/math/adapt_rk.h index 0bf9769660..483b2a85f7 100644 --- a/cpp/memilio/math/adapt_rk.h +++ b/cpp/memilio/math/adapt_rk.h @@ -67,7 +67,34 @@ class Tableau /** * @brief default is Runge-Kutta-Fehlberg4(5) tableau */ - Tableau(); + Tableau() + { + entries.resize(5); + for (size_t i = 0; i < entries.size(); i++) { + entries.at(i).resize(i + 2); + } + + entries[0][0] = 0.25; + entries[0][1] = 0.25; + entries[1][0] = 3 / 8.0; + entries[1][1] = 3 / 32.0; + entries[1][2] = 9 / 32.0; + entries[2][0] = 12 / 13.0; + entries[2][1] = 1932 / 2197.0; + entries[2][2] = -7200 / 2197.0; + entries[2][3] = 7296 / 2197.0; + entries[3][0] = 1.0; + entries[3][1] = 439 / 216.0; + entries[3][2] = -8.0; + entries[3][3] = 3680 / 513.0; + entries[3][4] = -845 / 4104.0; + entries[4][0] = 0.5; + entries[4][1] = -8 / 27.0; + entries[4][2] = 2.0; + entries[4][3] = -3544 / 2565.0; + entries[4][4] = 1859 / 4104.0; + entries[4][5] = -11 / 40.0; + } }; /* @@ -88,7 +115,24 @@ class TableauFinal /** * @brief default is Runge-Kutta-Fehlberg4(5) tableau */ - TableauFinal(); + TableauFinal() + { + entries_low.resize(6); + entries_high.resize(6); + + entries_low[0] = 25 / 216.0; + entries_low[1] = 0.0; + entries_low[2] = 1408 / 2565.0; + entries_low[3] = 2197 / 4104.0; + entries_low[4] = -0.2; + entries_low[5] = 0.0; + entries_high[0] = 16 / 135.0; + entries_high[1] = 0.0; + entries_high[2] = 6656 / 12825.0; + entries_high[3] = 28561 / 56430.0; + entries_high[4] = -9 / 50.0; + entries_high[5] = 2 / 55.0; + } }; /** @@ -96,7 +140,8 @@ class TableauFinal * * This class integrates a system of ODEs via the step method */ -class RKIntegratorCore : public IntegratorCore +template +class RKIntegratorCore : public IntegratorCore { public: /** @@ -164,19 +209,97 @@ class RKIntegratorCore : public IntegratorCore * @param[in,out] dt current time step size h=dt * @param[out] ytp1 approximated value y(t+1) */ - bool step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, - Eigen::Ref ytp1) const override; + bool step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, + Eigen::Ref ytp1) const override + { + assert(0 <= m_dt_min); + assert(m_dt_min <= m_dt_max); + + if (dt < m_dt_min || dt > m_dt_max) { + mio::log_warning("IntegratorCore: Restricting given step size dt = {} to [{}, {}].", dt, m_dt_min, + m_dt_max); + } + + dt = std::min(dt, m_dt_max); + + double t_eval; // shifted time for evaluating yt + double dt_new; // updated dt + + bool converged = false; // carry for convergence criterion + bool dt_is_invalid = false; + + if (m_yt_eval.size() != yt.size()) { + m_yt_eval.resize(yt.size()); + m_kt_values.resize(yt.size(), m_tab_final.entries_low.size()); + } + + m_yt_eval = yt; + + while (!converged && !dt_is_invalid) { + if (dt < m_dt_min) { + dt_is_invalid = true; + dt = m_dt_min; + } + // compute first column of kt, i.e. kt_0 for each y in yt_eval + f(m_yt_eval, t, m_kt_values.col(0)); + + for (Eigen::Index i = 1; i < m_kt_values.cols(); i++) { + // we first compute k_n1 for each y_j, then k_n2 for each y_j, etc. + t_eval = t; + t_eval += m_tab.entries[i - 1][0] * + dt; // t_eval = t + c_i * h // note: line zero of Butcher tableau not stored in array + // use ytp1 as temporary storage for evaluating m_kt_values[i] + ytp1 = m_yt_eval; + for (Eigen::VectorXd::Index k = 1; k < m_tab.entries[i - 1].size(); k++) { + ytp1 += (dt * m_tab.entries[i - 1][k]) * m_kt_values.col(k - 1); + } + // get the derivatives, i.e., compute kt_i for all y in ytp1: kt_i = f(t_eval, ytp1_low) + f(ytp1, t_eval, m_kt_values.col(i)); + } + // calculate low order estimate + ytp1 = m_yt_eval; + ytp1 += (dt * (m_kt_values * m_tab_final.entries_low)); + // truncation error estimate: yt_low - yt_high = O(h^(p+1)) where p = order of convergence + m_error_estimate = dt * (m_kt_values * (m_tab_final.entries_high - m_tab_final.entries_low)).array().abs(); + // calculate mixed tolerance + m_eps = m_abs_tol + ytp1.array().abs() * m_rel_tol; + + converged = (m_error_estimate <= m_eps).all(); // convergence criterion + + if (converged || dt_is_invalid) { + // if sufficiently exact, return ytp1, which currently contains the lower order approximation + // (higher order is not always higher accuracy) + t += dt; // this is the t where ytp1 belongs to + } + // else: repeat the calculation above (with updated dt) + + // compute new value for dt + // converged implies eps/error_estimate >= 1, so dt will be increased for the next step + // hence !converged implies 0 < eps/error_estimate < 1, strictly decreasing dt + dt_new = dt * std::pow((m_eps / m_error_estimate).minCoeff(), (1. / (m_tab_final.entries_low.size() - 1))); + // safety factor for more conservative step increases, + // and to avoid dt_new -> dt for step decreases when |error_estimate - eps| -> 0 + dt_new *= 0.9; + // check if updated dt stays within desired bounds and update dt for next step + dt = std::min(dt_new, m_dt_max); + } + dt = std::max(dt, m_dt_min); + // return 'converged' in favor of '!dt_is_invalid', as these values only differ if step sizing failed, + // but the step with size dt_min was accepted. + return converged; + } protected: Tableau m_tab; TableauFinal m_tab_final; - double m_abs_tol, m_rel_tol; - double m_dt_min, m_dt_max; - mutable Eigen::Matrix m_kt_values; - mutable Eigen::VectorXd m_yt_eval; + FP m_abs_tol, m_rel_tol; + FP m_dt_min, m_dt_max; + mutable Eigen::Matrix m_kt_values; + mutable Vector m_yt_eval; private: - mutable Eigen::ArrayXd m_eps, m_error_estimate; // tolerance and estimate used for time step adaption + mutable Eigen::Array m_eps, + m_error_estimate; // tolerance and estimate used for time step adaption }; } // namespace mio diff --git a/cpp/memilio/math/eigen.h b/cpp/memilio/math/eigen.h index 7774f1dca0..effd111876 100644 --- a/cpp/memilio/math/eigen.h +++ b/cpp/memilio/math/eigen.h @@ -17,14 +17,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef EPI_UTILS_EIGEN_H -#define EPI_UTILS_EIGEN_H +#ifndef MIO_UTILS_EIGEN_H +#define MIO_UTILS_EIGEN_H +#include "memilio/config.h" #include "memilio/utils/compiler_diagnostics.h" /* this file wraps includes from eigen3 library to disable warnings. */ -//C4996: some std functions that have been deprecated in c++17; maybe fixed in new eigen versions? +//C4996: some std functions that have been deprecated in c++17; maybe fixed in new eigen versions? MSVC_WARNING_DISABLE_PUSH(4996) GCC_CLANG_DIAGNOSTIC(push) @@ -37,4 +38,13 @@ GCC_CLANG_DIAGNOSTIC(pop) MSVC_WARNING_POP() -#endif //EPI_UTILS_EIGEN_H +namespace mio +{ + +/// A vector of type FP from the Eigen library +template +using Vector = Eigen::Matrix; + +} // namespace mio + +#endif // MIO_UTILS_EIGEN_H diff --git a/cpp/memilio/math/euler.cpp b/cpp/memilio/math/euler.cpp index 2fc9141f9c..32005b2cd5 100644 --- a/cpp/memilio/math/euler.cpp +++ b/cpp/memilio/math/euler.cpp @@ -18,18 +18,3 @@ * limitations under the License. */ #include "memilio/math/euler.h" - -namespace mio -{ - -bool EulerIntegratorCore::step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, - Eigen::Ref ytp1) const -{ - // we are misusing the next step y as temporary space to store the derivative - f(yt, t, ytp1); - ytp1 = yt + dt * ytp1; - t += dt; - return true; -} - -} // namespace mio diff --git a/cpp/memilio/math/euler.h b/cpp/memilio/math/euler.h index 82906e4085..afd237c211 100644 --- a/cpp/memilio/math/euler.h +++ b/cpp/memilio/math/euler.h @@ -20,17 +20,18 @@ #ifndef EULER_H #define EULER_H +#include "memilio/config.h" #include "memilio/math/integrator.h" -#include - namespace mio { /** * @brief Simple explicit euler integration y(t+1) = y(t) + h*f(t,y) for ODE y'(t) = f(t,y) + * @tparam FP A floating point type, e.g., ScalarType. */ -class EulerIntegratorCore : public IntegratorCore +template +class EulerIntegratorCore : public IntegratorCore { public: /** @@ -41,8 +42,15 @@ class EulerIntegratorCore : public IntegratorCore * @param[in,out] dt current time step h=dt * @param[out] ytp1 approximated value y(t+1) */ - bool step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, - Eigen::Ref ytp1) const override; + bool step(const DerivFunction& f, Eigen::Ref> yt, FP& t, FP& dt, + Eigen::Ref> ytp1) const override + { + // we are misusing the next step y as temporary space to store the derivative + f(yt, t, ytp1); + ytp1 = yt + dt * ytp1; + t += dt; + return true; + } }; } // namespace mio diff --git a/cpp/memilio/math/floating_point.h b/cpp/memilio/math/floating_point.h index 38c96b05bf..e4bb47351b 100644 --- a/cpp/memilio/math/floating_point.h +++ b/cpp/memilio/math/floating_point.h @@ -36,7 +36,9 @@ namespace mio template T abs_max(T v1, T v2) { - return std::max(std::abs(v1), std::abs(v2)); + using std::abs; + using std::max; + return max(abs(v1), abs(v2)); } /** @@ -52,7 +54,8 @@ T abs_max(T v1, T v2) template bool floating_point_equal(T v1, T v2, T abs_tol = 0, T rel_tol = std::numeric_limits::min()) { - auto diff = std::abs(v1 - v2); + using std::abs; + auto diff = abs(v1 - v2); return diff <= abs_tol || diff <= abs_max(v1, v2) * rel_tol; } diff --git a/cpp/memilio/math/integrator.cpp b/cpp/memilio/math/integrator.cpp index 78fbf90d47..e09e929c54 100644 --- a/cpp/memilio/math/integrator.cpp +++ b/cpp/memilio/math/integrator.cpp @@ -18,65 +18,3 @@ * limitations under the License. */ #include "memilio/math/integrator.h" -#include "memilio/utils/logging.h" -#include - -namespace mio -{ - -Eigen::Ref OdeIntegrator::advance(const DerivFunction& f, const double tmax, double& dt, - TimeSeries& results) -{ - const double t0 = results.get_last_time(); - assert(tmax > t0); - assert(dt > 0); - - const size_t num_steps = - static_cast(ceil((tmax - t0) / dt)); // estimated number of time steps (if equidistant) - - results.reserve(results.get_num_time_points() + num_steps); - - bool step_okay = true; - - double dt_cp; // used to check whether step sizing is adaptive - double dt_restore = 0; // used to restore dt if dt was decreased to reach tmax - double t = t0; - - for (size_t i = results.get_num_time_points() - 1; std::abs((tmax - t) / (tmax - t0)) > 1e-10; ++i) { - //we don't make timesteps too small as the error estimator of an adaptive integrator - //may not be able to handle it. this is very conservative and maybe unnecessary, - //but also unlikely to happen. may need to be reevaluated - - if (dt > tmax - t) { - dt_restore = dt; - dt = tmax - t; - } - dt_cp = dt; - - results.add_time_point(); - step_okay &= m_core->step(f, results[i], t, dt, results[i + 1]); - results.get_last_time() = t; - - // if dt has been changed (even slighly) by step, register the current m_core as adaptive - m_is_adaptive |= !floating_point_equal(dt, dt_cp); - } - // if dt was decreased to reach tmax in the last time iteration, - // we restore it as it is now probably smaller than required for tolerances - dt = std::max(dt, dt_restore); - - if (m_is_adaptive) { - if (!step_okay) { - log_warning("Adaptive step sizing failed. Forcing an integration step of size dt_min."); - } - else if (std::abs((tmax - t) / (tmax - t0)) > 1e-14) { - log_warning("Last time step too small. Could not reach tmax exactly."); - } - else { - log_info("Adaptive step sizing successful to tolerances."); - } - } - - return results.get_last_value(); -} - -} // namespace mio diff --git a/cpp/memilio/math/integrator.h b/cpp/memilio/math/integrator.h index cf6febe8ca..33da772d92 100644 --- a/cpp/memilio/math/integrator.h +++ b/cpp/memilio/math/integrator.h @@ -21,7 +21,7 @@ #define INTEGRATOR_H #include "memilio/utils/time_series.h" - +#include "memilio/utils/logging.h" #include #include @@ -31,9 +31,10 @@ namespace mio /** * Function template to be integrated */ -using DerivFunction = - std::function y, double t, Eigen::Ref dydt)>; +template +using DerivFunction = std::function> y, FP t, Eigen::Ref> dydt)>; +template class IntegratorCore { public: @@ -62,13 +63,15 @@ class IntegratorCore * @return Always true for nonadaptive methods. * (If adaptive, returns whether the adaptive step sizing was successful.) */ - virtual bool step(const DerivFunction& f, Eigen::Ref yt, double& t, double& dt, - Eigen::Ref ytp1) const = 0; + virtual bool step(const DerivFunction& f, Eigen::Ref> yt, FP& t, FP& dt, + Eigen::Ref> ytp1) const = 0; }; /** * Integrate initial value problems (IVP) of ordinary differential equations (ODE) of the form y' = f(y, t), y(t0) = y0. + * tparam FP a floating point type accepted by Eigen */ +template class OdeIntegrator { public: @@ -76,7 +79,7 @@ class OdeIntegrator * @brief create an integrator for a specific IVP * @param[in] core implements the solution method */ - OdeIntegrator(std::shared_ptr core) + OdeIntegrator(std::shared_ptr> core) : m_core(core) , m_is_adaptive(false) { @@ -91,17 +94,72 @@ class OdeIntegrator * intitial time and value. A new entry is added for each integration step. * @return A reference to the last value in the results time series. */ - Eigen::Ref advance(const DerivFunction& f, const double tmax, double& dt, - TimeSeries& results); - void set_integrator(std::shared_ptr integrator) + Eigen::Ref> advance(const DerivFunction& f, const FP tmax, FP& dt, TimeSeries& results) + { + // hint at std functions for ADL + using std::fabs; + using std::max; + const FP t0 = results.get_last_time(); + assert(tmax > t0); + assert(dt > 0); + + const size_t num_steps = + static_cast(ceil((tmax - t0) / dt)); // estimated number of time steps (if equidistant) + + results.reserve(results.get_num_time_points() + num_steps); + + bool step_okay = true; + + FP dt_copy; // used to check whether step sizing is adaptive + FP dt_restore = 0; // used to restore dt if dt was decreased to reach tmax + FP t = t0; + + for (size_t i = results.get_num_time_points() - 1; fabs((tmax - t) / (tmax - t0)) > 1e-10; ++i) { + //we don't make timesteps too small as the error estimator of an adaptive integrator + //may not be able to handle it. this is very conservative and maybe unnecessary, + //but also unlikely to happen. may need to be reevaluated + + if (dt > tmax - t) { + dt_restore = dt; + dt = tmax - t; + } + dt_copy = dt; + + results.add_time_point(); + step_okay &= m_core->step(f, results[i], t, dt, results[i + 1]); + results.get_last_time() = t; + + // if dt has been changed (even slighly) by step, register the current m_core as adaptive + m_is_adaptive |= !floating_point_equal(dt, dt_copy); + } + // if dt was decreased to reach tmax in the last time iteration, + // we restore it as it is now probably smaller than required for tolerances + dt = max(dt, dt_restore); + + if (m_is_adaptive) { + if (!step_okay) { + log_warning("Adaptive step sizing failed. Forcing an integration step of size dt_min."); + } + else if (fabs((tmax - t) / (tmax - t0)) > 1e-14) { + log_warning("Last time step too small. Could not reach tmax exactly."); + } + else { + log_info("Adaptive step sizing successful to tolerances."); + } + } + + return results.get_last_value(); + } + + void set_integrator(std::shared_ptr> integrator) { m_core = integrator; m_is_adaptive = false; } private: - std::shared_ptr m_core; + std::shared_ptr> m_core; bool m_is_adaptive; }; diff --git a/cpp/memilio/math/stepper_wrapper.h b/cpp/memilio/math/stepper_wrapper.h index d0517b3df7..673728e44d 100644 --- a/cpp/memilio/math/stepper_wrapper.h +++ b/cpp/memilio/math/stepper_wrapper.h @@ -20,22 +20,14 @@ #ifndef STEPPER_WRAPPER_H_ #define STEPPER_WRAPPER_H_ -#include "memilio/utils/compiler_diagnostics.h" #include "memilio/math/integrator.h" #include "memilio/utils/logging.h" -GCC_CLANG_DIAGNOSTIC(push) -GCC_CLANG_DIAGNOSTIC(ignored "-Wshadow") -GCC_CLANG_DIAGNOSTIC(ignored "-Wlanguage-extension-token") -MSVC_WARNING_DISABLE_PUSH(4127) #include "boost/numeric/odeint/external/eigen/eigen_algebra.hpp" #include "boost/numeric/odeint/stepper/controlled_runge_kutta.hpp" -#include "boost/numeric/odeint/stepper/runge_kutta4.hpp" #include "boost/numeric/odeint/stepper/runge_kutta_fehlberg78.hpp" #include "boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp" // #include "boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp" // TODO: reenable once boost bug is fixed -MSVC_WARNING_POP() -GCC_CLANG_DIAGNOSTIC(pop) namespace mio { @@ -44,14 +36,15 @@ namespace mio * @brief Creates and manages an instance of a boost::numeric::odeint::controlled_runge_kutta * integrator, wrapped as mio::IntegratorCore. */ -template