diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7816cf3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +build +!build/mod-*.tar.gz +stage diff --git a/.drone.jsonnet b/.drone.jsonnet index 07131e9..dcc15f0 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -7,11 +7,12 @@ local CoverageStep(withCoverage, compiler, boost) = if !withCoverage then null e environment: { CTEST_OUTPUT_ON_FAILURE: 1, CXX: compiler, + CXXFLAGS: "-Werror", }, commands: [ "mkdir covBuild", "cd covBuild", - "cmake ../ -DBUILD_TESTING=on -DBUILD_COVERAGE=on %s" % [boostArg(boost)], + "cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_COVERAGE=on %s" % [boostArg(boost)], "make", "make install", "make tests", @@ -19,6 +20,13 @@ local CoverageStep(withCoverage, compiler, boost) = if !withCoverage then null e "make coverage_build", "/copyCoverage.sh", ], + when: { + ref: [ + "refs/heads/develop", + "refs/heads/master", + "refs/tags/v*", + ] + }, volumes: [ { name: "www", @@ -36,27 +44,42 @@ local Volumes(withCoverage) = if !withCoverage then [] else [ }, ]; +local Bootstrap(dep=false) = { + name: "bootstrap", + image: image, + commands: [ + "git fetch --tags", + "git submodule update --init --recursive", + "./bootstrap.sh", + ], + [ if dep then "depends_on"]: [ "clone" ], +}; + +local Configure(compiler, boost, dep=false) = { + name: "configure", + image: image, + environment: { + CXX: compiler, + CXXFLAGS: "-Werror", + }, + commands: [ + "mkdir build", + "cd build", + "cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off %s" % [boostArg(boost)], + ], + [ if dep then "depends_on"]: [ "bootstrap" ], +}; + local Pipeline(withCoverage, compiler, boost) = { kind: "pipeline", name: "%s, Boost %s" % [compiler, boost], steps: [ - { - name: "bootstrap", - image: image, - commands: [ - "git fetch --tags", - "git submodule update --init --recursive", - "./bootstrap.sh", - ], - }, + Bootstrap(), + Configure(compiler, boost), { name: "build", image: image, - environment: { - CXX: compiler, - }, commands: [ - "mkdir build", "cd build", "cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off %s" % [boostArg(boost)], "make", @@ -84,8 +107,34 @@ local Pipeline(withCoverage, compiler, boost) = { commands: [ "cd build", "make install", - "ctest --output-on-failure", + "ctest --output-on-failure -E cmake_add_subdirectory_build", + ], + }, + { + name: "simple test", + image: image, + commands: [ + "cd build", + "make install", + "cd ../", + "mod -e \"smiles('O').print()\"", + ], + }, + { + name: "test subdirectory build", + image: image, + commands: [ + "cd build", + "make install", + "ctest --output-on-failure -R cmake_add_subdirectory_build", ], + when: { + ref: [ + "refs/heads/develop", + "refs/heads/master", + "refs/tags/v*", + ] + }, }, CoverageStep(withCoverage, compiler, boost), ], @@ -93,12 +142,99 @@ local Pipeline(withCoverage, compiler, boost) = { }; [ - Pipeline(boost == "1_74_0" && compiler == "g++-7", compiler, boost) + { + kind: "pipeline", + name: "Various Static Checks", + steps: [ + { + name: "Python, mypy", + image: image, + commands: [ + "./scripts/mypy.sh", + ], + depends_on: [ "clone" ], + }, + { + name: "Python, flake8", + image: image, + commands: [ + "./scripts/flake8.sh", + ], + depends_on: [ "clone" ], + }, + { + name: "Symbol Visibility, json", + image: image, + commands: [ + "./scripts/checkJsonVisibility.sh", + ], + depends_on: [ "clone" ], + }, + ] + }, + { + kind: "pipeline", + name: "Docker", + steps: [ + Bootstrap(false), + Configure("g++", "1_75_0", false), + { + name: "dist", + image: image, + commands: [ + "cd build", + "make dist", + ], + //depends_on: [ "configure" ], + }, + { + name: "Ubuntu", + image: "plugins/docker", + settings: { + repo: "jakobandersen/mod", + tags: ["ubuntu-test"], + dockerfile: "docker/Ubuntu.Dockerfile", + dry_run: true, + purge: true, + build_args: ["j=1"], + }, + //depends_on: [ "dist" ], + }, + { + name: "Fedora", + image: "plugins/docker", + settings: { + repo: "jakobandersen/mod", + tags: ["fedora-test"], + dockerfile: "docker/Fedora.Dockerfile", + dry_run: true, + purge: true, + build_args: ["j=1"], + }, + //depends_on: [ "dist" ], + }, + { + name: "Arch", + image: "plugins/docker", + settings: { + repo: "jakobandersen/mod", + tags: ["arch-test"], + dockerfile: "docker/Arch.Dockerfile", + dry_run: true, + purge: true, + build_args: ["j=1"], + }, + //depends_on: [ "dist" ], + }, + ] + }, +] + [ + Pipeline(boost == "1_74_0" && compiler == "g++-9", compiler, boost) for compiler in [ "g++-7", "g++-8", "g++-9", "g++-10", - "clang++-6.0", "clang++-7", "clang++-8", "clang++-9", "clang++-10", + "clang++-8", "clang++-9", "clang++-10", ] for boost in [ - "1_72_0", "1_73_0", "1_74_0", + "1_73_0", "1_74_0", "1_75_0", ] ] diff --git a/.drone.yml b/.drone.yml index 39de088..9f9065a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,51 +1,36 @@ --- kind: pipeline -name: g++-7, Boost 1_72_0 +name: Various Static Checks platform: os: linux arch: amd64 steps: -- name: bootstrap +- name: Python, mypy image: localhost:5000/jla/mod commands: - - git fetch --tags - - git submodule update --init --recursive - - ./bootstrap.sh + - ./scripts/mypy.sh + depends_on: + - clone -- name: build +- name: Python, flake8 image: localhost:5000/jla/mod commands: - - mkdir build - - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make - environment: - CXX: g++-7 + - ./scripts/flake8.sh + depends_on: + - clone -- name: install +- name: Symbol Visibility, json image: localhost:5000/jla/mod commands: - - cd build - - make install - -- name: build-test - image: localhost:5000/jla/mod - commands: - - cd build - - make tests - -- name: test - image: localhost:5000/jla/mod - commands: - - cd build - - make install - - ctest --output-on-failure + - ./scripts/checkJsonVisibility.sh + depends_on: + - clone --- kind: pipeline -name: g++-7, Boost 1_73_0 +name: Docker platform: os: linux @@ -59,38 +44,61 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: - CXX: g++-7 - -- name: install - image: localhost:5000/jla/mod - commands: - - cd build - - make install - -- name: build-test - image: localhost:5000/jla/mod - commands: - - cd build - - make tests - -- name: test - image: localhost:5000/jla/mod - commands: - - cd build - - make install - - ctest --output-on-failure + CXX: g++ + CXXFLAGS: -Werror + +- name: dist + image: localhost:5000/jla/mod + commands: + - cd build + - make dist + +- name: Ubuntu + image: plugins/docker + settings: + build_args: + - j=1 + dockerfile: docker/Ubuntu.Dockerfile + dry_run: true + purge: true + repo: jakobandersen/mod + tags: + - ubuntu-test + +- name: Fedora + image: plugins/docker + settings: + build_args: + - j=1 + dockerfile: docker/Fedora.Dockerfile + dry_run: true + purge: true + repo: jakobandersen/mod + tags: + - fedora-test + +- name: Arch + image: plugins/docker + settings: + build_args: + - j=1 + dockerfile: docker/Arch.Dockerfile + dry_run: true + purge: true + repo: jakobandersen/mod + tags: + - arch-test --- kind: pipeline -name: g++-7, Boost 1_74_0 +name: g++-7, Boost 1_73_0 platform: os: linux @@ -104,15 +112,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 environment: CXX: g++-7 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + - make - name: install image: localhost:5000/jla/mod @@ -131,35 +146,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build -- name: coverage +- name: simple test image: localhost:5000/jla/mod commands: - - mkdir covBuild - - cd covBuild - - cmake ../ -DBUILD_TESTING=on -DBUILD_COVERAGE=on -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cd build - make install - - make tests - - make coverage_collect - - make coverage_build - - /copyCoverage.sh - environment: - CTEST_OUTPUT_ON_FAILURE: 1 - CXX: g++-7 - volumes: - - name: www - path: /www + - cd ../ + - mod -e "smiles('O').print()" -volumes: -- name: www - host: - path: /www/results/mod +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-8, Boost 1_72_0 +name: g++-7, Boost 1_74_0 platform: os: linux @@ -173,15 +184,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 environment: - CXX: g++-8 + CXX: g++-7 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + - make - name: install image: localhost:5000/jla/mod @@ -200,56 +218,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure - ---- -kind: pipeline -name: g++-8, Boost 1_73_0 - -platform: - os: linux - arch: amd64 - -steps: -- name: bootstrap - image: localhost:5000/jla/mod - commands: - - git fetch --tags - - git submodule update --init --recursive - - ./bootstrap.sh + - ctest --output-on-failure -E cmake_add_subdirectory_build -- name: build - image: localhost:5000/jla/mod - commands: - - mkdir build - - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make - environment: - CXX: g++-8 - -- name: install +- name: simple test image: localhost:5000/jla/mod commands: - cd build - make install + - cd ../ + - mod -e "smiles('O').print()" -- name: build-test - image: localhost:5000/jla/mod - commands: - - cd build - - make tests - -- name: test +- name: test subdirectory build image: localhost:5000/jla/mod commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-8, Boost 1_74_0 +name: g++-7, Boost 1_75_0 platform: os: linux @@ -263,15 +256,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: - CXX: g++-8 + CXX: g++-7 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make - name: install image: localhost:5000/jla/mod @@ -290,56 +290,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure - ---- -kind: pipeline -name: g++-9, Boost 1_72_0 - -platform: - os: linux - arch: amd64 - -steps: -- name: bootstrap - image: localhost:5000/jla/mod - commands: - - git fetch --tags - - git submodule update --init --recursive - - ./bootstrap.sh + - ctest --output-on-failure -E cmake_add_subdirectory_build -- name: build - image: localhost:5000/jla/mod - commands: - - mkdir build - - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make - environment: - CXX: g++-9 - -- name: install +- name: simple test image: localhost:5000/jla/mod commands: - cd build - make install + - cd ../ + - mod -e "smiles('O').print()" -- name: build-test - image: localhost:5000/jla/mod - commands: - - cd build - - make tests - -- name: test +- name: test subdirectory build image: localhost:5000/jla/mod commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-9, Boost 1_73_0 +name: g++-8, Boost 1_73_0 platform: os: linux @@ -353,15 +328,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + environment: + CXX: g++-8 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - make - environment: - CXX: g++-9 - name: install image: localhost:5000/jla/mod @@ -380,11 +362,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-9, Boost 1_74_0 +name: g++-8, Boost 1_74_0 platform: os: linux @@ -398,15 +400,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + environment: + CXX: g++-8 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - make - environment: - CXX: g++-9 - name: install image: localhost:5000/jla/mod @@ -425,11 +434,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-10, Boost 1_72_0 +name: g++-8, Boost 1_75_0 platform: os: linux @@ -443,15 +472,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: - CXX: g++-10 + CXX: g++-8 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make - name: install image: localhost:5000/jla/mod @@ -470,11 +506,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-10, Boost 1_73_0 +name: g++-9, Boost 1_73_0 platform: os: linux @@ -488,15 +544,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + environment: + CXX: g++-9 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - make - environment: - CXX: g++-10 - name: install image: localhost:5000/jla/mod @@ -515,11 +578,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: g++-10, Boost 1_74_0 +name: g++-9, Boost 1_74_0 platform: os: linux @@ -533,15 +616,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + environment: + CXX: g++-9 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - make - environment: - CXX: g++-10 - name: install image: localhost:5000/jla/mod @@ -560,56 +650,61 @@ steps: commands: - cd build - make install - - ctest --output-on-failure - ---- -kind: pipeline -name: clang++-6.0, Boost 1_72_0 - -platform: - os: linux - arch: amd64 + - ctest --output-on-failure -E cmake_add_subdirectory_build -steps: -- name: bootstrap +- name: simple test image: localhost:5000/jla/mod commands: - - git fetch --tags - - git submodule update --init --recursive - - ./bootstrap.sh - -- name: build - image: localhost:5000/jla/mod - commands: - - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make - environment: - CXX: clang++-6.0 + - make install + - cd ../ + - mod -e "smiles('O').print()" -- name: install +- name: test subdirectory build image: localhost:5000/jla/mod commands: - cd build - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* -- name: build-test +- name: coverage image: localhost:5000/jla/mod commands: - - cd build + - mkdir covBuild + - cd covBuild + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_COVERAGE=on -DBOOST_ROOT=/opt/boost/1_74_0 + - make + - make install - make tests + - make coverage_collect + - make coverage_build + - /copyCoverage.sh + environment: + CTEST_OUTPUT_ON_FAILURE: 1 + CXX: g++-9 + CXXFLAGS: -Werror + volumes: + - name: www + path: /www + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* -- name: test - image: localhost:5000/jla/mod - commands: - - cd build - - make install - - ctest --output-on-failure +volumes: +- name: www + host: + path: /www/results/mod --- kind: pipeline -name: clang++-6.0, Boost 1_73_0 +name: g++-9, Boost 1_75_0 platform: os: linux @@ -623,83 +718,65 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: - CXX: clang++-6.0 - -- name: install - image: localhost:5000/jla/mod - commands: - - cd build - - make install + CXX: g++-9 + CXXFLAGS: -Werror -- name: build-test +- name: build image: localhost:5000/jla/mod commands: - cd build - - make tests + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make -- name: test +- name: install image: localhost:5000/jla/mod commands: - cd build - make install - - ctest --output-on-failure - ---- -kind: pipeline -name: clang++-6.0, Boost 1_74_0 - -platform: - os: linux - arch: amd64 - -steps: -- name: bootstrap - image: localhost:5000/jla/mod - commands: - - git fetch --tags - - git submodule update --init --recursive - - ./bootstrap.sh -- name: build +- name: build-test image: localhost:5000/jla/mod commands: - - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make - environment: - CXX: clang++-6.0 + - make tests -- name: install +- name: test image: localhost:5000/jla/mod commands: - cd build - make install + - ctest --output-on-failure -E cmake_add_subdirectory_build -- name: build-test +- name: simple test image: localhost:5000/jla/mod commands: - cd build - - make tests + - make install + - cd ../ + - mod -e "smiles('O').print()" -- name: test +- name: test subdirectory build image: localhost:5000/jla/mod commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-7, Boost 1_72_0 +name: g++-10, Boost 1_73_0 platform: os: linux @@ -713,15 +790,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 environment: - CXX: clang++-7 + CXX: g++-10 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + - make - name: install image: localhost:5000/jla/mod @@ -740,11 +824,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-7, Boost 1_73_0 +name: g++-10, Boost 1_74_0 platform: os: linux @@ -758,15 +862,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 environment: - CXX: clang++-7 + CXX: g++-10 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + - make - name: install image: localhost:5000/jla/mod @@ -785,11 +896,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-7, Boost 1_74_0 +name: g++-10, Boost 1_75_0 platform: os: linux @@ -803,15 +934,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: - CXX: clang++-7 + CXX: g++-10 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make - name: install image: localhost:5000/jla/mod @@ -830,11 +968,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-8, Boost 1_72_0 +name: clang++-8, Boost 1_73_0 platform: os: linux @@ -848,15 +1006,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 environment: CXX: clang++-8 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + - make - name: install image: localhost:5000/jla/mod @@ -875,11 +1040,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-8, Boost 1_73_0 +name: clang++-8, Boost 1_74_0 platform: os: linux @@ -893,15 +1078,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 environment: CXX: clang++-8 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + - make - name: install image: localhost:5000/jla/mod @@ -920,11 +1112,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-8, Boost 1_74_0 +name: clang++-8, Boost 1_75_0 platform: os: linux @@ -938,15 +1150,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: CXX: clang++-8 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make - name: install image: localhost:5000/jla/mod @@ -965,11 +1184,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-9, Boost 1_72_0 +name: clang++-9, Boost 1_73_0 platform: os: linux @@ -983,15 +1222,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 environment: CXX: clang++-9 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + - make - name: install image: localhost:5000/jla/mod @@ -1010,11 +1256,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-9, Boost 1_73_0 +name: clang++-9, Boost 1_74_0 platform: os: linux @@ -1028,15 +1294,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 environment: CXX: clang++-9 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + - make - name: install image: localhost:5000/jla/mod @@ -1055,11 +1328,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-9, Boost 1_74_0 +name: clang++-9, Boost 1_75_0 platform: os: linux @@ -1073,15 +1366,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: CXX: clang++-9 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make - name: install image: localhost:5000/jla/mod @@ -1100,11 +1400,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-10, Boost 1_72_0 +name: clang++-10, Boost 1_73_0 platform: os: linux @@ -1118,15 +1438,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_72_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 environment: CXX: clang++-10 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 + - make - name: install image: localhost:5000/jla/mod @@ -1145,11 +1472,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-10, Boost 1_73_0 +name: clang++-10, Boost 1_74_0 platform: os: linux @@ -1163,15 +1510,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_73_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 environment: CXX: clang++-10 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 + - make - name: install image: localhost:5000/jla/mod @@ -1190,11 +1544,31 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* --- kind: pipeline -name: clang++-10, Boost 1_74_0 +name: clang++-10, Boost 1_75_0 platform: os: linux @@ -1208,15 +1582,22 @@ steps: - git submodule update --init --recursive - ./bootstrap.sh -- name: build +- name: configure image: localhost:5000/jla/mod commands: - mkdir build - cd build - - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_74_0 - - make + - cmake ../ -DCMAKE_BUILD_TYPE=OptDebug -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 environment: CXX: clang++-10 + CXXFLAGS: -Werror + +- name: build + image: localhost:5000/jla/mod + commands: + - cd build + - cmake ../ -DBUILD_TESTING=on -DBUILD_TESTING_SANITIZERS=off -DBOOST_ROOT=/opt/boost/1_75_0 + - make - name: install image: localhost:5000/jla/mod @@ -1235,6 +1616,26 @@ steps: commands: - cd build - make install - - ctest --output-on-failure + - ctest --output-on-failure -E cmake_add_subdirectory_build + +- name: simple test + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - cd ../ + - mod -e "smiles('O').print()" + +- name: test subdirectory build + image: localhost:5000/jla/mod + commands: + - cd build + - make install + - ctest --output-on-failure -R cmake_add_subdirectory_build + when: + ref: + - refs/heads/develop + - refs/heads/master + - refs/tags/v* ... diff --git a/.github/workflows/Checks.yml b/.github/workflows/Checks.yml new file mode 100644 index 0000000..a22df74 --- /dev/null +++ b/.github/workflows/Checks.yml @@ -0,0 +1,23 @@ +name: CI +on: [push, pull_request] +jobs: + Checks: + runs-on: ubuntu-18.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + submodules: 'recursive' + - name: Set PATH + run: echo "${HOME}/.local/bin" >> $GITHUB_PATH + - name: Install pip dependencies + run: | + sudo apt install python3-setuptools python3-wheel + pip3 install -r requirements_dev.txt + - name: Python, mypy + run: ./scripts/mypy.sh + - name: Python, flake8 + run: ./scripts/flake8.sh + - name: Symbol Visibility, json + run: ./scripts/checkJsonVisibility.sh diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml new file mode 100644 index 0000000..291e2f1 --- /dev/null +++ b/.github/workflows/Linux.yml @@ -0,0 +1,55 @@ +name: CI +on: [push, pull_request] +jobs: + Ubuntu: + runs-on: ubuntu-18.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + submodules: 'recursive' + - name: Set PATH + run: echo "${HOME}/.local/bin" >> $GITHUB_PATH + - name: Install pip dependencies + run: | + sudo apt install python3-setuptools python3-wheel + pip3 install -r requirements.txt + - name: Install apt dependencies + run: | + sudo apt install -y $(bindep -b | tr '\n' ' ') + - name: Install Boost + run: | + wget https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.gz + tar -xf boost_1_74_0.tar.gz + cd boost_1_74_0 + ./bootstrap.sh --with-python=python3 --prefix=/opt/boost + ./b2 -j 2 --with-python --with-graph --with-iostreams install + - name: Install Graphviz + run: | + sudo apt install librsvg2-dev libpango1.0-dev libperl-dev + wget http://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz + tar -xf graphviz.tar.gz --one-top-level=graphviz --strip-components=1 + cd graphviz + ./configure + make -j 2 + sudo make install + - name: Bootstrap + run: ./bootstrap.sh + - name: Configure + env: + CXXFLAGS: -Werror + run: | + mkdir build + cd build + cmake ../ -DBUILD_TESTING=on -DBOOST_ROOT=/opt/boost + - name: Build + run: cd build && make -j 2 + - name: Install + run: cd build && sudo make install + - name: Build tests + run: cd build && make tests -j 2 + - name: Run tests + run: cd build && ctest --output-on-failure -j 2 + - name: Run simple test + run: mod -e "smiles('O').print()" diff --git a/.github/workflows/macOS.yml b/.github/workflows/macOS.yml new file mode 100644 index 0000000..33dd776 --- /dev/null +++ b/.github/workflows/macOS.yml @@ -0,0 +1,35 @@ +name: CI +on: [push, pull_request] +jobs: + macOS: + runs-on: macos-10.15 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + submodules: 'recursive' + - name: Install Brew dependencies + run: | + brew bundle + /usr/libexec/path_helper | sed -e 's/^PATH="//' -e 's/"; export PATH;//' | tr ":" "\n" | tail -r >> $GITHUB_PATH + - name: Install pip dependencies + run: | + pip3 install -r requirements.txt + - name: Bootstrap + run: ./bootstrap.sh + - name: Configure + run: | + mkdir build + cd build + cmake ../ -DBUILD_TESTING=on + - name: Build + run: cd build && make -j 2 + - name: Install + run: cd build && sudo make install + - name: Build tests + run: cd build && make tests -j 2 + - name: Run tests + run: cd build && ctest --output-on-failure -j 2 + - name: Run simple test + run: mod -e "smiles('O').print()" diff --git a/.gitignore b/.gitignore index 9b41e28..61a2842 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__ /VERSION /.idea +/conda/conda-bld /build /stage /test/py/**/out/ diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..f4fd291 --- /dev/null +++ b/Brewfile @@ -0,0 +1,7 @@ +brew "boost" +brew "boost-python3" +brew "open-babel" + +brew "graphviz" +brew "pdf2svg" +cask "mactex" diff --git a/CMakeLists.txt b/CMakeLists.txt index baba93c..c16fefd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.10) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) include(FindPythonModule) +include(MODUtils) ########################################################################### # Package Properties @@ -31,6 +32,7 @@ endif() ########################################################################### option(BUILD_DOC "Enable documentation building." ON) option(BUILD_POST_MOD "Enable building of the post processor." ON) +option(BUILD_POST_MOD_FMT "Enable building of the post processor Latex format files." ON) option(BUILD_PY_MOD "Enable building of the Python bindings." ON) option(BUILD_EPIM "Enable building of the EpiM extension (requires PyMØD)." ON) @@ -73,7 +75,10 @@ enable_testing() # should be included here to add the targets in the top-level ########################################################################### # Individual checks ########################################################################### -set(CMAKE_CXX_STANDARD 14) +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() set(libmod_config_dependencies "") set(libmod_config_find_files "FindPackageHandleStandardArgs.cmake;FindPackageMessage.cmake;FindPkgConfig.cmake;SelectLibraryConfigurations.cmake") @@ -81,14 +86,7 @@ set(libmod_config_find_files "FindPackageHandleStandardArgs.cmake;FindPackageMes # Boost # ------------------------------------------------------------------------- -# TODO: at Boost 1.70-1.72 there is a strange error with Boost.Pyton where the build yields: -# libs/pymod/CMakeFiles/pymod.dir/build.make:473: *** target pattern contains no '%'. Stop. -# CMakeFiles/Makefile2:681: recipe for target 'libs/pymod/CMakeFiles/pymod.dir/all' failed -# and that line has -# libs/pymod/libpymod.so: Boost::python-NOTFOUND -# so we use the CMake module only for now. -set(Boost_NO_BOOST_CMAKE ON) -set(v 1.72.0) +set(v 1.73.0) if(BUILD_PY_MOD) foreach(PY 3 34 35 36 37 38 39) set(lib "python${PY}") @@ -109,12 +107,11 @@ message(STATUS "(Boost include dir is ${Boost_INCLUDE_DIRS})") string(APPEND libmod_config_dependencies "set(Boost_NO_BOOST_CMAKE ON)\n") string(APPEND libmod_config_dependencies "set(BOOST_FOUND 0)\n") # TODO: remove when CMake 3.15 is required https://gitlab.kitware.com/cmake/cmake/issues/18590 string(APPEND libmod_config_dependencies "find_dependency(Boost ${v} COMPONENTS graph iostreams)\n") -list(APPEND libmod_config_find_files "FindBoost.cmake") # GraphCanon # ------------------------------------------------------------------------- -set(v 0.4) +set(v 0.5) if(USE_NESTED_GRAPH_CANON) message(STATUS "GraphCanon: using external/graph_canon") add_subdirectory(external/graph_canon) @@ -284,8 +281,10 @@ if(NOT hasParent) # https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/RPATH-handling set(CMAKE_SKIP_BUILD_RPATH FALSE) # use RPATH in the build tree set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) # but not the RPATH used in installation - set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}:${CMAKE_INSTALL_FULL_LIBDIR}/mod") # instead, add this one set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # in addition to those deduced automatically + # use + # set_target_properties(theTarget PROPERTIES INSTALL_RPATH "theRPATH") + # on each target that needs it endif() add_subdirectory(libs/epim) @@ -342,14 +341,17 @@ if(NOT hasParent) "${PNAME_FILE}-${CPACK_PACKAGE_VERSION}") set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES - ".swp$" + "\.swp$" "~$" "/__pycache__/" - ".pyc$" - "/.git/" - "/.idea/" + "\.pyc$" + "/\.git(/|$)" + "/\.gitmodules$" + "/\.idea/" + "/\.mypy_cache/" "/build/" "/stage/" + "/conda/conda-bld/" "/test/py/out/" "/test/py/summary/" "/test/py/.gdb_history$" diff --git a/ChangeLog.rst b/ChangeLog.rst index 8b2717d..6d786fd 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -4,6 +4,116 @@ Changes ####### + +v0.12.0 (2021-01-18) +==================== + +Incompatible Changes +-------------------- + +- Require C++17. +- Require Boost 1.73 to avoid CMake issue in 1.72. +- Require GraphCanon 0.5. +- Require Sphinx 3.4. +- Moved compilation instructions from :ref:`installation` to :ref:`compiling`. +- Renamed ``DGStratGraphState`` to :py:class:`DGStrat.GraphState`. +- Swap parameters for :cpp:func:`dg::DG::print` to be consistent with + :py:func:`DG.print`. +- The function ``mod::makeUniqueFilePrefix()`` has been renamed to + :cpp:func:`mod::post::makeUniqueFilePrefix`. +- Names for the left, context, and right graph of :py:class:`Rule` + has been moved and renamed to be nested types of :py:class:`Rule`. +- Names for graph interface types for + :py:class:`Graph`, + :py:class:`Rule`, + :py:class:`Rule.LeftGraph`, + :py:class:`Rule.ContextGraph`, and + :py:class:`Rule.RightGraph` + have been moved and renamed to be nested types of their graph class. +- Names for graph automorphism types for :py:class:`Graph` + have been moved and renamed to be nested types of :py:class:`Graph`. +- :cpp:func:`rule::Composer::eval`/:py:func:`RCEvaluator.eval` now returns a list + of results, possibly with duplicates, instead of only a collection of unique rules. + + +New Features +------------ + +- A pre-compiled Conda installation is now available on Linux, + see :ref:`installation` and https://anaconda.org/jakobandersen/mod. +- Added new higher-level installation instructions at :ref:`installation`, + with documentation for how to install via Conda and using the Docker image. +- Update ``bindep.txt`` and :ref:`quick-start` guide for Arch. +- Add ``Brewfile`` to to make installation of dependencies much easier on macOS. +- Improved verbose output from "add" strategies during + :cpp:func:`dg::Builder::execute`/:py:func:`DGBuilder.execute`. +- Improved rule application performance when evaluating + :ref:`rule strategies ` and executing + :cpp:func:`dg::Builder::apply`/:py:meth:`DGBuilder.apply`. +- Added a relaxed mode to + :cpp:func:`dg::Builder::apply`/:py:meth:`DGBuilder.apply` + via the ``onlyProper`` parameter. +- Add missing ``graph`` attributes to vertices and edges of the + four graph interfaces of :py:class:`Rule`. +- Add new class :cpp:class:`graph::Union`/:py:class:`UnionGraph`. +- Improve handling of pre-compiled Latex format files used in the + post-processor (thanks also to Nikolai Nøjgaard): + + - Add build option to not install the file during normal installation. + See ``-DBUILD_POST_MOD_FMT`` in :ref:`installation`. + - Teach the post-processor to dynamically compile the format file if it is + not installed. + - Add options :option:`mod_post --install-format` + and :option:`mod_post --install-format-sudo` + for installing/updating the pre-compiled format file after MØD was + installed. This can be used on an installation configured with + ``-DBUILD_POST_MOD_FMT=off`` or for resolving a + :ref:`known issue `. + +- Make :cpp:class:`AtomData`/:py:class:`AtomData` LessThanComparable. +- Make build work on macOS and add installation instructions. +- Rule composition: when using ``rcCommon``, skip duplicate overlaps yielded by + the underlying enumeration algorithm. + + +Bugs Fixed +---------- + +- Flush stdout in the end of + :cpp:func:`dg::ExecuteResult::list`/:py:func:`DGExecuteResult.list`. +- Fix printing/stringification of a null vertices for + :cpp:class:`graph::Graph`/:py:class:`Graph`, + :cpp:class:`rule::Rule`/:py:class:`Rule`, + :cpp:class:`rule::Rule::LeftGraph`/:py:class:`Rule.LeftGraph`, + :cpp:class:`rule::Rule::ContextGraph`/:py:class:`Rule.ContextGraph`, + :cpp:class:`rule::Rule::RightGraph`/:py:class:`Rule.ContextGraph`. +- Fix conversion of :py:class:`Graph.Edge` to ``bool``. +- Fix rule printing when hydrogens are collapsed to prevent occasional + Latex errors on the form + ``! Package pgf Error: No shape named `v-coord-' is known.``. +- Add missing ``operator!=`` for :cpp:class:`AtomData`. +- macOS build fixes: + + - Infinite recursion in doc building, due to missing toctrees. + - Disable leak sanitizer when using AppleClang as compiler. + - Disable more compiler/link options not in AppleClang. + +Other +----- + +- Doc, rearrange and deduplicate documentation for graph interfaces + in PyMØD. + Introduce the :ref:`py-protocols` section which documents common protocols + that several classes implement. + The documentation of the following classes has been simplified by mostly + referring to these protocols: + + - :py:class:`Graph` + - :py:class:`Rule` + +- Doc, improve documentation of the graph interfaces of :py:class:`Rule`. + + v0.11.0 (2020-08-31) ==================== @@ -56,7 +166,7 @@ New Features - Added :cpp:func:`dg::Printer::setGraphvizPrefix`/:cpp:func:`dg::Printer::getGraphvizPrefix`/:py:attr:`DGPrinter.graphvizPrefix`. - Added :cpp:func:`makeUniqueFilePrefix`/:py:func:`makeUniqueFilePrefix`. - Improve verbosity level 8 information from - :cpp:func:`dg::Builder::execute`/:py:func:`DGBuilder.execute` to the unvierse + :cpp:func:`dg::Builder::execute`/:py:func:`DGBuilder.execute` to the universe size. - Make :cpp:class:`LabelSettings`/:py:class:`LabelSettings` equality comparable. @@ -139,7 +249,7 @@ Bugs Fixed - Graph printing, fix coordinate overwrite when printing the same graph multiple times, but with different rotation or mirror settings, the layout of the last printing would be used for all of them. - Those with non-zero rotaion and mirroring now have their own file name. + Those with non-zero rotation and mirroring now have their own file name. - DG printing: fix bending of head/tail arrows when a tail vertex is also a head vertex so arrows don't overlap. - `#8 `__: @@ -170,7 +280,7 @@ Other :py:func:`DGPrinter.pushVertexColour`, :py:func:`DGPrinter.pushEdgeColour`, :py:func:`DGPrinter.setRotationOverwrite`, - :py:func:`DGPrinter.setMirrorOverwrite`, + :py:func:`DGPrinter.setMirrorOverwrite` accepts a constant as well as a callback. - Doc, fix callback type for :py:func:`DGPrinter.setRotationOverwrite` and @@ -374,16 +484,16 @@ New Features - :cpp:func:`dg::DG::HyperEdge::print`/:py:func:`DGHyperEdge.print` now returns a list of file data. - The vertices and edges of all graph interfaces now have a conversion to bool: - - :cpp:class:`graph::Graph::Vertex`/:py:class:`GraphVertex`, - :cpp:class:`graph::Graph::Edge`/:py:class:`GraphEdge` - - :cpp:class:`rule::Rule::Vertex`/:py:class:`RuleVertex`, - :cpp:class:`rule::Rule::Edge`/:py:class:`RuleEdge` - - :cpp:class:`rule::Rule::LeftGraph::Vertex`/:py:class:`RuleLeftGraphVertex`, - :cpp:class:`rule::Rule::LeftGraph::Edge`/:py:class:`RuleLeftGraphEdge` - - :cpp:class:`rule::Rule::ContextGraph::Vertex`/:py:class:`RuleContextGraphVertex`, - :cpp:class:`rule::Rule::ContextGraph::Edge`/:py:class:`RuleContextGraphEdge` - - :cpp:class:`rule::Rule::RightGraph::Vertex`/:py:class:`RuleRightGraphVertex`, - :cpp:class:`rule::Rule::RightGraph::Edge`/:py:class:`RuleRightGraphEdge` + - :cpp:class:`graph::Graph::Vertex`/:py:class:`Graph.Vertex`, + :cpp:class:`graph::Graph::Edge`/:py:class:`Graph.Edge` + - :cpp:class:`rule::Rule::Vertex`/:py:class:`Rule.Vertex`, + :cpp:class:`rule::Rule::Edge`/:py:class:`Rule.Edge` + - :cpp:class:`rule::Rule::LeftGraph::Vertex`/:py:class:`Rule.LeftGraph.Vertex`, + :cpp:class:`rule::Rule::LeftGraph::Edge`/:py:class:`Rule.LeftGraph.Edge` + - :cpp:class:`rule::Rule::ContextGraph::Vertex`/:py:class:`Rule.ContextGraph.Vertex`, + :cpp:class:`rule::Rule::ContextGraph::Edge`/:py:class:`Rule.ContextGraph.Edge` + - :cpp:class:`rule::Rule::RightGraph::Vertex`/:py:class:`Rule.RightGraph.Vertex`, + :cpp:class:`rule::Rule::RightGraph::Edge`/:py:class:`Rule.RightGraph.Edge` - :cpp:class:`dg::DG::Vertex`/:py:class:`DGVertex`, :cpp:class:`dg::DG::HyperEdge`/:py:class:`DGHyperEdge` diff --git a/bindep.txt b/bindep.txt index 7011676..fd30ae9 100644 --- a/bindep.txt +++ b/bindep.txt @@ -1,23 +1,35 @@ file make -g++ +gcc [platform:arch] +g++ [platform:dpkg platform:rpm] libasan [platform:rpm testing] libubsan [platform:rpm testing] +pkgconf [platform:arch] cmake -graphviz [platform:rpm] +boost [platform:arch] +boost-devel [platform:rpm] + +graphviz [platform:arch platform:rpm] pdf2svg + +python [platform:arch] python3-dev [platform:dpkg] python3-devel [platform:rpm] + +openbabel [platform:arch] libopenbabel-dev [platform:dpkg] openbabel-devel [platform:rpm] -coinor-libcbc-dev [platform:dpkg] -coin-or-Cbc-devel [platform:rpm] + +texlive-science [platform:arch] +texlive-pictures [platform:arch] +texlive-latexextra [platform:arch] texlive-science [platform:dpkg] texlive-pictures [platform:dpkg] texlive-latex-extra [platform:dpkg] lmodern [platform:dpkg] + texlive-collection-mathscience [platform:rpm] texlive-collection-pictures [platform:rpm] texlive-collection-latexextra [platform:rpm] diff --git a/bootstrap.sh b/bootstrap.sh index bb32476..c642849 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -33,10 +33,14 @@ function doDir { echo ")" echo "" if test -d test; then - echo "set(mod_$1_TEST_FILES" + echo "set(mod_$1_TEST_CPP_FILES" find test -iname "*.cpp" | sed "s/^test\/\(.*\)\.cpp$/\1/" | indent echo ")" echo "" + echo "set(mod_$1_TEST_PY_FILES" + find test -iname "*.py" | sed "s/^test\/\(.*\)\.py$/\1/" | indent + echo ")" + echo "" fi cd ../.. } diff --git a/cmake/FindBoost.cmake b/cmake/FindBoost.cmake deleted file mode 100644 index 5d9f1e2..0000000 --- a/cmake/FindBoost.cmake +++ /dev/null @@ -1,2234 +0,0 @@ -# This is a mix of the file from CMake v3.14.7, but with the dependency specification -# from CMake 3.16. The newer ones uses a policy added in CMake 3.12, but we only require 3.10. - -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindBoost ---------- - -Find Boost include dirs and libraries - -Use this module by invoking find_package with the form:: - - find_package(Boost - [version] [EXACT] # Minimum or EXACT version e.g. 1.67.0 - [REQUIRED] # Fail with error if Boost is not found - [COMPONENTS ...] # Boost libraries by their canonical name - # e.g. "date_time" for "libboost_date_time" - [OPTIONAL_COMPONENTS ...] - # Optional Boost libraries by their canonical name) - ) # e.g. "date_time" for "libboost_date_time" - -This module finds headers and requested component libraries OR a CMake -package configuration file provided by a "Boost CMake" build. For the -latter case skip to the "Boost CMake" section below. For the former -case results are reported in variables:: - - Boost_FOUND - True if headers and requested libraries were found - Boost_INCLUDE_DIRS - Boost include directories - Boost_LIBRARY_DIRS - Link directories for Boost libraries - Boost_LIBRARIES - Boost component libraries to be linked - Boost__FOUND - True if component was found ( is upper-case) - Boost__LIBRARY - Libraries to link for component (may include - target_link_libraries debug/optimized keywords) - Boost_VERSION - BOOST_VERSION value from boost/version.hpp - Boost_LIB_VERSION - Version string appended to library filenames - Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) - Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) - Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) - Boost_VERSION_STRING - Boost version number in x.y.z format - Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) - - Pass to add_definitions() to have diagnostic - information about Boost's automatic linking - displayed during compilation - -Note that Boost Python components require a Python version suffix -(Boost 1.67 and later), e.g. ``python36`` or ``python27`` for the -versions built against Python 3.6 and 2.7, respectively. This also -applies to additional components using Python including -``mpi_python`` and ``numpy``. Earlier Boost releases may use -distribution-specific suffixes such as ``2``, ``3`` or ``2.7``. -These may also be used as suffixes, but note that they are not -portable. - -This module reads hints about search locations from variables:: - - BOOST_ROOT - Preferred installation prefix - (or BOOSTROOT) - BOOST_INCLUDEDIR - Preferred include directory e.g. /include - BOOST_LIBRARYDIR - Preferred library directory e.g. /lib - Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not - specified by these hint variables. Default is OFF. - Boost_ADDITIONAL_VERSIONS - - List of Boost versions not known to this module - (Boost install locations may contain the version) - -and saves search results persistently in CMake cache entries:: - - Boost_INCLUDE_DIR - Directory containing Boost headers - Boost_LIBRARY_DIR_RELEASE - Directory containing release Boost libraries - Boost_LIBRARY_DIR_DEBUG - Directory containing debug Boost libraries - Boost__LIBRARY_DEBUG - Component library debug variant - Boost__LIBRARY_RELEASE - Component library release variant - -The following :prop_tgt:`IMPORTED` targets are also defined:: - - Boost::boost - Target for header-only dependencies - (Boost include directory) - Boost:: - Target for specific component dependency - (shared or static library); is lower- - case - Boost::diagnostic_definitions - interface target to enable diagnostic - information about Boost's automatic linking - during compilation (adds BOOST_LIB_DIAGNOSTIC) - Boost::disable_autolinking - interface target to disable automatic - linking with MSVC (adds BOOST_ALL_NO_LIB) - Boost::dynamic_linking - interface target to enable dynamic linking - linking with MSVC (adds BOOST_ALL_DYN_LINK) - -Implicit dependencies such as Boost::filesystem requiring -Boost::system will be automatically detected and satisfied, even -if system is not specified when using find_package and if -Boost::system is not added to target_link_libraries. If using -Boost::thread, then Threads::Threads will also be added automatically. - -It is important to note that the imported targets behave differently -than variables created by this module: multiple calls to -find_package(Boost) in the same directory or sub-directories with -different options (e.g. static or shared) will not override the -values of the targets created by the first call. - -Users may set these hints or results as cache entries. Projects -should not read these entries directly but instead use the above -result variables. Note that some hint names start in upper-case -"BOOST". One may specify these as environment variables if they are -not specified as CMake variables or cache entries. - -This module first searches for the Boost header files using the above -hint variables (excluding BOOST_LIBRARYDIR) and saves the result in -Boost_INCLUDE_DIR. Then it searches for requested component libraries -using the above hints (excluding BOOST_INCLUDEDIR and -Boost_ADDITIONAL_VERSIONS), "lib" directories near Boost_INCLUDE_DIR, -and the library name configuration settings below. It saves the -library directories in Boost_LIBRARY_DIR_DEBUG and -Boost_LIBRARY_DIR_RELEASE and individual library -locations in Boost__LIBRARY_DEBUG and Boost__LIBRARY_RELEASE. -When one changes settings used by previous searches in the same build -tree (excluding environment variables) this module discards previous -search results affected by the changes and searches again. - -Boost libraries come in many variants encoded in their file name. -Users or projects may tell this module which variant to find by -setting variables:: - - Boost_USE_DEBUG_LIBS - Set to ON or OFF to specify whether to search - and use the debug libraries. Default is ON. - Boost_USE_RELEASE_LIBS - Set to ON or OFF to specify whether to search - and use the release libraries. Default is ON. - Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded - libraries ('mt' tag). Default is ON. - Boost_USE_STATIC_LIBS - Set to ON to force the use of the static - libraries. Default is OFF. - Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use - libraries linked statically to the C++ runtime - ('s' tag). Default is platform dependent. - Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use - libraries linked to the MS debug C++ runtime - ('g' tag). Default is ON. - Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a - debug Python build ('y' tag). Default is OFF. - Boost_USE_STLPORT - Set to ON to use libraries compiled with - STLPort ('p' tag). Default is OFF. - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - - Set to ON to use libraries compiled with - STLPort deprecated "native iostreams" - ('n' tag). Default is OFF. - Boost_COMPILER - Set to the compiler-specific library suffix - (e.g. "-gcc43"). Default is auto-computed - for the C++ compiler in use. A list may be - used if multiple compatible suffixes should - be tested for, in decreasing order of - preference. - Boost_ARCHITECTURE - Set to the architecture-specific library suffix - (e.g. "-x64"). Default is auto-computed for the - C++ compiler in use. - Boost_THREADAPI - Suffix for "thread" component library name, - such as "pthread" or "win32". Names with - and without this suffix will both be tried. - Boost_NAMESPACE - Alternate namespace used to build boost with - e.g. if set to "myboost", will search for - myboost_thread instead of boost_thread. - -Other variables one may set to control this module are:: - - Boost_DEBUG - Set to ON to enable debug output from FindBoost. - Please enable this before filing any bug report. - Boost_DETAILED_FAILURE_MSG - - Set to ON to add detailed information to the - failure message even when the REQUIRED option - is not given to the find_package call. - Boost_REALPATH - Set to ON to resolve symlinks for discovered - libraries to assist with packaging. For example, - the "system" component library may be resolved to - "/usr/lib/libboost_system.so.1.67.0" instead of - "/usr/lib/libboost_system.so". This does not - affect linking and should not be enabled unless - the user needs this information. - Boost_LIBRARY_DIR - Default value for Boost_LIBRARY_DIR_RELEASE and - Boost_LIBRARY_DIR_DEBUG. - -On Visual Studio and Borland compilers Boost headers request automatic -linking to corresponding libraries. This requires matching libraries -to be linked explicitly or available in the link library search path. -In this case setting Boost_USE_STATIC_LIBS to OFF may not achieve -dynamic linking. Boost automatic linking typically requests static -libraries with a few exceptions (such as Boost.Python). Use:: - - add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) - -to ask Boost to report information about automatic linking requests. - -Example to find Boost headers only:: - - find_package(Boost 1.36.0) - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - add_executable(foo foo.cc) - endif() - -Example to find Boost libraries and use imported targets:: - - find_package(Boost 1.56 REQUIRED COMPONENTS - date_time filesystem iostreams) - add_executable(foo foo.cc) - target_link_libraries(foo Boost::date_time Boost::filesystem - Boost::iostreams) - -Example to find Boost Python 3.6 libraries and use imported targets:: - - find_package(Boost 1.67 REQUIRED COMPONENTS - python36 numpy36) - add_executable(foo foo.cc) - target_link_libraries(foo Boost::python36 Boost::numpy36) - -Example to find Boost headers and some *static* (release only) libraries:: - - set(Boost_USE_STATIC_LIBS ON) # only find static libs - set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and - set(Boost_USE_RELEASE_LIBS ON) # only find release libs - set(Boost_USE_MULTITHREADED ON) - set(Boost_USE_STATIC_RUNTIME OFF) - find_package(Boost 1.66.0 COMPONENTS date_time filesystem system ...) - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - add_executable(foo foo.cc) - target_link_libraries(foo ${Boost_LIBRARIES}) - endif() - -Boost CMake -^^^^^^^^^^^ - -If Boost was built using the boost-cmake project it provides a package -configuration file for use with find_package's Config mode. This -module looks for the package configuration file called -BoostConfig.cmake or boost-config.cmake and stores the result in cache -entry "Boost_DIR". If found, the package configuration file is loaded -and this module returns with no further action. See documentation of -the Boost CMake package configuration for details on what it provides. - -Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. -#]=======================================================================] - -# Save project's policies -cmake_policy(PUSH) -cmake_policy(SET CMP0057 NEW) # if IN_LIST - -#------------------------------------------------------------------------------- -# Before we go searching, check whether boost-cmake is available, unless the -# user specifically asked NOT to search for boost-cmake. -# -# If Boost_DIR is set, this behaves as any find_package call would. If not, -# it looks at BOOST_ROOT and BOOSTROOT to find Boost. -# -if (NOT Boost_NO_BOOST_CMAKE) - # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, - # since these are more conventional for Boost. - if ("$ENV{Boost_DIR}" STREQUAL "") - if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) - elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOSTROOT}) - endif() - endif() - - # Do the same find_package call but look specifically for the CMake version. - # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no - # need to delegate them to this find_package call. - find_package(Boost QUIET NO_MODULE) - mark_as_advanced(Boost_DIR) - - # If we found boost-cmake, then we're done. Print out what we found. - # Otherwise let the rest of the module try to find it. - if (Boost_FOUND) - message(STATUS "Boost ${Boost_FIND_VERSION} found.") - if (Boost_FIND_COMPONENTS) - message(STATUS "Found Boost components:\n ${Boost_FIND_COMPONENTS}") - endif() - # Restore project's policies - cmake_policy(POP) - return() - endif() -endif() - - -#------------------------------------------------------------------------------- -# FindBoost functions & macros -# - -############################################ -# -# Check the existence of the libraries. -# -############################################ -# This macro was taken directly from the FindQt4.cmake file that is included -# with the CMake distribution. This is NOT my work. All work was done by the -# original authors of the FindQt4.cmake file. Only minor modifications were -# made to remove references to Qt and make this file more generally applicable -# And ELSE/ENDIF pairs were removed for readability. -######################################################################### - -macro(_Boost_ADJUST_LIB_VARS basename) - if(Boost_INCLUDE_DIR ) - if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) - # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for - # single-config generators, set optimized and debug libraries - get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if(_isMultiConfig OR CMAKE_BUILD_TYPE) - set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - else() - # For single-config generators where CMAKE_BUILD_TYPE has no value, - # just use the release libraries - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - # FIXME: This probably should be set for both cases - set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # if only the release version was found, set the debug variable also to the release version - if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) - set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) - endif() - - # if only the debug version was found, set the release variable also to the debug version - if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) - set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # If the debug & release library ends up being the same, omit the keywords - if("${Boost_${basename}_LIBRARY_RELEASE}" STREQUAL "${Boost_${basename}_LIBRARY_DEBUG}") - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - - if(Boost_${basename}_LIBRARY AND Boost_${basename}_HEADER) - set(Boost_${basename}_FOUND ON) - if("x${basename}" STREQUAL "xTHREAD" AND NOT TARGET Threads::Threads) - string(APPEND Boost_ERROR_REASON_THREAD " (missing dependency: Threads)") - set(Boost_THREAD_FOUND OFF) - endif() - endif() - - endif() - # Make variables changeable to the advanced user - mark_as_advanced( - Boost_${basename}_LIBRARY_RELEASE - Boost_${basename}_LIBRARY_DEBUG - ) -endmacro() - -# Detect changes in used variables. -# Compares the current variable value with the last one. -# In short form: -# v != v_LAST -> CHANGED = 1 -# v is defined, v_LAST not -> CHANGED = 1 -# v is not defined, but v_LAST is -> CHANGED = 1 -# otherwise -> CHANGED = 0 -# CHANGED is returned in variable named ${changed_var} -macro(_Boost_CHANGE_DETECT changed_var) - set(${changed_var} 0) - foreach(v ${ARGN}) - if(DEFINED _Boost_COMPONENTS_SEARCHED) - if(${v}) - if(_${v}_LAST) - string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) - else() - set(_${v}_CHANGED 1) - endif() - elseif(_${v}_LAST) - set(_${v}_CHANGED 1) - endif() - if(_${v}_CHANGED) - set(${changed_var} 1) - endif() - else() - set(_${v}_CHANGED 0) - endif() - endforeach() -endmacro() - -# -# Find the given library (var). -# Use 'build_type' to support different lib paths for RELEASE or DEBUG builds -# -macro(_Boost_FIND_LIBRARY var build_type) - - find_library(${var} ${ARGN}) - - if(${var}) - # If this is the first library found then save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. - if(NOT Boost_LIBRARY_DIR_${build_type}) - get_filename_component(_dir "${${var}}" PATH) - set(Boost_LIBRARY_DIR_${build_type} "${_dir}" CACHE PATH "Boost library directory ${build_type}" FORCE) - endif() - elseif(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - # Try component-specific hints but do not save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. - find_library(${var} HINTS ${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT} ${ARGN}) - endif() - - # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is known then search only there. - if(Boost_LIBRARY_DIR_${build_type}) - set(_boost_LIBRARY_SEARCH_DIRS_${build_type} ${Boost_LIBRARY_DIR_${build_type}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " Boost_LIBRARY_DIR_${build_type} = ${Boost_LIBRARY_DIR_${build_type}}" - " _boost_LIBRARY_SEARCH_DIRS_${build_type} = ${_boost_LIBRARY_SEARCH_DIRS_${build_type}}") - endif() - endif() -endmacro() - -#------------------------------------------------------------------------------- - -# Convert CMAKE_CXX_COMPILER_VERSION to boost compiler suffix version. -function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION _OUTPUT_VERSION_MAJOR _OUTPUT_VERSION_MINOR) - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1" - _boost_COMPILER_VERSION_MAJOR "${CMAKE_CXX_COMPILER_VERSION}") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\2" - _boost_COMPILER_VERSION_MINOR "${CMAKE_CXX_COMPILER_VERSION}") - - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}${_boost_COMPILER_VERSION_MINOR}") - - set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) - set(${_OUTPUT_VERSION_MAJOR} ${_boost_COMPILER_VERSION_MAJOR} PARENT_SCOPE) - set(${_OUTPUT_VERSION_MINOR} ${_boost_COMPILER_VERSION_MINOR} PARENT_SCOPE) -endfunction() - -# -# Take a list of libraries with "thread" in it -# and prepend duplicates with "thread_${Boost_THREADAPI}" -# at the front of the list -# -function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) - set(_orig_libnames ${ARGN}) - string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") - set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) -endfunction() - -# -# If a library is found, replace its cache entry with its REALPATH -# -function(_Boost_SWAP_WITH_REALPATH _library _docstring) - if(${_library}) - get_filename_component(_boost_filepathreal ${${_library}} REALPATH) - unset(${_library} CACHE) - set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") - endif() -endfunction() - -function(_Boost_CHECK_SPELLING _var) - if(${_var}) - string(TOUPPER ${_var} _var_UC) - message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") - endif() -endfunction() - -# Guesses Boost's compiler prefix used in built library names -# Returns the guess by setting the variable pointed to by _ret -function(_Boost_GUESS_COMPILER_PREFIX _ret) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") - if(WIN32) - set (_boost_COMPILER "-iw") - else() - set (_boost_COMPILER "-il") - endif() - elseif (GHSMULTI) - set(_boost_COMPILER "-ghs") - elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 150) - # Not yet known. - set(_boost_COMPILER "") - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 140) - # MSVC toolset 14.x versions are forward compatible. - set(_boost_COMPILER "") - foreach(v 9 8 7 6 5 4 3 2 1 0) - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 14${v}) - list(APPEND _boost_COMPILER "-vc14${v}") - endif() - endforeach() - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80) - set(_boost_COMPILER "-vc${MSVC_TOOLSET_VERSION}") - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10) - set(_boost_COMPILER "-vc71") - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) # Good luck! - set(_boost_COMPILER "-vc7") # yes, this is correct - else() # VS 6.0 Good luck! - set(_boost_COMPILER "-vc6") # yes, this is correct - endif() - elseif (BORLAND) - set(_boost_COMPILER "-bcb") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") - set(_boost_COMPILER "-sw") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "XL") - set(_boost_COMPILER "-xlc") - elseif (MINGW) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR) - set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") - endif() - elseif (UNIX) - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR) - if(NOT Boost_VERSION VERSION_LESS 106900) - # From GCC 5 and clang 4, versioning changes and minor becomes patch. - # For those compilers, patch is exclude from compiler tag in Boost 1.69+ library naming. - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 4) - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 3) - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") - endif() - endif() - - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 - else() - # Determine which version of GCC we have. - if(APPLE) - if(Boost_MINOR_VERSION) - if(${Boost_MINOR_VERSION} GREATER 35) - # In Boost 1.36.0 and newer, the mangled compiler name used - # on macOS/Darwin is "xgcc". - set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") - else() - # In Boost <= 1.35.0, there is no mangled compiler name for - # the macOS/Darwin version of GCC. - set(_boost_COMPILER "") - endif() - else() - # We don't know the Boost version, so assume it's - # pre-1.36.0. - set(_boost_COMPILER "") - endif() - else() - set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") - endif() - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # TODO: Find out any Boost version constraints vs clang support. - set(_boost_COMPILER "-clang${_boost_COMPILER_VERSION}") - endif() - else() - # TODO at least Boost_DEBUG here? - set(_boost_COMPILER "") - endif() - set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) -endfunction() - -# -# Get component dependencies. Requires the dependencies to have been -# defined for the Boost release version. -# -# component - the component to check -# _ret - list of library dependencies -# -function(_Boost_COMPONENT_DEPENDENCIES component _ret) - # Note: to add a new Boost release, run - # - # % cmake -DBOOST_DIR=/path/to/boost/source -P Utilities/Scripts/BoostScanDeps.cmake - # - # The output may be added in a new block below. If it's the same as - # the previous release, simply update the version range of the block - # for the previous release. Also check if any new components have - # been added, and add any new components to - # _Boost_COMPONENT_HEADERS. - # - # This information was originally generated by running - # BoostScanDeps.cmake against every boost release to date supported - # by FindBoost: - # - # % for version in /path/to/boost/sources/* - # do - # cmake -DBOOST_DIR=$version -P Utilities/Scripts/BoostScanDeps.cmake - # done - # - # The output was then updated by search and replace with these regexes: - # - # - Strip message(STATUS) prefix dashes - # s;^-- ;; - # - Indent - # s;^set(; set(;; - # - Add conditionals - # s;Scanning /path/to/boost/sources/boost_\(.*\)_\(.*\)_\(.*); elseif(NOT Boost_VERSION VERSION_LESS \10\20\3 AND Boost_VERSION VERSION_LESS xxxx); - # - # This results in the logic seen below, but will require the xxxx - # replacing with the following Boost release version (or the next - # minor version to be released, e.g. 1.59 was the latest at the time - # of writing, making 1.60 the next, so 106000 is the needed version - # number). Identical consecutive releases were then merged together - # by updating the end range of the first block and removing the - # following redundant blocks. - # - # Running the script against all historical releases should be - # required only if the BoostScanDeps.cmake script logic is changed. - # The addition of a new release should only require it to be run - # against the new release. - - # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") - set(component "${CMAKE_MATCH_1}") - set(component_python_version "${CMAKE_MATCH_2}") - endif() - - set(_Boost_IMPORTED_TARGETS TRUE) - if(Boost_VERSION AND Boost_VERSION VERSION_LESS 103300) - message(WARNING "Imported targets and dependency information not available for Boost version ${Boost_VERSION} (all versions older than 1.33)") - set(_Boost_IMPORTED_TARGETS FALSE) - elseif(NOT Boost_VERSION VERSION_LESS 103300 AND Boost_VERSION VERSION_LESS 103500) - set(_Boost_IOSTREAMS_DEPENDENCIES regex thread) - set(_Boost_REGEX_DEPENDENCIES thread) - set(_Boost_WAVE_DEPENDENCIES filesystem thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103500 AND Boost_VERSION VERSION_LESS 103600) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103600 AND Boost_VERSION VERSION_LESS 103800) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103800 AND Boost_VERSION VERSION_LESS 104300) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104300 AND Boost_VERSION VERSION_LESS 104400) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104400 AND Boost_VERSION VERSION_LESS 104500) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random serialization) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES serialization filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104500 AND Boost_VERSION VERSION_LESS 104700) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104700 AND Boost_VERSION VERSION_LESS 104800) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104800 AND Boost_VERSION VERSION_LESS 105000) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105000 AND Boost_VERSION VERSION_LESS 105300) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105300 AND Boost_VERSION VERSION_LESS 105400) - set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105400 AND Boost_VERSION VERSION_LESS 105500) - set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105500 AND Boost_VERSION VERSION_LESS 105600) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105600 AND Boost_VERSION VERSION_LESS 105900) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105900 AND Boost_VERSION VERSION_LESS 106000) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106000 AND Boost_VERSION VERSION_LESS 106100) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106100 AND Boost_VERSION VERSION_LESS 106200) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106300) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106300 AND Boost_VERSION VERSION_LESS 106500) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_COROUTINE2_DEPENDENCIES context fiber thread chrono system date_time) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106500 AND Boost_VERSION VERSION_LESS 106700) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106700 AND Boost_VERSION VERSION_LESS 106800) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106800 AND Boost_VERSION VERSION_LESS 106900) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106900 AND Boost_VERSION VERSION_LESS 107000) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION_STRING VERSION_LESS 1.70.0 AND Boost_VERSION_STRING VERSION_LESS 1.72.0) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION_STRING VERSION_LESS 1.72.0) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l chrono atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(NOT Boost_VERSION_STRING VERSION_LESS 1.75.0) - message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") - endif() - endif() - - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) - - string(REGEX REPLACE ";" " " _boost_DEPS_STRING "${_Boost_${uppercomponent}_DEPENDENCIES}") - if (NOT _boost_DEPS_STRING) - set(_boost_DEPS_STRING "(none)") - endif() - # message(STATUS "Dependencies for Boost::${component}: ${_boost_DEPS_STRING}") -endfunction() - -# -# Get component headers. This is the primary header (or headers) for -# a given component, and is used to check that the headers are present -# as well as the library itself as an extra sanity check of the build -# environment. -# -# component - the component to check -# _hdrs -# -function(_Boost_COMPONENT_HEADERS component _hdrs) - # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") - set(component "${CMAKE_MATCH_1}") - set(component_python_version "${CMAKE_MATCH_2}") - endif() - - # Note: new boost components will require adding here. The header - # must be present in all versions of Boost providing a library. - set(_Boost_ATOMIC_HEADERS "boost/atomic.hpp") - set(_Boost_CHRONO_HEADERS "boost/chrono.hpp") - set(_Boost_CONTAINER_HEADERS "boost/container/container_fwd.hpp") - set(_Boost_CONTRACT_HEADERS "boost/contract.hpp") - if(Boost_VERSION VERSION_LESS 106100) - set(_Boost_CONTEXT_HEADERS "boost/context/all.hpp") - else() - set(_Boost_CONTEXT_HEADERS "boost/context/detail/fcontext.hpp") - endif() - set(_Boost_COROUTINE_HEADERS "boost/coroutine/all.hpp") - set(_Boost_DATE_TIME_HEADERS "boost/date_time/date.hpp") - set(_Boost_EXCEPTION_HEADERS "boost/exception/exception.hpp") - set(_Boost_FIBER_HEADERS "boost/fiber/all.hpp") - set(_Boost_FILESYSTEM_HEADERS "boost/filesystem/path.hpp") - set(_Boost_GRAPH_HEADERS "boost/graph/adjacency_list.hpp") - set(_Boost_GRAPH_PARALLEL_HEADERS "boost/graph/adjacency_list.hpp") - set(_Boost_IOSTREAMS_HEADERS "boost/iostreams/stream.hpp") - set(_Boost_LOCALE_HEADERS "boost/locale.hpp") - set(_Boost_LOG_HEADERS "boost/log/core.hpp") - set(_Boost_LOG_SETUP_HEADERS "boost/log/detail/setup_config.hpp") - set(_Boost_MATH_HEADERS "boost/math_fwd.hpp") - set(_Boost_MATH_C99_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_C99F_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_C99L_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1F_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1L_HEADERS "boost/math/tr1.hpp") - set(_Boost_MPI_HEADERS "boost/mpi.hpp") - set(_Boost_MPI_PYTHON_HEADERS "boost/mpi/python/config.hpp") - set(_Boost_NUMPY_HEADERS "boost/python/numpy.hpp") - set(_Boost_PRG_EXEC_MONITOR_HEADERS "boost/test/prg_exec_monitor.hpp") - set(_Boost_PROGRAM_OPTIONS_HEADERS "boost/program_options.hpp") - set(_Boost_PYTHON_HEADERS "boost/python.hpp") - set(_Boost_RANDOM_HEADERS "boost/random.hpp") - set(_Boost_REGEX_HEADERS "boost/regex.hpp") - set(_Boost_SERIALIZATION_HEADERS "boost/serialization/serialization.hpp") - set(_Boost_SIGNALS_HEADERS "boost/signals.hpp") - set(_Boost_STACKTRACE_ADDR2LINE_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_BACKTRACE_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_BASIC_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_NOOP_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_WINDBG_CACHED_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_WINDBG_HEADERS "boost/stacktrace.hpp") - set(_Boost_SYSTEM_HEADERS "boost/system/config.hpp") - set(_Boost_TEST_EXEC_MONITOR_HEADERS "boost/test/test_exec_monitor.hpp") - set(_Boost_THREAD_HEADERS "boost/thread.hpp") - set(_Boost_TIMER_HEADERS "boost/timer.hpp") - set(_Boost_TYPE_ERASURE_HEADERS "boost/type_erasure/config.hpp") - set(_Boost_UNIT_TEST_FRAMEWORK_HEADERS "boost/test/framework.hpp") - set(_Boost_WAVE_HEADERS "boost/wave.hpp") - set(_Boost_WSERIALIZATION_HEADERS "boost/archive/text_wiarchive.hpp") - if(WIN32) - set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") - set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") - endif() - - string(TOUPPER ${component} uppercomponent) - set(${_hdrs} ${_Boost_${uppercomponent}_HEADERS} PARENT_SCOPE) - - string(REGEX REPLACE ";" " " _boost_HDRS_STRING "${_Boost_${uppercomponent}_HEADERS}") - if (NOT _boost_HDRS_STRING) - set(_boost_HDRS_STRING "(none)") - endif() - # message(STATUS "Headers for Boost::${component}: ${_boost_HDRS_STRING}") -endfunction() - -# -# Determine if any missing dependencies require adding to the component list. -# -# Sets _Boost_${COMPONENT}_DEPENDENCIES for each required component, -# plus _Boost_IMPORTED_TARGETS (TRUE if imported targets should be -# defined; FALSE if dependency information is unavailable). -# -# componentvar - the component list variable name -# extravar - the indirect dependency list variable name -# -# -function(_Boost_MISSING_DEPENDENCIES componentvar extravar) - # _boost_unprocessed_components - list of components requiring processing - # _boost_processed_components - components already processed (or currently being processed) - # _boost_new_components - new components discovered for future processing - # - list(APPEND _boost_unprocessed_components ${${componentvar}}) - - while(_boost_unprocessed_components) - list(APPEND _boost_processed_components ${_boost_unprocessed_components}) - foreach(component ${_boost_unprocessed_components}) - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES) - set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) - foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES}) - if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components)) - list(APPEND _boost_new_components ${componentdep}) - endif() - endforeach() - endforeach() - set(_boost_unprocessed_components ${_boost_new_components}) - unset(_boost_new_components) - endwhile() - set(_boost_extra_components ${_boost_processed_components}) - if(_boost_extra_components AND ${componentvar}) - list(REMOVE_ITEM _boost_extra_components ${${componentvar}}) - endif() - set(${componentvar} ${_boost_processed_components} PARENT_SCOPE) - set(${extravar} ${_boost_extra_components} PARENT_SCOPE) -endfunction() - -# -# Some boost libraries may require particular set of compler features. -# The very first one was `boost::fiber` introduced in Boost 1.62. -# One can check required compiler features of it in -# - `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`; -# - `${Boost_ROOT}/libs/context/build/Jamfile.v2`. -# -# TODO (Re)Check compiler features on (every?) release ??? -# One may use the following command to get the files to check: -# -# $ find . -name Jamfile.v2 | grep build | xargs grep -l cxx1 -# -function(_Boost_COMPILER_FEATURES component _ret) - # Boost >= 1.62 - if(NOT Boost_VERSION VERSION_LESS 106200) - set(_Boost_FIBER_COMPILER_FEATURES - cxx_alias_templates - cxx_auto_type - cxx_constexpr - cxx_defaulted_functions - cxx_final - cxx_lambdas - cxx_noexcept - cxx_nullptr - cxx_rvalue_references - cxx_thread_local - cxx_variadic_templates - ) - # Compiler feature for `context` same as for `fiber`. - set(_Boost_CONTEXT_COMPILER_FEATURES ${_Boost_FIBER_COMPILER_FEATURES}) - endif() - - # Boost Contract library available in >= 1.67 - if(NOT Boost_VERSION_STRING VERSION_LESS 1.67.0) - # From `libs/contract/build/boost_contract_build.jam` - set(_Boost_CONTRACT_COMPILER_FEATURES - cxx_lambdas - cxx_variadic_templates - ) - endif() - - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE) -endfunction() - -# -# Update library search directory hint variable with paths used by prebuilt boost binaries. -# -# Prebuilt windows binaries (https://sourceforge.net/projects/boost/files/boost-binaries/) -# have library directories named using MSVC compiler version and architecture. -# This function would append corresponding directories if MSVC is a current compiler, -# so having `BOOST_ROOT` would be enough to specify to find everything. -# -function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_arch_suffix 64) - else() - set(_arch_suffix 32) - endif() - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 150) - # Not yet known. - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 140) - # MSVC toolset 14.x versions are forward compatible. - foreach(v 9 8 7 6 5 4 3 2 1 0) - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 14${v}) - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.${v}) - endif() - endforeach() - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80) - math(EXPR _toolset_major_version "${MSVC_TOOLSET_VERSION} / 10") - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-${_toolset_major_version}.0) - endif() - set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE) - endif() -endfunction() - -# -# End functions/macros -# -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# main. -#------------------------------------------------------------------------------- - - -# If the user sets Boost_LIBRARY_DIR, use it as the default for both -# configurations. -if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR) - set(Boost_LIBRARY_DIR_RELEASE "${Boost_LIBRARY_DIR}") -endif() -if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR) - set(Boost_LIBRARY_DIR_DEBUG "${Boost_LIBRARY_DIR}") -endif() - -if(NOT DEFINED Boost_USE_DEBUG_LIBS) - set(Boost_USE_DEBUG_LIBS TRUE) -endif() -if(NOT DEFINED Boost_USE_RELEASE_LIBS) - set(Boost_USE_RELEASE_LIBS TRUE) -endif() -if(NOT DEFINED Boost_USE_MULTITHREADED) - set(Boost_USE_MULTITHREADED TRUE) -endif() -if(NOT DEFINED Boost_USE_DEBUG_RUNTIME) - set(Boost_USE_DEBUG_RUNTIME TRUE) -endif() - -# Check the version of Boost against the requested version. -if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) - message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") -endif() - -if(Boost_FIND_VERSION_EXACT) - # The version may appear in a directory with or without the patch - # level, even when the patch level is non-zero. - set(_boost_TEST_VERSIONS - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") -else() - # The user has not requested an exact version. Among known - # versions, find those that are acceptable to the user request. - # - # Note: When adding a new Boost release, also update the dependency - # information in _Boost_COMPONENT_DEPENDENCIES and - # _Boost_COMPONENT_HEADERS. See the instructions at the top of - # _Boost_COMPONENT_DEPENDENCIES. - set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.70.0" "1.70" "1.69.0" "1.69" - "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" - "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" - "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" - "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" - "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" - "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" - "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" - "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" - "1.34" "1.33.1" "1.33.0" "1.33") - - set(_boost_TEST_VERSIONS) - if(Boost_FIND_VERSION) - set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - # Select acceptable versions. - foreach(version ${_Boost_KNOWN_VERSIONS}) - if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") - # This version is high enough. - list(APPEND _boost_TEST_VERSIONS "${version}") - elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") - # This version is a short-form for the requested version with - # the patch level dropped. - list(APPEND _boost_TEST_VERSIONS "${version}") - endif() - endforeach() - else() - # Any version is acceptable. - set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") - endif() -endif() - -# The reason that we failed to find Boost. This will be set to a -# user-friendly message when we fail to find some necessary piece of -# Boost. -set(Boost_ERROR_REASON) - -if(Boost_DEBUG) - # Output some of their choices - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") -endif() - -# Supply Boost_LIB_DIAGNOSTIC_DEFINITIONS as a convenience target. It -# will only contain any interface definitions on WIN32, but is created -# on all platforms to keep end user code free from platform dependent -# code. Also provide convenience targets to disable autolinking and -# enable dynamic linking. -if(NOT TARGET Boost::diagnostic_definitions) - add_library(Boost::diagnostic_definitions INTERFACE IMPORTED) - add_library(Boost::disable_autolinking INTERFACE IMPORTED) - add_library(Boost::dynamic_linking INTERFACE IMPORTED) -endif() -if(WIN32) - # In windows, automatic linking is performed, so you do not have - # to specify the libraries. If you are linking to a dynamic - # runtime, then you can choose to link to either a static or a - # dynamic Boost library, the default is to do a static link. You - # can alter this for a specific library "whatever" by defining - # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be - # linked dynamically. Alternatively you can force all Boost - # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. - - # This feature can be disabled for Boost library "whatever" by - # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining - # BOOST_ALL_NO_LIB. - - # If you want to observe which libraries are being linked against - # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking - # code to emit a #pragma message each time a library is selected - # for linking. - set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") - set_target_properties(Boost::diagnostic_definitions PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_LIB_DIAGNOSTIC") - set_target_properties(Boost::disable_autolinking PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_NO_LIB") - set_target_properties(Boost::dynamic_linking PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_DYN_LINK") -endif() - -_Boost_CHECK_SPELLING(Boost_ROOT) -_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) -_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) - -# Collect environment variable inputs as hints. Do not consider changes. -foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) - set(_env $ENV{${v}}) - if(_env) - file(TO_CMAKE_PATH "${_env}" _ENV_${v}) - else() - set(_ENV_${v} "") - endif() -endforeach() -if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) - set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") -endif() - -# Collect inputs and cached results. Detect changes since the last run. -if(NOT BOOST_ROOT AND BOOSTROOT) - set(BOOST_ROOT "${BOOSTROOT}") -endif() -set(_Boost_VARS_DIR - BOOST_ROOT - Boost_NO_SYSTEM_PATHS - ) - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Declared as CMake or Environmental Variables:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_ROOT = ${BOOST_ROOT}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") -endif() - -# ------------------------------------------------------------------------ -# Search for Boost include DIR -# ------------------------------------------------------------------------ - -set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) -_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) -# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) - unset(Boost_INCLUDE_DIR CACHE) -endif() - -if(NOT Boost_INCLUDE_DIR) - set(_boost_INCLUDE_SEARCH_DIRS "") - if(BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) - elseif(_ENV_BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) - endif() - - if( BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) - elseif( _ENV_BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) - endif() - - if( Boost_NO_SYSTEM_PATHS) - list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) - else() - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - foreach(ver ${_boost_TEST_VERSIONS}) - string(REPLACE "." "_" ver "${ver}") - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}") - endforeach() - endif() - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS - C:/boost/include - C:/boost - /sw/local/include - ) - endif() - - # Try to find Boost by stepping backwards through the Boost versions - # we know about. - # Build a list of path suffixes for each version. - set(_boost_PATH_SUFFIXES) - foreach(_boost_VER ${_boost_TEST_VERSIONS}) - # Add in a path suffix, based on the required version, ideally - # we could read this from version.hpp, but for that to work we'd - # need to know the include dir already - set(_boost_BOOSTIFIED_VERSION) - - # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 - if(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)") - set(_boost_BOOSTIFIED_VERSION - "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}_${CMAKE_MATCH_3}") - elseif(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)") - set(_boost_BOOSTIFIED_VERSION - "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}") - endif() - - list(APPEND _boost_PATH_SUFFIXES - "boost-${_boost_BOOSTIFIED_VERSION}" - "boost_${_boost_BOOSTIFIED_VERSION}" - "boost/boost-${_boost_BOOSTIFIED_VERSION}" - "boost/boost_${_boost_BOOSTIFIED_VERSION}" - ) - - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Include debugging info:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") - endif() - - # Look for a standard boost header file. - find_path(Boost_INCLUDE_DIR - NAMES boost/config.hpp - HINTS ${_boost_INCLUDE_SEARCH_DIRS} - PATH_SUFFIXES ${_boost_PATH_SUFFIXES} - ) -endif() - -# ------------------------------------------------------------------------ -# Extract version information from version.hpp -# ------------------------------------------------------------------------ - -# Set Boost_FOUND based only on header location and version. -# It will be updated below for component libraries. -if(Boost_INCLUDE_DIR) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") - endif() - - # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp - set(Boost_VERSION 0) - set(Boost_LIB_VERSION "") - file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") - set(_Boost_VERSION_REGEX "([0-9]+)") - set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") - foreach(v VERSION LIB_VERSION) - if("${_boost_VERSION_HPP_CONTENTS}" MATCHES "#define BOOST_${v} ${_Boost_${v}_REGEX}") - set(Boost_${v} "${CMAKE_MATCH_1}") - endif() - endforeach() - unset(_boost_VERSION_HPP_CONTENTS) - - math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") - math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") - math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") - set(Boost_VERSION_STRING "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - - string(APPEND Boost_ERROR_REASON - "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "version.hpp reveals boost " - "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - endif() - - if(Boost_FIND_VERSION) - # Set Boost_FOUND based on requested version. - set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "old") - elseif(Boost_FIND_VERSION_EXACT AND - NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "new") - else() - set(Boost_FOUND 1) - endif() - if(NOT Boost_FOUND) - # State that we found a version of Boost that is too new or too old. - string(APPEND Boost_ERROR_REASON - "\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - if (Boost_FIND_VERSION_PATCH) - string(APPEND Boost_ERROR_REASON - ".${Boost_FIND_VERSION_PATCH}") - endif () - if (NOT Boost_FIND_VERSION_EXACT) - string(APPEND Boost_ERROR_REASON " (or newer)") - endif () - string(APPEND Boost_ERROR_REASON ".") - endif () - else() - # Caller will accept any Boost version. - set(Boost_FOUND 1) - endif() -else() - set(Boost_FOUND 0) - string(APPEND Boost_ERROR_REASON - "Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") -endif() - -# ------------------------------------------------------------------------ -# Prefix initialization -# ------------------------------------------------------------------------ - -set(Boost_LIB_PREFIX "") -if ( (GHSMULTI AND Boost_USE_STATIC_LIBS) OR -(WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) ) - set(Boost_LIB_PREFIX "lib") -endif() - -if ( NOT Boost_NAMESPACE ) - set(Boost_NAMESPACE "boost") -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_LIB_PREFIX = ${Boost_LIB_PREFIX}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NAMESPACE = ${Boost_NAMESPACE}") -endif() - -# ------------------------------------------------------------------------ -# Suffix initialization and compiler suffix detection. -# ------------------------------------------------------------------------ - -set(_Boost_VARS_NAME - Boost_NAMESPACE - Boost_COMPILER - Boost_THREADAPI - Boost_USE_DEBUG_PYTHON - Boost_USE_MULTITHREADED - Boost_USE_STATIC_LIBS - Boost_USE_STATIC_RUNTIME - Boost_USE_STLPORT - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - ) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) - -# Setting some more suffixes for the library -if (Boost_COMPILER) - set(_boost_COMPILER ${Boost_COMPILER}) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_COMPILER = ${_boost_COMPILER}") - endif() -else() - # Attempt to guess the compiler suffix - # NOTE: this is not perfect yet, if you experience any issues - # please report them and use the Boost_COMPILER variable - # to work around the problems. - _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "guessed _boost_COMPILER = ${_boost_COMPILER}") - endif() -endif() - -set (_boost_MULTITHREADED "-mt") -if( NOT Boost_USE_MULTITHREADED ) - set (_boost_MULTITHREADED "") -endif() -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") -endif() - -#====================== -# Systematically build up the Boost ABI tag for the 'tagged' and 'versioned' layouts -# http://boost.org/doc/libs/1_66_0/more/getting_started/windows.html#library-naming -# http://boost.org/doc/libs/1_66_0/boost/config/auto_link.hpp -# http://boost.org/doc/libs/1_66_0/tools/build/src/tools/common.jam -# http://boost.org/doc/libs/1_66_0/boostcpp.jam -set( _boost_RELEASE_ABI_TAG "-") -set( _boost_DEBUG_ABI_TAG "-") -# Key Use this library when: -# s linking statically to the C++ standard library and -# compiler runtime support libraries. -if(Boost_USE_STATIC_RUNTIME) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") -endif() -# g using debug versions of the standard and runtime -# support libraries -if(WIN32 AND Boost_USE_DEBUG_RUNTIME) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" - OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang" - OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") - string(APPEND _boost_DEBUG_ABI_TAG "g") - endif() -endif() -# y using special debug build of python -if(Boost_USE_DEBUG_PYTHON) - string(APPEND _boost_DEBUG_ABI_TAG "y") -endif() -# d using a debug version of your code -string(APPEND _boost_DEBUG_ABI_TAG "d") -# p using the STLport standard library rather than the -# default one supplied with your compiler -if(Boost_USE_STLPORT) - string(APPEND _boost_RELEASE_ABI_TAG "p") - string(APPEND _boost_DEBUG_ABI_TAG "p") -endif() -# n using the STLport deprecated "native iostreams" feature -# removed from the documentation in 1.43.0 but still present in -# boost/config/auto_link.hpp -if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) - string(APPEND _boost_RELEASE_ABI_TAG "n") - string(APPEND _boost_DEBUG_ABI_TAG "n") -endif() - -# -x86 Architecture and address model tag -# First character is the architecture, then word-size, either 32 or 64 -# Only used in 'versioned' layout, added in Boost 1.66.0 -if(DEFINED Boost_ARCHITECTURE) - set(_boost_ARCHITECTURE_TAG "${Boost_ARCHITECTURE}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_ARCHITECTURE = ${_boost_ARCHITECTURE_TAG}") - endif() -else() - set(_boost_ARCHITECTURE_TAG "") - # {CMAKE_CXX_COMPILER_ARCHITECTURE_ID} is not currently set for all compilers - if(NOT "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x" AND NOT Boost_VERSION VERSION_LESS 106600) - string(APPEND _boost_ARCHITECTURE_TAG "-") - # This needs to be kept in-sync with the section of CMakePlatformId.h.in - # inside 'defined(_WIN32) && defined(_MSC_VER)' - if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "IA64") - string(APPEND _boost_ARCHITECTURE_TAG "i") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "X86" - OR CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "x64") - string(APPEND _boost_ARCHITECTURE_TAG "x") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID MATCHES "^ARM") - string(APPEND _boost_ARCHITECTURE_TAG "a") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "MIPS") - string(APPEND _boost_ARCHITECTURE_TAG "m") - endif() - - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - string(APPEND _boost_ARCHITECTURE_TAG "64") - else() - string(APPEND _boost_ARCHITECTURE_TAG "32") - endif() - endif() -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") -endif() - -# ------------------------------------------------------------------------ -# Begin finding boost libraries -# ------------------------------------------------------------------------ - -set(_Boost_VARS_LIB "") -foreach(c DEBUG RELEASE) - set(_Boost_VARS_LIB_${c} BOOST_LIBRARYDIR Boost_LIBRARY_DIR_${c}) - list(APPEND _Boost_VARS_LIB ${_Boost_VARS_LIB_${c}}) - _Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR_${c} ${_Boost_VARS_DIR} ${_Boost_VARS_LIB_${c}} Boost_INCLUDE_DIR) - # Clear Boost_LIBRARY_DIR_${c} if it did not change but other input affecting the - # location did. We will find a new one based on the new inputs. - if(_Boost_CHANGE_LIBDIR_${c} AND NOT _Boost_LIBRARY_DIR_${c}_CHANGED) - unset(Boost_LIBRARY_DIR_${c} CACHE) - endif() - - # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is set, prefer its value. - if(Boost_LIBRARY_DIR_${c}) - set(_boost_LIBRARY_SEARCH_DIRS_${c} ${Boost_LIBRARY_DIR_${c}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - else() - set(_boost_LIBRARY_SEARCH_DIRS_${c} "") - if(BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_LIBRARYDIR}) - elseif(_ENV_BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_LIBRARYDIR}) - endif() - - if(BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${BOOST_ROOT}") - elseif(_ENV_BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${_ENV_BOOST_ROOT}") - endif() - - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} - ${Boost_INCLUDE_DIR}/lib - ${Boost_INCLUDE_DIR}/../lib - ${Boost_INCLUDE_DIR}/stage/lib - ) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}/..") - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}") - if( Boost_NO_SYSTEM_PATHS ) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) - else() - foreach(ver ${_boost_TEST_VERSIONS}) - string(REPLACE "." "_" ver "${ver}") - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}") - endforeach() - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS - C:/boost/lib - C:/boost - /sw/local/lib - ) - endif() - endif() -endforeach() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_LIBRARY_SEARCH_DIRS_RELEASE = ${_boost_LIBRARY_SEARCH_DIRS_RELEASE}" - "_boost_LIBRARY_SEARCH_DIRS_DEBUG = ${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") -endif() - -# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES -if( Boost_USE_STATIC_LIBS ) - set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(WIN32) - list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a) - endif() -endif() - -# We want to use the tag inline below without risking double dashes -if(_boost_RELEASE_ABI_TAG) - if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") - set(_boost_RELEASE_ABI_TAG "") - endif() -endif() -if(_boost_DEBUG_ABI_TAG) - if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") - set(_boost_DEBUG_ABI_TAG "") - endif() -endif() - -# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled -# on WIN32 was to: -# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) -# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) -# We maintain this behavior since changing it could break people's builds. -# To disable the ambiguous behavior, the user need only -# set Boost_USE_STATIC_RUNTIME either ON or OFF. -set(_boost_STATIC_RUNTIME_WORKAROUND false) -if(WIN32 AND Boost_USE_STATIC_LIBS) - if(NOT DEFINED Boost_USE_STATIC_RUNTIME) - set(_boost_STATIC_RUNTIME_WORKAROUND TRUE) - endif() -endif() - -# On versions < 1.35, remove the System library from the considered list -# since it wasn't added until 1.35. -if(Boost_VERSION AND Boost_FIND_COMPONENTS) - if(Boost_VERSION LESS 103500) - list(REMOVE_ITEM Boost_FIND_COMPONENTS system) - endif() -endif() - -# Additional components may be required via component dependencies. -# Add any missing components to the list. -_Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS) - -# If thread is required, get the thread libs as a dependency -if("thread" IN_LIST Boost_FIND_COMPONENTS) - if(Boost_FIND_QUIETLY) - set(_Boost_find_quiet QUIET) - else() - set(_Boost_find_quiet "") - endif() - find_package(Threads ${_Boost_find_quiet}) - unset(_Boost_find_quiet) -endif() - -# If the user changed any of our control inputs flush previous results. -if(_Boost_CHANGE_LIBDIR_DEBUG OR _Boost_CHANGE_LIBDIR_RELEASE OR _Boost_CHANGE_LIBNAME) - foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - foreach(c DEBUG RELEASE) - set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) - unset(${_var} CACHE) - set(${_var} "${_var}-NOTFOUND") - endforeach() - endforeach() - set(_Boost_COMPONENTS_SEARCHED "") -endif() - -foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - - set( _boost_docstring_release "Boost ${COMPONENT} library (release)") - set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") - - # Compute component-specific hints. - set(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT "") - if(${COMPONENT} STREQUAL "mpi" OR ${COMPONENT} STREQUAL "mpi_python" OR - ${COMPONENT} STREQUAL "graph_parallel") - foreach(lib ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}) - if(IS_ABSOLUTE "${lib}") - get_filename_component(libdir "${lib}" PATH) - string(REPLACE "\\" "/" libdir "${libdir}") - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT ${libdir}) - endif() - endforeach() - endif() - - # Handle Python version suffixes - unset(COMPONENT_PYTHON_VERSION_MAJOR) - unset(COMPONENT_PYTHON_VERSION_MINOR) - if(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\$") - set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") - set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - elseif(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\\.?([0-9])\$") - set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") - set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - set(COMPONENT_PYTHON_VERSION_MINOR "${CMAKE_MATCH_3}") - endif() - - unset(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - if (COMPONENT_PYTHON_VERSION_MINOR) - # Boost >= 1.67 - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # Debian/Ubuntu (Some versions omit the 2 and/or 3 from the suffix) - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}-py${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-py${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # Gentoo - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-${COMPONENT_PYTHON_VERSION_MAJOR}.${COMPONENT_PYTHON_VERSION_MINOR}") - # RPMs - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - endif() - if (COMPONENT_PYTHON_VERSION_MAJOR AND NOT COMPONENT_PYTHON_VERSION_MINOR) - # Boost < 1.67 - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}") - endif() - - # Consolidate and report component-specific hints. - if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Component-specific library search names for ${COMPONENT_NAME}: " - "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME}") - endif() - endif() - if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Component-specific library search paths for ${COMPONENT}: " - "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT}") - endif() - endif() - - # - # Find headers - # - _Boost_COMPONENT_HEADERS("${COMPONENT}" Boost_${UPPERCOMPONENT}_HEADER_NAME) - # Look for a standard boost header file. - if(Boost_${UPPERCOMPONENT}_HEADER_NAME) - if(EXISTS "${Boost_INCLUDE_DIR}/${Boost_${UPPERCOMPONENT}_HEADER_NAME}") - set(Boost_${UPPERCOMPONENT}_HEADER ON) - else() - set(Boost_${UPPERCOMPONENT}_HEADER OFF) - endif() - else() - set(Boost_${UPPERCOMPONENT}_HEADER ON) - message(WARNING "No header defined for ${COMPONENT}; skipping header check") - endif() - - # - # Find RELEASE libraries - # - unset(_boost_RELEASE_NAMES) - foreach(component IN LISTS _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME COMPONENT) - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ) - endforeach() - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endforeach() - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endif() - endforeach() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") - endif() - - # if Boost_LIBRARY_DIR_RELEASE is not defined, - # but Boost_LIBRARY_DIR_DEBUG is, look there first for RELEASE libs - if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR_DEBUG) - list(INSERT _boost_LIBRARY_SEARCH_DIRS_RELEASE 0 ${Boost_LIBRARY_DIR_DEBUG}) - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}") - - if(Boost_USE_RELEASE_LIBS) - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE - NAMES ${_boost_RELEASE_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_release}" - ) - endif() - - # - # Find DEBUG libraries - # - unset(_boost_DEBUG_NAMES) - foreach(component IN LISTS _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME COMPONENT) - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ) - endforeach() - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endforeach() - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endif() - endforeach() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") - endif() - - # if Boost_LIBRARY_DIR_DEBUG is not defined, - # but Boost_LIBRARY_DIR_RELEASE is, look there first for DEBUG libs - if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR_RELEASE) - list(INSERT _boost_LIBRARY_SEARCH_DIRS_DEBUG 0 ${Boost_LIBRARY_DIR_RELEASE}) - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") - - if(Boost_USE_DEBUG_LIBS) - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG - NAMES ${_boost_DEBUG_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_debug}" - ) - endif () - - if(Boost_REALPATH) - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) - endif() - - _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) - - # Check if component requires some compiler features - _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) - -endforeach() - -# Restore the original find library ordering -if( Boost_USE_STATIC_LIBS ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -endif() - -# ------------------------------------------------------------------------ -# End finding boost libraries -# ------------------------------------------------------------------------ - -set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -set(Boost_LIBRARY_DIRS) -if(Boost_LIBRARY_DIR_RELEASE) - list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_RELEASE}) -endif() -if(Boost_LIBRARY_DIR_DEBUG) - list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_DEBUG}) -endif() -if(Boost_LIBRARY_DIRS) - list(REMOVE_DUPLICATES Boost_LIBRARY_DIRS) -endif() - -# The above setting of Boost_FOUND was based only on the header files. -# Update it for the requested component libraries. -if(Boost_FOUND) - # The headers were found. Check for requested component libs. - set(_boost_CHECKED_COMPONENT FALSE) - set(_Boost_MISSING_COMPONENTS "") - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(_boost_CHECKED_COMPONENT TRUE) - if(NOT Boost_${UPPERCOMPONENT}_FOUND AND Boost_FIND_REQUIRED_${COMPONENT}) - list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) - endif() - endforeach() - if(_Boost_MISSING_COMPONENTS AND _Boost_EXTRA_FIND_COMPONENTS) - # Optional indirect dependencies are not counted as missing. - list(REMOVE_ITEM _Boost_MISSING_COMPONENTS ${_Boost_EXTRA_FIND_COMPONENTS}) - endif() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") - endif() - - if (_Boost_MISSING_COMPONENTS) - set(Boost_FOUND 0) - # We were unable to find some libraries, so generate a sensible - # error message that lists the libraries we were unable to find. - string(APPEND Boost_ERROR_REASON - "\nCould not find the following") - if(Boost_USE_STATIC_LIBS) - string(APPEND Boost_ERROR_REASON " static") - endif() - string(APPEND Boost_ERROR_REASON - " Boost libraries:\n") - foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - string(APPEND Boost_ERROR_REASON - " ${Boost_NAMESPACE}_${COMPONENT}${Boost_ERROR_REASON_${UPPERCOMPONENT}}\n") - endforeach() - - list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) - list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) - if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) - string(APPEND Boost_ERROR_REASON - "No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - else () - string(APPEND Boost_ERROR_REASON - "Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - endif () - endif () - - if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) - # Compatibility Code for backwards compatibility with CMake - # 2.4's FindBoost module. - - # Look for the boost library path. - # Note that the user may not have installed any libraries - # so it is quite possible the Boost_LIBRARY_DIRS may not exist. - set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) - - if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if("${_boost_LIB_DIR}" MATCHES "/include$") - # Strip off the trailing "/include" in the path. - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if(EXISTS "${_boost_LIB_DIR}/lib") - string(APPEND _boost_LIB_DIR /lib) - elseif(EXISTS "${_boost_LIB_DIR}/stage/lib") - string(APPEND _boost_LIB_DIR "/stage/lib") - else() - set(_boost_LIB_DIR "") - endif() - - if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") - set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) - endif() - - endif() -else() - # Boost headers were not found so no components were found. - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(Boost_${UPPERCOMPONENT}_FOUND 0) - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Add imported targets -# ------------------------------------------------------------------------ - -if(Boost_FOUND) - # For header-only libraries - if(NOT TARGET Boost::boost) - add_library(Boost::boost INTERFACE IMPORTED) - if(Boost_INCLUDE_DIRS) - set_target_properties(Boost::boost PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") - endif() - endif() - - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - if(_Boost_IMPORTED_TARGETS AND NOT TARGET Boost::${COMPONENT}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - if(Boost_${UPPERCOMPONENT}_FOUND) - if(Boost_USE_STATIC_LIBS) - add_library(Boost::${COMPONENT} STATIC IMPORTED) - else() - # Even if Boost_USE_STATIC_LIBS is OFF, we might have static - # libraries as a result. - add_library(Boost::${COMPONENT} UNKNOWN IMPORTED) - endif() - if(Boost_INCLUDE_DIRS) - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY}") - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - IMPORTED_LOCATION "${Boost_${UPPERCOMPONENT}_LIBRARY}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS RELEASE) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" - IMPORTED_LOCATION_RELEASE "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS DEBUG) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" - IMPORTED_LOCATION_DEBUG "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - endif() - if(_Boost_${UPPERCOMPONENT}_DEPENDENCIES) - unset(_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES) - foreach(dep ${_Boost_${UPPERCOMPONENT}_DEPENDENCIES}) - list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Boost::${dep}) - endforeach() - if(COMPONENT STREQUAL "thread") - list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Threads::Threads) - endif() - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}") - endif() - if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}") - endif() - endif() - endif() - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Notification to end user about what was found -# ------------------------------------------------------------------------ - -set(Boost_LIBRARIES "") -if(Boost_FOUND) - if(NOT Boost_FIND_QUIETLY) - message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if(Boost_FIND_COMPONENTS) - message(STATUS "Found the following Boost libraries:") - endif() - endif() - foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) - string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) - if( Boost_${UPPERCOMPONENT}_FOUND ) - if(NOT Boost_FIND_QUIETLY) - message (STATUS " ${COMPONENT}") - endif() - list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) - if(COMPONENT STREQUAL "thread") - list(APPEND Boost_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - endif() - endif() - endforeach() -else() - if(Boost_FIND_REQUIRED) - message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") - else() - if(NOT Boost_FIND_QUIETLY) - # we opt not to automatically output Boost_ERROR_REASON here as - # it could be quite lengthy and somewhat imposing in its requests - # Since Boost is not always a required dependency we'll leave this - # up to the end-user. - if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) - message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") - else() - message(STATUS "Could NOT find Boost") - endif() - endif() - endif() -endif() - -# Configure display of cache entries in GUI. -foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) - get_property(_type CACHE ${v} PROPERTY TYPE) - if(_type) - set_property(CACHE ${v} PROPERTY ADVANCED 1) - if("x${_type}" STREQUAL "xUNINITIALIZED") - if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") - set_property(CACHE ${v} PROPERTY TYPE STRING) - else() - set_property(CACHE ${v} PROPERTY TYPE PATH) - endif() - endif() - endif() -endforeach() - -# Record last used values of input variables so we can -# detect on the next run if the user changed them. -foreach(v - ${_Boost_VARS_INC} ${_Boost_VARS_LIB} - ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} - ) - if(DEFINED ${v}) - set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") - else() - unset(_${v}_LAST CACHE) - endif() -endforeach() - -# Maintain a persistent list of components requested anywhere since -# the last flush. -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") -list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) -list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) -list(SORT _Boost_COMPONENTS_SEARCHED) -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" - CACHE INTERNAL "Components requested for this build tree.") - -# Restore project's policies -cmake_policy(POP) \ No newline at end of file diff --git a/cmake/MODUtils.cmake b/cmake/MODUtils.cmake new file mode 100644 index 0000000..24b3a99 --- /dev/null +++ b/cmake/MODUtils.cmake @@ -0,0 +1,12 @@ + + +function(make_py_test fileName testName extraEnv) + set(workDir ${CMAKE_CURRENT_BINARY_DIR}/workDir/${testName}) + file(MAKE_DIRECTORY ${workDir}) + add_test(NAME ${testName} + COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/mod -f ${CMAKE_CURRENT_LIST_DIR}/${fileName}.py + WORKING_DIRECTORY ${workDir}) + set_tests_properties(${testName} PROPERTIES + ENVIRONMENT "MOD_NUM_POST_THREADS=1${extraEnv}") + add_coverage_case(${testName}) +endfunction() diff --git a/conda/build.Dockerfile b/conda/build.Dockerfile new file mode 100644 index 0000000..a2985c2 --- /dev/null +++ b/conda/build.Dockerfile @@ -0,0 +1,79 @@ +FROM ubuntu:20.04 AS build +# Based on continuumio/miniconda3 + +#ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 +ENV PATH /opt/conda/bin:$PATH + +RUN apt-get update --fix-missing \ + && apt-get install -y wget bzip2 ca-certificates curl git + +RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh -O ~/miniconda.sh && \ + /bin/bash ~/miniconda.sh -b -p /opt/conda && \ + rm ~/miniconda.sh && \ + /opt/conda/bin/conda clean -tipsy && \ + ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \ + echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \ + echo "conda activate base" >> ~/.bashrc + +# and now ours + +# TexLive +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y \ + texlive-science texlive-pictures texlive-latex-extra lmodern + +RUN conda install conda-build conda-verify + +ARG version +ENV MOD_CONDA_BUILD_VERSION=$version + +WORKDIR /opt/mod +COPY ./build/mod-*.tar.gz ./build/ +COPY ./conda/build.sh ./conda/ +COPY ./conda/meta.yaml ./conda/ +RUN conda build -c jakobandersen -c conda-forge ./conda + + +############################################################################### +# Test +############################################################################### + +FROM ubuntu:20.04 AS test +# Based on continuumio/miniconda3 + +#ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 +ENV PATH /opt/conda/bin:$PATH + +RUN apt-get update --fix-missing \ + && apt-get install -y wget bzip2 ca-certificates curl git + +RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh -O ~/miniconda.sh && \ + /bin/bash ~/miniconda.sh -b -p /opt/conda && \ + rm ~/miniconda.sh && \ + /opt/conda/bin/conda clean -tipsy && \ + ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \ + echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \ + echo "conda activate base" >> ~/.bashrc + +# and now ours + +# TexLive +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y \ + texlive-science texlive-pictures texlive-latex-extra lmodern + +RUN conda install conda-build conda-verify + + +COPY --from=build /opt/conda/conda-bld/linux-64/mod-*.tar.bz2 \ + /opt/conda-bld/linux-64/ + +RUN conda index /opt/conda-bld +RUN conda install -c file:///opt/conda-bld -c jakobandersen -c conda-forge mod + +WORKDIR /opt/test +COPY conda/test.py ./ + +RUN mod -f test.py +RUN mod_post --install-format +RUN mod -f test.py diff --git a/conda/build.sh b/conda/build.sh new file mode 100644 index 0000000..0f7bf88 --- /dev/null +++ b/conda/build.sh @@ -0,0 +1,19 @@ +#!/bin/bash +j=$CPU_COUNT + +mkdir src +cd src +tar xzf ../mod-*.tar.gz --strip-components=1 +mkdir build +cd build +cmake ../ -DCMAKE_INSTALL_PREFIX=$PREFIX \ + -DBUILD_DOC=no \ + -DBUILD_POST_MOD_FMT=off \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_MODULE_LINKER_FLAGS="-flto=$j" \ + -DCMAKE_SHARED_LINKER_FLAGS="-flto=$j" \ + -DBUILD_TESTING=on +make -j $j +make tests -j $j +make install +ctest -j $j --output-on-failure -E cmake_add_subdirectory diff --git a/conda/meta.yaml b/conda/meta.yaml new file mode 100644 index 0000000..9d2f420 --- /dev/null +++ b/conda/meta.yaml @@ -0,0 +1,67 @@ +{% set version = environ.get('MOD_CONDA_BUILD_VERSION') %} +{% set pyPackages = [ + "ipython", + "networkx", + "parse", + "typing_extensions", +] %} +{% set packages = [ + "boost==1.74", + "boost-cpp==1.74", + "openbabel", + "python", +] %} +{% set exePackages = [ + "make", + "graphviz==2.42.3.1", + "pdf2svg", +] %} + + +package: + name: mod + {% if version %} + version: {{ version }} + {% endif %} + +source: + {% if version %} + path: {{ "../build/mod-" + version + ".tar.gz" }} + {% endif %} + +build: + skip: True # [win] + +requirements: + build: + - {{ compiler('cxx') }} + - make + - pkg-config + - cmake +# - texlive-core + {% for p in exePackages %} + - {{ p }} + {% endfor %} + {% for p in pyPackages %} + - {{ p }} + {% endfor %} + host: + {% for p in packages %} + - {{ p }} + {% endfor %} + run: + {% for p in exePackages %} + - {{ p }} + {% endfor %} + {% for p in packages %} + - {{ p }} + {% endfor %} + {% for p in pyPackages %} + - {{ p }} + {% endfor %} + +test: + commands: + - mod -e "smiles('O').print()" + - mod_post --install-format + - mod -e "smiles('O').print()" diff --git a/conda/test.py b/conda/test.py new file mode 100644 index 0000000..0771d02 --- /dev/null +++ b/conda/test.py @@ -0,0 +1,18 @@ +g = smiles('C') +r = ruleGMLString("""rule [ + left [ + node [ id 1 label "C" ] + node [ id 2 label "H" ] + edge [ source 1 target 2 label "-" ] + ] + right [ + node [ id 1 label "C-" ] + node [ id 2 label "H+" ] + ] +]""") +dg = DG() +dg.build().execute(addSubset(g) >> r) + +g.print() +r.print() +dg.print() diff --git a/doc/makeDocs.sh b/doc/makeDocs.sh index f6fdc59..78d0358 100755 --- a/doc/makeDocs.sh +++ b/doc/makeDocs.sh @@ -23,14 +23,7 @@ BEGIN { lastNested = "" } { - if($0 ~ /^[\t]*\/\/ rst: .. py:class::/) { - sub(/^[\t]*\/\/ rst: .. py:class:: /, "") - print "" - print "Class ``" $0 "``" - print "--------------------------------------------------------------------------------------------------------------------------------" - print "" - print ".. py:class:: " $0 - } else if($0 ~ /^[\t]*\/\/ rst:/) { + if($0 ~ /^[\t]*\/\/ rst:/) { sub(/^[\t]*\/\/ rst:[ ]?/, "") if(inClass) if(inNested) @@ -119,7 +112,7 @@ BEGIN { } function getModHeaders { - find $topSrcDir/libs/libmod/src/mod/ -iname "*.hpp" \ + find $topSrcDir/libs/libmod/src/mod -iname "*.hpp" \ | grep -v -e "/lib/" \ | grep -v -e "/internal/" \ | sed -e "s/.*\/src\/mod\///" -e "s/\.hpp$//" \ @@ -127,16 +120,27 @@ function getModHeaders { } function getPyModCPPs { - find $topSrcDir/libs/pymod/src/mod/py -iname "*.cpp" \ - | sed -e "s!.*/libs/pymod/src/mod/py/!!" -e "s/\.cpp$//" \ - | sort \ - | grep -v Module | grep -v Collections | grep -v Function + function raw { + find $topSrcDir/libs/pymod/src/mod/py -iname "*.cpp" \ + | sed -e "s!.*/libs/pymod/src/mod/py/!!" -e "s/\.cpp$//" \ + | sort \ + | grep -v Module | grep -v Collections | grep -v Function + } + raw | while read f; do + fFull=$topSrcDir/libs/pymod/src/mod/py/$f.cpp + grep "rst:" $fFull &> /dev/null + if [ $? -ne 0 ]; then + continue + fi + echo $f + done; } function makeIndex { function indexFiles { cat << "EOF" installation + compiling libmod/libmod pymod/pymod postmod/postmod @@ -321,6 +325,7 @@ EOF echo ".. toctree::" echo " :maxdepth: 1" echo "" + echo " protocols" getPyModCPPs | grep -v "/" | sed 's/^/ /' echo "" echo ".. toctree::" diff --git a/doc/source/_static/haxes.css b/doc/source/_static/haxes.css index fa63330..063350e 100644 --- a/doc/source/_static/haxes.css +++ b/doc/source/_static/haxes.css @@ -1,12 +1,16 @@ dd { - margin-left: 20px; + margin-left: 30px; } code { color: black; } +.literal { + background-color: #fdf6e3; +} + code > a, a > code { color: #003080; } diff --git a/doc/source/compiling.rst b/doc/source/compiling.rst new file mode 100644 index 0000000..c93ab1b --- /dev/null +++ b/doc/source/compiling.rst @@ -0,0 +1,289 @@ +.. _compiling: + +.. py:currentmodule:: mod +.. cpp:namespace:: mod + +Compiling from Source +===================== + +.. _quick-start: + +Quick Start +----------- + +These are simplified instructions for Ubuntu, Fedora, Arch, and macOS. +If a step doesn't work or fit your case, please consult the sections below. + +First, get MØD and install the easy dependencies: + +.. code-block:: bash + + git clone --recursive https://github.com/jakobandersen/mod.git + ./bootstrap.sh + pip3 install -r requirements.txt + # Ubuntu: + sudo apt install $(bindep -b | tr '\n' ' ') + # Fedora: + sudo dnf install $(bindep -b | tr '\n' ' ') + # Arch: + sudo pacman -Suy $(bindep -b | tr '\n' ' ') + # macOS: + brew tap Homebrew/bundle # may not be needed + brew bundle + +Then: + +1. (Ubuntu and Fedora < 33) + Install Boost from source, see :ref:`install_boost_python`. + Remember the installation path. +2. (Ubuntu) Install Graphviz from source: + + .. code-block:: bash + + sudo apt install librsvg2-dev libpango1.0-dev + wget http://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz + tar -xf graphviz.tar.gz --one-top-level=graphviz --strip-components=1 + cd graphviz + ./configure + make + sudo make install + +Finally, compile and install MØD: + +.. code-block:: bash + + mkdir build + cd build + cmake ../ -DCMAKE_PREFIX_PATH=path/to/boost + make + sudo make install + + +From a Git Repository +--------------------- + +After a checkout of the desired version, do: + +.. code-block:: bash + + git submodule update --init --recursive + ./bootstrap.sh + +This is needed to first fetch certain dependencies and second +to generate build files, extract the API documentation, +and create the file ``VERSION`` based on the current commit. + +See :ref:`source-build` on how to then build the package. + + +As Dependency of Another CMake Project +-------------------------------------- + +MØD supports use via ``add_subdirectory`` in CMake. +The target ``mod::libmod`` is exported, +which can be used with ``target_link_libraries`` to link against libMØD. +The version is in the variable ``mod_VERSION``. +Note that running ``./bootstrap.sh`` is still needed if the +source is a repository clone (e.g., a Git submodule). + + +.. _source-build: + +From a Source Archive +--------------------- + +The package is build and installed from source as a CMake project. +Generally that means something like: + +.. code-block:: bash + + mkdir build + cd build + cmake ../ + make -j + make install + +A source archive can also be created with ``make dist``. + +The following is a list of commonly used options for ``cmake``. +Additional options specific for MØD along with their default valule are also +listed. +See also :ref:`dependencies` for elaboration on some of them. + +- ``-DCMAKE_INSTALL_PREFIX=``, set a non-standard installation + directory. Note also that the `GNUInstallDirs + `__ + module is used. +- ``-DCMAKE_BUILD_TYPE=``, set a non-standard build type. + The default is `RelWithDebInfo + `__. + An additional build type ``OptDebug`` is available which adds the compilation + flags ``-g -O3``. +- ``-DCMAKE_PREFIX_PATH=``, set a ``;``-separated list of paths used for + finding most dependencies. The paths should generally be the prefixes + specified when the dependency was installed. + See also https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html#variable:CMAKE_PREFIX_PATH. +- ``-DBUILD_DOC=on``, whether to build documentation or not. + This is forced to ``off`` when used via ``add_subdirectory``. +- ``-DBUILD_POST_MOD=on``, whether to build the post-processor or not. +- ``-DBUILD_POST_MOD_FMT=on``, whether to build the Latex format files used by + the post-processor or not. + Format files may need to be updated when the Latex compiler is updated, + so when making a binary distribution of MØD that does not include the Latex + compiler, it is probably a good idea to set this to ``off``. + If the format files are not installed they will be compiled dynamically + by the post-processor when needed, i.e., making each post-processor run + slightly slower. + Alternatively, the format file can be (re)installed by the post-processor + using the + :option:`mod_post --install-format`/:option:`mod_post --install-format-sudo` + options. +- ``-DBUILD_PY_MOD=on``, whether to build the Python bindings or not. +- ``-DBUILD_TESTING=off``, whether to allow test building or not. + This is forced to ``off`` when used via ``add_subdirectory``. + When ``on`` the tests can be build with ``make tests`` and run with ``ctest``. +- ``-DBUILD_TESTING_SANITIZERS=on``, whether to compile libraries and tests + with sanitizers or not. This is forced to ``off`` when ``BUILD_COVERAGE=on``. +- ``-DBUILD_EXAMPLES=off``, whether to build and allow running of examples as + tests or not. + This is forced to ``off`` when used via ``add_subdirectory``. + This is forced to ``off`` when ``BUILD_TESTING`` is ``off``. +- ``-DBUILD_COVERAGE=off``, whether to compile code and run tests with GCov. + When ``on`` the sanitizers on tests will be disabled. + After building the tests, execute ``make coverage_collect`` without parallel + jobs to run tests. Afterwards, execute ``make coverage_build`` to compile the + code coverage report. +- ``-DENABLE_SYMBOL_HIDING=on``, whether symbols internal to the library are + hidden or not. Disabling this option may degrade performance, and should only + be done while developing extensions to the C++ library. +- ``-DENABLE_DEP_SYMBOL_HIDING=on``, whether symbols from library dependencies + are hidden or not. Disabling this option may make it slower to load the + library at runtime. +- ``-DENABLE_IPO=on``, whether to use link-time optimization or not. + Disabling this option may degrade performance, but speed up linking time. + As default the link-time optimizer will only use 1 thread. + To use more threads, e.g., 7, use the following options for configuration + ``-DCMAKE_MODULE_LINKER_FLAGS="-flto=7" -DCMAKE_SHARED_LINKER_FLAGS="-flto=7"``, + when using GCC as the compiler. +- ``-DUSE_NESTED_GRAPH_CANON=on``, whether to use the dependency GraphCanon + from the Git submodule or not. +- ``-DUSE_NESTED_NLOHMANN_JSON=on``, whether to use the dependency + `nlohmann/json `__ from the Git submodule + or not. +- ``-DWITH_OPENBABEL=on``, whether to enable/disable features depending on Open Babel. + + +.. _dependencies: + +Dependencies +------------ + +Python dependencies are listed in ``requirements.txt`` (which includes +``requirements_nodoc.txt``). + +Dependencies that can be satisfied via the system package manager are listed in +``bindep.txt``. Any missing package can be listed using the +`Bindep `__ program +(which can be installed via ``requirements.txt``). + +The following is a detailed list of all dependencies and the CMake switches +related to them. + +- This documentation requires (``-DBUILD_DOC=on``): + + - A supported version of `Sphinx `__. + - The Python package ``sphinx-autoapi`` (module name: ``autoapi``). + +- libMØD: + + - A C++ compiler with reasonable C++17 support is needed. + - `Boost `__ dev >= 1.73 + (use ``-DBOOST_ROOT=`` for non-standard locations). + - `GraphCanon `__ >= 0.5. + This is fulfilled via a Git submodule (make sure to do + ``git submodule update --init --recursive``), + but if another source is needed, set ``-DUSE_NESTED_GRAPH_CANON=off``. + - `nlohmann/json `__ >= 3.7.3. + This is fulfilled via a Git submodule (make sure to do + ``git submodule update --init --recursive``), + but if another source is needed, set ``-DUSE_NESTED_NLOHMANN_JSON=off``. + - (optional) `Open Babel`_ dev, >= 2.3.2 (``-DWITH_OPENBABEL=on``). + +- PyMØD (``-DBUILD_PY_MOD=on``): + + - Python 3 dev + - Boost.Python built with Python 3 + - (Optional) IPython 3 + +- PostMØD (``-DBUILD_POST_MOD=on``): + + - ``pdflatex`` available in the ``PATH`` or in ``CMAKE_PROGRAM_PATH``, + with not too old packages (Tex Live 2012 or newer should work). + - ``pdf2svg`` available in the ``PATH`` or in ``CMAKE_PROGRAM_PATH``. + - ``dot`` and ``neato`` from Graphviz available in the ``PATH`` or in + ``CMAKE_PROGRAM_PATH``. + They must additionally be able to load SVG files and output as both SVG and + PDF files (all via cairo). + That is, in the output of ``dot -P`` the following edges must exist: + + - ``cairo_device_svg -> output_svg`` + - ``cairo_device_pdf -> output_pdf`` + - ``rsvg_loadimage_svg -> render_cairo`` + + - If you install Graphviz from source, you can check if the status output in + the end of ``configure`` includes the following two lines:: + + pangocairo: Yes + rsvg: Yes + + +.. _install_boost_python: + +Boost and Boost.Python with Python 3 +------------------------------------ + +A package with the sources of Boost can be downloaded from `http://boost.org`. + + +Basic Installation +"""""""""""""""""" + +Boost uses a custom build system which may be difficult to use. +A procedure for compiling and installing Boost with Python 3 for Boost.Python +is the following. + +1. ``./bootstrap.sh --with-python=python3`` (optionally give + ``--prefix=some/path`` to specify a non-standard installation path. +2. ``./b2`` (optionally give ``-j N`` (similar to GNU Make) to compile with + multiple threads) +3. ``./b2 install`` (optionally give ``--prefix=some/path`` to specify a + non-standard installation path (if not done earlier). + +After ``bootstrap.sh`` has been run, the file ``project-config.jam`` +has been created, which can be edited to customise installation path and a lot +of other things. All edits should be done before running ``b2``. + + +Non-standard Python Installation +"""""""""""""""""""""""""""""""" + +Passing ``--with-python=python3`` to ``bootstrap.sh`` should work. +This adds a line similar to "``using python : 3.3 ;``" to +``project-config.jam``. +After compilation (running ``b2``) the file ``stage/lib/libboost_python3.so`` +should exist. If not, it did not detect Python 3 properly. + +If Python is installed in a non-standard location, add the a line similar to +"``using python : 3.3 : python3 : /path/to/python/3/installtion/include ;``" to +``project-config.jam``, where the last path is the path to the +``include``-folder of the Python-installation. + + +Custom GCC Version +"""""""""""""""""" + +Before running ``b2`` create the file ``user-config.jam`` in the root of the +home dir (see `here +`__ +for the full documentation). Put a line similar to +"``using gcc : : /path/to/g++-4.8``" in the file. diff --git a/doc/source/conf.py b/doc/source/conf.py index 88b788c..3a719f6 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -57,6 +57,7 @@ def generateExamples(): with open("examples/index.rst", "w") as f: f.truncate() f.write(".. Autogenerated in conf.py\n\n") + f.write(".. _examples:\n\n") f.write("Examples\n########\n\n") f.write(".. toctree::\n\n") for s in sections: @@ -118,7 +119,7 @@ def generateExamples(): # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '3.0.0' +needs_sphinx = '3.4.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom diff --git a/doc/source/dgStrat/dgStrat.rst b/doc/source/dgStrat/dgStrat.rst index efb61f5..2fbe485 100644 --- a/doc/source/dgStrat/dgStrat.rst +++ b/doc/source/dgStrat/dgStrat.rst @@ -112,12 +112,12 @@ Rule #### A rule (:cpp:class:`C++ `/:py:class:`Python `) can be used directly as a strategy. -It will search for proper derivations using a multiset of graphhs drawn from the input unvierse. +It will search for proper derivations using a multiset of graphs drawn from the input unvierse. However, each candidate multiset will have at least one graph from the active subset. -Newly discovered graphs will be the active subset of the output. +The active subset of the output will be comprised of the newly discovered graphs. That is, if :math:`D = \{G\Rightarrow^{p} H\mid G\subseteq \mathcal{U} \wedge G\cap \mathcal{S} \neq \emptyset\}` is the set of all proper derivations using at least one graph from the active input subset, -then the resutl is :math:`F' = (\mathcal{U}', \mathcal{S}')` with +then the result is :math:`F' = (\mathcal{U}', \mathcal{S}')` with :math:`\mathcal{S}' = \bigcup_{G\Rightarrow^{p} H\in D} H\backslash \mathcal{U}`, and :math:`\mathcal{U}' = \mathcal{U}\cup \mathcal{S}'`. diff --git a/doc/source/installation.rst b/doc/source/installation.rst index 1da4f8d..bdaf41a 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -6,267 +6,87 @@ Installation ============ -.. _quick-start: +Currently there are the following options for installing the +package: -Quick Start ------------ +- :ref:`compiling` +- Installing via Conda. +- Running via a pre-compiled Docker image. -These are simplified instructions for Ubuntu and Fedora. If a step doesn't work -or fit your case, please consult the sections below. -First, get MØD and install the easy dependencies: +Conda +----- -.. code-block:: bash - - git clone --recursive https://github.com/jakobandersen/mod.git - ./bootstrap.sh - pip3 install -r requirements.txt - # Ubuntu: - sudo apt install $(bindep -b | tr '\n' ' ') - # Fedora: - sudo dnf install $(bindep -b | tr '\n' ' ') +This is currently only available for Linux. -Then: +1. Install Latex on your system. + E.g., see the provided ``bindep.txt`` file for which + TeX Live packages are needed for a selection of popular + Linux distribuions. +2. ``conda install -c jakobandersen -c conda-forge mod`` +3. (Optional, but recommended) Install a pre-compiled Latex + format file. + During figure generation by :ref:`mod_post` a Latex format + file is needed. It depends on your Latex installation and + can therefore not be provided in the Conda package. + It will then be compiled at each invocation. To check, + try running, e.g., ``mod -e "smiles('O').print()"``. + If the post-processor output has a line with + ``compileFmt``, the format file is not installed. -1. Install Boost from source, see :ref:`install_boost_python`. - Remember the installation path. -2. On Ubuntu: install Graphviz from source: + Run ``mod_post --install-format`` to install the format + file (or ``mod_post --install-format-sudo`` if you don't + own the folder with the Conda installation). - .. code-block:: bash - sudo apt install librsvg2-dev libpango1.0-dev - wget http://graphviz.gitlab.io/pub/graphviz/stable/SOURCES/graphviz.tar.gz - tar -xf graphviz.tar.gz --one-top-level=graphviz --strip-components=1 - cd graphviz - ./configure - make - sudo make install +Docker +------ -Finally, compile and install MØD: +A Docker image with an installation is available at +`Docker Hub `__, +so getting started can be done simply via .. code-block:: bash - mkdir build - cd build - cmake ../ -DCMAKE_PREFIX_PATH=path/to/boost - make - sudo make install - + docker run -it jakobandersen/mod -From a Git Repository ---------------------- +It will put you into an empty folder ``/workDir``. +The image is build with a copy of the :ref:`examples` in ``/examples``. -After a checkout of the desired version, do: +In order to exchange data with the container it may be convient to start the +container with a local folder mounted, for example the current folder .. code-block:: bash - git submodule update --init --recursive - ./bootstrap.sh - -This is needed to first fetch certain dependencies and second -to generate build files, extract the API documentation, -and create the file ``VERSION`` based on the current commit. - -See :ref:`source-build` on how to then build the package. - - -As Dependency of Another CMake Project --------------------------------------- - -MØD supports use via ``add_subdirectory`` in CMake. -The target ``mod::libmod`` is exported, -which can be used with ``target_link_libraries`` to link against libMØD. -The version is in the variable ``mod_VERSION``. -Note that running ``./bootstrap.sh`` is still needed if the -source is a repository clone (e.g., a Git submodule). - - -.. _source-build: - -From a Source Archive ---------------------- + docker run -it -v $(pwd):/workdir jakobandersen/mod -The package is build and installed from source as a CMake project. -Generally that means something like: +However, the user running inside the container is ``root`` so all files you +create inside the shared folder will have ``root`` as owner and group. +Therefore, it may be better to tell Docker to run with your own user and group +inside .. code-block:: bash - mkdir build - cd build - cmake ../ - make -j - make install - -A source archive can also be created with ``make dist``. - -The following is a list of commonly used options for ``cmake``. -Additional options specific for MØD along with their default valule are also -listed. -See also :ref:`dependencies` for elaboration on some of them. - -- ``-DCMAKE_INSTALL_PREFIX=``, set a non-standard installation - directory. Note also that the `GNUInstallDirs - `__ - module is used. -- ``-DCMAKE_BUILD_TYPE=``, set a non-standard build type. - The default is `RelWithDebInfo - `__. - An additional build type ``OptDebug`` is available which adds the compilation - flags ``-g -O3``. -- ``-DCMAKE_PREFIX_PATH=``, set a ``;``-separated list of paths used for - finding most dependencies. The paths should generally be the prefixes - specified when the dependency was installed. - See also https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html#variable:CMAKE_PREFIX_PATH. -- ``-DBUILD_DOC=on``, whether to build documentation or not. - This is forced to ``off`` when used via ``add_subdirectory``. -- ``-DBUILD_POST_MOD=on``, whether to build the post-processor or not. -- ``-DBUILD_PY_MOD=on``, whether to build the Python bindings or not. -- ``-DBUILD_TESTING=off``, whether to allow test building or not. - This is forced to ``off`` when used via ``add_subdirectory``. - When ``on`` the tests can be build with ``make tests`` and run with ``ctest``. -- ``-DBUILD_TESTING_SANITIZERS=on``, whether to compile libraries and tests - with sanitizers or not. This is forced to ``off`` when ``BUILD_COVERAGE=on``. -- ``-DBUILD_EXAMPLES=off``, whether to build and allow running of examples as - tests or not. - This is forced to ``off`` when used via ``add_subdirectory``. - This is forced to ``off`` when ``BUILD_TESTING`` is ``off``. -- ``-DBUILD_COVERAGE=off``, whether to compile code and run tests with GCov. - When ``on`` the sanitizers on tests will be disabled. - After building the tests, execute ``make coverage_collect`` without parallel - jobs to run tests. Afterwards, execute ``make coverage_build`` to compile the - code coverage report. -- ``-DENABLE_SYMBOL_HIDING=on``, whether symbols internal to the library are - hidden or not. Disabling this option may degrade performance, and should only - be done while developing extensions to the C++ library. -- ``-DENABLE_DEP_SYMBOL_HIDING=on``, whether symbols from library dependencies - are hidden or not. Disabling this option may make it slower to load the - library at runtime. -- ``-DENABLE_IPO=on``, whether to use link-time optimization or not. - Disabling this option may degrade performance, but speed up linking time. - As default the link-time optimizer will only use 1 thread. - To use more threads, e.g., 7, use the following options for configuration - ``-DCMAKE_MODULE_LINKER_FLAGS="-flto=7" -DCMAKE_SHARED_LINKER_FLAGS="-flto=7"``, - when using GCC as the compiler. -- ``-DUSE_NESTED_GRAPH_CANON=on``, whether to use the dependency GraphCanon - from the Git submodule or not. -- ``-DUSE_NESTED_NLOHMANN_JSON=on``, whether to use the dependency - `nlohmann/json `__ from the Git submodule - or not. -- ``-DWITH_OPENBABEL=on``, whether to enable/disable features depending on Open Babel. - - -.. _dependencies: - -Dependencies ------------- - -Python dependencies are listed in ``requirements.txt`` (which includes -``requirements_nodoc.txt``). - -Dependencies that can be satisfied via the system package manager are listed in -``bindep.txt``. Any missing package can be listed using the -`Bindep `__ program -(which can be installed via ``requirements.txt``). - -The following is a detailed list of all dependencies and the CMake switches -related to them. - -- This documentation requires (``-DBUILD_DOC=on``): - - - A supported version of `Sphinx `__. - - The Python package ``sphinx-autoapi`` (module name: ``autoapi``). + docker run -it -v $(pwd):/workdir -u $(id -u):$(id -g) jakobandersen/mod -- libMØD: +Note though, that your user/group probably doesn't exist in the container so +you may get some warnings about the group not existing and that the user does +not have a name. This is however usually not a problem. - - A C++ compiler with reasonable C++14 support is needed. GCC 6.1 or later - should work. - - `Boost `__ dev >= 1.72 - (use ``-DBOOST_ROOT=`` for non-standard locations). - - `GraphCanon `__ >= 0.4. - This is fulfilled via a Git submodule (make sure to do - ``git submodule update --init --recursive``), - but if another source is needed, set ``-DUSE_NESTED_GRAPH_CANON=off``. - - `nlohmann/json `__ >= 3.7.3. - This is fulfilled via a Git submodule (make sure to do - ``git submodule update --init --recursive``), - but if another source is needed, set ``-DUSE_NESTED_NLOHMANN_JSON=off``. - - (optional) `Open Babel`_ dev, >= 2.3.2 (``-DWITH_OPENBABEL=on``). - -- PyMØD (``-DBUILD_PY_MOD=on``): - - - Python 3 dev - - Boost.Python built with Python 3 - - (Optional) IPython 3 - -- PostMØD (``-DBUILD_POST_MOD=on``): - - - ``pdflatex`` available in the ``PATH`` or in ``CMAKE_PROGRAM_PATH``, - with not too old packages (Tex Live 2012 or newer should work). - - ``pdf2svg`` available in the ``PATH`` or in ``CMAKE_PROGRAM_PATH``. - - ``dot`` and ``neato`` from Graphviz available in the ``PATH`` or in - ``CMAKE_PROGRAM_PATH``. - They must additionally be able to load SVG files and output as both SVG and - PDF files (all via cairo). - That is, in the output of ``dot -P`` the following edges must exist: - - - ``cairo_device_svg -> output_svg`` - - ``cairo_device_pdf -> output_pdf`` - - ``rsvg_loadimage_svg -> render_cairo`` - - - If you install Graphviz from source, you can check if the status output in - the end of ``configure`` includes the following two lines:: - - pangocairo: Yes - rsvg: Yes - - -.. _install_boost_python: - -Boost and Boost.Python with Python 3 ------------------------------------- - -A package with the sources of Boost can be downloaded from `http://boost.org`. - - -Basic Installation -"""""""""""""""""" - -Boost uses a custom build system which may be difficult to use. -A procedure for compiling and installing Boost with Python 3 for Boost.Python -is the following. - -1. ``./bootstrap.sh --with-python=python3`` (optionally give - ``--prefix=some/path`` to specify a non-standard installation path. -2. ``./b2`` (optionally give ``-j N`` (similar to GNU Make) to compile with - multiple threads) -3. ``./b2 install`` (optionally give ``--prefix=some/path`` to specify a - non-standard installation path (if not done earlier). - -After ``bootstrap.sh`` has been run, the file ``project-config.jam`` -has been created, which can be edited to customise installation path and a lot -of other things. All edits should be done before running ``b2``. - - -Non-standard Python Installation -"""""""""""""""""""""""""""""""" - -Passing ``--with-python=python3`` to ``bootstrap.sh`` should work. -This adds a line similar to "``using python : 3.3 ;``" to -``project-config.jam``. -After compilation (running ``b2``) the file ``stage/lib/libboost_python3.so`` -should exist. If not, it did not detect Python 3 properly. - -If Python is installed in a non-standard location, add the a line similar to -"``using python : 3.3 : python3 : /path/to/python/3/installtion/include ;``" to -``project-config.jam``, where the last path is the path to the -``include``-folder of the Python-installation. +As a final optimization, every time you execute the command above, you create +a new container. You can use ``docker container prune`` to delete stopped +containers. Assuming you only work within the shared ``/workdir`` there is +no particular reason for the container to hang around once you exit, +so you can add ``--rm`` to the command to let Docker automatically delete it +once you exit. +We thus arrive at the following full command +.. code-block:: bash -Custom GCC Version -"""""""""""""""""" + docker run -it --rm -v $(pwd):/workdir -u $(id -u):$(id -g) jakobandersen/mod -Before running ``b2`` create the file ``user-config.jam`` in the root of the -home dir (see `here -`__ -for the full documentation). Put a line similar to -"``using gcc : : /path/to/g++-4.8``" in the file. +As a quick test, you can try running ``mod -e "smiles('O').print()`` inside +the container. When it's done, then outside the container you should now be +able to open the printed summary ``summary/summary.pdf``. +You can thus use the ``mod`` command inside the container, but otherwise +do all file manipulation outside the container. diff --git a/doc/source/knownIssues.rst b/doc/source/knownIssues.rst index 5218e0f..6179e37 100644 --- a/doc/source/knownIssues.rst +++ b/doc/source/knownIssues.rst @@ -1,6 +1,8 @@ Known Issues ============ +.. _issue-fmt: + Error ``/share/mod/commonPreamble.fmt made by different executable version`` during post-processing ----------------------------------------------------------------------------------------------------------- @@ -8,8 +10,6 @@ This error message may be printed by ``pdflatex`` when ``post_mod`` is compiling MØD installs a precompiled Latex format file for speeding up figure compilation. However, if the Latex installation is upgraded after MØD is installed this error may happen. - -Completely reinstalling MØD will definitely solve the problem. -However, in the build directory, if you find ``commonPreabmle.fmt`` and delete it, -then running ``make`` and ``make install`` should quickly recompile just the format file -and update the installation. +To recompile and install the format file again, call the post-processor as +:option:`mod_post --install-format` or +:option:`mod_post --install-format-sudo`. diff --git a/doc/source/postmod/postmod.rst b/doc/source/postmod/postmod.rst index f723451..b6ce98a 100644 --- a/doc/source/postmod/postmod.rst +++ b/doc/source/postmod/postmod.rst @@ -1,3 +1,5 @@ +.. _mod_post: + **************************** PostMØD (``mod_post``) **************************** @@ -38,6 +40,17 @@ Options When running ``make``, use ``-j `` as additional arguments. This parameter defaults to 2. +.. option:: --install-format + --install-format-sudo + + Compile the common Latex preamble used for figure generation + and install it. Use the ``-sudo`` version to install using ``sudo``. + This may be useful to do if you encounter the issue about the format being + :ref:`made by different executable version `, + or if MØD was configured to not install the format file + (``-DBUILD_POST_MOD_FMT=off``). + + Environtment Variables ---------------------- diff --git a/doc/source/pymod/protocols.rst b/doc/source/pymod/protocols.rst new file mode 100644 index 0000000..e3934dd --- /dev/null +++ b/doc/source/pymod/protocols.rst @@ -0,0 +1,247 @@ +.. _py-protocols: + +.. default-domain:: py + +.. py:currentmodule:: mod.protocols +.. cpp:namespace:: mod + +********************************************************** +Protocols +********************************************************** + +In Python a protocol is a specification for structural subtyping +(static duck-typing), +e.g., see https://www.python.org/dev/peps/pep-0544/. +This is very similar to what is called a "concept" in C++, +e.g., see https://en.wikipedia.org/wiki/Concept_(generic_programming). +Python for example has the Iterator protocol that specifies how to implement +objects one can iterate over. + +This page describes protocols in MØD that are implemented by several classes +in the Python interface. +Note that these classes are not real types, but merely serves as a +documentation device. + + +.. class:: Graph + + The undirected graph protocol. + + In addition to the following elements, a graph is also equality comparable. + + .. attribute:: numVertices + + (Read-only) The number of vertices in the graph. + + :type: int + + .. attribute:: vertices + + (Read-only) An iterable of all vertices in the graph. + + :type: VertexRange + + .. attribute:: numEdges + + (Read-only) The number of edges in the graph. + + :type: int + + .. attribute:: edges + + (Read-only) An iterable of all edges in the graph. + + :type: EdgeRange + + .. class:: Vertex + + A descriptor of either a vertex in a graph, or a null vertex. + + Besides the operations below, descriptors are + + - equality comparable, + - totally ordered, and + - hashable + + .. method:: __init__() + + Constructs a null descriptor. + + .. :method:: __bool__() + + :returns: ``not isNull()`` + :rtype: bool + + .. method:: isNull() + + :returns: whether this is a null descriptor or not. + :rtype: bool + + .. py:attribute:: id + + (Read-only) The index of the vertex. A non-negative number. + The IDs are not guaranteed in general to be consequtive. + See the documentation for concrete graphs for sepcific additional + guarantees. + + :type: int + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: graph + + (Read-only) The graph the vertex belongs to. + + :type: Graph + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + + .. attribute:: degree + + (Read-only) The degree of the vertex. + + :type: int + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + + .. attribute:: incidentEdges + + (Read-only) A range of incident edges to this vertex. + + :type: Graph.IncidentEdgeRange + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + + .. class:: Edge + + A descriptor of either an edge in a graph, or a null edge. + + Besides the operations below, descriptors are + + - equality comparable, and + - totally ordered + + .. method:: __init__() + + Constructs a null descriptor. + + .. method:: __bool__() + + :returns: ``not isNull()`` + :rtype: bool + + .. method:: isNull() + + :returns: whether this is a null descriptor or not. + :rtype: bool + + .. attribute:: graph + + (Read-only) The graph the edge belongs to. + + :type: Graph + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: source + + (Read-only) The source vertex of the edge. + + :type: Graph.Vertex + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: target + + (Read-only) The target vertex of the edge. + + :type: Graph.Vertex + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + + .. class:: VertexRange + + An iterable of all vertices in the graph. + + .. class:: EdgeRange + + An iterable of all edges in the graph. + + .. class:: IncidentEdgeRange + + An iterable of all edges incident to a specific vertex in the graph. + + + +.. class:: LabelledGraph + + An extension of the :class:`Graph` protocol, + with access to label information on vertices and edges. + + .. class:: Vertex + + An extension of the :class:`Graph.Vertex` protocol. + + .. py:attribute:: stringLabel + + (Read-only) The string label of the vertex. + + :type: str + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: atomId + + (Read-only) The atom ID of the vertex. + + :type: AtomId + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: isotope + + (Read-only) The isotope of the vertex. + + :type: Isotope + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: charge + + (Read-only) The charge of the vertex. + + :type: Charge + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. :attribute:: radical + + (Read-only) The radical status of the vertex. + + :type: bool + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. method:: printStereo() + printStereo(p) + + Print the stereo configuration for the vertex. + + :param GraphPrinter p: the printing options used for the depiction. + :returns: the name of the PDF-file that will be compiled in + post-processing. + :rtype: str + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + + .. class:: Edge + + An extension of the :class:`Graph.Edge` protocol. + + .. attribute:: stringLabel + + (Read-only) The string label of the edge. + + :type: str + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + .. attribute:: bondType + + (Read-only) The bond type of the edge. + + :type: BondType + :raises: :class:`~mod.LogicError` if it is a null descriptor. + + diff --git a/docker/Arch.Dockerfile b/docker/Arch.Dockerfile new file mode 100644 index 0000000..0e16bc9 --- /dev/null +++ b/docker/Arch.Dockerfile @@ -0,0 +1,30 @@ +FROM archlinux +ARG j=7 + +WORKDIR /opt/mod +COPY ./build/mod-*.tar.gz ./ +RUN tar xzf mod-*.tar.gz --strip-components=1 + +RUN pacman -Suy --noconfirm \ + python-pip \ + && pip3 install -r requirements_nodoc.txt \ + && cp docker/bindep_depends_arch.py \ + /usr/lib/python3.9/site-packages/bindep/depends.py \ + && pacman -Suy --noconfirm \ + $(bindep -b | tr '\n' ' ') \ + && rm -rf /var/cache/pacman + + +WORKDIR /opt/mod/build +RUN cmake ../ -DBUILD_DOC=no \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING_SANITIZERS=off \ + -DCMAKE_MODULE_LINKER_FLAGS="-flto=$j" -DCMAKE_SHARED_LINKER_FLAGS="-flto=$j" \ + -DBUILD_TESTING=on \ + && make -j $j \ + && make tests -j $j \ + && make install \ + && ctest -j $j --output-on-failure -E cmake_ \ + && rm -rf /opt/mod + +WORKDIR /workdir diff --git a/docker/Fedora b/docker/Fedora.Dockerfile similarity index 58% rename from docker/Fedora rename to docker/Fedora.Dockerfile index 1eef0d5..4513ace 100644 --- a/docker/Fedora +++ b/docker/Fedora.Dockerfile @@ -1,4 +1,4 @@ -FROM fedora:32 +FROM fedora:33 ARG j=7 WORKDIR /opt/mod @@ -13,23 +13,6 @@ RUN dnf install -y \ && dnf clean all \ && rm -rf /var/cache/yum -# Boost -# the folder can apparently not be called just 'boost', therefore 'boostDir' -WORKDIR /opt/boostDir -#RUN wget \ -# https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.gz \ -# -O boost.tar.gz -COPY build/boost.tar.gz ./ -RUN \ - tar -xf boost.tar.gz --one-top-level=boostSrc --strip-components=1 \ - && cd boostSrc \ - && ./bootstrap.sh --with-python=python3 \ - && ./b2 --with-python --with-graph --with-iostreams -j $j \ - && ./b2 install \ - && cd .. \ - && rm -rf /opt/boostDir - - WORKDIR /opt/mod/build RUN cmake ../ -DBUILD_DOC=no \ diff --git a/docker/Ubuntu b/docker/Ubuntu.Dockerfile similarity index 93% rename from docker/Ubuntu rename to docker/Ubuntu.Dockerfile index 097b894..d1a1efc 100644 --- a/docker/Ubuntu +++ b/docker/Ubuntu.Dockerfile @@ -43,10 +43,9 @@ RUN \ # Boost # the folder can apparently not be called just 'boost', therefore 'boostDir' WORKDIR /opt/boostDir -#RUN wget \ -# https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.gz \ -# -O boost.tar.gz -COPY build/boost.tar.gz ./ +RUN wget \ + https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.gz \ + -O boost.tar.gz RUN \ tar -xf boost.tar.gz --one-top-level=boostSrc --strip-components=1 \ && cd boostSrc \ @@ -66,7 +65,9 @@ RUN cmake ../ -DBUILD_DOC=no \ && make -j $j \ && make tests -j $j \ && make install \ + && cp -a ../examples/py /examples \ && ctest -j $j --output-on-failure -E cmake_ \ && rm -rf /opt/mod WORKDIR /workdir +RUN chmod og+rwX . diff --git a/docker/bindep_depends_arch.py b/docker/bindep_depends_arch.py new file mode 100644 index 0000000..cacc863 --- /dev/null +++ b/docker/bindep_depends_arch.py @@ -0,0 +1,702 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# 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. + +from locale import getpreferredencoding +import logging +import os.path +from parsley import makeGrammar +import platform +import subprocess +import sys +# packaging is newer, usually available but not guaranteed +try: + from packaging.version import parse as as_ver +except ImportError: + from distutils.version import LooseVersion as as_ver +import distro + + +debversion_grammar = """ +epoch = :d ':' -> d +trailingdeb = (upstream_segment* '-' debver) +upstream_segment = (letterOrDigit | '.' | '+' | '~' | ':') +upstreamver = digit (upstream_segment | ('-' ~~trailingdeb))* +upstreamver_no_hyphen = digit (letterOrDigit | '.' | '+' | '~' | ':')* +debver = (letterOrDigit | '.' | '+' | '~')+ +upstream_no_hyphen = epoch?:e :u -> (e or '0', u, "") +upstream_hyphen = epoch?:e :u '-' :d -> (e or '0', u, d) +debversion = upstream_hyphen | upstream_no_hyphen +""" + +debversion_compiled = makeGrammar(debversion_grammar, {}) + + +grammar = debversion_grammar + """ +rules = (rule|comment|blank)*:bits -> [r for r in bits if r is not None] +rule = :name selector?:selector version?:version ('\n'|comment) -> ( + name, selector or [], version or []) +lowercase = ('a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|'n'|'o'|'p' + |'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z') +name = (letterOrDigit|'/'):start (letterOrDigit|'.'|'+'|'-'|'_'|'/')+:rest +ws = ' '+ +profile = ('!'?:neg <(lowercase|digit|':'|'-'|'.')+>:name) -> (neg!='!', name) +profiles = '(' (ws? profile)*:p ws? ')' -> p +group = profiles | profile +selector = ws '[' (ws? group)*:p ws? ']' -> p +oneversion = <('<=' | '<' | '!=' | '==' | '>=' | '>')>:rel :v -> ( + rel, v) +version = ws oneversion:v1 (',' oneversion)*:v2 -> [v1] + v2 +comment = ws? '#' any* '\n' -> None +any = ~'\n' anything +blank = ws? '\n' -> None +""" +PY2 = "base-py2" +PY3 = "base-py3" + + +def get_depends(filename=None): + fd = get_depends_file(filename) + if not fd: + return None + return Depends(fd.read()) + + +def get_depends_file(filename=None): + log = logging.getLogger(__name__) + if filename == "-": + return sys.stdin + elif filename: + try: + fd = open(filename, 'rt') + except IOError: + log.error('Error reading file %s.' % filename) + return None + else: + if (os.path.isfile('bindep.txt') and + os.path.isfile('other-requirements.txt')): + log.error( + 'Both bindep.txt and other-requirements.txt ' + 'files exist, choose one.') + return None + if os.path.isfile('bindep.txt'): + try: + fd = open('bindep.txt', 'rt') + except IOError: + log.error('Error reading file bindep.txt.') + return None + elif os.path.isfile('other-requirements.txt'): + try: + fd = open('other-requirements.txt', 'rt') + except IOError: + log.error('Error reading file other-requirements.txt.') + return None + else: + log.error( + 'Neither file bindep.txt nor file ' + 'other-requirements.txt exist.') + return None + return fd + + +class Depends(object): + """Project dependencies.""" + + # Truth table for combining platform and user profiles: + # (platform, user) where False means that component + # voted definitely no, True means that that component + # voted definitely yes and None means that that component + # hasn't voted. + _include = { + (False, False): False, + (False, None): False, + (False, True): False, + (None, False): False, + (None, None): True, + (None, True): True, + (True, False): False, + (True, None): True, + (True, True): True, + } + + def __init__(self, depends_string): + """Construct a Depends instance. + + :param depends_string: The string description of the requirements that + need to be satisfied. See the bindep README.rst for syntax for the + requirements list. + """ + parser = makeGrammar(grammar, {})(depends_string) + self._rules = parser.rules() + + def _partition(self, rule): + """Separate conditions into platform and user profiles. + + :return Two lists, the platform and user profiles. + """ + platform = [] + user = [] + for group in rule[1]: + if isinstance(group, list): + user.append(group) + continue + sense, profile = group + if profile.startswith("platform:"): + platform.append((sense, profile)) + else: + user.append((sense, profile)) + return platform, user + + def _evaluate(self, partition_rule, profiles): + """Evaluate rule. Does it match the profiles? + + :return Result is trinary: False for definitely no, True for + definitely yes, None for no rules present. + """ + if partition_rule == []: + return None + + # Have we seen any positive selectors - if not, the absence of + # negatives means we include the rule, but if we any positive + # selectors we need a match. + positive = False + match_found = False + group_found = False + group_match_found = False + negative = False + for group in partition_rule: + if isinstance(group, list): + group_found = True + if self._match_all(group, profiles): + group_match_found = True + continue + sense, profile = group + if sense: + positive = True + if profile in profiles: + match_found = True + else: + if profile in profiles: + negative = True + break + if not negative: + if group_match_found or match_found: + return True + if not group_found and not positive: + return True + return False + + def _match_all(self, partition_rules, profiles): + """Evaluate rules. Do they all match the profiles? + + :return Result True if all profiles match else False + """ + def matches(sense, profile, profiles): + return sense if profile in profiles else not sense + + for sense, profile in partition_rules: + if not matches(sense, profile, profiles): + return False + return True + + def active_rules(self, profiles): + """Return the rules active given profiles. + + :param profiles: A list of profiles to consider active. This should + include platform profiles - they are not automatically included. + """ + profiles = set(profiles) + result = [] + for rule in self._rules: + # Partition rules + platform_profiles, user_profiles = self._partition(rule) + # Evaluate each partition separately + platform_status = self._evaluate(platform_profiles, profiles) + user_status = self._evaluate(user_profiles, profiles) + # Combine results + # These are trinary: False for definitely no, True for + # definitely yes, None for no rules present. + if self._include[platform_status, user_status]: + result.append(rule) + return result + + def list_all_packages(self, rules, output_format='newline'): + """Print a list of all packages that are required on this platform + according to the passed in rules. This is useful if we want to build + RPMs based on the deps listed in bindeps.txt + + :param rules: A list of rules, as returned by active_rules. + :param output_format: The format to print the output in. Currently + we support newline format which will print 1 package per line, and + csv format which prints a csv list. + :return: List of all required packages regardless of whether they are + missing. + """ + packages_list = [rule[0] for rule in rules] + if output_format == 'csv': + logging.info(','.join(packages_list)) + elif output_format == 'newline': + logging.info('\n'.join(packages_list)) + return packages_list + + def check_rules(self, rules): + """Evaluate rules against the local environment. + + :param rules: A list of rules, as returned by active_rules. + :return: A list of unsatisfied rules. + """ + missing = set() + incompatible = [] + for rule in rules: + installed = self.platform.get_pkg_version(rule[0]) + if not installed: + missing.add(rule[0]) + continue + for operator, constraint in rule[2]: + if not _eval(installed, operator, constraint): + incompatible.append( + (rule[0], '%s%s' % (operator, constraint), installed)) + result = [] + if missing: + result.append(("missing", sorted(missing))) + if incompatible: + result.append(("badversion", incompatible)) + return result + + def profiles(self): + profiles = set() + for rule in self._rules: + # Partition rules, but keep only the user ones + _, user_profiles = self._partition(rule) + for profile in user_profiles: + # Flatten a series of AND conditionals in a user rule + if isinstance(profile, list): + profiles.update([rule[1] for rule in profile]) + elif isinstance(profile, tuple): + profiles.add(profile[1]) + return sorted(profiles) + + def codenamebits(self, distro_id, codename): + atoms = set() + codenamebits = codename.split() + for i in range(len(codenamebits)): + atoms.add("%s-%s" % (distro_id, "-".join(codenamebits[:i + 1]))) + return atoms + + def releasebits(self, distro_id, release): + atoms = set() + releasebits = release.split(".") + for i in range(len(releasebits)): + atoms.add("%s-%s" % (distro_id, ".".join(releasebits[:i + 1]))) + return atoms + + def platform_profiles(self): + if platform.system() == 'Darwin': + atoms = set(['darwin']) + # detect available macos package managers + if os.system('which brew >/dev/null') == 0: + atoms.add('brew') + atoms.add(PY2) + self.platform = Brew() + return ["platform:%s" % (atom,) for atom in sorted(atoms)] + distro_id = distro.id() + if not distro_id: + log = logging.getLogger(__name__) + log.error('Unable to determine distro ID. ' + 'Does /etc/os-release exist or ' + 'is lsb_release installed?') + raise Exception('Distro name not found') + # NOTE(toabctl): distro can be more than one string (i.e. "SUSE LINUX") + codename = distro.codename().lower() + release = distro.version().lower() + release_version = as_ver(release) + # NOTE(toabctl): space is a delimiter for bindep, so remove the spaces + distro_id = "".join(distro_id.split()).lower() + atoms = set([distro_id]) + atoms.update(self.codenamebits(distro_id, codename)) + atoms.update(self.releasebits(distro_id, release)) + if distro_id in ["debian", "ubuntu"]: + atoms.add("dpkg") + # https://wiki.debian.org/Python + # https://wiki.ubuntu.com/Python + if (distro_id == 'ubuntu' and release_version >= + as_ver("16.04")) or (distro_id == 'debian' and + release_version >= as_ver("10")): + atoms.add(PY3) + else: + atoms.add(PY2) + self.platform = Dpkg() + # RPM distros seem to be especially complicated + elif distro_id in ["amzn", "amazonami", + "centos", "rhel", + "redhatenterpriseserver", + "redhatenterpriseworkstation", + "fedora", + "opensuseproject", "opensuse", "opensuse-leap", + "opensuse-tumbleweed", "sles", "suselinux", + "ol", "oracle"]: + # Distro aliases + if distro_id in ["redhatenterpriseserver", + "redhatenterpriseworkstation"]: + # just short alias + atoms.add("rhel") + atoms.update(self.codenamebits("rhel", codename)) + atoms.update(self.releasebits("rhel", release)) + atoms.add(PY2 if release_version < as_ver("8") else PY3) + elif distro_id == 'rhel' and 'server' in distro.name().lower(): + atoms.add("redhatenterpriseserver") + atoms.update(self.codenamebits("redhatenterpriseserver", + codename)) + atoms.update(self.releasebits("redhatenterpriseserver", + release)) + atoms.add(PY2 if release_version < as_ver("8") else PY3) + elif (distro_id == 'rhel' and + 'workstation' in distro.name().lower()): + atoms.add("redhatenterpriseworkstation") + atoms.update(self.codenamebits("redhatenterpriseworkstation", + codename)) + atoms.update(self.releasebits("redhatenterpriseworkstation", + release)) + atoms.add(PY2 if release_version < as_ver("8") else PY3) + elif "amzn" in distro_id: + atoms.add("amazonami") + atoms.update(self.codenamebits("amazonami", codename)) + atoms.update(self.releasebits("amazonami", release)) + elif "amazonami" in distro_id: + atoms.add("amzn") + atoms.update(self.codenamebits("amzn", codename)) + atoms.update(self.releasebits("amzn", release)) + elif "opensuse" in distro_id: + # just short alias + atoms.add("opensuse") + atoms.update(self.codenamebits("opensuse", codename)) + atoms.update(self.releasebits("opensuse", release)) + atoms.add("opensuseproject") + atoms.update(self.codenamebits("opensuseproject", codename)) + atoms.update(self.releasebits("opensuseproject", release)) + elif "sles" in distro_id: + atoms.add("suselinux") + atoms.update(self.codenamebits("suselinux", codename)) + atoms.update(self.releasebits("suselinux", release)) + elif "suselinux" in distro_id: + atoms.add("sles") + atoms.update(self.codenamebits("sles", codename)) + atoms.update(self.releasebits("sles", release)) + elif "fedora" in distro_id: + atoms.add(PY2 if release_version < as_ver("23") else PY3) + elif any(w in distro_id for w in ["centos", "oracle", "rhel"]): + atoms.add(PY2 if release_version < as_ver("8") else PY3) + + # Family aliases + if 'suse' in distro_id or distro_id == 'sles': + atoms.add("suse") + else: + atoms.add("redhat") + + atoms.add("rpm") + self.platform = Rpm() + elif distro_id in ["gentoo"]: + atoms.add("emerge") + self.platform = Emerge() + elif distro_id in ["arch"]: + atoms.add("pacman") + self.platform = Pacman() + elif distro_id in ["alpine"]: + atoms.add("apk") + self.platform = Apk() + else: + self.platform = Unknown() + return ["platform:%s" % (atom,) for atom in sorted(atoms)] + + +class Platform(object): + """Interface for querying platform specific info.""" + + def get_pkg_version(self, pkg_name): + """Find the installed version of pkg_name. + + :return: None if pkg_name is not installed, or a version otherwise. + """ + raise NotImplementedError(self.get_pkg_version) + + +class Unknown(Platform): + """Unknown platform implementation. Raises error.""" + + def get_pkg_version(self, pkg_name): + raise Exception("Uknown package manager for current platform.") + + +class Brew(Platform): + """brew specific platform implementation.""" + + def get_pkg_version(self, pkg_name): + try: + output = subprocess.check_output( + ['brew', 'list', '--versions', + pkg_name], + stderr=subprocess.STDOUT).decode(getpreferredencoding(False)) + except subprocess.CalledProcessError as e: + if (e.returncode == 1): + return None + raise + # output looks like + # git 2.15.1_1 2.15.0 + output = output.strip() + elements = output.split(' ')[1:] + # brew supports multiple versions, we will only return the first one + return elements[0] + + +class Dpkg(Platform): + """dpkg specific platform implementation. + + This currently shells out to dpkg, it could in future use python-apt. + """ + + def get_pkg_version(self, pkg_name): + try: + output = subprocess.check_output( + ["dpkg-query", "-W", "-f", "${Package} ${Status} ${Version}\n", + pkg_name], + stderr=subprocess.STDOUT).decode(getpreferredencoding(False)) + except subprocess.CalledProcessError as e: + eoutput = e.output.decode(getpreferredencoding(False)) + if (e.returncode == 1 and + (eoutput.startswith('dpkg-query: no packages found') or + eoutput.startswith('No packages found matching'))): + return None + raise + # output looks like + # name planned status install-status version + output = output.strip() + elements = output.split(' ') + if elements[3] != 'installed': + return None + return elements[4] + + +class Rpm(Platform): + """rpm specific platform implementation. + + This currently shells out to rpm, it could in future use rpm-python if + that ever gets uploaded to PyPI. + """ + + def get_pkg_version(self, pkg_name): + try: + output = subprocess.check_output( + ["rpm", "--qf", + "%{NAME} %|EPOCH?{%{EPOCH}:}|%{VERSION}-%{RELEASE}\n", + "--whatprovides", "-q", pkg_name], + stderr=subprocess.STDOUT).decode(getpreferredencoding(False)) + except subprocess.CalledProcessError as e: + eoutput = e.output.decode(getpreferredencoding(False)) + if (e.returncode == 1 and + (eoutput.strip().endswith('is not installed') or + (eoutput.strip().startswith('no package provides')))): + return None + raise + # output looks like + # name version + output = output.strip() + elements = output.split(' ') + return elements[1] + + +class Emerge(Platform): + """emerge specific implementation. + + This currently shells out to equery, it could be changed to eix to be + faster but that would add another dependency and eix's cache would need to + be updated before this is run. + """ + + def get_pkg_version(self, pkg_name): + try: + output = subprocess.check_output( + ['equery', 'l', '--format=\'$version\'', pkg_name], + stderr=subprocess.STDOUT).decode(getpreferredencoding(False)) + except subprocess.CalledProcessError as e: + # The output is currently not used in the test cases. + # Nevertheless the next statement checks if the given + # parameter has the correct type. + e.output.decode(getpreferredencoding(False)) + if e.returncode == 3: + return None + raise + # output looks like + # version + output = output.strip() + elements = output.split(' ') + return elements[0] + + +class Pacman(Platform): + """pacman specific implementation. + + This shells out to pacman + """ + + def get_pkg_version(self, pkg_name): + try: + output = subprocess.check_output( + ['pacman', '-Q', pkg_name], + stderr=subprocess.STDOUT).decode(getpreferredencoding(False)) + except subprocess.CalledProcessError as e: + eoutput = e.output.decode(getpreferredencoding(False)) + s = "error: package '{}' was not found".format(pkg_name) + if e.returncode == 1 and s in eoutput: + return None + raise + # output looks like + # version + elements = output.strip().split(' ') + return elements[1] + + +class Apk(Platform): + """apk (Alpine Linux) specific implementation. + + This shells out to apk + """ + + def get_pkg_version(self, pkg_name): + apk = subprocess.Popen( + ['apk', 'version', pkg_name], stdout=subprocess.PIPE) + output, _ = apk.communicate() + if apk.returncode == 1: + return None + output = output.decode(getpreferredencoding(False)) + # output looks like + # version + output = output.strip() + elements = output.split() + if len(elements) < 4: + return None + return elements[4] + + +def _eval_diff(operator, diff): + """Return the boolean result for operator given diff. + + :param diff: An int with negative values meaning the right most parameter + to the _eval function was greater than the left most parameter. + :return: True if the operator was satisfied. + """ + if operator == "==": + return diff == 0 + if operator == "!=": + return diff != 0 + if operator == "<": + return diff < 0 + if operator == "<=": + return diff <= 0 + if operator == ">": + return diff > 0 + if operator == ">=": + return diff >= 0 + + +def _to_ord(character): + # Per http://www.debian.org/doc/debian-policy/ch-controlfields.html + # The lexical comparison is a comparison of ASCII values modified so that + # all the letters sort earlier than all the non-letters and so that a + # tilde sorts before anything, even the end of a part. + # ord(~) -> 126 + # ord('A') -> 65 + # ord('Z') -> 90 + # ord('a') -> 97 + # ord('z') -> 122 + # ord('+') -> 43 + # ord('-') -> 45 + # ord('.') -> 46 + # ord(':') -> 58 + if not character or character.isdigit(): # end of a part + return 1 + elif character == '~': + return 0 + else: + ordinal = ord(character) + if ordinal < 65: + # Shift non-characters up beyond the highest character. + ordinal += 100 + return ordinal + + +def _cmp_nondigit(left, right): + l_ord = _to_ord(left) + r_ord = _to_ord(right) + return l_ord - r_ord + + +def _find_int(a_str, offset): + """Find an int within a_str. + + :return: The int and the offset of the first character after the int. + """ + if offset == len(a_str): + return 0, offset + initial_offset = offset + while offset < len(a_str): + offset += 1 + try: + int(a_str[initial_offset:offset]) + except ValueError: + # past the end of the decimal bit + offset -= 1 + break + return int(a_str[initial_offset:offset]), offset + + +def _eval(installed, operator, constraint): + if operator == "==": + return installed == constraint + if operator == "!=": + return installed != constraint + constraint_parsed = debversion_compiled(constraint).debversion() + installed_parsed = debversion_compiled(installed).debversion() + diff = int(installed_parsed[0]) - int(constraint_parsed[0]) + if diff: + return _eval_diff(operator, diff) + diff = _cmp_segment(installed_parsed[1], constraint_parsed[1]) + if diff: + return _eval_diff(operator, diff) + diff = _cmp_segment(installed_parsed[2], constraint_parsed[2]) + return _eval_diff(operator, diff) + + +def _cmp_segment(l_str, r_str): + r_offset = 0 + l_offset = 0 + while (r_offset < len(r_str)) or (l_offset < len(l_str)): + r_char = r_str[r_offset:r_offset + 1] + l_char = l_str[l_offset:l_offset + 1] + if ((not r_char or r_char.isdigit()) and + (not l_char or l_char.isdigit())): + l_int, l_offset = _find_int(l_str, l_offset) + r_int, r_offset = _find_int(r_str, r_offset) + diff = l_int - r_int + if diff: + return diff + diff = _cmp_nondigit(l_char, r_char) + if diff: + return diff + if not l_char.isdigit() and l_offset < len(l_str): + l_offset += 1 + if not r_char.isdigit() and r_offset < len(r_str): + r_offset += 1 + return 0 diff --git a/examples/cmake/FindBoost.cmake b/examples/cmake/FindBoost.cmake deleted file mode 100644 index ce307fa..0000000 --- a/examples/cmake/FindBoost.cmake +++ /dev/null @@ -1,2164 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindBoost ---------- - -Find Boost include dirs and libraries - -Use this module by invoking find_package with the form:: - - find_package(Boost - [version] [EXACT] # Minimum or EXACT version e.g. 1.67.0 - [REQUIRED] # Fail with error if Boost is not found - [COMPONENTS ...] # Boost libraries by their canonical name - # e.g. "date_time" for "libboost_date_time" - [OPTIONAL_COMPONENTS ...] - # Optional Boost libraries by their canonical name) - ) # e.g. "date_time" for "libboost_date_time" - -This module finds headers and requested component libraries OR a CMake -package configuration file provided by a "Boost CMake" build. For the -latter case skip to the "Boost CMake" section below. For the former -case results are reported in variables:: - - Boost_FOUND - True if headers and requested libraries were found - Boost_INCLUDE_DIRS - Boost include directories - Boost_LIBRARY_DIRS - Link directories for Boost libraries - Boost_LIBRARIES - Boost component libraries to be linked - Boost__FOUND - True if component was found ( is upper-case) - Boost__LIBRARY - Libraries to link for component (may include - target_link_libraries debug/optimized keywords) - Boost_VERSION - BOOST_VERSION value from boost/version.hpp - Boost_LIB_VERSION - Version string appended to library filenames - Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) - Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) - Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) - Boost_VERSION_STRING - Boost version number in x.y.z format - Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) - - Pass to add_definitions() to have diagnostic - information about Boost's automatic linking - displayed during compilation - -Note that Boost Python components require a Python version suffix -(Boost 1.67 and later), e.g. ``python36`` or ``python27`` for the -versions built against Python 3.6 and 2.7, respectively. This also -applies to additional components using Python including -``mpi_python`` and ``numpy``. Earlier Boost releases may use -distribution-specific suffixes such as ``2``, ``3`` or ``2.7``. -These may also be used as suffixes, but note that they are not -portable. - -This module reads hints about search locations from variables:: - - BOOST_ROOT - Preferred installation prefix - (or BOOSTROOT) - BOOST_INCLUDEDIR - Preferred include directory e.g. /include - BOOST_LIBRARYDIR - Preferred library directory e.g. /lib - Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not - specified by these hint variables. Default is OFF. - Boost_ADDITIONAL_VERSIONS - - List of Boost versions not known to this module - (Boost install locations may contain the version) - -and saves search results persistently in CMake cache entries:: - - Boost_INCLUDE_DIR - Directory containing Boost headers - Boost_LIBRARY_DIR_RELEASE - Directory containing release Boost libraries - Boost_LIBRARY_DIR_DEBUG - Directory containing debug Boost libraries - Boost__LIBRARY_DEBUG - Component library debug variant - Boost__LIBRARY_RELEASE - Component library release variant - -The following :prop_tgt:`IMPORTED` targets are also defined:: - - Boost::boost - Target for header-only dependencies - (Boost include directory) - Boost:: - Target for specific component dependency - (shared or static library); is lower- - case - Boost::diagnostic_definitions - interface target to enable diagnostic - information about Boost's automatic linking - during compilation (adds BOOST_LIB_DIAGNOSTIC) - Boost::disable_autolinking - interface target to disable automatic - linking with MSVC (adds BOOST_ALL_NO_LIB) - Boost::dynamic_linking - interface target to enable dynamic linking - linking with MSVC (adds BOOST_ALL_DYN_LINK) - -Implicit dependencies such as Boost::filesystem requiring -Boost::system will be automatically detected and satisfied, even -if system is not specified when using find_package and if -Boost::system is not added to target_link_libraries. If using -Boost::thread, then Threads::Threads will also be added automatically. - -It is important to note that the imported targets behave differently -than variables created by this module: multiple calls to -find_package(Boost) in the same directory or sub-directories with -different options (e.g. static or shared) will not override the -values of the targets created by the first call. - -Users may set these hints or results as cache entries. Projects -should not read these entries directly but instead use the above -result variables. Note that some hint names start in upper-case -"BOOST". One may specify these as environment variables if they are -not specified as CMake variables or cache entries. - -This module first searches for the Boost header files using the above -hint variables (excluding BOOST_LIBRARYDIR) and saves the result in -Boost_INCLUDE_DIR. Then it searches for requested component libraries -using the above hints (excluding BOOST_INCLUDEDIR and -Boost_ADDITIONAL_VERSIONS), "lib" directories near Boost_INCLUDE_DIR, -and the library name configuration settings below. It saves the -library directories in Boost_LIBRARY_DIR_DEBUG and -Boost_LIBRARY_DIR_RELEASE and individual library -locations in Boost__LIBRARY_DEBUG and Boost__LIBRARY_RELEASE. -When one changes settings used by previous searches in the same build -tree (excluding environment variables) this module discards previous -search results affected by the changes and searches again. - -Boost libraries come in many variants encoded in their file name. -Users or projects may tell this module which variant to find by -setting variables:: - - Boost_USE_DEBUG_LIBS - Set to ON or OFF to specify whether to search - and use the debug libraries. Default is ON. - Boost_USE_RELEASE_LIBS - Set to ON or OFF to specify whether to search - and use the release libraries. Default is ON. - Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded - libraries ('mt' tag). Default is ON. - Boost_USE_STATIC_LIBS - Set to ON to force the use of the static - libraries. Default is OFF. - Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use - libraries linked statically to the C++ runtime - ('s' tag). Default is platform dependent. - Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use - libraries linked to the MS debug C++ runtime - ('g' tag). Default is ON. - Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a - debug Python build ('y' tag). Default is OFF. - Boost_USE_STLPORT - Set to ON to use libraries compiled with - STLPort ('p' tag). Default is OFF. - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - - Set to ON to use libraries compiled with - STLPort deprecated "native iostreams" - ('n' tag). Default is OFF. - Boost_COMPILER - Set to the compiler-specific library suffix - (e.g. "-gcc43"). Default is auto-computed - for the C++ compiler in use. A list may be - used if multiple compatible suffixes should - be tested for, in decreasing order of - preference. - Boost_ARCHITECTURE - Set to the architecture-specific library suffix - (e.g. "-x64"). Default is auto-computed for the - C++ compiler in use. - Boost_THREADAPI - Suffix for "thread" component library name, - such as "pthread" or "win32". Names with - and without this suffix will both be tried. - Boost_NAMESPACE - Alternate namespace used to build boost with - e.g. if set to "myboost", will search for - myboost_thread instead of boost_thread. - -Other variables one may set to control this module are:: - - Boost_DEBUG - Set to ON to enable debug output from FindBoost. - Please enable this before filing any bug report. - Boost_DETAILED_FAILURE_MSG - - Set to ON to add detailed information to the - failure message even when the REQUIRED option - is not given to the find_package call. - Boost_REALPATH - Set to ON to resolve symlinks for discovered - libraries to assist with packaging. For example, - the "system" component library may be resolved to - "/usr/lib/libboost_system.so.1.67.0" instead of - "/usr/lib/libboost_system.so". This does not - affect linking and should not be enabled unless - the user needs this information. - Boost_LIBRARY_DIR - Default value for Boost_LIBRARY_DIR_RELEASE and - Boost_LIBRARY_DIR_DEBUG. - -On Visual Studio and Borland compilers Boost headers request automatic -linking to corresponding libraries. This requires matching libraries -to be linked explicitly or available in the link library search path. -In this case setting Boost_USE_STATIC_LIBS to OFF may not achieve -dynamic linking. Boost automatic linking typically requests static -libraries with a few exceptions (such as Boost.Python). Use:: - - add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) - -to ask Boost to report information about automatic linking requests. - -Example to find Boost headers only:: - - find_package(Boost 1.36.0) - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - add_executable(foo foo.cc) - endif() - -Example to find Boost libraries and use imported targets:: - - find_package(Boost 1.56 REQUIRED COMPONENTS - date_time filesystem iostreams) - add_executable(foo foo.cc) - target_link_libraries(foo Boost::date_time Boost::filesystem - Boost::iostreams) - -Example to find Boost Python 3.6 libraries and use imported targets:: - - find_package(Boost 1.67 REQUIRED COMPONENTS - python36 numpy36) - add_executable(foo foo.cc) - target_link_libraries(foo Boost::python36 Boost::numpy36) - -Example to find Boost headers and some *static* (release only) libraries:: - - set(Boost_USE_STATIC_LIBS ON) # only find static libs - set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and - set(Boost_USE_RELEASE_LIBS ON) # only find release libs - set(Boost_USE_MULTITHREADED ON) - set(Boost_USE_STATIC_RUNTIME OFF) - find_package(Boost 1.66.0 COMPONENTS date_time filesystem system ...) - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - add_executable(foo foo.cc) - target_link_libraries(foo ${Boost_LIBRARIES}) - endif() - -Boost CMake -^^^^^^^^^^^ - -If Boost was built using the boost-cmake project it provides a package -configuration file for use with find_package's Config mode. This -module looks for the package configuration file called -BoostConfig.cmake or boost-config.cmake and stores the result in cache -entry "Boost_DIR". If found, the package configuration file is loaded -and this module returns with no further action. See documentation of -the Boost CMake package configuration for details on what it provides. - -Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. -#]=======================================================================] - -# Save project's policies -cmake_policy(PUSH) -cmake_policy(SET CMP0057 NEW) # if IN_LIST - -#------------------------------------------------------------------------------- -# Before we go searching, check whether boost-cmake is available, unless the -# user specifically asked NOT to search for boost-cmake. -# -# If Boost_DIR is set, this behaves as any find_package call would. If not, -# it looks at BOOST_ROOT and BOOSTROOT to find Boost. -# -if (NOT Boost_NO_BOOST_CMAKE) - # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, - # since these are more conventional for Boost. - if ("$ENV{Boost_DIR}" STREQUAL "") - if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) - elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOSTROOT}) - endif() - endif() - - # Do the same find_package call but look specifically for the CMake version. - # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no - # need to delegate them to this find_package call. - find_package(Boost QUIET NO_MODULE) - mark_as_advanced(Boost_DIR) - - # If we found boost-cmake, then we're done. Print out what we found. - # Otherwise let the rest of the module try to find it. - if (Boost_FOUND) - message(STATUS "Boost ${Boost_FIND_VERSION} found.") - if (Boost_FIND_COMPONENTS) - message(STATUS "Found Boost components:\n ${Boost_FIND_COMPONENTS}") - endif() - # Restore project's policies - cmake_policy(POP) - return() - endif() -endif() - - -#------------------------------------------------------------------------------- -# FindBoost functions & macros -# - -############################################ -# -# Check the existence of the libraries. -# -############################################ -# This macro was taken directly from the FindQt4.cmake file that is included -# with the CMake distribution. This is NOT my work. All work was done by the -# original authors of the FindQt4.cmake file. Only minor modifications were -# made to remove references to Qt and make this file more generally applicable -# And ELSE/ENDIF pairs were removed for readability. -######################################################################### - -macro(_Boost_ADJUST_LIB_VARS basename) - if(Boost_INCLUDE_DIR ) - if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) - # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for - # single-config generators, set optimized and debug libraries - get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if(_isMultiConfig OR CMAKE_BUILD_TYPE) - set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - else() - # For single-config generators where CMAKE_BUILD_TYPE has no value, - # just use the release libraries - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - # FIXME: This probably should be set for both cases - set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # if only the release version was found, set the debug variable also to the release version - if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) - set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) - endif() - - # if only the debug version was found, set the release variable also to the debug version - if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) - set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # If the debug & release library ends up being the same, omit the keywords - if("${Boost_${basename}_LIBRARY_RELEASE}" STREQUAL "${Boost_${basename}_LIBRARY_DEBUG}") - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - - if(Boost_${basename}_LIBRARY AND Boost_${basename}_HEADER) - set(Boost_${basename}_FOUND ON) - if("x${basename}" STREQUAL "xTHREAD" AND NOT TARGET Threads::Threads) - string(APPEND Boost_ERROR_REASON_THREAD " (missing dependency: Threads)") - set(Boost_THREAD_FOUND OFF) - endif() - endif() - - endif() - # Make variables changeable to the advanced user - mark_as_advanced( - Boost_${basename}_LIBRARY_RELEASE - Boost_${basename}_LIBRARY_DEBUG - ) -endmacro() - -# Detect changes in used variables. -# Compares the current variable value with the last one. -# In short form: -# v != v_LAST -> CHANGED = 1 -# v is defined, v_LAST not -> CHANGED = 1 -# v is not defined, but v_LAST is -> CHANGED = 1 -# otherwise -> CHANGED = 0 -# CHANGED is returned in variable named ${changed_var} -macro(_Boost_CHANGE_DETECT changed_var) - set(${changed_var} 0) - foreach(v ${ARGN}) - if(DEFINED _Boost_COMPONENTS_SEARCHED) - if(${v}) - if(_${v}_LAST) - string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) - else() - set(_${v}_CHANGED 1) - endif() - elseif(_${v}_LAST) - set(_${v}_CHANGED 1) - endif() - if(_${v}_CHANGED) - set(${changed_var} 1) - endif() - else() - set(_${v}_CHANGED 0) - endif() - endforeach() -endmacro() - -# -# Find the given library (var). -# Use 'build_type' to support different lib paths for RELEASE or DEBUG builds -# -macro(_Boost_FIND_LIBRARY var build_type) - - find_library(${var} ${ARGN}) - - if(${var}) - # If this is the first library found then save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. - if(NOT Boost_LIBRARY_DIR_${build_type}) - get_filename_component(_dir "${${var}}" PATH) - set(Boost_LIBRARY_DIR_${build_type} "${_dir}" CACHE PATH "Boost library directory ${build_type}" FORCE) - endif() - elseif(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - # Try component-specific hints but do not save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. - find_library(${var} HINTS ${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT} ${ARGN}) - endif() - - # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is known then search only there. - if(Boost_LIBRARY_DIR_${build_type}) - set(_boost_LIBRARY_SEARCH_DIRS_${build_type} ${Boost_LIBRARY_DIR_${build_type}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " Boost_LIBRARY_DIR_${build_type} = ${Boost_LIBRARY_DIR_${build_type}}" - " _boost_LIBRARY_SEARCH_DIRS_${build_type} = ${_boost_LIBRARY_SEARCH_DIRS_${build_type}}") - endif() - endif() -endmacro() - -#------------------------------------------------------------------------------- - -# Convert CMAKE_CXX_COMPILER_VERSION to boost compiler suffix version. -function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION _OUTPUT_VERSION_MAJOR _OUTPUT_VERSION_MINOR) - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1" - _boost_COMPILER_VERSION_MAJOR "${CMAKE_CXX_COMPILER_VERSION}") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\2" - _boost_COMPILER_VERSION_MINOR "${CMAKE_CXX_COMPILER_VERSION}") - - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}${_boost_COMPILER_VERSION_MINOR}") - - set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) - set(${_OUTPUT_VERSION_MAJOR} ${_boost_COMPILER_VERSION_MAJOR} PARENT_SCOPE) - set(${_OUTPUT_VERSION_MINOR} ${_boost_COMPILER_VERSION_MINOR} PARENT_SCOPE) -endfunction() - -# -# Take a list of libraries with "thread" in it -# and prepend duplicates with "thread_${Boost_THREADAPI}" -# at the front of the list -# -function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) - set(_orig_libnames ${ARGN}) - string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") - set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) -endfunction() - -# -# If a library is found, replace its cache entry with its REALPATH -# -function(_Boost_SWAP_WITH_REALPATH _library _docstring) - if(${_library}) - get_filename_component(_boost_filepathreal ${${_library}} REALPATH) - unset(${_library} CACHE) - set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") - endif() -endfunction() - -function(_Boost_CHECK_SPELLING _var) - if(${_var}) - string(TOUPPER ${_var} _var_UC) - message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") - endif() -endfunction() - -# Guesses Boost's compiler prefix used in built library names -# Returns the guess by setting the variable pointed to by _ret -function(_Boost_GUESS_COMPILER_PREFIX _ret) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") - if(WIN32) - set (_boost_COMPILER "-iw") - else() - set (_boost_COMPILER "-il") - endif() - elseif (GHSMULTI) - set(_boost_COMPILER "-ghs") - elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141) - set(_boost_COMPILER "-vc141;-vc140") - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80) - set(_boost_COMPILER "-vc${MSVC_TOOLSET_VERSION}") - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10) - set(_boost_COMPILER "-vc71") - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) # Good luck! - set(_boost_COMPILER "-vc7") # yes, this is correct - else() # VS 6.0 Good luck! - set(_boost_COMPILER "-vc6") # yes, this is correct - endif() - elseif (BORLAND) - set(_boost_COMPILER "-bcb") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") - set(_boost_COMPILER "-sw") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "XL") - set(_boost_COMPILER "-xlc") - elseif (MINGW) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR) - set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") - endif() - elseif (UNIX) - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR) - if(NOT Boost_VERSION VERSION_LESS 106900) - # From GCC 5 and clang 4, versioning changes and minor becomes patch. - # For those compilers, patch is exclude from compiler tag in Boost 1.69+ library naming. - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 4) - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 3) - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") - endif() - endif() - - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 - else() - # Determine which version of GCC we have. - if(APPLE) - if(Boost_MINOR_VERSION) - if(${Boost_MINOR_VERSION} GREATER 35) - # In Boost 1.36.0 and newer, the mangled compiler name used - # on macOS/Darwin is "xgcc". - set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") - else() - # In Boost <= 1.35.0, there is no mangled compiler name for - # the macOS/Darwin version of GCC. - set(_boost_COMPILER "") - endif() - else() - # We don't know the Boost version, so assume it's - # pre-1.36.0. - set(_boost_COMPILER "") - endif() - else() - set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") - endif() - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # TODO: Find out any Boost version constraints vs clang support. - set(_boost_COMPILER "-clang${_boost_COMPILER_VERSION}") - endif() - else() - # TODO at least Boost_DEBUG here? - set(_boost_COMPILER "") - endif() - set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) -endfunction() - -# -# Get component dependencies. Requires the dependencies to have been -# defined for the Boost release version. -# -# component - the component to check -# _ret - list of library dependencies -# -function(_Boost_COMPONENT_DEPENDENCIES component _ret) - # Note: to add a new Boost release, run - # - # % cmake -DBOOST_DIR=/path/to/boost/source -P Utilities/Scripts/BoostScanDeps.cmake - # - # The output may be added in a new block below. If it's the same as - # the previous release, simply update the version range of the block - # for the previous release. Also check if any new components have - # been added, and add any new components to - # _Boost_COMPONENT_HEADERS. - # - # This information was originally generated by running - # BoostScanDeps.cmake against every boost release to date supported - # by FindBoost: - # - # % for version in /path/to/boost/sources/* - # do - # cmake -DBOOST_DIR=$version -P Utilities/Scripts/BoostScanDeps.cmake - # done - # - # The output was then updated by search and replace with these regexes: - # - # - Strip message(STATUS) prefix dashes - # s;^-- ;; - # - Indent - # s;^set(; set(;; - # - Add conditionals - # s;Scanning /path/to/boost/sources/boost_\(.*\)_\(.*\)_\(.*); elseif(NOT Boost_VERSION VERSION_LESS \10\20\3 AND Boost_VERSION VERSION_LESS xxxx); - # - # This results in the logic seen below, but will require the xxxx - # replacing with the following Boost release version (or the next - # minor version to be released, e.g. 1.59 was the latest at the time - # of writing, making 1.60 the next, so 106000 is the needed version - # number). Identical consecutive releases were then merged together - # by updating the end range of the first block and removing the - # following redundant blocks. - # - # Running the script against all historical releases should be - # required only if the BoostScanDeps.cmake script logic is changed. - # The addition of a new release should only require it to be run - # against the new release. - - # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") - set(component "${CMAKE_MATCH_1}") - set(component_python_version "${CMAKE_MATCH_2}") - endif() - - set(_Boost_IMPORTED_TARGETS TRUE) - if(Boost_VERSION AND Boost_VERSION VERSION_LESS 103300) - message(WARNING "Imported targets and dependency information not available for Boost version ${Boost_VERSION} (all versions older than 1.33)") - set(_Boost_IMPORTED_TARGETS FALSE) - elseif(NOT Boost_VERSION VERSION_LESS 103300 AND Boost_VERSION VERSION_LESS 103500) - set(_Boost_IOSTREAMS_DEPENDENCIES regex thread) - set(_Boost_REGEX_DEPENDENCIES thread) - set(_Boost_WAVE_DEPENDENCIES filesystem thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103500 AND Boost_VERSION VERSION_LESS 103600) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103600 AND Boost_VERSION VERSION_LESS 103800) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103800 AND Boost_VERSION VERSION_LESS 104300) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104300 AND Boost_VERSION VERSION_LESS 104400) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104400 AND Boost_VERSION VERSION_LESS 104500) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random serialization) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES serialization filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104500 AND Boost_VERSION VERSION_LESS 104700) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104700 AND Boost_VERSION VERSION_LESS 104800) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104800 AND Boost_VERSION VERSION_LESS 105000) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105000 AND Boost_VERSION VERSION_LESS 105300) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105300 AND Boost_VERSION VERSION_LESS 105400) - set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105400 AND Boost_VERSION VERSION_LESS 105500) - set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105500 AND Boost_VERSION VERSION_LESS 105600) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105600 AND Boost_VERSION VERSION_LESS 105900) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105900 AND Boost_VERSION VERSION_LESS 106000) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106000 AND Boost_VERSION VERSION_LESS 106100) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106100 AND Boost_VERSION VERSION_LESS 106200) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106300) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106300 AND Boost_VERSION VERSION_LESS 106500) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_COROUTINE2_DEPENDENCIES context fiber thread chrono system date_time) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106500 AND Boost_VERSION VERSION_LESS 106700) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106700 AND Boost_VERSION VERSION_LESS 106800) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106800 AND Boost_VERSION VERSION_LESS 106900) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - else() - if(NOT Boost_VERSION VERSION_LESS 106900) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - endif() - if(NOT Boost_VERSION VERSION_LESS 107000) - message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") - endif() - endif() - - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) - - string(REGEX REPLACE ";" " " _boost_DEPS_STRING "${_Boost_${uppercomponent}_DEPENDENCIES}") - if (NOT _boost_DEPS_STRING) - set(_boost_DEPS_STRING "(none)") - endif() - # message(STATUS "Dependencies for Boost::${component}: ${_boost_DEPS_STRING}") -endfunction() - -# -# Get component headers. This is the primary header (or headers) for -# a given component, and is used to check that the headers are present -# as well as the library itself as an extra sanity check of the build -# environment. -# -# component - the component to check -# _hdrs -# -function(_Boost_COMPONENT_HEADERS component _hdrs) - # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") - set(component "${CMAKE_MATCH_1}") - set(component_python_version "${CMAKE_MATCH_2}") - endif() - - # Note: new boost components will require adding here. The header - # must be present in all versions of Boost providing a library. - set(_Boost_ATOMIC_HEADERS "boost/atomic.hpp") - set(_Boost_CHRONO_HEADERS "boost/chrono.hpp") - set(_Boost_CONTAINER_HEADERS "boost/container/container_fwd.hpp") - set(_Boost_CONTRACT_HEADERS "boost/contract.hpp") - if(Boost_VERSION VERSION_LESS 106100) - set(_Boost_CONTEXT_HEADERS "boost/context/all.hpp") - else() - set(_Boost_CONTEXT_HEADERS "boost/context/detail/fcontext.hpp") - endif() - set(_Boost_COROUTINE_HEADERS "boost/coroutine/all.hpp") - set(_Boost_DATE_TIME_HEADERS "boost/date_time/date.hpp") - set(_Boost_EXCEPTION_HEADERS "boost/exception/exception.hpp") - set(_Boost_FIBER_HEADERS "boost/fiber/all.hpp") - set(_Boost_FILESYSTEM_HEADERS "boost/filesystem/path.hpp") - set(_Boost_GRAPH_HEADERS "boost/graph/adjacency_list.hpp") - set(_Boost_GRAPH_PARALLEL_HEADERS "boost/graph/adjacency_list.hpp") - set(_Boost_IOSTREAMS_HEADERS "boost/iostreams/stream.hpp") - set(_Boost_LOCALE_HEADERS "boost/locale.hpp") - set(_Boost_LOG_HEADERS "boost/log/core.hpp") - set(_Boost_LOG_SETUP_HEADERS "boost/log/detail/setup_config.hpp") - set(_Boost_MATH_HEADERS "boost/math_fwd.hpp") - set(_Boost_MATH_C99_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_C99F_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_C99L_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1F_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1L_HEADERS "boost/math/tr1.hpp") - set(_Boost_MPI_HEADERS "boost/mpi.hpp") - set(_Boost_MPI_PYTHON_HEADERS "boost/mpi/python/config.hpp") - set(_Boost_NUMPY_HEADERS "boost/python/numpy.hpp") - set(_Boost_PRG_EXEC_MONITOR_HEADERS "boost/test/prg_exec_monitor.hpp") - set(_Boost_PROGRAM_OPTIONS_HEADERS "boost/program_options.hpp") - set(_Boost_PYTHON_HEADERS "boost/python.hpp") - set(_Boost_RANDOM_HEADERS "boost/random.hpp") - set(_Boost_REGEX_HEADERS "boost/regex.hpp") - set(_Boost_SERIALIZATION_HEADERS "boost/serialization/serialization.hpp") - set(_Boost_SIGNALS_HEADERS "boost/signals.hpp") - set(_Boost_STACKTRACE_ADDR2LINE_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_BACKTRACE_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_BASIC_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_NOOP_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_WINDBG_CACHED_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_WINDBG_HEADERS "boost/stacktrace.hpp") - set(_Boost_SYSTEM_HEADERS "boost/system/config.hpp") - set(_Boost_TEST_EXEC_MONITOR_HEADERS "boost/test/test_exec_monitor.hpp") - set(_Boost_THREAD_HEADERS "boost/thread.hpp") - set(_Boost_TIMER_HEADERS "boost/timer.hpp") - set(_Boost_TYPE_ERASURE_HEADERS "boost/type_erasure/config.hpp") - set(_Boost_UNIT_TEST_FRAMEWORK_HEADERS "boost/test/framework.hpp") - set(_Boost_WAVE_HEADERS "boost/wave.hpp") - set(_Boost_WSERIALIZATION_HEADERS "boost/archive/text_wiarchive.hpp") - if(WIN32) - set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") - set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") - endif() - - string(TOUPPER ${component} uppercomponent) - set(${_hdrs} ${_Boost_${uppercomponent}_HEADERS} PARENT_SCOPE) - - string(REGEX REPLACE ";" " " _boost_HDRS_STRING "${_Boost_${uppercomponent}_HEADERS}") - if (NOT _boost_HDRS_STRING) - set(_boost_HDRS_STRING "(none)") - endif() - # message(STATUS "Headers for Boost::${component}: ${_boost_HDRS_STRING}") -endfunction() - -# -# Determine if any missing dependencies require adding to the component list. -# -# Sets _Boost_${COMPONENT}_DEPENDENCIES for each required component, -# plus _Boost_IMPORTED_TARGETS (TRUE if imported targets should be -# defined; FALSE if dependency information is unavailable). -# -# componentvar - the component list variable name -# extravar - the indirect dependency list variable name -# -# -function(_Boost_MISSING_DEPENDENCIES componentvar extravar) - # _boost_unprocessed_components - list of components requiring processing - # _boost_processed_components - components already processed (or currently being processed) - # _boost_new_components - new components discovered for future processing - # - list(APPEND _boost_unprocessed_components ${${componentvar}}) - - while(_boost_unprocessed_components) - list(APPEND _boost_processed_components ${_boost_unprocessed_components}) - foreach(component ${_boost_unprocessed_components}) - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES) - set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) - foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES}) - if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components)) - list(APPEND _boost_new_components ${componentdep}) - endif() - endforeach() - endforeach() - set(_boost_unprocessed_components ${_boost_new_components}) - unset(_boost_new_components) - endwhile() - set(_boost_extra_components ${_boost_processed_components}) - if(_boost_extra_components AND ${componentvar}) - list(REMOVE_ITEM _boost_extra_components ${${componentvar}}) - endif() - set(${componentvar} ${_boost_processed_components} PARENT_SCOPE) - set(${extravar} ${_boost_extra_components} PARENT_SCOPE) -endfunction() - -# -# Some boost libraries may require particular set of compler features. -# The very first one was `boost::fiber` introduced in Boost 1.62. -# One can check required compiler features of it in -# `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`. -# -function(_Boost_COMPILER_FEATURES component _ret) - # Boost >= 1.62 and < 1.67 - if(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106700) - set(_Boost_FIBER_COMPILER_FEATURES - cxx_alias_templates - cxx_auto_type - cxx_constexpr - cxx_defaulted_functions - cxx_final - cxx_lambdas - cxx_noexcept - cxx_nullptr - cxx_rvalue_references - cxx_thread_local - cxx_variadic_templates - ) - endif() - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE) -endfunction() - -# -# Update library search directory hint variable with paths used by prebuilt boost binaries. -# -# Prebuilt windows binaries (https://sourceforge.net/projects/boost/files/boost-binaries/) -# have library directories named using MSVC compiler version and architecture. -# This function would append corresponding directories if MSVC is a current compiler, -# so having `BOOST_ROOT` would be enough to specify to find everything. -# -function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_arch_suffix 64) - else() - set(_arch_suffix 32) - endif() - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141) - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1) - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80) - math(EXPR _toolset_major_version "${MSVC_TOOLSET_VERSION} / 10") - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-${_toolset_major_version}.0) - endif() - set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE) - endif() -endfunction() - -# -# End functions/macros -# -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# main. -#------------------------------------------------------------------------------- - - -# If the user sets Boost_LIBRARY_DIR, use it as the default for both -# configurations. -if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR) - set(Boost_LIBRARY_DIR_RELEASE "${Boost_LIBRARY_DIR}") -endif() -if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR) - set(Boost_LIBRARY_DIR_DEBUG "${Boost_LIBRARY_DIR}") -endif() - -if(NOT DEFINED Boost_USE_DEBUG_LIBS) - set(Boost_USE_DEBUG_LIBS TRUE) -endif() -if(NOT DEFINED Boost_USE_RELEASE_LIBS) - set(Boost_USE_RELEASE_LIBS TRUE) -endif() -if(NOT DEFINED Boost_USE_MULTITHREADED) - set(Boost_USE_MULTITHREADED TRUE) -endif() -if(NOT DEFINED Boost_USE_DEBUG_RUNTIME) - set(Boost_USE_DEBUG_RUNTIME TRUE) -endif() - -# Check the version of Boost against the requested version. -if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) - message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") -endif() - -if(Boost_FIND_VERSION_EXACT) - # The version may appear in a directory with or without the patch - # level, even when the patch level is non-zero. - set(_boost_TEST_VERSIONS - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") -else() - # The user has not requested an exact version. Among known - # versions, find those that are acceptable to the user request. - # - # Note: When adding a new Boost release, also update the dependency - # information in _Boost_COMPONENT_DEPENDENCIES and - # _Boost_COMPONENT_HEADERS. See the instructions at the top of - # _Boost_COMPONENT_DEPENDENCIES. - set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.69.0" "1.69" - "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" - "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" - "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" - "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" - "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" - "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" - "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" - "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" - "1.34" "1.33.1" "1.33.0" "1.33") - - set(_boost_TEST_VERSIONS) - if(Boost_FIND_VERSION) - set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - # Select acceptable versions. - foreach(version ${_Boost_KNOWN_VERSIONS}) - if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") - # This version is high enough. - list(APPEND _boost_TEST_VERSIONS "${version}") - elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") - # This version is a short-form for the requested version with - # the patch level dropped. - list(APPEND _boost_TEST_VERSIONS "${version}") - endif() - endforeach() - else() - # Any version is acceptable. - set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") - endif() -endif() - -# The reason that we failed to find Boost. This will be set to a -# user-friendly message when we fail to find some necessary piece of -# Boost. -set(Boost_ERROR_REASON) - -if(Boost_DEBUG) - # Output some of their choices - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") -endif() - -# Supply Boost_LIB_DIAGNOSTIC_DEFINITIONS as a convenience target. It -# will only contain any interface definitions on WIN32, but is created -# on all platforms to keep end user code free from platform dependent -# code. Also provide convenience targets to disable autolinking and -# enable dynamic linking. -if(NOT TARGET Boost::diagnostic_definitions) - add_library(Boost::diagnostic_definitions INTERFACE IMPORTED) - add_library(Boost::disable_autolinking INTERFACE IMPORTED) - add_library(Boost::dynamic_linking INTERFACE IMPORTED) -endif() -if(WIN32) - # In windows, automatic linking is performed, so you do not have - # to specify the libraries. If you are linking to a dynamic - # runtime, then you can choose to link to either a static or a - # dynamic Boost library, the default is to do a static link. You - # can alter this for a specific library "whatever" by defining - # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be - # linked dynamically. Alternatively you can force all Boost - # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. - - # This feature can be disabled for Boost library "whatever" by - # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining - # BOOST_ALL_NO_LIB. - - # If you want to observe which libraries are being linked against - # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking - # code to emit a #pragma message each time a library is selected - # for linking. - set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") - set_target_properties(Boost::diagnostic_definitions PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_LIB_DIAGNOSTIC") - set_target_properties(Boost::disable_autolinking PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_NO_LIB") - set_target_properties(Boost::dynamic_linking PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_DYN_LINK") -endif() - -_Boost_CHECK_SPELLING(Boost_ROOT) -_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) -_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) - -# Collect environment variable inputs as hints. Do not consider changes. -foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) - set(_env $ENV{${v}}) - if(_env) - file(TO_CMAKE_PATH "${_env}" _ENV_${v}) - else() - set(_ENV_${v} "") - endif() -endforeach() -if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) - set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") -endif() - -# Collect inputs and cached results. Detect changes since the last run. -if(NOT BOOST_ROOT AND BOOSTROOT) - set(BOOST_ROOT "${BOOSTROOT}") -endif() -set(_Boost_VARS_DIR - BOOST_ROOT - Boost_NO_SYSTEM_PATHS - ) - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Declared as CMake or Environmental Variables:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_ROOT = ${BOOST_ROOT}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") -endif() - -# ------------------------------------------------------------------------ -# Search for Boost include DIR -# ------------------------------------------------------------------------ - -set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) -_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) -# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) - unset(Boost_INCLUDE_DIR CACHE) -endif() - -if(NOT Boost_INCLUDE_DIR) - set(_boost_INCLUDE_SEARCH_DIRS "") - if(BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) - elseif(_ENV_BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) - endif() - - if( BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) - elseif( _ENV_BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) - endif() - - if( Boost_NO_SYSTEM_PATHS) - list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) - else() - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - foreach(ver ${_boost_TEST_VERSIONS}) - string(REPLACE "." "_" ver "${ver}") - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}") - endforeach() - endif() - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS - C:/boost/include - C:/boost - /sw/local/include - ) - endif() - - # Try to find Boost by stepping backwards through the Boost versions - # we know about. - # Build a list of path suffixes for each version. - set(_boost_PATH_SUFFIXES) - foreach(_boost_VER ${_boost_TEST_VERSIONS}) - # Add in a path suffix, based on the required version, ideally - # we could read this from version.hpp, but for that to work we'd - # need to know the include dir already - set(_boost_BOOSTIFIED_VERSION) - - # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 - if(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)") - set(_boost_BOOSTIFIED_VERSION - "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}_${CMAKE_MATCH_3}") - elseif(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)") - set(_boost_BOOSTIFIED_VERSION - "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}") - endif() - - list(APPEND _boost_PATH_SUFFIXES - "boost-${_boost_BOOSTIFIED_VERSION}" - "boost_${_boost_BOOSTIFIED_VERSION}" - "boost/boost-${_boost_BOOSTIFIED_VERSION}" - "boost/boost_${_boost_BOOSTIFIED_VERSION}" - ) - - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Include debugging info:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") - endif() - - # Look for a standard boost header file. - find_path(Boost_INCLUDE_DIR - NAMES boost/config.hpp - HINTS ${_boost_INCLUDE_SEARCH_DIRS} - PATH_SUFFIXES ${_boost_PATH_SUFFIXES} - ) -endif() - -# ------------------------------------------------------------------------ -# Extract version information from version.hpp -# ------------------------------------------------------------------------ - -# Set Boost_FOUND based only on header location and version. -# It will be updated below for component libraries. -if(Boost_INCLUDE_DIR) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") - endif() - - # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp - set(Boost_VERSION 0) - set(Boost_LIB_VERSION "") - file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") - set(_Boost_VERSION_REGEX "([0-9]+)") - set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") - foreach(v VERSION LIB_VERSION) - if("${_boost_VERSION_HPP_CONTENTS}" MATCHES "#define BOOST_${v} ${_Boost_${v}_REGEX}") - set(Boost_${v} "${CMAKE_MATCH_1}") - endif() - endforeach() - unset(_boost_VERSION_HPP_CONTENTS) - - math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") - math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") - math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") - set(Boost_VERSION_STRING "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - - string(APPEND Boost_ERROR_REASON - "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "version.hpp reveals boost " - "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - endif() - - if(Boost_FIND_VERSION) - # Set Boost_FOUND based on requested version. - set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "old") - elseif(Boost_FIND_VERSION_EXACT AND - NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "new") - else() - set(Boost_FOUND 1) - endif() - if(NOT Boost_FOUND) - # State that we found a version of Boost that is too new or too old. - string(APPEND Boost_ERROR_REASON - "\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - if (Boost_FIND_VERSION_PATCH) - string(APPEND Boost_ERROR_REASON - ".${Boost_FIND_VERSION_PATCH}") - endif () - if (NOT Boost_FIND_VERSION_EXACT) - string(APPEND Boost_ERROR_REASON " (or newer)") - endif () - string(APPEND Boost_ERROR_REASON ".") - endif () - else() - # Caller will accept any Boost version. - set(Boost_FOUND 1) - endif() -else() - set(Boost_FOUND 0) - string(APPEND Boost_ERROR_REASON - "Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") -endif() - -# ------------------------------------------------------------------------ -# Prefix initialization -# ------------------------------------------------------------------------ - -set(Boost_LIB_PREFIX "") -if ( (GHSMULTI AND Boost_USE_STATIC_LIBS) OR - (WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) ) - set(Boost_LIB_PREFIX "lib") -endif() - -if ( NOT Boost_NAMESPACE ) - set(Boost_NAMESPACE "boost") -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_LIB_PREFIX = ${Boost_LIB_PREFIX}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NAMESPACE = ${Boost_NAMESPACE}") -endif() - -# ------------------------------------------------------------------------ -# Suffix initialization and compiler suffix detection. -# ------------------------------------------------------------------------ - -set(_Boost_VARS_NAME - Boost_NAMESPACE - Boost_COMPILER - Boost_THREADAPI - Boost_USE_DEBUG_PYTHON - Boost_USE_MULTITHREADED - Boost_USE_STATIC_LIBS - Boost_USE_STATIC_RUNTIME - Boost_USE_STLPORT - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - ) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) - -# Setting some more suffixes for the library -if (Boost_COMPILER) - set(_boost_COMPILER ${Boost_COMPILER}) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_COMPILER = ${_boost_COMPILER}") - endif() -else() - # Attempt to guess the compiler suffix - # NOTE: this is not perfect yet, if you experience any issues - # please report them and use the Boost_COMPILER variable - # to work around the problems. - _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "guessed _boost_COMPILER = ${_boost_COMPILER}") - endif() -endif() - -set (_boost_MULTITHREADED "-mt") -if( NOT Boost_USE_MULTITHREADED ) - set (_boost_MULTITHREADED "") -endif() -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") -endif() - -#====================== -# Systematically build up the Boost ABI tag for the 'tagged' and 'versioned' layouts -# http://boost.org/doc/libs/1_66_0/more/getting_started/windows.html#library-naming -# http://boost.org/doc/libs/1_66_0/boost/config/auto_link.hpp -# http://boost.org/doc/libs/1_66_0/tools/build/src/tools/common.jam -# http://boost.org/doc/libs/1_66_0/boostcpp.jam -set( _boost_RELEASE_ABI_TAG "-") -set( _boost_DEBUG_ABI_TAG "-") -# Key Use this library when: -# s linking statically to the C++ standard library and -# compiler runtime support libraries. -if(Boost_USE_STATIC_RUNTIME) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") -endif() -# g using debug versions of the standard and runtime -# support libraries -if(WIN32 AND Boost_USE_DEBUG_RUNTIME) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" - OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang" - OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") - string(APPEND _boost_DEBUG_ABI_TAG "g") - endif() -endif() -# y using special debug build of python -if(Boost_USE_DEBUG_PYTHON) - string(APPEND _boost_DEBUG_ABI_TAG "y") -endif() -# d using a debug version of your code -string(APPEND _boost_DEBUG_ABI_TAG "d") -# p using the STLport standard library rather than the -# default one supplied with your compiler -if(Boost_USE_STLPORT) - string(APPEND _boost_RELEASE_ABI_TAG "p") - string(APPEND _boost_DEBUG_ABI_TAG "p") -endif() -# n using the STLport deprecated "native iostreams" feature -# removed from the documentation in 1.43.0 but still present in -# boost/config/auto_link.hpp -if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) - string(APPEND _boost_RELEASE_ABI_TAG "n") - string(APPEND _boost_DEBUG_ABI_TAG "n") -endif() - -# -x86 Architecture and address model tag -# First character is the architecture, then word-size, either 32 or 64 -# Only used in 'versioned' layout, added in Boost 1.66.0 -if(DEFINED Boost_ARCHITECTURE) - set(_boost_ARCHITECTURE_TAG "${Boost_ARCHITECTURE}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_ARCHITECTURE = ${_boost_ARCHITECTURE_TAG}") - endif() -else() - set(_boost_ARCHITECTURE_TAG "") - # {CMAKE_CXX_COMPILER_ARCHITECTURE_ID} is not currently set for all compilers - if(NOT "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x" AND NOT Boost_VERSION VERSION_LESS 106600) - string(APPEND _boost_ARCHITECTURE_TAG "-") - # This needs to be kept in-sync with the section of CMakePlatformId.h.in - # inside 'defined(_WIN32) && defined(_MSC_VER)' - if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "IA64") - string(APPEND _boost_ARCHITECTURE_TAG "i") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "X86" - OR CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "x64") - string(APPEND _boost_ARCHITECTURE_TAG "x") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID MATCHES "^ARM") - string(APPEND _boost_ARCHITECTURE_TAG "a") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "MIPS") - string(APPEND _boost_ARCHITECTURE_TAG "m") - endif() - - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - string(APPEND _boost_ARCHITECTURE_TAG "64") - else() - string(APPEND _boost_ARCHITECTURE_TAG "32") - endif() - endif() -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") -endif() - -# ------------------------------------------------------------------------ -# Begin finding boost libraries -# ------------------------------------------------------------------------ - -set(_Boost_VARS_LIB "") -foreach(c DEBUG RELEASE) - set(_Boost_VARS_LIB_${c} BOOST_LIBRARYDIR Boost_LIBRARY_DIR_${c}) - list(APPEND _Boost_VARS_LIB ${_Boost_VARS_LIB_${c}}) - _Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR_${c} ${_Boost_VARS_DIR} ${_Boost_VARS_LIB_${c}} Boost_INCLUDE_DIR) - # Clear Boost_LIBRARY_DIR_${c} if it did not change but other input affecting the - # location did. We will find a new one based on the new inputs. - if(_Boost_CHANGE_LIBDIR_${c} AND NOT _Boost_LIBRARY_DIR_${c}_CHANGED) - unset(Boost_LIBRARY_DIR_${c} CACHE) - endif() - - # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is set, prefer its value. - if(Boost_LIBRARY_DIR_${c}) - set(_boost_LIBRARY_SEARCH_DIRS_${c} ${Boost_LIBRARY_DIR_${c}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - else() - set(_boost_LIBRARY_SEARCH_DIRS_${c} "") - if(BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_LIBRARYDIR}) - elseif(_ENV_BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_LIBRARYDIR}) - endif() - - if(BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${BOOST_ROOT}") - elseif(_ENV_BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${_ENV_BOOST_ROOT}") - endif() - - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} - ${Boost_INCLUDE_DIR}/lib - ${Boost_INCLUDE_DIR}/../lib - ${Boost_INCLUDE_DIR}/stage/lib - ) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}/..") - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}") - if( Boost_NO_SYSTEM_PATHS ) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) - else() - foreach(ver ${_boost_TEST_VERSIONS}) - string(REPLACE "." "_" ver "${ver}") - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}") - endforeach() - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS - C:/boost/lib - C:/boost - /sw/local/lib - ) - endif() - endif() -endforeach() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_LIBRARY_SEARCH_DIRS_RELEASE = ${_boost_LIBRARY_SEARCH_DIRS_RELEASE}" - "_boost_LIBRARY_SEARCH_DIRS_DEBUG = ${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") -endif() - -# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES -if( Boost_USE_STATIC_LIBS ) - set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(WIN32) - list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a) - endif() -endif() - -# We want to use the tag inline below without risking double dashes -if(_boost_RELEASE_ABI_TAG) - if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") - set(_boost_RELEASE_ABI_TAG "") - endif() -endif() -if(_boost_DEBUG_ABI_TAG) - if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") - set(_boost_DEBUG_ABI_TAG "") - endif() -endif() - -# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled -# on WIN32 was to: -# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) -# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) -# We maintain this behavior since changing it could break people's builds. -# To disable the ambiguous behavior, the user need only -# set Boost_USE_STATIC_RUNTIME either ON or OFF. -set(_boost_STATIC_RUNTIME_WORKAROUND false) -if(WIN32 AND Boost_USE_STATIC_LIBS) - if(NOT DEFINED Boost_USE_STATIC_RUNTIME) - set(_boost_STATIC_RUNTIME_WORKAROUND TRUE) - endif() -endif() - -# On versions < 1.35, remove the System library from the considered list -# since it wasn't added until 1.35. -if(Boost_VERSION AND Boost_FIND_COMPONENTS) - if(Boost_VERSION LESS 103500) - list(REMOVE_ITEM Boost_FIND_COMPONENTS system) - endif() -endif() - -# Additional components may be required via component dependencies. -# Add any missing components to the list. -_Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS) - -# If thread is required, get the thread libs as a dependency -if("thread" IN_LIST Boost_FIND_COMPONENTS) - if(Boost_FIND_QUIETLY) - set(_Boost_find_quiet QUIET) - else() - set(_Boost_find_quiet "") - endif() - find_package(Threads ${_Boost_find_quiet}) - unset(_Boost_find_quiet) -endif() - -# If the user changed any of our control inputs flush previous results. -if(_Boost_CHANGE_LIBDIR_DEBUG OR _Boost_CHANGE_LIBDIR_RELEASE OR _Boost_CHANGE_LIBNAME) - foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - foreach(c DEBUG RELEASE) - set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) - unset(${_var} CACHE) - set(${_var} "${_var}-NOTFOUND") - endforeach() - endforeach() - set(_Boost_COMPONENTS_SEARCHED "") -endif() - -foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - - set( _boost_docstring_release "Boost ${COMPONENT} library (release)") - set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") - - # Compute component-specific hints. - set(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT "") - if(${COMPONENT} STREQUAL "mpi" OR ${COMPONENT} STREQUAL "mpi_python" OR - ${COMPONENT} STREQUAL "graph_parallel") - foreach(lib ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}) - if(IS_ABSOLUTE "${lib}") - get_filename_component(libdir "${lib}" PATH) - string(REPLACE "\\" "/" libdir "${libdir}") - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT ${libdir}) - endif() - endforeach() - endif() - - # Handle Python version suffixes - unset(COMPONENT_PYTHON_VERSION_MAJOR) - unset(COMPONENT_PYTHON_VERSION_MINOR) - if(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\$") - set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") - set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - elseif(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\\.?([0-9])\$") - set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") - set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - set(COMPONENT_PYTHON_VERSION_MINOR "${CMAKE_MATCH_3}") - endif() - - unset(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - if (COMPONENT_PYTHON_VERSION_MINOR) - # Boost >= 1.67 - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # Debian/Ubuntu (Some versions omit the 2 and/or 3 from the suffix) - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}-py${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-py${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # Gentoo - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # RPMs - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - endif() - if (COMPONENT_PYTHON_VERSION_MAJOR AND NOT COMPONENT_PYTHON_VERSION_MINOR) - # Boost < 1.67 - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}") - endif() - - # Consolidate and report component-specific hints. - if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Component-specific library search names for ${COMPONENT_NAME}: " - "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME}") - endif() - endif() - if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Component-specific library search paths for ${COMPONENT}: " - "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT}") - endif() - endif() - - # - # Find headers - # - _Boost_COMPONENT_HEADERS("${COMPONENT}" Boost_${UPPERCOMPONENT}_HEADER_NAME) - # Look for a standard boost header file. - if(Boost_${UPPERCOMPONENT}_HEADER_NAME) - if(EXISTS "${Boost_INCLUDE_DIR}/${Boost_${UPPERCOMPONENT}_HEADER_NAME}") - set(Boost_${UPPERCOMPONENT}_HEADER ON) - else() - set(Boost_${UPPERCOMPONENT}_HEADER OFF) - endif() - else() - set(Boost_${UPPERCOMPONENT}_HEADER ON) - message(WARNING "No header defined for ${COMPONENT}; skipping header check") - endif() - - # - # Find RELEASE libraries - # - unset(_boost_RELEASE_NAMES) - foreach(component IN LISTS _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME COMPONENT) - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ) - endforeach() - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endforeach() - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endif() - endforeach() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") - endif() - - # if Boost_LIBRARY_DIR_RELEASE is not defined, - # but Boost_LIBRARY_DIR_DEBUG is, look there first for RELEASE libs - if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR_DEBUG) - list(INSERT _boost_LIBRARY_SEARCH_DIRS_RELEASE 0 ${Boost_LIBRARY_DIR_DEBUG}) - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}") - - if(Boost_USE_RELEASE_LIBS) - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE - NAMES ${_boost_RELEASE_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_release}" - ) - endif() - - # - # Find DEBUG libraries - # - unset(_boost_DEBUG_NAMES) - foreach(component IN LISTS _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME COMPONENT) - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ) - endforeach() - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endforeach() - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endif() - endforeach() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") - endif() - - # if Boost_LIBRARY_DIR_DEBUG is not defined, - # but Boost_LIBRARY_DIR_RELEASE is, look there first for DEBUG libs - if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR_RELEASE) - list(INSERT _boost_LIBRARY_SEARCH_DIRS_DEBUG 0 ${Boost_LIBRARY_DIR_RELEASE}) - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") - - if(Boost_USE_DEBUG_LIBS) - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG - NAMES ${_boost_DEBUG_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_debug}" - ) - endif () - - if(Boost_REALPATH) - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) - endif() - - _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) - - # Check if component requires some compiler features - _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) - -endforeach() - -# Restore the original find library ordering -if( Boost_USE_STATIC_LIBS ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -endif() - -# ------------------------------------------------------------------------ -# End finding boost libraries -# ------------------------------------------------------------------------ - -set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -set(Boost_LIBRARY_DIRS) -if(Boost_LIBRARY_DIR_RELEASE) - list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_RELEASE}) -endif() -if(Boost_LIBRARY_DIR_DEBUG) - list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_DEBUG}) -endif() -if(Boost_LIBRARY_DIRS) - list(REMOVE_DUPLICATES Boost_LIBRARY_DIRS) -endif() - -# The above setting of Boost_FOUND was based only on the header files. -# Update it for the requested component libraries. -if(Boost_FOUND) - # The headers were found. Check for requested component libs. - set(_boost_CHECKED_COMPONENT FALSE) - set(_Boost_MISSING_COMPONENTS "") - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(_boost_CHECKED_COMPONENT TRUE) - if(NOT Boost_${UPPERCOMPONENT}_FOUND AND Boost_FIND_REQUIRED_${COMPONENT}) - list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) - endif() - endforeach() - if(_Boost_MISSING_COMPONENTS AND _Boost_EXTRA_FIND_COMPONENTS) - # Optional indirect dependencies are not counted as missing. - list(REMOVE_ITEM _Boost_MISSING_COMPONENTS ${_Boost_EXTRA_FIND_COMPONENTS}) - endif() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") - endif() - - if (_Boost_MISSING_COMPONENTS) - set(Boost_FOUND 0) - # We were unable to find some libraries, so generate a sensible - # error message that lists the libraries we were unable to find. - string(APPEND Boost_ERROR_REASON - "\nCould not find the following") - if(Boost_USE_STATIC_LIBS) - string(APPEND Boost_ERROR_REASON " static") - endif() - string(APPEND Boost_ERROR_REASON - " Boost libraries:\n") - foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - string(APPEND Boost_ERROR_REASON - " ${Boost_NAMESPACE}_${COMPONENT}${Boost_ERROR_REASON_${UPPERCOMPONENT}}\n") - endforeach() - - list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) - list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) - if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) - string(APPEND Boost_ERROR_REASON - "No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - else () - string(APPEND Boost_ERROR_REASON - "Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - endif () - endif () - - if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) - # Compatibility Code for backwards compatibility with CMake - # 2.4's FindBoost module. - - # Look for the boost library path. - # Note that the user may not have installed any libraries - # so it is quite possible the Boost_LIBRARY_DIRS may not exist. - set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) - - if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if("${_boost_LIB_DIR}" MATCHES "/include$") - # Strip off the trailing "/include" in the path. - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if(EXISTS "${_boost_LIB_DIR}/lib") - string(APPEND _boost_LIB_DIR /lib) - elseif(EXISTS "${_boost_LIB_DIR}/stage/lib") - string(APPEND _boost_LIB_DIR "/stage/lib") - else() - set(_boost_LIB_DIR "") - endif() - - if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") - set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) - endif() - - endif() -else() - # Boost headers were not found so no components were found. - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(Boost_${UPPERCOMPONENT}_FOUND 0) - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Add imported targets -# ------------------------------------------------------------------------ - -if(Boost_FOUND) - # For header-only libraries - if(NOT TARGET Boost::boost) - add_library(Boost::boost INTERFACE IMPORTED) - if(Boost_INCLUDE_DIRS) - set_target_properties(Boost::boost PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") - endif() - endif() - - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - if(_Boost_IMPORTED_TARGETS AND NOT TARGET Boost::${COMPONENT}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - if(Boost_${UPPERCOMPONENT}_FOUND) - if(Boost_USE_STATIC_LIBS) - add_library(Boost::${COMPONENT} STATIC IMPORTED) - else() - # Even if Boost_USE_STATIC_LIBS is OFF, we might have static - # libraries as a result. - add_library(Boost::${COMPONENT} UNKNOWN IMPORTED) - endif() - if(Boost_INCLUDE_DIRS) - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY}") - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - IMPORTED_LOCATION "${Boost_${UPPERCOMPONENT}_LIBRARY}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS RELEASE) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" - IMPORTED_LOCATION_RELEASE "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS DEBUG) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" - IMPORTED_LOCATION_DEBUG "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - endif() - if(_Boost_${UPPERCOMPONENT}_DEPENDENCIES) - unset(_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES) - foreach(dep ${_Boost_${UPPERCOMPONENT}_DEPENDENCIES}) - list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Boost::${dep}) - endforeach() - if(COMPONENT STREQUAL "thread") - list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Threads::Threads) - endif() - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}") - endif() - if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}") - endif() - endif() - endif() - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Notification to end user about what was found -# ------------------------------------------------------------------------ - -set(Boost_LIBRARIES "") -if(Boost_FOUND) - if(NOT Boost_FIND_QUIETLY) - message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if(Boost_FIND_COMPONENTS) - message(STATUS "Found the following Boost libraries:") - endif() - endif() - foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) - string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) - if( Boost_${UPPERCOMPONENT}_FOUND ) - if(NOT Boost_FIND_QUIETLY) - message (STATUS " ${COMPONENT}") - endif() - list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) - if(COMPONENT STREQUAL "thread") - list(APPEND Boost_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - endif() - endif() - endforeach() -else() - if(Boost_FIND_REQUIRED) - message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") - else() - if(NOT Boost_FIND_QUIETLY) - # we opt not to automatically output Boost_ERROR_REASON here as - # it could be quite lengthy and somewhat imposing in its requests - # Since Boost is not always a required dependency we'll leave this - # up to the end-user. - if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) - message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") - else() - message(STATUS "Could NOT find Boost") - endif() - endif() - endif() -endif() - -# Configure display of cache entries in GUI. -foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) - get_property(_type CACHE ${v} PROPERTY TYPE) - if(_type) - set_property(CACHE ${v} PROPERTY ADVANCED 1) - if("x${_type}" STREQUAL "xUNINITIALIZED") - if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") - set_property(CACHE ${v} PROPERTY TYPE STRING) - else() - set_property(CACHE ${v} PROPERTY TYPE PATH) - endif() - endif() - endif() -endforeach() - -# Record last used values of input variables so we can -# detect on the next run if the user changed them. -foreach(v - ${_Boost_VARS_INC} ${_Boost_VARS_LIB} - ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} - ) - if(DEFINED ${v}) - set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") - else() - unset(_${v}_LAST CACHE) - endif() -endforeach() - -# Maintain a persistent list of components requested anywhere since -# the last flush. -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") -list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) -list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) -list(SORT _Boost_COMPONENTS_SEARCHED) -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" - CACHE INTERNAL "Components requested for this build tree.") - -# Restore project's policies -cmake_policy(POP) diff --git a/examples/cmake/FindPython.cmake b/examples/cmake/FindPython.cmake deleted file mode 100644 index 8645a0d..0000000 --- a/examples/cmake/FindPython.cmake +++ /dev/null @@ -1,206 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindPython ----------- - -Find Python interpreter, compiler and development environment (include -directories and libraries). - -Three components are supported: - -* ``Interpreter``: search for Python interpreter. -* ``Compiler``: search for Python compiler. Only offered by IronPython. -* ``Development``: search for development artifacts (include directories and - libraries). - -If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed. - -To ensure consistent versions between components ``Interpreter``, ``Compiler`` -and ``Development``, specify all components at the same time:: - - find_package (Python COMPONENTS Interpreter Development) - -This module looks preferably for version 3 of Python. If not found, version 2 -is searched. -To manage concurrent versions 3 and 2 of Python, use :module:`FindPython3` and -:module:`FindPython2` modules rather than this one. - -Imported Targets -^^^^^^^^^^^^^^^^ - -This module defines the following :ref:`Imported Targets `: - -``Python::Interpreter`` - Python interpreter. Target defined if component ``Interpreter`` is found. -``Python::Compiler`` - Python compiler. Target defined if component ``Compiler`` is found. -``Python::Python`` - Python library. Target defined if component ``Development`` is found. - -Result Variables -^^^^^^^^^^^^^^^^ - -This module will set the following variables in your project -(see :ref:`Standard Variable Names `): - -``Python_FOUND`` - System has the Python requested components. -``Python_Interpreter_FOUND`` - System has the Python interpreter. -``Python_EXECUTABLE`` - Path to the Python interpreter. -``Python_INTERPRETER_ID`` - A short string unique to the interpreter. Possible values include: - * Python - * ActivePython - * Anaconda - * Canopy - * IronPython -``Python_STDLIB`` - Standard platform independent installation directory. - - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``. -``Python_STDARCH`` - Standard platform dependent installation directory. - - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``. -``Python_SITELIB`` - Third-party platform independent installation directory. - - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``. -``Python_SITEARCH`` - Third-party platform dependent installation directory. - - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``. -``Python_Compiler_FOUND`` - System has the Python compiler. -``Python_COMPILER`` - Path to the Python compiler. Only offered by IronPython. -``Python_COMPILER_ID`` - A short string unique to the compiler. Possible values include: - * IronPython -``Python_Development_FOUND`` - System has the Python development artifacts. -``Python_INCLUDE_DIRS`` - The Python include directories. -``Python_LIBRARIES`` - The Python libraries. -``Python_LIBRARY_DIRS`` - The Python library directories. -``Python_RUNTIME_LIBRARY_DIRS`` - The Python runtime library directories. -``Python_VERSION`` - Python version. -``Python_VERSION_MAJOR`` - Python major version. -``Python_VERSION_MINOR`` - Python minor version. -``Python_VERSION_PATCH`` - Python patch version. - -Hints -^^^^^ - -``Python_ROOT_DIR`` - Define the root directory of a Python installation. - -``Python_USE_STATIC_LIBS`` - * If not defined, search for shared libraries and static libraries in that - order. - * If set to TRUE, search **only** for static libraries. - * If set to FALSE, search **only** for shared libraries. - -``Python_FIND_REGISTRY`` - On Windows the ``Python_FIND_REGISTRY`` variable determine the order - of preference between registry and environment variables. - the ``Python_FIND_REGISTRY`` variable can be set to empty or one of the - following: - - * ``FIRST``: Try to use registry before environment variables. - This is the default. - * ``LAST``: Try to use registry after environment variables. - * ``NEVER``: Never try to use registry. - -``CMAKE_FIND_FRAMEWORK`` - On OS X the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of - preference between Apple-style and unix-style package components. - - .. note:: - - Value ``ONLY`` is not supported so ``FIRST`` will be used instead. - -.. note:: - - If a Python virtual environment is configured, set variable - ``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with - value ``LAST`` or ``NEVER`` to select it preferably. - -Commands -^^^^^^^^ - -This module defines the command ``Python_add_library`` which have the same -semantic as :command:`add_library` but take care of Python module naming rules -(only applied if library is of type ``MODULE``) and add dependency to target -``Python::Python``:: - - Python_add_library (my_module MODULE src1.cpp) - -If library type is not specified, ``MODULE`` is assumed. -#]=======================================================================] - - -set (_PYTHON_PREFIX Python) - -if (DEFINED Python_FIND_VERSION) - set (_Python_REQUIRED_VERSION_MAJOR ${Python_FIND_VERSION_MAJOR}) - - include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake) -else() - # iterate over versions in quiet and NOT required modes to avoid multiple - # "Found" messages and prematurally failure. - set (_Python_QUIETLY ${Python_FIND_QUIETLY}) - set (_Python_REQUIRED ${Python_FIND_REQUIRED}) - set (Python_FIND_QUIETLY TRUE) - set (Python_FIND_REQUIRED FALSE) - - set (_Python_REQUIRED_VERSIONS 3 2) - set (_Python_REQUIRED_VERSION_LAST 2) - - foreach (_Python_REQUIRED_VERSION_MAJOR IN LISTS _Python_REQUIRED_VERSIONS) - set (Python_FIND_VERSION ${_Python_REQUIRED_VERSION_MAJOR}) - include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake) - if (Python_FOUND OR - _Python_REQUIRED_VERSION_MAJOR EQUAL _Python_REQUIRED_VERSION_LAST) - break() - endif() - # clean-up some CACHE variables to ensure look-up restart from scratch - foreach (_Python_ITEM IN LISTS _Python_CACHED_VARS) - unset (${_Python_ITEM} CACHE) - endforeach() - endforeach() - - unset (Python_FIND_VERSION) - - set (Python_FIND_QUIETLY ${_Python_QUIETLY}) - set (Python_FIND_REQUIRED ${_Python_REQUIRED}) - if (Python_FIND_REQUIRED OR NOT Python_FIND_QUIETLY) - # call again validation command to get "Found" or error message - find_package_handle_standard_args (Python HANDLE_COMPONENTS - REQUIRED_VARS ${_Python_REQUIRED_VARS} - VERSION_VAR Python_VERSION) - endif() -endif() - -if (COMMAND __Python_add_library) - macro (Python_add_library) - __Python_add_library (Python ${ARGV}) - endmacro() -endif() - -unset (_PYTHON_PREFIX) diff --git a/examples/libmod_cmake/CMakeLists.txt b/examples/libmod_cmake/CMakeLists.txt index ffb475c..5ef885b 100644 --- a/examples/libmod_cmake/CMakeLists.txt +++ b/examples/libmod_cmake/CMakeLists.txt @@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.10) project(LibmodTestProject CXX) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + find_package(mod REQUIRED) add_executable(doStuff main.cpp) diff --git a/examples/pymod_extension/CMakeLists.txt b/examples/pymod_extension/CMakeLists.txt index 587d25d..1aaa434 100644 --- a/examples/pymod_extension/CMakeLists.txt +++ b/examples/pymod_extension/CMakeLists.txt @@ -3,6 +3,9 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) project(PyModTestProject CXX) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + # MØD # ------------------------------------------------------------------------- find_package(mod REQUIRED) diff --git a/external/graph_canon b/external/graph_canon index 3f2ef09..dce6d19 160000 --- a/external/graph_canon +++ b/external/graph_canon @@ -1 +1 @@ -Subproject commit 3f2ef09e2fc0288bb6b323027ba976166ba7962b +Subproject commit dce6d19df303d311cba89d6977200526e7b141ce diff --git a/external/json_schema b/external/json_schema index 3b89cf3..1519c84 160000 --- a/external/json_schema +++ b/external/json_schema @@ -1 +1 @@ -Subproject commit 3b89cf3818300123fad14c5eadd2d6e31630e499 +Subproject commit 1519c845c2b1bbf35021feb11c23625de603ca1e diff --git a/external/nlohmann_json b/external/nlohmann_json index 53ef076..fd7a9f6 160000 --- a/external/nlohmann_json +++ b/external/nlohmann_json @@ -1 +1 @@ -Subproject commit 53ef076715b1a7140f10556f6430e1adde133e94 +Subproject commit fd7a9f600712b2724463e9f7f703878ade676d6e diff --git a/libs/epim/lib/mod/epim/__init__.py b/libs/epim/lib/mod/epim/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/libs/epim/lib/mod/epim/encode/__init__.py b/libs/epim/lib/mod/epim/encode/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/libs/epim/lib/mod/epim/encode/graph_constants.py b/libs/epim/lib/mod/epim/encode/graph_constants.py index 647695b..fe1814c 100644 --- a/libs/epim/lib/mod/epim/encode/graph_constants.py +++ b/libs/epim/lib/mod/epim/encode/graph_constants.py @@ -1,5 +1,5 @@ -from .graph_interface import GraphInterface -from . import graph_terms as term +from mod.epim.encode import graph_terms as term +from mod.epim.encode.graph_interface import GraphInterface def ccall(name, args): g = GraphInterface() diff --git a/libs/epim/lib/mod/epim/encode/graph_interface.py b/libs/epim/lib/mod/epim/encode/graph_interface.py index a0bc972..c844c6c 100644 --- a/libs/epim/lib/mod/epim/encode/graph_interface.py +++ b/libs/epim/lib/mod/epim/encode/graph_interface.py @@ -1,7 +1,8 @@ -import networkx as nx -from networkx.drawing.nx_agraph import to_agraph +import networkx as nx # type: ignore +from networkx.drawing.nx_agraph import to_agraph # type: ignore +from parse import parse # type: ignore + import mod -from parse import parse class GraphInterface: def __init__(self): diff --git a/libs/epim/lib/mod/epim/process.py b/libs/epim/lib/mod/epim/process.py index 43e312f..5ec6e66 100644 --- a/libs/epim/lib/mod/epim/process.py +++ b/libs/epim/lib/mod/epim/process.py @@ -1,8 +1,8 @@ -from .encode.graph_constants import * -from .transform.normalform import normalform -from .gen_image import setImage +from parse import parse # type: ignore -from parse import parse +from mod.epim.encode.graph_constants import * +from mod.epim.gen_image import setImage +from mod.epim.transform.normalform import normalform class ProcessConfig: def __init__(self): diff --git a/libs/epim/lib/mod/epim/recursive_process.py b/libs/epim/lib/mod/epim/recursive_process.py index d9c30c9..1a0523d 100644 --- a/libs/epim/lib/mod/epim/recursive_process.py +++ b/libs/epim/lib/mod/epim/recursive_process.py @@ -1,6 +1,6 @@ from mod import * -from .process import Process -from .encode import graph_terms as term +from mod.epim.process import Process +from mod.epim.encode import graph_terms as term def make_call_rule(name, args, p): g = p.encode() diff --git a/libs/epim/lib/mod/epim/transform/__init__.py b/libs/epim/lib/mod/epim/transform/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/libs/epim/lib/mod/epim/transform/normalform.py b/libs/epim/lib/mod/epim/transform/normalform.py index 47595b6..d683993 100644 --- a/libs/epim/lib/mod/epim/transform/normalform.py +++ b/libs/epim/lib/mod/epim/transform/normalform.py @@ -1,6 +1,6 @@ from mod import * -from .util import * -from ..encode import graph_terms as term +from mod.epim.transform.util import * +from mod.epim.encode import graph_terms as term def biop_str(op, t): return """rule [ diff --git a/libs/epim/lib/mod/epim/transform/reduction_dg.py b/libs/epim/lib/mod/epim/transform/reduction_dg.py index 99bf36d..b4f10a4 100644 --- a/libs/epim/lib/mod/epim/transform/reduction_dg.py +++ b/libs/epim/lib/mod/epim/transform/reduction_dg.py @@ -1,8 +1,8 @@ from mod import * -from .util import apply_confluent_gts, merge, get_go_graphs -from ..process import Process -from ..gen_image import setImage -from ..recursive_process import RecursiveProcess +from mod.epim.transform.util import apply_confluent_gts, merge, get_go_graphs +from mod.epim.process import Process +from mod.epim.gen_image import setImage +from mod.epim.recursive_process import RecursiveProcess reduction_rules =[ ruleGMLString("""rule [ ruleID "reduction rule" @@ -280,4 +280,4 @@ def print(self, use_raw_dg = False, use_example = False): dg = self.raw_dg dg.print(dgp) return - dg.print() \ No newline at end of file + dg.print() diff --git a/libs/epim/lib/mod/epim/transform/util.py b/libs/epim/lib/mod/epim/transform/util.py index e409046..15e8db7 100644 --- a/libs/epim/lib/mod/epim/transform/util.py +++ b/libs/epim/lib/mod/epim/transform/util.py @@ -105,4 +105,4 @@ def apply_confluent_gts(b, graph, rule_list, apply_cleanup_rules = True): graph = merge(b, graph) tmp = b.apply(graph, rule) config.dg.applyLimit = oldLimit - return graph \ No newline at end of file + return graph diff --git a/libs/gml/CMakeLists.txt b/libs/gml/CMakeLists.txt index df4f3ac..bf0df90 100644 --- a/libs/gml/CMakeLists.txt +++ b/libs/gml/CMakeLists.txt @@ -9,11 +9,11 @@ add_library(GML::gml ALIAS gml) target_include_directories(gml PUBLIC $ - $ - ${Boost_INCLUDE_DIR}) # we only use header-only libs from Boost, right? + $) target_compile_options(gml PRIVATE -Wall -Wextra -Wno-unused-parameter -Wno-parentheses) +target_link_libraries(gml PUBLIC Boost::boost) set_target_properties(gml PROPERTIES POSITION_INDEPENDENT_CODE ON CXX_VISIBILITY_PRESET hidden @@ -41,10 +41,14 @@ if(BUILD_TESTING) if(NOT TARGET tests) add_custom_target(tests) endif() - add_dependencies(tests ${mod_gml_TEST_FILES}) + add_dependencies(tests ${mod_gml_TEST_CPP_FILES}) - set(sanFlags -g -fsanitize=undefined -fsanitize=address -fsanitize=leak) - foreach(testName ${mod_gml_TEST_FILES}) + if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xAppleClang") + set(sanFlags -g -fsanitize=undefined -fsanitize=address) + else() + set(sanFlags -g -fsanitize=undefined -fsanitize=address -fsanitize=leak) + endif() + foreach(testName ${mod_gml_TEST_CPP_FILES}) add_executable(${testName} EXCLUDE_FROM_ALL test/${testName}.cpp) target_compile_options(${testName} PRIVATE -Wall -Wextra -Werror -pedantic -Wno-unused-parameter diff --git a/libs/gml/include/gml/ast.hpp b/libs/gml/include/gml/ast.hpp index 4c100cb..4eb687e 100644 --- a/libs/gml/include/gml/ast.hpp +++ b/libs/gml/include/gml/ast.hpp @@ -11,8 +11,7 @@ namespace spirit = boost::spirit; namespace x3 = boost::spirit::x3; -namespace gml { -namespace ast { +namespace gml::ast { struct LocationInfo { std::size_t line, column; @@ -20,7 +19,7 @@ struct LocationInfo { struct List; -struct Value : x3::variant >, LocationInfo { +struct Value : x3::variant>, LocationInfo { using base_type::base_type; using base_type::operator=; }; @@ -34,15 +33,14 @@ struct List { std::vector list; }; -} // namespace ast -} // namespace gml +} // namespace gml::ast BOOST_FUSION_ADAPT_STRUCT(gml::ast::KeyValue, - (std::string, key) - (gml::ast::Value, value) - ) + (std::string, key) + (gml::ast::Value, value) +) BOOST_FUSION_ADAPT_STRUCT(gml::ast::List, - (std::vector, list) - ) + (std::vector, list) +) #endif /* GML_AST_HPP */ \ No newline at end of file diff --git a/libs/gml/include/gml/attr_handler.hpp b/libs/gml/include/gml/attr_handler.hpp index 1f39cc6..aaa4c07 100644 --- a/libs/gml/include/gml/attr_handler.hpp +++ b/libs/gml/include/gml/attr_handler.hpp @@ -3,8 +3,7 @@ #include -namespace gml { -namespace converter { +namespace gml::converter { template struct AttrHandler { @@ -44,7 +43,6 @@ struct AttrHandler { T C::*m; }; -} // namespace converter -} // namespace gml +} // namespace gml::converter #endif /* ATTR_HANDLER_HPP */ diff --git a/libs/gml/include/gml/converter.hpp b/libs/gml/include/gml/converter.hpp index 2f78b8c..4a13427 100644 --- a/libs/gml/include/gml/converter.hpp +++ b/libs/gml/include/gml/converter.hpp @@ -3,8 +3,7 @@ #include -namespace gml { -namespace converter { +namespace gml::converter { template bool convert(IterBegin &iterBegin, const IterEnd &iterEnd, const Expression &expr, std::ostream &err, Attr &attr) { @@ -28,7 +27,6 @@ bool convert(IterBegin &iterBegin, const IterEnd &iterEnd, const Expression &exp return convert(iterBegin, iterEnd, expr, err, unused); } -} // namespace converter -} // namespace gml +} // namespace gml::converter #endif /* GML_CONVERTER_HPP */ \ No newline at end of file diff --git a/libs/gml/include/gml/converter_edsl.hpp b/libs/gml/include/gml/converter_edsl.hpp index 289c05a..d895345 100644 --- a/libs/gml/include/gml/converter_edsl.hpp +++ b/libs/gml/include/gml/converter_edsl.hpp @@ -4,8 +4,8 @@ #include #include -namespace gml { -namespace converter { +namespace gml::converter { +// TODO: C++20, merge the two namespace decls inline namespace edsl { // such that 'using namespace gml::converter::edsl;' gives Parent as well using gml::converter::Parent; @@ -75,7 +75,6 @@ list(const std::string &key, AttrHandlerData attrHandlerData = Unused()) { } } // inline namespace edsl -} // namespace converter -} // namespace gml +} // namespace gml::converter #endif /* GML_CONVERTER_EDSL_HPP */ \ No newline at end of file diff --git a/libs/gml/include/gml/converter_expressions.hpp b/libs/gml/include/gml/converter_expressions.hpp index f67f812..3be7cc4 100644 --- a/libs/gml/include/gml/converter_expressions.hpp +++ b/libs/gml/include/gml/converter_expressions.hpp @@ -7,8 +7,7 @@ #include -namespace gml { -namespace converter { +namespace gml::converter { namespace detail { struct ExpressionBase { @@ -235,7 +234,6 @@ Expression asConverter(const Expression &expr) { return expr; } -} // namespace converter -} // namespace gml +} // namespace gml::converter #endif /* GML_CONVERTER_EXPRESSIONS_HPP */ diff --git a/libs/gml/include/gml/parser.hpp b/libs/gml/include/gml/parser.hpp index b743e15..8fac3a5 100644 --- a/libs/gml/include/gml/parser.hpp +++ b/libs/gml/include/gml/parser.hpp @@ -3,12 +3,12 @@ #include -namespace gml { -namespace parser { +#include -bool parse(std::istream &s, ast::KeyValue &ast, std::ostream &err); +namespace gml::parser { -} // namespace parser -} // namespace gml +bool parse(std::string_view src, ast::KeyValue &ast, std::ostream &err); -#endif /* GML_PARSER_HPP */ \ No newline at end of file +} // namespace gml::parser + +#endif // GML_PARSER_HPP \ No newline at end of file diff --git a/libs/gml/src/converter_expressions.cpp b/libs/gml/src/converter_expressions.cpp index ffcbc84..8aa473c 100644 --- a/libs/gml/src/converter_expressions.cpp +++ b/libs/gml/src/converter_expressions.cpp @@ -1,8 +1,6 @@ #include -namespace gml { -namespace converter { -namespace detail { +namespace gml::converter::detail { bool ExpressionBase::checkKey(const std::string &key) const { return key == this->key; @@ -30,6 +28,4 @@ bool ExpressionBase::checkAndErrorOnType(const ast::Value &value, std::ostream & return true; } -} // namespace detail -} // namespace converter -} // namespace gml \ No newline at end of file +} // namespace gml::converter::detail \ No newline at end of file diff --git a/libs/gml/src/parser.cpp b/libs/gml/src/parser.cpp index 8e5f40a..f747664 100644 --- a/libs/gml/src/parser.cpp +++ b/libs/gml/src/parser.cpp @@ -13,22 +13,21 @@ #include #include #include -#include -#include +#include namespace spirit = boost::spirit; namespace x3 = boost::spirit::x3; -namespace gml { -namespace parser { +namespace gml::parser { +namespace { +constexpr int SpacesPerTabs = 4; +} // namespace struct LocationHandler { - template - void on_success(const Iterator &first, const Iterator &last, ast::LocationInfo &locInfo, const Context&) { - const auto &pos = first.get_position(); - locInfo.line = pos.line; - locInfo.column = pos.column; + void on_success(const Iterator &first, const Iterator &last, ast::LocationInfo &locInfo, const Context &) { + locInfo.line = get_line(first); + locInfo.column = get_column(first, last, SpacesPerTabs); } }; @@ -41,7 +40,7 @@ struct value_class : LocationHandler { const x3::rule skipper = "skipper"; const x3::rule gml = "gml"; const x3::rule list = "list"; -const x3::rule > listInner = "key or ']'"; +const x3::rule> listInner = "key or ']'"; const x3::rule keyValue = "keyValue"; const x3::rule key = "key"; const x3::rule value = "value"; @@ -70,34 +69,32 @@ const auto tab_def = 't' >> x3::attr('\t'); const auto explicitBackslash_def = '\\' >> x3::attr('\\'); const auto implicitBackslash_def = x3::attr('\\'); -BOOST_SPIRIT_DEFINE(skipper, gml, list, listInner, keyValue, key, value, valueInner, string, escaped, plain, tab, explicitBackslash, implicitBackslash); +BOOST_SPIRIT_DEFINE(skipper, gml, list, listInner, keyValue, key, value, valueInner, string, escaped, plain, tab, + explicitBackslash, implicitBackslash); -template -bool parse(TextIter &textIter, const TextIter &textIterEnd, ast::KeyValue &ast, std::ostream &err) { - using Iter = spirit::classic::position_iterator2; - Iter iter(textIter, textIterEnd), iterEnd; +bool parse(std::string_view src, ast::KeyValue &ast, std::ostream &err) { + using PosIter = spirit::line_pos_iterator; + PosIter iter(src.begin()); // referenced in doError auto doError = [&]() { - const auto &pos = iter.get_position(); - auto lineNumber = pos.line; - auto column = pos.column; - std::string line = iter.get_currentline(); + const auto lineNumber = iter.position(); + const auto lineRange = get_current_line(PosIter(src.begin()), iter, PosIter(src.end())); + const auto column = get_column(lineRange.begin(), iter, SpacesPerTabs); err << "Parsing failed at " << lineNumber << ":" << column << ":\n"; - // each tab is 4 in the position iterator - for(const char c : line) { - if(c == '\t') err << " "; + for(const char c : lineRange) { + if(c == '\t') err << std::string(SpacesPerTabs, ' '); else err << c; } err << "\n"; err << std::string(column - 1, '-') << "^\n"; }; try { - bool res = x3::phrase_parse(iter, iterEnd, gml, skipper, ast); - if(!res || iter != iterEnd) { + bool res = x3::phrase_parse(iter, PosIter(src.end()), gml, skipper, ast); + if(!res || iter != PosIter(src.end())) { doError(); err << "End of x3 error.\n"; return false; } - } catch(const x3::expectation_failure &e) { + } catch(const x3::expectation_failure &e) { iter = e.where(); doError(); err << "Expected " << e.which() << ".\n"; @@ -107,25 +104,4 @@ bool parse(TextIter &textIter, const TextIter &textIterEnd, ast::KeyValue &ast, return true; } -bool parse(std::istream &s, ast::KeyValue &ast, std::ostream &err) { - - struct FlagsHolder { - - FlagsHolder(std::istream &s) : s(s), flags(s.flags()) { } - - ~FlagsHolder() { - s.flags(flags); - } - private: - std::istream &s; - std::ios::fmtflags flags; - } flagsHolder(s); - s.unsetf(std::ios::skipws); - - using Iter = spirit::multi_pass >; - Iter iterBegin(s), iterEnd; - return parse(iterBegin, iterEnd, ast, err); -} - -} // namespace parser -} // namespace gml \ No newline at end of file +} // namespace gml::parser \ No newline at end of file diff --git a/libs/gml/test/test_gml.cpp b/libs/gml/test/test_gml.cpp index a60c22c..57fb2b8 100644 --- a/libs/gml/test/test_gml.cpp +++ b/libs/gml/test/test_gml.cpp @@ -14,11 +14,9 @@ std::ostream &operator<<(std::ostream &s, const std::vector &v) { } struct T { - friend std::ostream &operator<<(std::ostream &s, const T &t) { return s << "i = " << t.i << ", d = " << t.d << ", s = '" << t.s << "'"; } - public: int i = 0; double d = 0; @@ -26,18 +24,16 @@ struct T { }; struct V { - friend std::ostream &operator<<(std::ostream &s, const V &v) { return s << "vi = " << v.vi << ", vd = " << v.vd << ", vs = " << v.vs; } - public: std::vector vi; std::vector vd; std::vector vs; }; -void print(std::ostream &) { } +void print(std::ostream &) {} template void print(std::ostream &s, const Attr &attr) { @@ -45,14 +41,12 @@ void print(std::ostream &s, const Attr &attr) { } template -void test(std::string str, const Expression &expr, Attr &...attr) { - std::cout << "Testing: '" << str << "' with '" << asConverter(expr) << "'" << std::endl << std::string(70, '-') - << std::endl; - std::stringstream ss; - ss << str; +void test(std::string src, const Expression &expr, Attr &...attr) { + std::cout << "Testing: '" << src << "' with '" << asConverter(expr) << "'" << std::endl << std::string(70, '-') + << std::endl; std::stringstream err; gml::ast::KeyValue ast; - bool res = gml::parser::parse(ss, ast, err); + bool res = gml::parser::parse(src, ast, err); if(!res) { std::cout << err.str() << std::endl; std::cout << "Parsing failed." << std::endl; @@ -71,14 +65,12 @@ void test(std::string str, const Expression &expr, Attr &...attr) { } template -void fail(std::string str, const Expression &expr, Attr &...attr) { - std::cout << "Testing for fail: '" << str << "' with '" << asConverter(expr) << "'" << std::endl - << std::string(70, '-') << std::endl; - std::stringstream ss; - ss << str; +void fail(std::string src, const Expression &expr, Attr &...attr) { + std::cout << "Testing for fail: '" << src << "' with '" << asConverter(expr) << "'" << std::endl + << std::string(70, '-') << std::endl; std::stringstream err; gml::ast::KeyValue ast; - bool res = gml::parser::parse(ss, ast, err); + bool res = gml::parser::parse(src, ast, err); if(!res) { std::cout << err.str() << std::endl; std::cout << "Parsing failed." << std::endl; diff --git a/libs/jla_boost/CMakeLists.txt b/libs/jla_boost/CMakeLists.txt index 29278b9..27df66a 100644 --- a/libs/jla_boost/CMakeLists.txt +++ b/libs/jla_boost/CMakeLists.txt @@ -40,10 +40,14 @@ if(BUILD_TESTING) if(NOT TARGET tests) add_custom_target(tests) endif() - add_dependencies(tests ${mod_jla_boost_TEST_FILES}) + add_dependencies(tests ${mod_jla_boost_TEST_CPP_FILES}) - set(sanFlags -g -fsanitize=undefined -fsanitize=address -fsanitize=leak) - foreach(testName ${mod_jla_boost_TEST_FILES}) + if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xAppleClang") + set(sanFlags -g -fsanitize=undefined -fsanitize=address) + else() + set(sanFlags -g -fsanitize=undefined -fsanitize=address -fsanitize=leak) + endif() + foreach(testName ${mod_jla_boost_TEST_CPP_FILES}) add_executable(${testName} EXCLUDE_FROM_ALL test/${testName}.cpp) target_link_libraries(${testName} PRIVATE JLA::boost) if(BUILD_TESTING_SANITIZERS AND NOT BUILD_COVERAGE) diff --git a/libs/jla_boost/include/jla_boost/graph/PairToRangeAdaptor.hpp b/libs/jla_boost/include/jla_boost/graph/PairToRangeAdaptor.hpp index 7be3b35..149efbb 100644 --- a/libs/jla_boost/include/jla_boost/graph/PairToRangeAdaptor.hpp +++ b/libs/jla_boost/include/jla_boost/graph/PairToRangeAdaptor.hpp @@ -22,6 +22,10 @@ struct range : std::pair { Iter end() const { return this->second; } + + decltype(auto) operator[](int i) const { + return begin()[i]; + } }; template diff --git a/libs/jla_boost/include/jla_boost/graph/UnionGraph.hpp b/libs/jla_boost/include/jla_boost/graph/UnionGraph.hpp index f0c1c86..1bd55c3 100644 --- a/libs/jla_boost/include/jla_boost/graph/UnionGraph.hpp +++ b/libs/jla_boost/include/jla_boost/graph/UnionGraph.hpp @@ -13,7 +13,7 @@ namespace jla_boost { template struct union_graph { - using GraphStore = std::vector; + using GraphStore = std::vector; using const_iterator = typename GraphStore::const_iterator; using base_traits = boost::graph_traits; @@ -59,10 +59,12 @@ struct union_graph { vertices_size_type get_vertex_idx_offset(std::size_t gIdx) const; edges_size_type get_num_edges() const; edges_size_type get_edge_idx_offset(std::size_t gIdx) const; + std::pair get_gIdx_and_vIdx(vertices_size_type vId) const; + std::pair get_gIdx_and_eIdx(edges_size_type eId) const; private: // idxOffset.back() is the number of vertices in the graph // idxOffset.size() == graphs.size() + 1 - std::vector graphs; + std::vector graphs; std::vector vertexIdxOffset; std::vector edgeIdxOffset; }; @@ -71,7 +73,7 @@ struct union_graph { //------------------------------------------------------------------------------ template -union_graph::union_graph() : vertexIdxOffset(1, 0), edgeIdxOffset(1, 0) { } +union_graph::union_graph() : vertexIdxOffset(1, 0), edgeIdxOffset(1, 0) {} template void union_graph::push_back(const Graph *g) { @@ -122,12 +124,35 @@ typename union_graph::edges_size_type union_graph::get_edge_idx_of return edgeIdxOffset[gIdx]; } +template +std::pair::vertices_size_type> +union_graph::get_gIdx_and_vIdx(vertices_size_type vId) const { + assert(vId <= get_num_vertices()); + for(std::size_t gIdx = 1; gIdx <= size(); ++gIdx) { + const auto baseOffset = get_vertex_idx_offset(gIdx); + if(baseOffset > vId) + return {gIdx - 1, vId - get_vertex_idx_offset(gIdx - 1)}; + } + return {size(), 0}; +} + +template +std::pair::edges_size_type> +union_graph::get_gIdx_and_eIdx(edges_size_type eId) const { + assert(eId <= get_num_edges()); + for(std::size_t gIdx = 1; gIdx <= size(); ++gIdx) { + const auto baseOffset = get_edge_idx_offset(gIdx); + if(baseOffset > eId) + return {gIdx - 1, eId - get_edge_idx_offset(gIdx - 1)}; + } + return {size(), 0}; +} + // Graph //------------------------------------------------------------------------------ template struct union_graph::vertex_descriptor { - friend bool operator==(const vertex_descriptor &l, const vertex_descriptor &r) { return std::tie(l.gIdx, l.v) == std::tie(r.gIdx, r.v); } @@ -150,7 +175,6 @@ struct union_graph::vertex_descriptor { template struct union_graph::edge_descriptor { - friend bool operator==(const edge_descriptor &l, const edge_descriptor &r) { return std::tie(l.gIdx, l.e) == std::tie(r.gIdx, r.e); } @@ -181,11 +205,10 @@ typename union_graph::vertex_descriptor union_graph::null_vertex() template struct union_graph::out_edge_iterator -: boost::iterator_facade::out_edge_iterator, typename union_graph::edge_descriptor, -typename std::iterator_traits::iterator_category, typename union_graph::edge_descriptor> { + : boost::iterator_facade::out_edge_iterator, typename union_graph::edge_descriptor, + typename std::iterator_traits::iterator_category, typename union_graph::edge_descriptor> { out_edge_iterator() = default; - - out_edge_iterator(std::size_t gIdx, typename base_traits::out_edge_iterator eIter) : gIdx(gIdx), eIter(eIter) { } + out_edge_iterator(std::size_t gIdx, typename base_traits::out_edge_iterator eIter) : gIdx(gIdx), eIter(eIter) {} private: friend class boost::iterator_core_access; @@ -200,9 +223,18 @@ typename std::iterator_traits::iterator void increment() { // Incrementable Iterator ++eIter; } - //a.decrement() unused Bidirectional Traversal Iterator - //a.advance(n) unused Random Access Traversal Iterator - //c.distance_to(z) convertible to F::difference_type equivalent to distance(c, X(z)). Random Access Traversal Iterator + + void decrement() { // Bidirectional Traversal Iterator + --eIter; + } + + void advance(std::ptrdiff_t n) { // Random Access Traversal Iterator + eIter += n; + } + + std::ptrdiff_t distance_to(const vertex_iterator &other) const { // Random Access Traversal Iterator + return other.eIter - eIter; + } private: std::size_t gIdx; typename base_traits::out_edge_iterator eIter; @@ -218,17 +250,20 @@ out_edges(typename union_graph::vertex_descriptor v, const union_graph -typename union_graph::vertex_descriptor source(typename union_graph::edge_descriptor e, const union_graph &g) { +typename union_graph::vertex_descriptor +source(typename union_graph::edge_descriptor e, const union_graph &g) { return typename union_graph::vertex_descriptor{e.gIdx, source(e.e, g[e.gIdx])}; } template -typename union_graph::vertex_descriptor target(typename union_graph::edge_descriptor e, const union_graph &g) { +typename union_graph::vertex_descriptor +target(typename union_graph::edge_descriptor e, const union_graph &g) { return typename union_graph::vertex_descriptor{e.gIdx, target(e.e, g[e.gIdx])}; } template -typename union_graph::degree_size_type out_degree(typename union_graph::vertex_descriptor v, const union_graph &g) { +typename union_graph::degree_size_type +out_degree(typename union_graph::vertex_descriptor v, const union_graph &g) { return out_degree(v.v, g[v.gIdx]); } @@ -237,11 +272,10 @@ typename union_graph::degree_size_type out_degree(typename union_graph struct union_graph::in_edge_iterator -: boost::iterator_facade::in_edge_iterator, typename union_graph::edge_descriptor, -typename std::iterator_traits::iterator_category, typename union_graph::edge_descriptor> { + : boost::iterator_facade::in_edge_iterator, typename union_graph::edge_descriptor, + typename std::iterator_traits::iterator_category, typename union_graph::edge_descriptor> { in_edge_iterator() = default; - - in_edge_iterator(std::size_t gIdx, typename base_traits::in_edge_iterator eIter) : gIdx(gIdx), eIter(eIter) { } + in_edge_iterator(std::size_t gIdx, typename base_traits::in_edge_iterator eIter) : gIdx(gIdx), eIter(eIter) {} private: friend class boost::iterator_core_access; @@ -274,12 +308,14 @@ in_edges(typename union_graph::vertex_descriptor v, const union_graph -typename union_graph::degree_size_type in_degree(typename union_graph::vertex_descriptor v, const union_graph &g) { +typename union_graph::degree_size_type +in_degree(typename union_graph::vertex_descriptor v, const union_graph &g) { return in_degree(v.v, g[v.gIdx]); } template -typename union_graph::degree_size_type degree(typename union_graph::vertex_descriptor v, const union_graph &g) { +typename union_graph::degree_size_type +degree(typename union_graph::vertex_descriptor v, const union_graph &g) { return degree(v.v, g[v.gIdx]); } @@ -289,15 +325,15 @@ typename union_graph::degree_size_type degree(typename union_graph template struct union_graph::vertex_iterator -: boost::iterator_facade::vertex_iterator, typename union_graph::vertex_descriptor, -typename std::iterator_traits::iterator_category, typename union_graph::vertex_descriptor> { + : boost::iterator_facade::vertex_iterator, typename union_graph::vertex_descriptor, + typename std::iterator_traits::iterator_category, typename union_graph::vertex_descriptor> { vertex_iterator() = default; explicit vertex_iterator(const union_graph *g) - : g(g), gIdx(g->size()) { } + : g(g), gIdx(g->size()) {} vertex_iterator(const union_graph *g, std::size_t gIdx, typename base_traits::vertex_iterator vIter) - : g(g), gIdx(gIdx), vIter(vIter) { } + : g(g), gIdx(gIdx), vIter(vIter) {} private: friend class boost::iterator_core_access; @@ -313,16 +349,29 @@ typename std::iterator_traits::iterator_c void increment() { // Incrementable Iterator ++vIter; while(vIter == vertices((*g)[gIdx]).second) { - gIdx++; + ++gIdx; if(gIdx == g->size()) break; vIter = vertices((*g)[gIdx]).first; } } - //a.decrement() unused Bidirectional Traversal Iterator - //a.advance(n) unused Random Access Traversal Iterator + + void decrement() { // Bidirectional Traversal Iterator + while(vIter == vertices((*g)[gIdx]).first) { + --gIdx; + vIter = vertices((*g)[gIdx]).second; + } + --vIter; + } + + void advance(std::ptrdiff_t n) { // Random Access Traversal Iterator + std::size_t idxThis = gIdx == g->size() ? g->get_num_vertices() : get(boost::vertex_index_t(), *g, **this); + auto[gIdxNew, vIdxNew] = g->get_gIdx_and_vIdx(idxThis + n); + gIdx = gIdxNew; + vIter = vertices((*g)[gIdx]).first + vIdxNew; + } std::ptrdiff_t distance_to(const vertex_iterator &other) const { // Random Access Traversal Iterator - std::size_t idxThis = gIdx == g->size() ? g->get_num_vertices() : get(boost::vertex_index_t(), *g, * * this); + std::size_t idxThis = gIdx == g->size() ? g->get_num_vertices() : get(boost::vertex_index_t(), *g, **this); std::size_t idxOther = other.gIdx == g->size() ? g->get_num_vertices() : get(boost::vertex_index_t(), *g, *other); return idxOther - idxThis; } @@ -336,11 +385,12 @@ template std::pair::vertex_iterator, typename union_graph::vertex_iterator> vertices(const union_graph &g) { auto endIter = typename union_graph::vertex_iterator(&g); - for(std::size_t gIdx = 0; gIdx < g.size(); gIdx++) { - if(num_vertices(g[gIdx]) > 0) { - auto iter = typename union_graph::vertex_iterator(&g, gIdx, vertices(g[gIdx]).first); - return std::make_pair(iter, endIter); - } + auto[gIdx, vIdx] = g.get_gIdx_and_vIdx(0); + assert(vIdx == 0); + (void) vIdx; + if(gIdx != g.size()) { + auto iter = typename union_graph::vertex_iterator(&g, gIdx, vertices(g[gIdx]).first); + return std::make_pair(iter, endIter); } return std::make_pair(endIter, endIter); } @@ -355,15 +405,15 @@ typename union_graph::vertices_size_type num_vertices(const union_graph struct union_graph::edge_iterator -: boost::iterator_facade::edge_iterator, typename union_graph::edge_descriptor, -typename std::iterator_traits::iterator_category, typename union_graph::edge_descriptor> { + : boost::iterator_facade::edge_iterator, typename union_graph::edge_descriptor, + typename std::iterator_traits::iterator_category, typename union_graph::edge_descriptor> { edge_iterator() = default; explicit edge_iterator(const union_graph *g) - : g(g), gIdx(g->size()) { } + : g(g), gIdx(g->size()) {} edge_iterator(const union_graph *g, std::size_t gIdx, typename base_traits::edge_iterator eIter) - : g(g), gIdx(gIdx), eIter(eIter) { } + : g(g), gIdx(gIdx), eIter(eIter) {} private: friend class boost::iterator_core_access; @@ -379,7 +429,7 @@ typename std::iterator_traits::iterator_cat void increment() { // Incrementable Iterator ++eIter; while(eIter == edges((*g)[gIdx]).second) { - gIdx++; + ++gIdx; if(gIdx == g->size()) break; eIter = edges((*g)[gIdx]).first; } @@ -397,11 +447,12 @@ template std::pair::edge_iterator, typename union_graph::edge_iterator> edges(const union_graph &g) { auto endIter = typename union_graph::edge_iterator(&g); - for(std::size_t gIdx = 0; gIdx < g.size(); gIdx++) { - if(num_edges(g[gIdx]) > 0) { - auto iter = typename union_graph::edge_iterator(&g, gIdx, edges(g[gIdx]).first); - return std::make_pair(iter, endIter); - } + auto[gIdx, eIdx] = g.get_gIdx_and_eIdx(0); + assert(eIdx == 0); + (void) eIdx; + if(gIdx != g.size()) { + auto iter = typename union_graph::edge_iterator(&g, gIdx, edges(g[gIdx]).first); + return std::make_pair(iter, endIter); } return std::make_pair(endIter, endIter); } @@ -416,7 +467,8 @@ typename union_graph::edges_size_type num_edges(const union_graph template std::pair::edge_descriptor, bool> -edge(typename union_graph::vertex_descriptor u, typename union_graph::vertex_descriptor v, const union_graph &g) { +edge(typename union_graph::vertex_descriptor u, typename union_graph::vertex_descriptor v, + const union_graph &g) { if(u.gIdx != v.gIdx) return std::make_pair(typename union_graph::edge_descriptor(), false); auto base = edge(u.v, v.v, g[u.gIdx]); return std::make_pair(typename union_graph::edge_descriptor{u.gIdx, base.first}, base.second); @@ -450,22 +502,22 @@ struct union_graph_property_map { using key_type = typename union_graph::type>::vertex_descriptor; using category = typename base_traits::category; public: - - union_graph_property_map(UnionGraph &g) : g(g) { } + union_graph_property_map(UnionGraph &g) : g(g) {} //private: UnionGraph &g; }; template struct property_getter { - static typename union_graph_property_map::value_type - apply(const union_graph_property_map &map, typename union_graph::type>::vertex_descriptor v) { + apply(const union_graph_property_map &map, + typename union_graph::type>::vertex_descriptor v) { return get(Property{}, map.g[v.gIdx], v.v); } static typename union_graph_property_map::value_type - apply(const union_graph_property_map &map, typename union_graph::type>::edge_descriptor e) { + apply(const union_graph_property_map &map, + typename union_graph::type>::edge_descriptor e) { return get(Property{}, map.g[e.gIdx], e.e); } }; @@ -475,7 +527,8 @@ struct property_getter { using Property = boost::vertex_index_t; static typename union_graph_property_map::value_type - apply(const union_graph_property_map &map, typename union_graph::type>::vertex_descriptor v) { + apply(const union_graph_property_map &map, + typename union_graph::type>::vertex_descriptor v) { return get(boost::vertex_index_t(), map.g[v.gIdx], v.v) + map.g.get_vertex_idx_offset(v.gIdx); } }; @@ -485,20 +538,23 @@ struct property_getter { using Property = boost::edge_index_t; static typename union_graph_property_map::value_type - apply(const union_graph_property_map &map, typename union_graph::type>::edge_descriptor e) { + apply(const union_graph_property_map &map, + typename union_graph::type>::edge_descriptor e) { return get(boost::edge_index_t(), map.g[e.gIdx], e.e) + map.g.get_edge_idx_offset(e.gIdx); } }; template typename union_graph_property_map::value_type -get(const union_graph_property_map &map, typename union_graph::type>::vertex_descriptor v) { +get(const union_graph_property_map &map, + typename union_graph::type>::vertex_descriptor v) { return property_getter::apply(map, v); } template typename union_graph_property_map::value_type -get(const union_graph_property_map &map, typename union_graph::type>::edge_descriptor e) { +get(const union_graph_property_map &map, + typename union_graph::type>::edge_descriptor e) { return property_getter::apply(map, e); } @@ -529,11 +585,12 @@ typename boost::property_map, Property>::type get(Property, union template typename boost::property_map, Property>::const_type get(Property, const union_graph &g) { - return detail::union_graph_property_map, Property>(g); + return detail::union_graph_property_map < detail::const_wrapper < G > , Property > (g); } template -typename boost::property_map, Property>::type::value_type get(const Property &p, const union_graph &g, const Key &k) { +typename boost::property_map, Property>::type::value_type +get(const Property &p, const union_graph &g, const Key &k) { return get(get(p, g), k); } @@ -543,18 +600,10 @@ typename boost::property_map, Property>::type::value_type get(con //------------------------------------------------------------------------------ template -typename union_graph::vertex_descriptor vertex(typename union_graph::vertices_size_type vId, const union_graph &g) { - assert(g.size() > 0); - assert(g.get_vertex_idx_offset(0) == 0); - const auto gIdx = [&]() -> std::size_t { - for(std::size_t gIdx = 1; gIdx < g.size(); ++gIdx) { - if(g.get_vertex_idx_offset(gIdx) > vId) return gIdx - 1; - } - return g.size() - 1; - }(); - const auto baseOffset = g.get_vertex_idx_offset(gIdx); - assert(baseOffset <= vId); - return typename union_graph::vertex_descriptor{gIdx, vertex(vId - baseOffset, g[gIdx])}; +typename union_graph::vertex_descriptor +vertex(typename union_graph::vertices_size_type vId, const union_graph &g) { + auto[gIdx, vIdx] = g.get_gIdx_and_vIdx(vId); + return typename union_graph::vertex_descriptor{gIdx, vertex(vIdx, g[gIdx])}; } } // namespace jla_boost diff --git a/libs/jla_boost/include/jla_boost/graph/morphism/callbacks/Print.hpp b/libs/jla_boost/include/jla_boost/graph/morphism/callbacks/Print.hpp index f0a5295..deeeb5a 100644 --- a/libs/jla_boost/include/jla_boost/graph/morphism/callbacks/Print.hpp +++ b/libs/jla_boost/include/jla_boost/graph/morphism/callbacks/Print.hpp @@ -11,7 +11,6 @@ namespace GraphMorphism { template struct PrintCallback { - PrintCallback(Next next) : next(next) { } template diff --git a/libs/jla_boost/include/jla_boost/graph/morphism/finders/vf2.hpp b/libs/jla_boost/include/jla_boost/graph/morphism/finders/vf2.hpp index bca4bdc..850fb5b 100644 --- a/libs/jla_boost/include/jla_boost/graph/morphism/finders/vf2.hpp +++ b/libs/jla_boost/include/jla_boost/graph/morphism/finders/vf2.hpp @@ -19,8 +19,6 @@ #include #include -#include -#include #include #include #include diff --git a/libs/jla_boost/test/vf2.cpp b/libs/jla_boost/test/vf2.cpp index 715207c..3f782eb 100644 --- a/libs/jla_boost/test/vf2.cpp +++ b/libs/jla_boost/test/vf2.cpp @@ -6,11 +6,6 @@ #include #include #include -#include -#include -#include -#include -#include #include @@ -22,6 +17,7 @@ #include #include #include +#include namespace jla_boost { namespace test { @@ -31,21 +27,6 @@ using namespace GM; namespace { -template -struct random_functor { - - random_functor(Generator &g) : g(g) {} - - std::size_t operator()(std::size_t n) { - boost::uniform_int distrib(0, n - 1); - boost::variate_generator > - x(g, distrib); - return x(); - } - - Generator &g; -}; - template void randomly_permute_graph(Graph1 &g1, const Graph2 &g2) { BOOST_REQUIRE(num_vertices(g1) <= num_vertices(g2)); @@ -56,13 +37,12 @@ void randomly_permute_graph(Graph1 &g1, const Graph2 &g2) { typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename graph_traits::edge_iterator edge_iterator; - boost::mt19937 gen; - random_functor rand_fun(gen); + std::mt19937 gen; // Decide new order std::vector orig_vertices; std::copy(vertices(g2).first, vertices(g2).second, std::back_inserter(orig_vertices)); - std::random_shuffle(orig_vertices.begin(), orig_vertices.end(), rand_fun); + std::shuffle(orig_vertices.begin(), orig_vertices.end(), gen); std::map vertex_map; std::size_t i = 0; @@ -92,17 +72,15 @@ void generate_random_digraph(Graph &g, double edge_probability, BOOST_REQUIRE(0 <= max_vertex_name); typedef typename graph_traits::vertex_iterator vertex_iterator; - boost::mt19937 random_gen; - boost::uniform_real dist_real(0.0, 1.0); - boost::variate_generator > - random_real_dist(random_gen, dist_real); + std::mt19937 gen; + std::uniform_real_distribution dist_real(0.0, 1.0); for(vertex_iterator u = vertices(g).first; u != vertices(g).second; ++u) { for(vertex_iterator v = vertices(g).first; v != vertices(g).second; ++v) { - if(random_real_dist() <= edge_probability) { + if(dist_real(gen) <= edge_probability) { add_edge(*u, *v, g); for(int i = 0; i < max_parallel_edges; ++i) { - if(random_real_dist() <= parallel_edge_probability) + if(dist_real(gen) <= parallel_edge_probability) add_edge(*u, *v, g); } } @@ -110,17 +88,18 @@ void generate_random_digraph(Graph &g, double edge_probability, } { - boost::uniform_int dist_int(0, max_edge_name); - boost::variate_generator > - random_int_dist(random_gen, dist_int); + std::uniform_int_distribution dist_int(0, max_edge_name); + const auto random_int_dist = [&dist_int, &gen]() { + return dist_int(gen); + }; randomize_property(g, random_int_dist); } { - boost::uniform_int dist_int(0, max_vertex_name); - boost::variate_generator > - random_int_dist(random_gen, dist_int); - + std::uniform_int_distribution dist_int(0, max_vertex_name); + const auto random_int_dist = [&dist_int, &gen]() { + return dist_int(gen); + }; randomize_property(g, random_int_dist); } diff --git a/libs/libmod/CMakeLists.txt b/libs/libmod/CMakeLists.txt index d954710..bb62bae 100644 --- a/libs/libmod/CMakeLists.txt +++ b/libs/libmod/CMakeLists.txt @@ -48,17 +48,20 @@ target_link_libraries(libmod PRIVATE #$<$:-Wl,--no-undefined> # TODO: is there an equivalent? ) # https://stackoverflow.com/questions/52018092/how-to-set-rpath-and-runpath-with-gcc-ld -target_link_libraries(libmod PRIVATE -Wl,--disable-new-dtags) +target_link_libraries(libmod PRIVATE + $<$:-Wl,--disable-new-dtags> + $<$:-Wl,--disable-new-dtags> + ) target_compile_options(libmod PRIVATE -Wall -Wextra -Wno-unused-parameter -Wno-comment -Wno-sign-compare -Wno-unused-local-typedefs - -Wno-unused-const-variable - -Wno-error=maybe-uninitialized # gives false positive for boost::optional - $<$:-Wno-unused-private-field> + # gives false positive for boost::optional + $<$:-Wno-error=maybe-uninitialized> ) target_compile_options(libmod PUBLIC + -DBOOST_ALLOW_DEPRECATED_HEADERS # until Boost stops using include/boost/detail/iterator.hpp $<$:-Wno-mismatched-tags> $<$:-Wno-mismatched-tags>) set_target_properties(libmod PROPERTIES OUTPUT_NAME "mod") diff --git a/libs/libmod/src/mod/Chem.hpp b/libs/libmod/src/mod/Chem.hpp index 38285f4..1d3adec 100644 --- a/libs/libmod/src/mod/Chem.hpp +++ b/libs/libmod/src/mod/Chem.hpp @@ -1,10 +1,12 @@ -#ifndef MOD_CHEM_H -#define MOD_CHEM_H +#ifndef MOD_CHEM_HPP +#define MOD_CHEM_HPP #include #include #include +#include +#include #include #include @@ -142,6 +144,8 @@ struct MOD_DECL AtomData { // rst: Retrieve the radical status. constexpr bool getRadical() const; friend constexpr bool operator==(const AtomData &a1, const AtomData &a2); + friend constexpr bool operator!=(const AtomData &a1, const AtomData &a2); + friend constexpr bool operator<(const AtomData &a1, const AtomData &a2); // rst: .. function:: friend std::ostream &operator<<(std::ostream &s, const AtomData &data) // rst: // rst: Format the atom data adhering to the string encoding of atoms (see :ref:`mol-enc`). @@ -408,6 +412,15 @@ inline constexpr bool operator==(const AtomData &a1, const AtomData &a2) { && a1.getRadical() == a2.getRadical(); } +inline constexpr bool operator!=(const AtomData &a1, const AtomData &a2) { + return !(a1 == a2); +} + +inline constexpr bool operator<(const AtomData &a1, const AtomData &a2) { + return std::make_tuple(a1.getAtomId(), a1.getIsotope(), a1.getCharge(), a1.getRadical()) + < std::make_tuple(a2.getAtomId(), a2.getIsotope(), a2.getCharge(), a2.getRadical()); +} + } // namespace mod -#endif /* MOD_CHEM_H */ \ No newline at end of file +#endif // MOD_CHEM_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/Config.cpp b/libs/libmod/src/mod/Config.cpp index a96413e..8c937c2 100644 --- a/libs/libmod/src/mod/Config.cpp +++ b/libs/libmod/src/mod/Config.cpp @@ -1,6 +1,6 @@ #include "Config.hpp" -#include +#include #include namespace mod { diff --git a/libs/libmod/src/mod/Config.hpp b/libs/libmod/src/mod/Config.hpp index d09f33b..0e7bea1 100644 --- a/libs/libmod/src/mod/Config.hpp +++ b/libs/libmod/src/mod/Config.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_CONFIG_H -#define MOD_CONFIG_H +#ifndef MOD_CONFIG_HPP +#define MOD_CONFIG_HPP // rst: .. _libmod-config: // rst: @@ -217,13 +217,13 @@ struct Config { Config(Config &&) = delete; Config &operator=(Config &&) = delete; - // BOOST_PP_SEQ( - // BOOST_PP_TUPLE(NamespaceClass, NamespaceName, - // BOOST_PP_SEQ( - // BOOST_PP_TUPLE(Type, Name, DefaultValue) - // ) - // ) - // ) +// BOOST_PP_SEQ( +// BOOST_PP_TUPLE(NamespaceClass, NamespaceName, +// BOOST_PP_SEQ( +// BOOST_PP_TUPLE(Type, Name, DefaultValue) +// ) +// ) +// ) #define MOD_CONFIG_DATA_NS_SIZE() 3 #define MOD_CONFIG_DATA_SETTING_SIZE() 3 @@ -238,12 +238,11 @@ struct Config { ((unsigned int, numThreads, 1)) \ )) \ ((DG, dg, \ + ((bool, useOldRuleApplication, false)) \ ((bool, calculateVerbosePrint, false)) \ - ((bool, onlyProduceMolecules, false)) \ ((bool, putAllProductsInSubset, false)) \ ((bool, dryDerivationPrinting, false)) \ ((bool, derivationDebugOutput, false)) \ - ((bool, ignoreSubset, false)) \ ((bool, disableRepeatFixedPointCheck, false)) \ ((std::string, tikzPictureOption, "scale=\\modDGHyperScale")) \ ((bool, printNonHyper, false)) \ @@ -282,6 +281,8 @@ struct Config { ((bool, composeConstraints, true)) \ ((bool, printMatches, false)) \ ((bool, matchesWithIndex, false)) \ + ((bool, printMatchesOnlyHaxChem, false)) \ + ((int, componentWiseMorphismLimit, 0)) \ )) \ ((Stereo, stereo, \ ((bool, silenceDeductionWarnings, false)) \ @@ -321,7 +322,7 @@ struct Config { #define MOD_toString(s) MOD_toString1(s) #define MOD_toString1(s) #s - BOOST_PP_SEQ_FOR_EACH(MOD_CONFIG_nsIter, ~, MOD_CONFIG_DATA()) +BOOST_PP_SEQ_FOR_EACH(MOD_CONFIG_nsIter, ~, MOD_CONFIG_DATA()) #undef MOD_CONFIG_settingIterCons #undef MOD_CONFIG_settingIter @@ -330,4 +331,4 @@ struct Config { } // namespace mod -#endif /* MOD_CONFIG_H */ +#endif // MOD_CONFIG_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/Error.cpp b/libs/libmod/src/mod/Error.cpp index c17ffe8..e48abfc 100644 --- a/libs/libmod/src/mod/Error.cpp +++ b/libs/libmod/src/mod/Error.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include namespace mod { diff --git a/libs/libmod/src/mod/Error.hpp b/libs/libmod/src/mod/Error.hpp index 55ac590..00a877d 100644 --- a/libs/libmod/src/mod/Error.hpp +++ b/libs/libmod/src/mod/Error.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_ERROR_H -#define MOD_ERROR_H +#ifndef MOD_ERROR_HPP +#define MOD_ERROR_HPP #include @@ -158,9 +158,9 @@ struct MOD_DECL StereoDeductionError : public Exception { MOD_DECL void fatal(std::string function, std::string file, - std::size_t line) __attribute__((__noreturn__)); // TODO: change to C++11 syntax at some point + std::size_t line) __attribute__((__noreturn__)); // TODO: change to C++11 syntax at some point #define MOD_ABORT mod::fatal(__func__, __FILE__, __LINE__) } // namespace mod -#endif /* MOD_ERROR_H */ +#endif // MOD_ERROR_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/Function.cpp b/libs/libmod/src/mod/Function.cpp index e1b9be2..0beb668 100644 --- a/libs/libmod/src/mod/Function.cpp +++ b/libs/libmod/src/mod/Function.cpp @@ -1,7 +1,6 @@ #include "Function.hpp" -namespace mod { -namespace detail_function { +namespace mod::detail_function { void dont_call_only_for_test() { std::function f = []() { @@ -10,5 +9,4 @@ void dont_call_only_for_test() { auto b = fromStdFunction("test", f); } -} // namespace detail_function -} // namespace mod \ No newline at end of file +} // namespace mod::detail_function \ No newline at end of file diff --git a/libs/libmod/src/mod/Function.hpp b/libs/libmod/src/mod/Function.hpp index 43890c5..d47f740 100644 --- a/libs/libmod/src/mod/Function.hpp +++ b/libs/libmod/src/mod/Function.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_FUNCTION_H -#define MOD_FUNCTION_H +#ifndef MOD_FUNCTION_HPP +#define MOD_FUNCTION_HPP // rst: The class template `Function` is used throughout the library to represent // rst: function objects. @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace mod { @@ -114,4 +115,4 @@ std::function toStdFunction(std::shared_ptr> fMod) { } // namespace mod -#endif /* MOD_FUNCTION_H */ \ No newline at end of file +#endif // MOD_FUNCTION_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/GraphConcepts.hpp b/libs/libmod/src/mod/GraphConcepts.hpp new file mode 100644 index 0000000..4096ef4 --- /dev/null +++ b/libs/libmod/src/mod/GraphConcepts.hpp @@ -0,0 +1,136 @@ +#ifndef MOD_GRAPHCONCEPTS_HPP +#define MOD_GRAPHCONCEPTS_HPP + +#include +#include + +#include + +#include + +namespace mod::concepts { + +template +struct Graph { + using GraphHandle = std::conditional_t, GraphT>; + + using Vertex = typename GraphT::Vertex; + BOOST_CONCEPT_ASSERT((boost::DefaultConstructible)); + BOOST_CONCEPT_ASSERT((boost::EqualityComparable)); + BOOST_CONCEPT_ASSERT((boost::LessThanComparable)); + + using Edge = typename GraphT::Edge; + BOOST_CONCEPT_ASSERT((boost::DefaultConstructible)); + BOOST_CONCEPT_ASSERT((boost::EqualityComparable)); + BOOST_CONCEPT_ASSERT((boost::LessThanComparable)); + + using VertexRange = typename GraphT::VertexRange; + using VertexIterator = typename GraphT::VertexIterator; + BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); + static_assert(std::is_convertible_v::value_type, Vertex>); + + using EdgeRange = typename GraphT::EdgeRange; + using EdgeIterator = typename GraphT::EdgeIterator; + BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); + static_assert(std::is_convertible_v::value_type, Edge>); + + using IncidentEdgeRange = typename GraphT::IncidentEdgeRange; + using IncidentEdgeIterator = typename GraphT::IncidentEdgeIterator; + BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); + static_assert(std::is_convertible_v::value_type, Edge>); +public: + BOOST_CONCEPT_USAGE(Graph) { + // Vertex + *s << v; + nSize = v.hash(); + b = bool(v); + b = v.isNull(); + nSize = v.getId(); + gHandle = v.getGraph(); + nSize = v.getDegree(); + ieRangeMut = v.incidentEdges(); + + // Edge + *s << e; + b = bool(e); + b = v.isNull(); + gHandle = e.getGraph(); + vMut = e.source(); + vMut = e.target(); + + // VertexRange + vIterMut = vRange->begin(); + vIterMut = vRange->end(); + + // EdgeRange + eIterMut = eRange->begin(); + eIterMut = eRange->end(); + + // IncidentEdgeRange + ieIterMut = ieRange->begin(); + ieIterMut = ieRange->end(); + + // Graph + nSize = g->numVertices(); + vRangeMut = g->vertices(); + nSize = g->numEdges(); + eRangeMut = g->edges(); + } +private: + const GraphT *g; + const Vertex v; + const Edge e; + const VertexRange *vRange; + const EdgeRange *eRange; + const IncidentEdgeRange *ieRange; +private: + bool b; + std::size_t nSize; + std::ostream *s; + GraphHandle gHandle; + Vertex vMut; + VertexRange vRangeMut; + VertexIterator vIterMut; + EdgeRange eRangeMut; + EdgeIterator eIterMut; + IncidentEdgeRange ieRangeMut; + IncidentEdgeIterator ieIterMut; +}; + + +template +struct LabelledGraph { + BOOST_CONCEPT_ASSERT((Graph)); + using Vertex = typename GraphT::Vertex; + using Edge = typename GraphT::Edge; +public: + BOOST_CONCEPT_USAGE(LabelledGraph) { + // Vertex + str = v.getStringLabel(); + atomId = v.getAtomId(); + isotope = v.getIsotope(); + charge = v.getCharge(); + b = v.getRadical(); + str = v.printStereo(); + str = v.printStereo(printer); + + // Edge + str = e.getStringLabel(); + bondType = e.getBondType(); + } +private: + const Vertex v; + const Edge e; +private: + std::string str; + AtomId atomId; + Isotope isotope; + Charge charge; + bool b; + const graph::Printer printer; + BondType bondType; +}; + +} // namespace mod::concepts + +#endif // MOD_GRAPHCONCEPTS_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/Misc.cpp b/libs/libmod/src/mod/Misc.cpp index 39e9a88..968fe6c 100644 --- a/libs/libmod/src/mod/Misc.cpp +++ b/libs/libmod/src/mod/Misc.cpp @@ -16,6 +16,7 @@ #include #include +#include #include namespace mod { @@ -32,22 +33,6 @@ double rngUniformReal() { return std::uniform_real_distribution(0, 1)(lib::getRng()); } -void post(const std::string &text) { - lib::IO::post() << text << std::endl; -} - -void postChapter(const std::string &chapterTitle) { - lib::IO::post() << "summaryChapter \"" << chapterTitle << "\"" << std::endl; -} - -void postSection(const std::string §ionTitle) { - lib::IO::post() << "summarySection \"" << sectionTitle << "\"" << std::endl; -} - -std::string makeUniqueFilePrefix() { - return lib::IO::getUniqueFilePrefix(); -} - void showDump(const std::string &file) { boost::iostreams::mapped_file_source ifs(file); std::vector data(ifs.begin(), ifs.end()); @@ -55,7 +40,7 @@ void showDump(const std::string &file) { auto jOpt = lib::IO::readJson(data, err); if(!jOpt) throw InputError("Error showing dump: " + err.str()); - lib::IO::log() << std::setw(3) << *jOpt << std::endl; + std::cout << std::setw(3) << *jOpt << std::endl; } void printGeometryGraph() { diff --git a/libs/libmod/src/mod/Misc.hpp b/libs/libmod/src/mod/Misc.hpp index a4d54dc..941eb86 100644 --- a/libs/libmod/src/mod/Misc.hpp +++ b/libs/libmod/src/mod/Misc.hpp @@ -24,18 +24,8 @@ MOD_DECL void rngReseed(unsigned int seed); // rst: :returns: a uniformly random real number between 0 and 1. MOD_DECL double rngUniformReal(); -MOD_DECL void post(const std::string &text); -MOD_DECL void postChapter(const std::string &chapterTitle); -MOD_DECL void postSection(const std::string §ionTitle); - -// rst: .. function:: std::string makeUniqueFilePrefix() -// rst: -// rst: :returns: a unique file prefix from the ``out/`` folder. -MOD_DECL std::string makeUniqueFilePrefix(); - MOD_DECL void showDump(const std::string &file); - MOD_DECL void printGeometryGraph(); diff --git a/libs/libmod/src/mod/Post.cpp b/libs/libmod/src/mod/Post.cpp new file mode 100644 index 0000000..ec65277 --- /dev/null +++ b/libs/libmod/src/mod/Post.cpp @@ -0,0 +1,46 @@ +#include "Post.hpp" + +#include +#include + +#include + +namespace mod::post { + +FileHandle::FileHandle(std::string name) : name(name) { + if(name.find("out/") != 0) + throw LogicError("The file is not in the out/ folder."); + stream.open(name.c_str()); + if(!stream) + throw LogicError("Could not open file '" + name + "'."); +} + +void command(const std::string &text) { + lib::IO::post() << text << std::endl; +} + +void reset() { + lib::IO::postReset(); +} + +void flush() { + lib::IO::post() << std::flush; +} + +void disable() { + lib::IO::postDisable(); +} + +void summaryChapter(const std::string &chapterTitle) { + lib::IO::post() << "summaryChapter \"" << chapterTitle << "\"" << std::endl; +} + +void summarySection(const std::string §ionTitle) { + lib::IO::post() << "summarySection \"" << sectionTitle << "\"" << std::endl; +} + +std::string makeUniqueFilePrefix() { + return lib::IO::getUniqueFilePrefix(); +} + +} // namespace mod::post \ No newline at end of file diff --git a/libs/libmod/src/mod/Post.hpp b/libs/libmod/src/mod/Post.hpp new file mode 100644 index 0000000..58886e2 --- /dev/null +++ b/libs/libmod/src/mod/Post.hpp @@ -0,0 +1,47 @@ +#ifndef MOD_POST_HPP +#define MOD_POST_HPP + +#include + +#include +#include + +namespace mod::post { + +struct MOD_DECL FileHandle { + // throws LogicError if the file can not be opened + explicit FileHandle(std::string name); + + operator std::ostream &() { + return stream; + } + + operator std::string() { + return name; + } + + template + friend std::ostream &operator<<(FileHandle &s, T &&t) { + return s.stream << std::forward(t); + } +public: + std::ofstream stream; + std::string name; +}; + +MOD_DECL void command(const std::string &text); +MOD_DECL void reset(); +MOD_DECL void flush(); +MOD_DECL void disable(); + +MOD_DECL void summaryChapter(const std::string &chapterTitle); +MOD_DECL void summarySection(const std::string §ionTitle); + +// rst: .. function:: std::string makeUniqueFilePrefix() +// rst: +// rst: :returns: a unique file prefix from the ``out/`` folder. +MOD_DECL std::string makeUniqueFilePrefix(); + +} // namespace mod::post + +#endif // MOD_POST_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/Term.cpp b/libs/libmod/src/mod/Term.cpp index aa1b539..942ece9 100644 --- a/libs/libmod/src/mod/Term.cpp +++ b/libs/libmod/src/mod/Term.cpp @@ -5,12 +5,13 @@ #include #include -namespace mod { -namespace Term { +#include + +namespace mod::Term { void mgu(const std::string &left, const std::string &right) { - auto tRawLeftOpt = lib::IO::Term::Read::rawTerm(left, lib::Term::getStrings(), lib::IO::log()); - auto tRawRightOpt = lib::IO::Term::Read::rawTerm(right, lib::Term::getStrings(), lib::IO::log()); + auto tRawLeftOpt = lib::IO::Term::Read::rawTerm(left, lib::Term::getStrings(), std::cout); + auto tRawRightOpt = lib::IO::Term::Read::rawTerm(right, lib::Term::getStrings(), std::cout); if(!tRawLeftOpt || !tRawRightOpt) return; auto tRawLeft = tRawLeftOpt.get(); auto tRawRight = tRawRightOpt.get(); @@ -21,28 +22,27 @@ void mgu(const std::string &left, const std::string &right) { auto addrRight = lib::Term::append(machineTemp, tRawRight, storeMachineTemp); machine.setTemp(machineTemp); addrRight.type = lib::Term::AddressType::Temp; - lib::IO::log() << "=================================================" << std::endl; - lib::IO::Term::Write::wam(machine, lib::Term::getStrings(), lib::IO::log()); - lib::IO::log() << "Left = " << addrLeft << ", Right = " << addrRight << std::endl; - lib::IO::log() << "Most general unifier of" << std::endl + std::cout << "=================================================" << std::endl; + lib::IO::Term::Write::wam(machine, lib::Term::getStrings(), std::cout); + std::cout << "Left = " << addrLeft << ", Right = " << addrRight << std::endl; + std::cout << "Most general unifier of" << std::endl << "\t"; - lib::IO::Term::Write::term(machine, addrLeft, lib::Term::getStrings(), lib::IO::log()); - lib::IO::log() << " =? "; - lib::IO::Term::Write::term(machine, addrRight, lib::Term::getStrings(), lib::IO::log()); - lib::IO::log() << std::endl; - lib::IO::log() << "\t"; - lib::IO::Term::Write::rawTerm(tRawLeft, lib::Term::getStrings(), lib::IO::log()); - lib::IO::log() << " =? "; - lib::IO::Term::Write::rawTerm(tRawRight, lib::Term::getStrings(), lib::IO::log()); - lib::IO::log() << std::endl; + lib::IO::Term::Write::term(machine, addrLeft, lib::Term::getStrings(), std::cout); + std::cout << " =? "; + lib::IO::Term::Write::term(machine, addrRight, lib::Term::getStrings(), std::cout); + std::cout << std::endl; + std::cout << "\t"; + lib::IO::Term::Write::rawTerm(tRawLeft, lib::Term::getStrings(), std::cout); + std::cout << " =? "; + lib::IO::Term::Write::rawTerm(tRawRight, lib::Term::getStrings(), std::cout); + std::cout << std::endl; auto mgu = machine.unifyHeapTemp(addrLeft.addr, addrRight.addr); - lib::IO::Term::Write::wam(machine, lib::Term::getStrings(), lib::IO::log() << "is "); - lib::IO::log() << "Left = " << machine.deref(addrLeft) << ", Right = " << machine.deref(addrRight) << std::endl; + lib::IO::Term::Write::wam(machine, lib::Term::getStrings(), std::cout << "is "); + std::cout << "Left = " << machine.deref(addrLeft) << ", Right = " << machine.deref(addrRight) << std::endl; - lib::IO::Term::Write::mgu(machine, mgu, lib::Term::getStrings(), lib::IO::log()); - lib::IO::log() << std::endl; + lib::IO::Term::Write::mgu(machine, mgu, lib::Term::getStrings(), std::cout); + std::cout << std::endl; } -} // namespace Term -} // namespace mod \ No newline at end of file +} // namespace mod::Term \ No newline at end of file diff --git a/libs/libmod/src/mod/Term.hpp b/libs/libmod/src/mod/Term.hpp index f19d1bb..50455d7 100644 --- a/libs/libmod/src/mod/Term.hpp +++ b/libs/libmod/src/mod/Term.hpp @@ -1,16 +1,14 @@ -#ifndef MOD_UNIFICATION_H -#define MOD_UNIFICATION_H +#ifndef MOD_UNIFICATION_HPP +#define MOD_UNIFICATION_HPP #include #include -namespace mod { -namespace Term { +namespace mod::Term { MOD_DECL void mgu(const std::string &left, const std::string &right); -} // namespace Term -} // namespace mod +} // namespace mod::Term -#endif /* MOD_UNIFICATION_H */ \ No newline at end of file +#endif // MOD_UNIFICATION_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/Builder.cpp b/libs/libmod/src/mod/dg/Builder.cpp index f26af9d..a5092db 100644 --- a/libs/libmod/src/mod/dg/Builder.cpp +++ b/libs/libmod/src/mod/dg/Builder.cpp @@ -13,8 +13,7 @@ #include -namespace mod { -namespace dg { +namespace mod::dg { struct Builder::Pimpl { Pimpl(std::shared_ptr dg_, lib::DG::NonHyperBuilder &dgLib) : dg_(dg_), b(dgLib.build()) {} @@ -82,25 +81,26 @@ ExecuteResult Builder::execute(std::shared_ptr strategy, int verbosity std::vector Builder::apply(const std::vector > &graphs, std::shared_ptr r) { - return apply(graphs, r, 0); + return apply(graphs, r, true, 0); } std::vector Builder::apply(const std::vector > &graphs, - std::shared_ptr r, + std::shared_ptr r, bool onlyProper, int verbosity) { - return apply(graphs, r, verbosity, IsomorphismPolicy::Check); + return apply(graphs, r, onlyProper, verbosity, IsomorphismPolicy::Check); } std::vector Builder::apply(const std::vector > &graphs, - std::shared_ptr r, - int verbosity, - IsomorphismPolicy graphPolicy) { + std::shared_ptr r, bool onlyProper, + int verbosity, IsomorphismPolicy graphPolicy) { check(p); if(std::any_of(graphs.begin(), graphs.end(), [](const auto &p) { return !p; })) throw LogicError("One of the graphs is a null pointer."); if(!r) throw LogicError("The rule is a null pointer."); - auto innerRes = p->b.apply(graphs, r, verbosity, graphPolicy); + auto innerRes = onlyProper + ? p->b.apply(graphs, r, verbosity, graphPolicy) + : p->b.applyRelaxed(graphs, r, verbosity, graphPolicy); std::vector res; const auto &nonHyper = p->dg_->getNonHyper(); const auto &hyper = p->dg_->getHyper(); @@ -149,7 +149,7 @@ ExecuteResult::~ExecuteResult() = default; const std::vector> &ExecuteResult::getSubset() const { if(p->subset.empty()) { - const auto &inner = p->res.getResult().getSubset(0); + const auto &inner = p->res.getResult().getSubset(); p->subset.reserve(inner.size()); for(const auto *g : inner) p->subset.push_back(g->getAPIReference()); @@ -170,5 +170,4 @@ void ExecuteResult::list(bool withUniverse) const { p->res.list(withUniverse); } -} // namespace dg -} // namespace mod +} // namespace mod::dg \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/Builder.hpp b/libs/libmod/src/mod/dg/Builder.hpp index 6c9b7a6..db4a9cc 100644 --- a/libs/libmod/src/mod/dg/Builder.hpp +++ b/libs/libmod/src/mod/dg/Builder.hpp @@ -14,7 +14,8 @@ namespace DG { struct ExecuteResult; } // namespace DG } // namespace lib -namespace dg { +} // namespace mod +namespace mod::dg { // rst-class: dg::Builder // rst: @@ -95,13 +96,16 @@ class MOD_DECL Builder { // rst: .. function:: std::vector apply(const std::vector > &graphs, \ // rst: std::shared_ptr r) // rst: std::vector apply(const std::vector > &graphs, \ - // rst: std::shared_ptr r, \ + // rst: std::shared_ptr r, bool onlyProper, \ // rst: int verbosity) // rst: std::vector apply(const std::vector > &graphs, \ - // rst: std::shared_ptr r, \ + // rst: std::shared_ptr r, bool onlyProper, \ // rst: int verbosity, IsomorphismPolicy graphPolicy) // rst: - // rst: Compute proper direct derivations with `graphs` the left-hand side and `r` as the rule. + // rst: Compute direct derivations using `graphs` for the left-hand side and `r` as the rule. + // rst: + // rst: When `onlyProper` is `true`, then all of `graphs` must be used in each direct derivation. + // rst: The default is `true`. // rst: // rst: The given :var:`graphPolicy` refers to adding the graphs in :var:`graphs`, // rst: and it defaults to :enumerator:`IsomorphismPolicy::Check`. @@ -111,8 +115,8 @@ class MOD_DECL Builder { // rst: // rst: - 0 (or less): no information is printed. // rst: - 2: Print minimal information about graph binding. - // rst: - 10: Print information about morphism generation for rule composition. - // rst: - 20: Print rule composition information. + // rst: - 10: Print information about morphism generation for rule composition. + // rst: - 20: Print rule composition information. // rst: // rst: :returns: a list of hyper edges representing the found direct derivations. // rst: The list may contain duplicates if there are multiple ways of constructing @@ -125,10 +129,10 @@ class MOD_DECL Builder { std::vector apply(const std::vector > &graphs, std::shared_ptr r); std::vector apply(const std::vector > &graphs, - std::shared_ptr r, + std::shared_ptr r, bool onlyProper, int verbosity); std::vector apply(const std::vector > &graphs, - std::shared_ptr r, + std::shared_ptr r, bool onlyProper, int verbosity, IsomorphismPolicy graphPolicy); // rst: .. function:: void addAbstract(const std::string &description) // rst: @@ -194,7 +198,6 @@ class MOD_DECL ExecuteResult { }; // rst-class-end: -} // namespace dg -} // namespace mod +} // namespace mod::dg #endif /* MOD_DG_BUILDER_H */ diff --git a/libs/libmod/src/mod/dg/DG.cpp b/libs/libmod/src/mod/dg/DG.cpp index 492b761..42546ca 100644 --- a/libs/libmod/src/mod/dg/DG.cpp +++ b/libs/libmod/src/mod/dg/DG.cpp @@ -1,7 +1,6 @@ #include "DG.hpp" #include -#include #include #include #include @@ -18,8 +17,9 @@ #include -namespace mod { -namespace dg { +#include + +namespace mod::dg { //------------------------------------------------------------------------------ // DG @@ -165,7 +165,7 @@ const std::vector > &DG::getProducts() const { return getNonHyper().getProducts(); } -std::pair DG::print(const PrintData &data, const Printer &printer) const { +std::pair DG::print(const Printer &printer, const PrintData &data) const { if(data.getDG() != getNonHyper().getAPIReference()) { std::ostringstream err; err << "PrintData is for another derivation graph (id=" << data.getDG()->getId() @@ -183,7 +183,7 @@ std::string DG::dump() const { void DG::listStats() const { if(!p->dg->getHasCalculated()) throw LogicError("No stats can be printed before calculation.\n"); - else p->dg->getHyper().printStats(lib::IO::log()); + else p->dg->getHyper().printStats(std::cout); } //------------------------------------------------------------------------------ @@ -246,5 +246,4 @@ void DG::diff(std::shared_ptr dg1, std::shared_ptr dg2) { lib::DG::NonHyper::diff(dg1->getNonHyper(), dg2->getNonHyper()); } -} // namespace dg -} // namespace mod +} // namespace mod::dg \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/DG.hpp b/libs/libmod/src/mod/dg/DG.hpp index f87ac2f..7344247 100644 --- a/libs/libmod/src/mod/dg/DG.hpp +++ b/libs/libmod/src/mod/dg/DG.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_DG_DG_H -#define MOD_DG_DG_H +#ifndef MOD_DG_DG_HPP +#define MOD_DG_DG_HPP #include #include @@ -11,8 +11,7 @@ #include #include -namespace mod { -namespace dg { +namespace mod::dg { // rst-class: dg::DG // rst: @@ -131,13 +130,13 @@ struct MOD_DECL DG { // rst: // rst: :returns: the list of new graphs discovered by the derivation graph. const std::vector > &getProducts() const; - // rst: .. function:: std::pair print(const PrintData &data, const Printer &printer) const + // rst: .. function:: std::pair print(const Printer &printer, const PrintData &data) const // rst: // rst: Print the derivation graph in style of a hypergraph. // rst: // rst: :returns: the name of the PDF-file that will be compiled in post-processing and the name of the coordinate tex-file used. // rst: :throws: :class:`LogicError` if the print data is not for this DG. - std::pair print(const PrintData &data, const Printer &printer) const; + std::pair print(const Printer &printer, const PrintData &data) const; // rst: .. function:: std::string dump() const // rst: // rst: Exports the derivation graph to a text file, which can be imported. @@ -200,8 +199,8 @@ struct MOD_DECL DG { // rst: In the end the derivation graph is locked. // rst: // rst: .. note:: If the dump to be loaded was made by version 0.10 or earlier, it does not contain the full rules - // rst: but only the rule name. It is then crucial that the names of the given rules match with those used to - // rst: create the dump in the first place. + // rst: but only the rule name. It is then crucial that the names of the given rules match with those used to + // rst: create the dump in the first place. // rst: // rst: The :cpp:var:`verbosity` defaults to level 2. // rst: The levels have the following meaning: @@ -230,7 +229,6 @@ struct MOD_DECL DG { }; // rst-class-end: -} // namespace dg -} // namespace mod +} // namespace mod::dg -#endif /* MOD_DG_DG_H */ +#endif // MOD_DG_DG_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/ForwardDecl.hpp b/libs/libmod/src/mod/dg/ForwardDecl.hpp index b82c17e..b55dc40 100644 --- a/libs/libmod/src/mod/dg/ForwardDecl.hpp +++ b/libs/libmod/src/mod/dg/ForwardDecl.hpp @@ -1,16 +1,15 @@ #ifndef MOD_DG_FORWARDDECL_H #define MOD_DG_FORWARDDECL_H -namespace mod { -namespace dg { +namespace mod::dg { struct Builder; struct DG; struct ExecuteResult; struct PrintData; struct Printer; struct Strategy; -} // namespace dg -namespace lib { +} // namespace mod::dg +namespace mod::lib { namespace DG { struct Hyper; struct NonHyper; @@ -19,15 +18,10 @@ namespace Strategies { struct Strategy; } // namespace Strategies } // namespace DG -namespace IO { -namespace DG { -namespace Write { +namespace IO::DG::Write { struct Data; struct Printer; -} // namespace Write -} // namespace DG -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace IO::DG::Write +} // namespace mod::lib #endif /* MOD_DG_FORWARDDECL_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/GraphInterface.cpp b/libs/libmod/src/mod/dg/GraphInterface.cpp index 49524fd..ddf6cc8 100644 --- a/libs/libmod/src/mod/dg/GraphInterface.cpp +++ b/libs/libmod/src/mod/dg/GraphInterface.cpp @@ -7,16 +7,21 @@ #include #include -namespace mod { -namespace dg { +namespace mod::dg { //------------------------------------------------------------------------------ // Vertex //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Vertex(DG, dg, g->getHyper().getGraph(), g, DG) +MOD_GRAPHPIMPL_Define_Vertex_noGraph(DG, DG, + g->getHyper().getGraph(), g, DG) -MOD_GRAPHPIMPL_Define_Vertex_Directed(DG, dg, g->getHyper().getGraph(), g) +std::shared_ptr DG::Vertex::getDG() const { + if(!g) throw LogicError("Can not get DG on a null vertex."); + return g; +} + +MOD_GRAPHPIMPL_Define_Vertex_Directed(DG, g->getHyper().getGraph(), g) DG::InEdgeRange DG::Vertex::inEdges() const { if(!g) throw LogicError("Can not get in-edges on a null vertex."); @@ -438,5 +443,4 @@ std::size_t DG::RuleRange::size() const { return rs.size(); } -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/GraphInterface.hpp b/libs/libmod/src/mod/dg/GraphInterface.hpp index b0e87ce..d220669 100644 --- a/libs/libmod/src/mod/dg/GraphInterface.hpp +++ b/libs/libmod/src/mod/dg/GraphInterface.hpp @@ -12,8 +12,7 @@ #include -namespace mod { -namespace dg { +namespace mod::dg { // Graph // ----------------------------------------------------------------------------- @@ -611,8 +610,7 @@ inline DG::RuleIterator DG::RuleRange::end() const { return RuleIterator(); } -} // namespace dg -} // namespace mod +} // namespace mod::dg template<> struct std::hash { @@ -628,4 +626,4 @@ struct std::hash { } }; -#endif /* MOD_DG_GRAPHINTERFACE_H */ +#endif /* MOD_DG_GRAPHINTERFACE_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/Printer.cpp b/libs/libmod/src/mod/dg/Printer.cpp index d6d089a..2af4801 100644 --- a/libs/libmod/src/mod/dg/Printer.cpp +++ b/libs/libmod/src/mod/dg/Printer.cpp @@ -10,8 +10,7 @@ #include -namespace mod { -namespace dg { +namespace mod::dg { //------------------------------------------------------------------------------ // PrintData @@ -307,5 +306,4 @@ const std::string &Printer::getGraphvizPrefix() const { return printer->getGraphvizPrefix(); } -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/Printer.hpp b/libs/libmod/src/mod/dg/Printer.hpp index 25f34a4..3fb85ed 100644 --- a/libs/libmod/src/mod/dg/Printer.hpp +++ b/libs/libmod/src/mod/dg/Printer.hpp @@ -7,8 +7,7 @@ #include #include -namespace mod { -namespace dg { +namespace mod::dg { // rst-class: dg::PrintData // rst: @@ -280,7 +279,6 @@ struct MOD_DECL Printer { }; // rst-class-end: -} // namespace dg -} // namespace mod +} // namespace mod::dg -#endif /* MOD_DG_PRINTER_H */ +#endif /* MOD_DG_PRINTER_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/Strategies.cpp b/libs/libmod/src/mod/dg/Strategies.cpp index 0504ba5..a0f80e1 100644 --- a/libs/libmod/src/mod/dg/Strategies.cpp +++ b/libs/libmod/src/mod/dg/Strategies.cpp @@ -16,8 +16,7 @@ #include -namespace mod { -namespace dg { +namespace mod::dg { //------------------------------------------------------------------------------ // GraphState @@ -177,5 +176,4 @@ std::shared_ptr Strategy::makeRepeat(int limit, std::shared_ptr(strategy->getStrategy().clone(), limit))); } -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg \ No newline at end of file diff --git a/libs/libmod/src/mod/dg/Strategies.hpp b/libs/libmod/src/mod/dg/Strategies.hpp index d1ccd29..ed4c39b 100644 --- a/libs/libmod/src/mod/dg/Strategies.hpp +++ b/libs/libmod/src/mod/dg/Strategies.hpp @@ -15,7 +15,8 @@ namespace mod { struct Derivation; template class Function; -namespace dg { +} // namespace mod +namespace mod::dg { // rst-class: dg::Strategy // rst: @@ -140,7 +141,6 @@ struct MOD_DECL Strategy { }; // rst-class-end: -} // namespace dg -} // namespace mod +} // namespace mod::dg #endif /* MOD_DG_STRATEGIES_H */ diff --git a/libs/libmod/src/mod/graph/Automorphism.cpp b/libs/libmod/src/mod/graph/Automorphism.cpp index e257c93..dd1df97 100644 --- a/libs/libmod/src/mod/graph/Automorphism.cpp +++ b/libs/libmod/src/mod/graph/Automorphism.cpp @@ -5,8 +5,7 @@ #include -namespace mod { -namespace graph { +namespace mod::graph { //============================================================================== // Aut @@ -102,5 +101,4 @@ std::ostream &operator<<(std::ostream &s, const Graph::AutGroup &a) { return s; } -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Automorphism.hpp b/libs/libmod/src/mod/graph/Automorphism.hpp index 92b2c1d..038cb99 100644 --- a/libs/libmod/src/mod/graph/Automorphism.hpp +++ b/libs/libmod/src/mod/graph/Automorphism.hpp @@ -6,15 +6,13 @@ #include -namespace mod { -namespace graph { +namespace mod::graph { // rst-class: graph::Graph::Aut // rst: // rst: A class representing an automorphism of a :class:`Graph`. // rst: // rst-class-start: - struct Graph::Aut { Aut(std::shared_ptr g, LabelType lt, bool withStereo, std::size_t i); // rst: .. cpp:function:: Vertex operator[](Vertex v) const @@ -35,16 +33,13 @@ struct Graph::Aut { // rst: A class representing the automorphism group of a :class:`Graph`. // rst: // rst-class-start: - struct Graph::AutGroup { // rst-nested: graph::Graph::AutGroup::Gens // rst: // rst: A random-access range of the generators for the automorphism group. // rst: // rst-nested-start: - struct Gens { - class iterator : public boost::iterator_facade { friend class Gens; iterator() = default; @@ -76,7 +71,6 @@ struct Graph::AutGroup { LabelType lt; bool withStereo; }; - // rst-nested-end: public: // rst: .. function:: AutGroup(std::shared_ptr g, LabelSettings labelSettings) @@ -94,7 +88,6 @@ struct Graph::AutGroup { }; // rst-class-end: -} // namespace graph -} // namespace mod +} // namespace mod::graph #endif /* MOD_GRAPH_AUTOMORPHISM_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/ForwardDecl.hpp b/libs/libmod/src/mod/graph/ForwardDecl.hpp index 959ec3e..687b96d 100644 --- a/libs/libmod/src/mod/graph/ForwardDecl.hpp +++ b/libs/libmod/src/mod/graph/ForwardDecl.hpp @@ -1,24 +1,21 @@ -#ifndef MOD_GRAPH_FORWARDDECL_H -#define MOD_GRAPH_FORWARDDECL_H +#ifndef MOD_GRAPH_FORWARDDECL_HPP +#define MOD_GRAPH_FORWARDDECL_HPP -namespace mod { -namespace graph { +namespace mod::graph { struct Graph; struct GraphLess; struct Printer; -} // namespace graph -namespace lib { -namespace Graph { +} // namespace mod::graph +namespace mod::lib { +template +struct LabelledUnionGraph; +} // namespace mod::lib +namespace mod::lib::Graph { +struct LabelledGraph; struct Single; -} // namespace Graph -namespace IO { -namespace Graph { -namespace Write { +} // namespace mod::lib::Graph +namespace mod::lib::IO::Graph::Write { struct Options; -} // namespace Write -} // namespace Graph -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::Graph::Write -#endif /* MOD_GRAPH_FORWARDDECL_H */ \ No newline at end of file +#endif // MOD_GRAPH_FORWARDDECL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Graph.cpp b/libs/libmod/src/mod/graph/Graph.cpp index f63f131..09c7c4c 100644 --- a/libs/libmod/src/mod/graph/Graph.cpp +++ b/libs/libmod/src/mod/graph/Graph.cpp @@ -1,7 +1,6 @@ #include "Graph.hpp" #include -#include #include #include #include @@ -14,18 +13,17 @@ #include #include +#include #include #include -namespace mod { -namespace graph { +namespace mod::graph { // Graph //------------------------------------------------------------------------------ struct Graph::Pimpl { - Pimpl(std::unique_ptr g) : g(std::move(g)) { assert(this->g); } @@ -34,9 +32,9 @@ struct Graph::Pimpl { std::unique_ptr > externalToInternalIds; }; -Graph::Graph(std::unique_ptr g) : p(new Pimpl(std::move(g))) { } +Graph::Graph(std::unique_ptr g) : p(new Pimpl(std::move(g))) {} -Graph::~Graph() { } +Graph::~Graph() {} std::size_t Graph::getId() const { return p->g->getId(); @@ -175,13 +173,15 @@ void checkTermParsing(const lib::Graph::Single &g, LabelSettings ls) { } // namespace -std::size_t Graph::isomorphism(std::shared_ptr g, std::size_t maxNumMatches, LabelSettings labelSettings) const { +std::size_t +Graph::isomorphism(std::shared_ptr g, std::size_t maxNumMatches, LabelSettings labelSettings) const { checkTermParsing(this->getGraph(), labelSettings); checkTermParsing(g->getGraph(), labelSettings); return lib::Graph::Single::isomorphism(getGraph(), g->getGraph(), maxNumMatches, labelSettings); } -std::size_t Graph::monomorphism(std::shared_ptr g, std::size_t maxNumMatches, LabelSettings labelSettings) const { +std::size_t +Graph::monomorphism(std::shared_ptr g, std::size_t maxNumMatches, LabelSettings labelSettings) const { checkTermParsing(this->getGraph(), labelSettings); checkTermParsing(g->getGraph(), labelSettings); return lib::Graph::Single::monomorphism(getGraph(), g->getGraph(), maxNumMatches, labelSettings); @@ -236,7 +236,8 @@ void Graph::instantiateStereo() const { namespace { -std::shared_ptr handleLoadedGraph(lib::IO::Graph::Read::Data data, const std::string &source, std::ostringstream &err) { +std::shared_ptr +handleLoadedGraph(lib::IO::Graph::Read::Data data, const std::string &source, std::ostringstream &err) { if(!data.g) { throw InputError("Error in graph loading from " + source + ".\n" + err.str()); } @@ -245,10 +246,11 @@ std::shared_ptr handleLoadedGraph(lib::IO::Graph::Read::Data data, const auto numComponents = boost::connected_components(*data.g, cMap.data()); if(numComponents > 1) { throw InputError("Error in graph loading from " + source - + ".\nThe graph is not connected (" + std::to_string(numComponents) + " components)."); + + ".\nThe graph is not connected (" + std::to_string(numComponents) + " components)."); } } - auto gInternal = std::make_unique(std::move(data.g), std::move(data.pString), std::move(data.pStereo)); + auto gInternal = std::make_unique(std::move(data.g), std::move(data.pString), + std::move(data.pStereo)); std::shared_ptr g = Graph::makeGraph(std::move(gInternal), std::move(data.externalToInternalIds)); return g; } @@ -256,20 +258,19 @@ std::shared_ptr handleLoadedGraph(lib::IO::Graph::Read::Data data, const } // namespace std::shared_ptr Graph::graphGMLString(const std::string &data) { - std::istringstream ss(data); std::ostringstream err; - auto gData = lib::IO::Graph::Read::gml(ss, err); + auto gData = lib::IO::Graph::Read::gml(data, err); return handleLoadedGraph(std::move(gData), "inline GML string", err); } std::shared_ptr Graph::graphGML(const std::string &file) { - std::ifstream ifs(file); + boost::iostreams::mapped_file_source ifs(file); std::ostringstream err; if(!ifs) { err << "Could not open graph GML file '" << file << "'.\n"; throw InputError(err.str()); } - auto gData = lib::IO::Graph::Read::gml(ifs, err); + auto gData = lib::IO::Graph::Read::gml({ifs.begin(), ifs.size()}, err); return handleLoadedGraph(std::move(gData), "file, '" + file + "'", err); } @@ -283,25 +284,27 @@ std::shared_ptr Graph::smiles(const std::string &smiles) { return Graph::smiles(smiles, false, SmilesClassPolicy::NoneOnDuplicate); } -std::shared_ptr Graph::smiles(const std::string &smiles, const bool allowAbstract, SmilesClassPolicy classPolicy) { +std::shared_ptr +Graph::smiles(const std::string &smiles, const bool allowAbstract, SmilesClassPolicy classPolicy) { std::ostringstream err; auto gData = lib::IO::Graph::Read::smiles(smiles, err, allowAbstract, classPolicy); return handleLoadedGraph(std::move(gData), "smiles string, '" + smiles + "'", err); } std::shared_ptr Graph::makeGraph(std::unique_ptr g) { - return makeGraph(std::move(g),{}); + return makeGraph(std::move(g), {}); } -std::shared_ptr Graph::makeGraph(std::unique_ptr g, std::map externalToInternalIds) { +std::shared_ptr +Graph::makeGraph(std::unique_ptr g, std::map externalToInternalIds) { if(!g) MOD_ABORT; - std::shared_ptr wrapped = std::shared_ptr (new Graph(std::move(g))); + std::shared_ptr wrapped = std::shared_ptr(new Graph(std::move(g))); wrapped->p->g->setAPIReference(wrapped); if(!externalToInternalIds.empty()) { - wrapped->p->externalToInternalIds = std::make_unique >(std::move(externalToInternalIds)); + wrapped->p->externalToInternalIds = std::make_unique >( + std::move(externalToInternalIds)); } return wrapped; } -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Graph.hpp b/libs/libmod/src/mod/graph/Graph.hpp index 922526b..1fbd7b5 100644 --- a/libs/libmod/src/mod/graph/Graph.hpp +++ b/libs/libmod/src/mod/graph/Graph.hpp @@ -12,8 +12,10 @@ #include namespace mod { -template struct Function; -namespace graph { +template +struct Function; +} // namespace mod +namespace mod::graph { // rst-class: graph::Graph // rst: @@ -25,7 +27,6 @@ namespace graph { // rst: graph interface for this class. // rst: // rst-class-start: - struct MOD_DECL Graph { class Vertex; class Edge; @@ -38,14 +39,6 @@ struct MOD_DECL Graph { public: struct Aut; struct AutGroup; - // rst: .. function:: std::string printStereo() const - // rst: std::string printStereo(const Printer &p) const - // rst: - // rst: Print the stereo configuration for the vertex. - // rst: - // rst: :returns: the name of the PDF-file that will be compiled in post-processing. - std::string printStereo() const; - std::string printStereo(const Printer &p) const; private: // The actual class interface Graph(std::unique_ptr g); Graph(const Graph&) = delete; @@ -270,13 +263,11 @@ struct MOD_DECL Graph { // rst-class-end: struct GraphLess { - bool operator()(std::shared_ptr g1, std::shared_ptr g2) const { return g1->getId() < g2->getId(); } }; -} // namespace graph -} // namespace mod +} // namespace mod::graph #endif /* MOD_GRAPH_GRAPH_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/GraphInterface.cpp b/libs/libmod/src/mod/graph/GraphInterface.cpp index 340e219..cf52e69 100644 --- a/libs/libmod/src/mod/graph/GraphInterface.cpp +++ b/libs/libmod/src/mod/graph/GraphInterface.cpp @@ -9,15 +9,15 @@ #include #include -namespace mod { -namespace graph { +namespace mod::graph { //------------------------------------------------------------------------------ // Vertex //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Vertex(Graph, graph, g->getGraph().getGraph(), g, Graph) -MOD_GRAPHPIMPL_Define_Vertex_Undirected(Graph, graph, g->getGraph().getGraph(), g) +MOD_GRAPHPIMPL_Define_Vertex(Graph, Graph, std::shared_ptr, + g->getGraph().getGraph(), g, Graph) +MOD_GRAPHPIMPL_Define_Vertex_Undirected(Graph, g->getGraph().getGraph(), g) const std::string &Graph::Vertex::getStringLabel() const { if(!g) throw LogicError("Can not get string label on a null vertex."); @@ -77,18 +77,14 @@ std::string Graph::Vertex::printStereo(const Printer &p) const { using boost::vertices; auto v = *(vertices(graph).first + vId); const auto &conf = get_stereo(gLabelled)[v]; - return lib::IO::Stereo::Write::summary(g->getGraph(), v, *conf, p.getOptions()); + return lib::IO::Stereo::Write::summary(g->getGraph(), v, *conf, p.getOptions(), 0, ""); } //------------------------------------------------------------------------------ // Edge //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Indices(Graph, graph, g->getGraph().getGraph(), g, getGraph, Graph) - -BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); -BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); -BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); +MOD_GRAPHPIMPL_Define_Indices(Graph, Graph, std::shared_ptr, g->getGraph().getGraph(), g, Graph) const std::string &Graph::Edge::getStringLabel() const { if(!g) throw LogicError("Can not get string label on a null edge."); @@ -108,5 +104,4 @@ BondType Graph::Edge::getBondType() const { return g->getGraph().getMoleculeState()[e]; } -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/GraphInterface.hpp b/libs/libmod/src/mod/graph/GraphInterface.hpp index 25bca5f..caf8744 100644 --- a/libs/libmod/src/mod/graph/GraphInterface.hpp +++ b/libs/libmod/src/mod/graph/GraphInterface.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_GRAPH_GRAPHINTERFACE_H -#define MOD_GRAPH_GRAPHINTERFACE_H +#ifndef MOD_GRAPH_GRAPHINTERFACE_HPP +#define MOD_GRAPH_GRAPHINTERFACE_HPP // rst: This header contains the definitions for the graph interface for :cpp:class:`graph::Graph`. // rst: @@ -16,7 +16,8 @@ struct AtomId; struct Isotope; struct Charge; enum class BondType; -namespace graph { +} // namespace mod +namespace mod::graph { // Graph // ----------------------------------------------------------------------------- @@ -25,7 +26,6 @@ namespace graph { // rst: // rst: A descriptor of either a vertex in a graph, or a null vertex. // rst-class-start: - struct MOD_DECL Graph::Vertex { Vertex(std::shared_ptr g, std::size_t vId); public: @@ -110,12 +110,7 @@ struct MOD_DECL Graph::Vertex { // rst: // rst: A descriptor of either an edge in a graph, or a null edge. // rst-class-start: - -class MOD_DECL Graph::Edge { - friend class EdgeIterator; - - friend class IncidentEdgeIterator; - +struct MOD_DECL Graph::Edge { Edge(std::shared_ptr g, std::size_t vId, std::size_t eId); public: // rst: .. function:: Edge() @@ -174,11 +169,9 @@ class MOD_DECL Graph::Edge { // rst: An iterator for traversing all vertices in a graph. // rst: It models a forward iterator. // rst-class-start: - class MOD_DECL Graph::VertexIterator : public boost::iterator_facade { friend class Graph; - VertexIterator(std::shared_ptr g); public: // rst: .. function:: VertexIterator() @@ -201,13 +194,11 @@ class MOD_DECL Graph::VertexIterator // rst: // rst: A range of all vertices in a graph. // rst-class-start: - struct Graph::VertexRange { using iterator = VertexIterator; using const_iterator = iterator; private: friend class Graph; - VertexRange(std::shared_ptr g); public: VertexIterator begin() const; @@ -227,11 +218,9 @@ struct Graph::VertexRange { // rst: An iterator for traversing all edges in a graph. // rst: It models a forward iterator. // rst-class-start: - class MOD_DECL Graph::EdgeIterator : public boost::iterator_facade { friend class Graph; - EdgeIterator(std::shared_ptr g); public: // rst: .. function:: EdgeIterator() @@ -240,7 +229,6 @@ class MOD_DECL Graph::EdgeIterator EdgeIterator(); private: friend class boost::iterator_core_access; - Edge dereference() const; bool equal(const EdgeIterator &iter) const; void increment(); @@ -255,13 +243,11 @@ class MOD_DECL Graph::EdgeIterator // rst: // rst: A range of all edges in a graph. // rst-class-start: - struct Graph::EdgeRange { using iterator = EdgeIterator; using const_iterator = iterator; private: friend class Graph; - EdgeRange(std::shared_ptr g); public: EdgeIterator begin() const; @@ -280,11 +266,9 @@ struct Graph::EdgeRange { // rst: An iterator for traversing all edges in a graph. // rst: It models a forward iterator. // rst-class-start: - class MOD_DECL Graph::IncidentEdgeIterator : public boost::iterator_facade { friend class Graph; - IncidentEdgeIterator(std::shared_ptr g, std::size_t vId); public: // rst: .. function:: IncidentEdgeIterator() @@ -293,7 +277,6 @@ class MOD_DECL Graph::IncidentEdgeIterator IncidentEdgeIterator(); private: friend class boost::iterator_core_access; - Edge dereference() const; bool equal(const IncidentEdgeIterator &iter) const; void increment(); @@ -307,13 +290,11 @@ class MOD_DECL Graph::IncidentEdgeIterator // rst: // rst: A range of all incident edges to a vertex in a graph. // rst-class-start: - struct Graph::IncidentEdgeRange { using iterator = IncidentEdgeIterator; using const_iterator = iterator; private: friend class Vertex; - IncidentEdgeRange(std::shared_ptr g, std::size_t vId); public: IncidentEdgeIterator begin() const; @@ -372,18 +353,13 @@ inline Graph::IncidentEdgeIterator Graph::IncidentEdgeRange::end() const { return IncidentEdgeIterator(); } -} // namespace graph -} // namespace mod -namespace std { +} // namespace mod::graph template<> -struct hash { - +struct std::hash { std::size_t operator()(const mod::graph::Graph::Vertex &v) const { return v.hash(); } }; -} // namespace std - -#endif /* MOD_GRAPH_GRAPHINTERFACE_H */ +#endif // MOD_GRAPH_GRAPHINTERFACE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Printer.cpp b/libs/libmod/src/mod/graph/Printer.cpp index 07fb672..2583124 100644 --- a/libs/libmod/src/mod/graph/Printer.cpp +++ b/libs/libmod/src/mod/graph/Printer.cpp @@ -2,8 +2,7 @@ #include -namespace mod { -namespace graph { +namespace mod::graph { //------------------------------------------------------------------------------ // Printer @@ -147,5 +146,4 @@ bool Printer::getMirror() const { return options->mirror; } -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Printer.hpp b/libs/libmod/src/mod/graph/Printer.hpp index bdaeb23..faf305f 100644 --- a/libs/libmod/src/mod/graph/Printer.hpp +++ b/libs/libmod/src/mod/graph/Printer.hpp @@ -6,8 +6,7 @@ #include -namespace mod { -namespace graph { +namespace mod::graph { // rst-class: graph::Printer // rst: @@ -18,7 +17,6 @@ namespace graph { // rst: and may make non-molecules look like molecules. // rst: // rst-class-start: - struct MOD_DECL Printer { // rst: .. function Printer() // rst: @@ -125,7 +123,6 @@ struct MOD_DECL Printer { }; // rst-class-end: -} // namespace graph -} // namespace mod +} // namespace mod::graph #endif /* MOD_GRAPH_PRINTER_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Union.cpp b/libs/libmod/src/mod/graph/Union.cpp new file mode 100644 index 0000000..d31381a --- /dev/null +++ b/libs/libmod/src/mod/graph/Union.cpp @@ -0,0 +1,248 @@ +#include "Union.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace mod::graph { + +struct Union::Pimpl { + friend std::ostream &operator<<(std::ostream &s, const Pimpl &p) { + s << "UnionGraph{"; + bool first = true; + for(const auto &g : p.graphs) { + if(first) first = false; + else s << ", "; + s << g->getName(); + } + return s << "}"; + } +public: + std::vector> graphs; + lib::LabelledUnionGraph g; +}; + +Union::Union() : p(std::make_unique()) {} + +Union::Union(std::vector> graphs) { + auto p = std::unique_ptr(new Pimpl{std::move(graphs), {}}); + for(const auto &gOther : p->graphs) + p->g.push_back(&gOther->getGraph().getLabelledGraph()); + this->p = std::move(p); +} + +Union::Union(std::shared_ptr p) : p(p) {} + +Union::Union(const Union &other) = default; +Union &Union::operator=(const Union &other) = default; +Union::Union(Union &&other) = default; +Union &Union::operator=(Union &&other) = default; + +bool operator==(const Union &a, const Union &b) { + return a.p->graphs == b.p->graphs; +} + +bool operator!=(const Union &a, const Union &b) { + return a.p->graphs != b.p->graphs; +} + +std::ostream &operator<<(std::ostream &s, const Union &ug) { + return s << *ug.p; +} + +std::size_t Union::size() const { + return get_graph(p->g).size(); +} + +Union::const_iterator Union::begin() const { + return p->graphs.begin(); +} + +Union::const_iterator Union::end() const { + return p->graphs.end(); +} + +std::shared_ptr Union::operator[](std::size_t i) const { + if(i >= size()) throw LogicError("Index is out of range."); + return begin()[i]; +} + +std::size_t Union::numVertices() const { + return num_vertices(get_graph(p->g)); +} + +Union::VertexRange Union::vertices() const { + return VertexRange(p); +} + +std::size_t Union::numEdges() const { + return num_edges(get_graph(p->g)); +} + +Union::EdgeRange Union::edges() const { + return EdgeRange(p); +} + + + +//------------------------------------------------------------------------------ +// Vertex +//------------------------------------------------------------------------------ + +MOD_GRAPHPIMPL_Define_Vertex(Union, UnionGraph, Union, + get_graph(p->g), p, const Pimpl) +MOD_GRAPHPIMPL_Define_Vertex_Undirected(Union, get_graph(p->g), p) + +const std::string &Union::Vertex::getStringLabel() const { + if(!p) throw LogicError("Can not get string label on a null vertex."); + const auto &graph = get_graph(p->g); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + return get_string(p->g)[v]; +} + +AtomId Union::Vertex::getAtomId() const { + if(!p) throw LogicError("Can not get atom id on a null vertex."); + const auto &graph = get_graph(p->g); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + return get_molecule(p->g)[v].getAtomId(); +} + +Isotope Union::Vertex::getIsotope() const { + if(!p) throw LogicError("Can not get isotope on a null vertex."); + const auto &graph = get_graph(p->g); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + return get_molecule(p->g)[v].getIsotope(); +} + +Charge Union::Vertex::getCharge() const { + if(!p) throw LogicError("Can not get charge on a null vertex."); + const auto &graph = get_graph(p->g); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + return get_molecule(p->g)[v].getCharge(); +} + +bool Union::Vertex::getRadical() const { + if(!p) throw LogicError("Can not get radical status on a null vertex."); + const auto &graph = get_graph(p->g); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + return get_molecule(p->g)[v].getRadical(); +} + +//------------------------------------------------------------------------------ + +std::string Union::Vertex::printStereo() const { + Printer p; + p.setMolDefault(); + p.setWithIndex(true); + p.setCollapseHydrogens(false); + p.setSimpleCarbons(false); + return printStereo(p); +} + +std::string Union::Vertex::printStereo(const Printer &p) const { + if(!this->p) throw LogicError("Can not print stereo on a null vertex."); + const auto &gLabelled = this->p->g; + const auto &graph = get_graph(gLabelled); + using boost::vertices; + // note, the Boost.Iterator library implements [] through returning proxy objects + const auto v = *std::next(vertices(graph).first, vId); + const auto &conf = get_stereo(gLabelled)[v]; + const auto vInner = v.v; + const auto gIdx = v.gIdx; + const auto &gInner = this->p->graphs[gIdx]->getGraph(); + return lib::IO::Stereo::Write::summary( + gInner, vInner, *conf, p.getOptions(), graph.get_vertex_idx_offset(gIdx), + " (" + boost::lexical_cast(*this)) + ")"; +} + +int Union::Vertex::getGraphIndex() const { + if(!this->p) throw LogicError("Can not get graph index of a null vertex."); + const auto &graph = get_graph(this->p->g); + using boost::vertices; + // note, the Boost.Iterator library implements [] through returning proxy objects + const auto v = *std::next(vertices(graph).first, vId); + return v.gIdx; +} + +Graph::Vertex Union::Vertex::getVertex() const { + if(!this->p) throw LogicError("Can not get graph vertex of a null vertex."); + const auto &graph = get_graph(this->p->g); + using boost::vertices; + // note, the Boost.Iterator library implements [] through returning proxy objects + const auto v = *std::next(vertices(graph).first, vId); + const auto gExtInner = this->p->graphs[v.gIdx]; + const auto &gInner = gExtInner->getGraph().getGraph(); + return Graph::Vertex(gExtInner, get(boost::vertex_index_t(), gInner, v.v)); +} + + +//------------------------------------------------------------------------------ +// Edge +//------------------------------------------------------------------------------ + +MOD_GRAPHPIMPL_Define_Indices(Union, UnionGraph, Union, + get_graph(p->g), p, const Pimpl) + +BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); +BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); +BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); + +const std::string &Union::Edge::getStringLabel() const { + if(!this->p) throw LogicError("Can not get string label on a null edge."); + const auto &gLabelled = this->p->g; + const auto &graph = get_graph(gLabelled); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + const auto e = out_edges(v, graph).first[eId]; + return get_string(p->g)[e]; +} + +BondType Union::Edge::getBondType() const { + if(!this->p) throw LogicError("Can not get bond type on a null edge."); + const auto &gLabelled = this->p->g; + const auto &graph = get_graph(gLabelled); + using boost::vertices; + const auto v = vertices(graph).first[vId]; + const auto e = out_edges(v, graph).first[eId]; + return get_molecule(p->g)[e]; +} + +int Union::Edge::getGraphIndex() const { + if(!this->p) throw LogicError("Can not get graph index of a null edge."); + const auto &graph = get_graph(this->p->g); + using boost::vertices; + // note, the Boost.Iterator library implements [] through returning proxy objects + const auto v = *std::next(vertices(graph).first, vId); + return v.gIdx; +} + +Graph::Edge Union::Edge::getEdge() const { + if(!this->p) throw LogicError("Can not get graph vertex of a null edge."); + const auto &graph = get_graph(this->p->g); + using boost::vertices; + // note, the Boost.Iterator library implements [] through returning proxy objects + const auto v = *std::next(vertices(graph).first, vId); + const auto gExtInner = this->p->graphs[v.gIdx]; + const auto &gInner = gExtInner->getGraph().getGraph(); + return Graph::Edge(gExtInner, get(boost::vertex_index_t(), gInner, v.v), eId); +} + +} // namespace mod::graph \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/Union.hpp b/libs/libmod/src/mod/graph/Union.hpp new file mode 100644 index 0000000..f659007 --- /dev/null +++ b/libs/libmod/src/mod/graph/Union.hpp @@ -0,0 +1,482 @@ +#ifndef MOD_GRAPH_UNION_HPP +#define MOD_GRAPH_UNION_HPP + +#include +#include +#include + +#include + +#include +#include + +namespace mod { +struct AtomId; +struct Isotope; +struct Charge; +enum class BondType; +} // namespace mod +namespace mod::graph { + +// rst-class: graph::Union +// rst: +// rst: An adaptor for a multiset of :class:`Graph`\ s to present them +// rst: as their disjoint union. +// rst-class-start: +struct MOD_DECL Union { + class Vertex; + class Edge; + class VertexIterator; + class VertexRange; + class EdgeIterator; + class EdgeRange; + class IncidentEdgeIterator; + class IncidentEdgeRange; +private: + struct Pimpl; + Union(std::shared_ptr p); +public: + // rst: .. type:: const_iterator + // rst: iterator = const_iterator + // rst: + // rst: A random-access iterator over the :class:`Graph`\ s adapted by this object. + using const_iterator = std::vector>::const_iterator; + using iterator = const_iterator; +public: + // rst: .. function:: Union() + // rst: + // rst: Construct an empty graph. + Union(); + // rst: .. function:: explicit Union(std::vector> graphs) + // rst: + // rst: Construct a graph representing the disjoint union of `graphs`. + explicit Union(std::vector> graphs); + Union(const Union &other); + Union &operator=(const Union &other); + Union(Union &&other); + Union &operator=(Union &&other); + MOD_DECL friend bool operator==(const Union &a, const Union &b); + MOD_DECL friend bool operator!=(const Union &a, const Union &b); + // rst: .. function:: friend std::ostream &operator<<(std::ostream &s, const Union &ug) + MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Union &ug); + // rst: .. function:: std::size_t size() const + // rst: + // rst: :returns: the number of adapted graphs. + std::size_t size() const; + // rst: .. function:: const_iterator begin() const + // rst: const_iterator end() const + // rst: + // rst: :returns: the range of graphs adapted by this object. + const_iterator begin() const; + const_iterator end() const; + // rst: .. function:: std::shared_ptr operator[](std::size_t i) const + // rst: + // rst: :returns: the `i`\ th adapted graph. + // rst: :throws: :class:`LogicError` if `i` is out of range. + std::shared_ptr operator[](std::size_t i) const; +public: + // rst: .. function:: std::size_t numVertices() const + // rst: + // rst: :returns: the number of vertices in the graph. + std::size_t numVertices() const; + // rst: .. function:: VertexRange vertices() const + // rst: + // rst: :returns: a range of all vertices in the graph. + VertexRange vertices() const; + // rst: .. function:: std::size_t numEdges() const + // rst: + // rst: :returns: the number of edges in the graph. + std::size_t numEdges() const; + // rst: .. function:: EdgeRange edges() const + // rst: + // rst: :returns: a range of all edges in the graph. + EdgeRange edges() const; +private: + std::shared_ptr p; +}; +// rst-class-end: + + +// Graph +// ----------------------------------------------------------------------------- + +// rst-class: graph::Union::Vertex +// rst: +// rst: A descriptor of either a vertex in a union graph, or a null vertex. +// rst-class-start: +struct MOD_DECL Union::Vertex { + Vertex(std::shared_ptr p, std::size_t vId); +public: + // rst: .. function:: Vertex() + // rst: + // rst: Constructs a null descriptor. + Vertex(); + MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Vertex &v); + MOD_DECL friend bool operator==(const Vertex &v1, const Vertex &v2); + MOD_DECL friend bool operator!=(const Vertex &v1, const Vertex &v2); + MOD_DECL friend bool operator<(const Vertex &v1, const Vertex &v2); + std::size_t hash() const; + // rst: .. function:: explicit operator bool() const + // rst: + // rst: :returns: :cpp:expr:`!isNull()` + explicit operator bool() const; + // rst: .. function:: bool isNull() const + // rst: + // rst: :returns: whether this is a null descriptor or not. + bool isNull() const; + // rst: .. function:: std::size_t getId() const + // rst: + // rst: :returns: the index of the vertex. It will be in the range :math:`[0, numVertices[`. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::size_t getId() const; + // rst: .. function:: Union getGraph() const + // rst: + // rst: :returns: the union graph the vertex belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Union getGraph() const; + // rst: .. function:: std::size_t getDegree() const + // rst: + // rst: :returns: the degree of the vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::size_t getDegree() const; + // rst: .. function:: IncidentEdgeRange incidentEdges() const + // rst: + // rst: :returns: a range of incident edges to this vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + IncidentEdgeRange incidentEdges() const; + // rst: .. function:: const std::string &getStringLabel() const + // rst: + // rst: :returns: the string label of the vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + const std::string &getStringLabel() const; + // rst: .. function:: AtomId getAtomId() const + // rst: + // rst: :returns: the atom id of the vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + AtomId getAtomId() const; + // rst: .. function:: Isotope getIsotope() const + // rst: + // rst: :returns: the isotope of the vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Isotope getIsotope() const; + // rst: .. function:: Charge getCharge() const + // rst: + // rst: :returns: the charge of the vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Charge getCharge() const; + // rst: .. function:: bool getRadical() const + // rst: + // rst: :returns: the radical status of the vertex. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + bool getRadical() const; + // rst: .. function:: std::string printStereo() const + // rst: std::string printStereo(const Printer &p) const + // rst: + // rst: Print the stereo configuration for the vertex. + // rst: + // rst: :returns: the name of the PDF-file that will be compiled in post-processing. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::string printStereo() const; + std::string printStereo(const Printer &p) const; + // rst: .. function:: int getGraphIndex() const + // rst: + // rst: :returns: The index of the graph in the owning :class:`Union` graph this vertex + // rst: is from. The index is thus in the range :math:`[0, len(getGraph())[`. + // rst: + // rst: We can obtain the underlying :class:`Graph` this vertex + // rst: is from both directly via `getVertex()` as `getVertex().getGraph()`, + // rst: or via the graph index as ``getGraph()[getGraphIndex()]``. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + int getGraphIndex() const; + // rst: .. function:: int getVertex() const + // rst: + // rst: :returns: The underlying :class:`Graph::Vertex` this vertex represents. + // rst: + // rst: We can obtain the underlying :class:`Graph` this vertex + // rst: is from both directly via `getVertex()` as `getVertex().getGraph()`, + // rst: or via the graph index as ``getGraph()[getGraphIndex()]``. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Graph::Vertex getVertex() const; +private: + std::shared_ptr p; + std::size_t vId; +}; +// rst-class-end: + +// rst-class: graph::Union::Edge +// rst: +// rst: A descriptor of either an edge in a union graph, or a null edge. +// rst-class-start: +class MOD_DECL Union::Edge { + friend class EdgeIterator; + friend class IncidentEdgeIterator; + Edge(std::shared_ptr p, std::size_t vId, std::size_t eId); +public: + // rst: .. function:: Edge() + // rst: + // rst: Constructs a null descriptor. + Edge(); + MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Edge &e); + MOD_DECL friend bool operator==(const Edge &e1, const Edge &e2); + MOD_DECL friend bool operator!=(const Edge &e1, const Edge &e2); + MOD_DECL friend bool operator<(const Edge &e1, const Edge &e2); + // rst: .. function:: explicit operator bool() const + // rst: + // rst: :returns: :cpp:expr:`!isNull()` + explicit operator bool() const; + // rst: .. function:: bool isNull() const + // rst: + // rst: :returns: whether this is a null descriptor or not. + bool isNull() const; + // rst: .. function:: Union getGraph() const + // rst: + // rst: :returns: the graph the edge belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Union getGraph() const; + // rst: .. function:: Vertex source() const + // rst: + // rst: :returns: the source vertex of the edge. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Vertex source() const; + // rst: .. function:: Vertex target() const + // rst: + // rst: :returns: the target vertex of the edge. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Vertex target() const; + // rst: .. function:: const std::string &getStringLabel() const + // rst: + // rst: :returns: the string label of the edge. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + const std::string &getStringLabel() const; + // rst: .. function:: BondType getBondType() const + // rst: + // rst: :returns: the bond type of the edge. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + BondType getBondType() const; + // rst: .. function:: int getGraphIndex() const + // rst: + // rst: :returns: The index of the graph in the owning :class:`Union` graph this e + // rst: is from. The index is thus in the range :math:`[0, len(getGraph())[`. + // rst: + // rst: We can obtain the underlying :class:`Graph` this edge + // rst: is from both directly via `getEdge()` as `getEdge().getGraph()`, + // rst: or via the graph index as ``getGraph()[getGraphIndex()]``. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + int getGraphIndex() const; + // rst: .. function:: int getEdge() const + // rst: + // rst: :returns: The underlying :class:`Graph::Vertex` this vertex represents. + // rst: + // rst: We can obtain the underlying :class:`Graph` this edge + // rst: is from both directly via `getEdge()` as `getEdge().getGraph()`, + // rst: or via the graph index as ``getGraph()[getGraphIndex()]``. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + Graph::Edge getEdge() const; +private: + std::shared_ptr p; + std::size_t vId, eId; +}; +// rst-class-end: + + +// VertexList +// ----------------------------------------------------------------------------- + +// rst-class: graph::Union::VertexIterator +// rst: +// rst: An iterator for traversing all vertices in a union graph. +// rst: It models a forward iterator. +// rst-class-start: +class MOD_DECL Union::VertexIterator + : public boost::iterator_facade { + friend class Union; + VertexIterator(std::shared_ptr p); +public: + // rst: .. function:: VertexIterator() + // rst: + // rst: Construct a past-the-end iterator. + VertexIterator(); +private: + friend class boost::iterator_core_access; + Vertex dereference() const; + bool equal(const VertexIterator &iter) const; + void increment(); +private: + std::shared_ptr p; + std::size_t vId; +}; +// rst-class-end: + +// rst-class: graph::Union::VertexRange +// rst: +// rst: A range of all vertices in a union graph. +// rst-class-start: +struct Union::VertexRange { + using iterator = VertexIterator; + using const_iterator = iterator; +private: + friend class Union; + VertexRange(std::shared_ptr p); +public: + VertexIterator begin() const; + VertexIterator end() const; + Vertex operator[](std::size_t i) const; +private: + std::shared_ptr p; +}; +// rst-class-end: + + +// EdgeList +// ----------------------------------------------------------------------------- + +// rst-class: graph::Union::EdgeIterator +// rst: +// rst: An iterator for traversing all edges in a union graph. +// rst: It models a forward iterator. +// rst-class-start: +class MOD_DECL Union::EdgeIterator + : public boost::iterator_facade { + friend class Union; + EdgeIterator(std::shared_ptr p); +public: + // rst: .. function:: EdgeIterator() + // rst: + // rst: Construct a past-the-end iterator. + EdgeIterator(); +private: + friend class boost::iterator_core_access; + Edge dereference() const; + bool equal(const EdgeIterator &iter) const; + void increment(); + void advanceToValid(); +private: + std::shared_ptr p; + std::size_t vId, eId; +}; +// rst-class-end: + +// rst-class: graph::Union::EdgeRange +// rst: +// rst: A range of all edges in a union graph. +// rst-class-start: +struct Union::EdgeRange { + using iterator = EdgeIterator; + using const_iterator = iterator; +private: + friend class Union; + EdgeRange(std::shared_ptr p); +public: + EdgeIterator begin() const; + EdgeIterator end() const; +private: + std::shared_ptr p; +}; +// rst-class-end: + + +// Incidence +// ----------------------------------------------------------------------------- + +// rst-class: graph::Union::IncidnetEdgeIterator +// rst: +// rst: An iterator for traversing all edges in a union graph. +// rst: It models a forward iterator. +// rst-class-start: +class MOD_DECL Union::IncidentEdgeIterator + : public boost::iterator_facade { + friend class Union; + IncidentEdgeIterator(std::shared_ptr p, std::size_t vId); +public: + // rst: .. function:: IncidentEdgeIterator() + // rst: + // rst: Construct a past-the-end iterator. + IncidentEdgeIterator(); +private: + friend class boost::iterator_core_access; + Edge dereference() const; + bool equal(const IncidentEdgeIterator &iter) const; + void increment(); +private: + std::shared_ptr p; + std::size_t vId, eId; +}; +// rst-class-end: + +// rst-class: graph::Union::IncidentEdgeRange +// rst: +// rst: A range of all incident edges to a vertex in a union graph. +// rst-class-start: +struct Union::IncidentEdgeRange { + using iterator = IncidentEdgeIterator; + using const_iterator = iterator; +private: + friend class Vertex; + IncidentEdgeRange(std::shared_ptr p, std::size_t vId); +public: + IncidentEdgeIterator begin() const; + IncidentEdgeIterator end() const; +private: + std::shared_ptr p; + std::size_t vId; +}; +// rst-class-end: + + +//------------------------------------------------------------------------------ +// Implementation Details +//------------------------------------------------------------------------------ + +// VertexRange +//------------------------------------------------------------------------------ + +inline Union::VertexRange::VertexRange(std::shared_ptr p) : p(p) {} + +inline Union::VertexIterator Union::VertexRange::begin() const { + return VertexIterator(p); +} + +inline Union::VertexIterator Union::VertexRange::end() const { + return VertexIterator(); +} + +inline Union::Vertex Union::VertexRange::operator[](std::size_t i) const { + return Vertex(p, i); // it will convert to a null descriptor if out of range +} + +// EdgeRange +//------------------------------------------------------------------------------ + +inline Union::EdgeRange::EdgeRange(std::shared_ptr p) : p(p) {} + +inline Union::EdgeIterator Union::EdgeRange::begin() const { + return EdgeIterator(p); +} + +inline Union::EdgeIterator Union::EdgeRange::end() const { + return EdgeIterator(); +} + +// IncidentEdgeRange +//------------------------------------------------------------------------------ + +inline Union::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr p, std::size_t vId) : p(p), vId(vId) {} + +inline Union::IncidentEdgeIterator Union::IncidentEdgeRange::begin() const { + return IncidentEdgeIterator(p, vId); +} + +inline Union::IncidentEdgeIterator Union::IncidentEdgeRange::end() const { + return IncidentEdgeIterator(); +} + +} // namespace mod::graph + +template<> +struct std::hash { + std::size_t operator()(const mod::graph::Union::Vertex &v) const { + return v.hash(); + } +}; + +#endif // MOD_GRAPH_UNION_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/internal/ForwardDecl.hpp b/libs/libmod/src/mod/graph/internal/ForwardDecl.hpp index e4f6272..2583ace 100644 --- a/libs/libmod/src/mod/graph/internal/ForwardDecl.hpp +++ b/libs/libmod/src/mod/graph/internal/ForwardDecl.hpp @@ -3,12 +3,14 @@ #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::graph { +struct Graph; +} // namespace mod::graph +namespace mod::lib::Graph { struct Single; -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph +namespace mod::lib::IO::Graph::Write { +struct Options; +} // namespace mod::lib::IO::Graph::Write #endif // MOD_GRAPH_INTERNAL_FORWARDDECL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/internal/Graph.cpp b/libs/libmod/src/mod/graph/internal/Graph.cpp index b1a2d2b..82d5641 100644 --- a/libs/libmod/src/mod/graph/internal/Graph.cpp +++ b/libs/libmod/src/mod/graph/internal/Graph.cpp @@ -1,17 +1,73 @@ #include "Graph.hpp" +#include #include #include +#include #include +#include -namespace mod { -namespace graph { -namespace internal { +namespace mod::graph::internal { + +// Graph +// ---------------------------------------------------------------------------- + +const lib::Graph::GraphType &getGraph(const lib::Graph::Single &g) { + return g.getGraph(); +} const lib::Graph::LabelledGraph &getLabelledGraph(const lib::Graph::Single &g) { return g.getLabelledGraph(); } +std::unique_ptr makePropString(const lib::Graph::GraphType &g) { + return std::make_unique(g); +} + +void add(lib::Graph::PropString &pString, boost::graph_traits::vertex_descriptor v, + const std::string &value) { + pString.addVertex(v, value); +} + +void add(lib::Graph::PropString &pString, boost::graph_traits::edge_descriptor e, + const std::string &value) { + pString.addEdge(e, value); +} + +std::shared_ptr makeGraph( + std::unique_ptr g, + std::unique_ptr pString, + std::unique_ptr pStereo) { + auto gLib = std::make_unique(std::move(g), std::move(pString), std::move(pStereo)); + return graph::Graph::makeGraph(std::move(gLib)); +} + +std::string writePDF(const lib::Graph::Single &g, const mod::lib::IO::Graph::Write::Options &options) { + return lib::IO::Graph::Write::pdf(g, options); +} + +// LabelledGraph +// ---------------------------------------------------------------------------- + +const lib::Graph::GraphType &getGraph(const lib::Graph::LabelledGraph &g) { + return get_graph(g); +} + +const std::string &getString( + boost::graph_traits::vertex_descriptor v, + const lib::Graph::LabelledGraph &g) { + return get_string(g)[v]; +} + +const std::string &getString( + boost::graph_traits::edge_descriptor e, + const lib::Graph::LabelledGraph &g) { + return get_string(g)[e]; +} + +// LabelledUnionGraph +// ---------------------------------------------------------------------------- + void push_back(lib::LabelledUnionGraph &ug, const lib::Graph::LabelledGraph *g) { ug.push_back(g); } @@ -45,6 +101,4 @@ BondType getMolecule( return get_molecule(g)[e]; } -} // namespace internal -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph::internal \ No newline at end of file diff --git a/libs/libmod/src/mod/graph/internal/Graph.hpp b/libs/libmod/src/mod/graph/internal/Graph.hpp index 6d32273..cfd5001 100644 --- a/libs/libmod/src/mod/graph/internal/Graph.hpp +++ b/libs/libmod/src/mod/graph/internal/Graph.hpp @@ -6,12 +6,31 @@ #include #include -namespace mod { -namespace graph { -namespace internal { +namespace mod::graph::internal { // Graph +MOD_DECL const lib::Graph::GraphType &getGraph(const lib::Graph::Single &g); MOD_DECL const lib::Graph::LabelledGraph &getLabelledGraph(const lib::Graph::Single &g); +MOD_DECL std::unique_ptr makePropString(const lib::Graph::GraphType &g); +MOD_DECL void add(lib::Graph::PropString &pString, boost::graph_traits::vertex_descriptor v, + const std::string &value); +MOD_DECL void add(lib::Graph::PropString &pString, boost::graph_traits::edge_descriptor e, + const std::string &value); +MOD_DECL std::shared_ptr makeGraph( + std::unique_ptr g, + std::unique_ptr pString, + std::unique_ptr pStereo); + +MOD_DECL std::string writePDF(const lib::Graph::Single &g, const mod::lib::IO::Graph::Write::Options &options); + +// LablledGraph +MOD_DECL const lib::Graph::GraphType &getGraph(const lib::Graph::LabelledGraph &g); +MOD_DECL const std::string &getString( + boost::graph_traits::vertex_descriptor v, + const lib::Graph::LabelledGraph &g); +MOD_DECL const std::string &getString( + boost::graph_traits::edge_descriptor e, + const lib::Graph::LabelledGraph &g); // LabelledUnionGraph MOD_DECL void push_back(lib::LabelledUnionGraph &ug, const lib::Graph::LabelledGraph *g); @@ -33,8 +52,6 @@ MOD_DECL BondType getMolecule( boost::graph_traits::GraphType>::edge_descriptor e, const lib::LabelledUnionGraph &g); -} // namespace internal -} // namespace graph -} // namespace mod +} // namespace mod::graph::internal #endif // MOD_GRAPH_INTERNAL_GRAPH_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Chem/OBabel.cpp b/libs/libmod/src/mod/lib/Chem/OBabel.cpp index 03315b1..7b8f5a3 100644 --- a/libs/libmod/src/mod/lib/Chem/OBabel.cpp +++ b/libs/libmod/src/mod/lib/Chem/OBabel.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include #include @@ -31,9 +30,7 @@ #include -namespace mod { -namespace lib { -namespace Chem { +namespace mod::lib::Chem { struct OBMolHandle::Pimpl { std::unique_ptr m; @@ -82,9 +79,9 @@ double OBMolHandle::getMolarMass() const { double OBMolHandle::getEnergy() const { auto &mol = const_cast (*p->m); // becuase bah if(getConfig().obabel.verbose.get()) - IO::log() << "OBabel energy: '" << mol.GetTitle() << "'" - << "\t" << mol.NumAtoms() << " atoms\t" << mol.NumBonds() << " bonds" - << std::endl; + std::cout << "OBabel energy: '" << mol.GetTitle() << "'" + << "\t" << mol.NumAtoms() << " atoms\t" << mol.NumBonds() << " bonds" + << std::endl; // code originally from GGL OpenBabel::OBForceField *pFF = nullptr; @@ -93,7 +90,7 @@ double OBMolHandle::getEnergy() const { unsigned int geomSteps = 100; { // gen3D stuff - if(getConfig().obabel.verbose.get()) IO::log() << "\tgen 3D" << std::endl; + if(getConfig().obabel.verbose.get()) std::cout << "\tgen 3D" << std::endl; pFF = OpenBabel::OBForceField::FindForceField("MMFF94"); assert(pFF); OpenBabel::OBBuilder builder; @@ -102,7 +99,7 @@ double OBMolHandle::getEnergy() const { const bool setupOK = pFF->Setup(mol); if(!setupOK) { - IO::log() << "ERROR: Setup of Open Babel forcefield failed, using 0 as energy." << std::endl; + std::cout << "ERROR: Setup of Open Babel forcefield failed, using 0 as energy." << std::endl; return 0; } @@ -119,7 +116,7 @@ double OBMolHandle::getEnergy() const { } { // conformer stuff - if(getConfig().obabel.verbose.get()) IO::log() << "\tconformer" << std::endl; + if(getConfig().obabel.verbose.get()) std::cout << "\tconformer" << std::endl; pFF = OpenBabel::OBForceField::FindForceField("MMFF94"); assert(pFF); const bool setupOK = pFF->Setup(mol); @@ -132,7 +129,7 @@ double OBMolHandle::getEnergy() const { } // calculate energy - if(getConfig().obabel.verbose.get()) IO::log() << "\tenergy" << std::endl; + if(getConfig().obabel.verbose.get()) std::cout << "\tenergy" << std::endl; double energy = pFF->Energy(false); // calculate appropriate unit scaling @@ -152,7 +149,7 @@ void OBMolHandle::print2Dsvg(std::ostream &s) const { conv.AddOption("h"); conv.Write(p->m.get(), &s); // conv.SetOutFormat("smi"); - // conv.Write(&mol, &IO::log()); + // conv.Write(&mol, &std::cout); } double OBMolHandle::getCoordScaling() const { @@ -208,12 +205,12 @@ void generateCoordinates(OpenBabel::OBMol &mol) { OpenBabel::OBOp *op = OpenBabel::OBOp::FindType("gen2D"); if(!op) { std::cerr << "MØD Error: Could not load Open Babel gen2D operation." - " This can happen if the MØD library or an extension library was loaded with dlopen," - " but without the RTLD_GLOBAL flag. If you are executing from Python then you can insert\n" - "\timport ctypes\n" - "\timport sys\n" - "\tsys.setdlopenflags(sys.getdlopenflags() | ctypes.RTLD_GLOBAL)\n" - "before importing any modules. If this does not work, please open an issue.\n"; + " This can happen if the MØD library or an extension library was loaded with dlopen," + " but without the RTLD_GLOBAL flag. If you are executing from Python then you can insert\n" + "\timport ctypes\n" + "\timport sys\n" + "\tsys.setdlopenflags(sys.getdlopenflags() | ctypes.RTLD_GLOBAL)\n" + "before importing any modules. If this does not work, please open an issue.\n"; std::exit(1); } bool res = op->Do(&mol); @@ -222,10 +219,11 @@ void generateCoordinates(OpenBabel::OBMol &mol) { template OBMolHandle makeOBMolImpl(const Graph &g, - std::function::vertex_descriptor)> atomData, - std::function::edge_descriptor)> bondData, - MayCollapse mayCollapse, - const bool ignoreDuplicateBonds, const bool withCoordinates, Callback callback) { + std::function::vertex_descriptor)> atomData, + std::function::edge_descriptor)> bondData, + MayCollapse mayCollapse, + const bool ignoreDuplicateBonds, const bool withCoordinates, Callback callback) { std::unique_ptr mol(new OpenBabel::OBMol()); mol->BeginModify(); @@ -254,15 +252,20 @@ OBMolHandle makeOBMolImpl(const Graph &g, int order; switch(bondData(e)) { case BondType::Invalid: - case BondType::Single: order = 1; + case BondType::Single: + order = 1; break; - case BondType::Aromatic: order = 5; + case BondType::Aromatic: + order = 5; break; - case BondType::Double: order = 2; + case BondType::Double: + order = 2; break; - case BondType::Triple: order = 3; + case BondType::Triple: + order = 3; break; - default: std::abort(); + default: + std::abort(); } OpenBabel::OBBond *bond = mol->GetBond(src, tar); if(!ignoreDuplicateBonds && bond) MOD_ABORT; @@ -289,10 +292,10 @@ OBMolHandle makeOBMolImpl(const Graph &g, template void convertStereo(const Graph &g, - std::function::vertex_descriptor)> atomData, - std::function::edge_descriptor)> bondData, - std::function::vertex_descriptor)> hasImportantStereo, - const bool withHydrogen, const Stereo &pStereo, OpenBabel::OBMol &mol) { + std::function::vertex_descriptor)> atomData, + std::function::edge_descriptor)> bondData, + std::function::vertex_descriptor)> hasImportantStereo, + const bool withHydrogen, const Stereo &pStereo, OpenBabel::OBMol &mol) { using Emb = lib::Stereo::EmbeddingEdge; for(const auto v : asRange(vertices(g))) { const auto vId = get(boost::vertex_index_t(), g, v); @@ -330,10 +333,14 @@ void convertStereo(const Graph &g, return ref == OpenBabel::OBStereo::ImplicitRef; }); switch(numImplicit) { - case 0: break; // Ok - case 1: break; // hmm, does OpenBabel like this? - case 2: continue; // otherwise OpenBabel seg. faults (GetVector on a nullptr Atom) - case 3: continue; // otherwise OpenBabel loops infinitely + case 0: + break; // Ok + case 1: + break; // hmm, does OpenBabel like this? + case 2: + continue; // otherwise OpenBabel seg. faults (GetVector on a nullptr Atom) + case 3: + continue; // otherwise OpenBabel loops infinitely } // { // debug // std::cout << "OBabelTetra(" << config.center << "): " << config.from; @@ -356,10 +363,10 @@ OBMolHandle copyOBMol(const OBMolHandle &mol) { } OBMolHandle makeOBMol(const lib::Graph::GraphType &g, - std::function atomData, - std::function bondData, - std::function hasImportantStereo, - const bool withHydrogen, const lib::Graph::PropStereo *pStereo) { + std::function atomData, + std::function bondData, + std::function hasImportantStereo, + const bool withHydrogen, const lib::Graph::PropStereo *pStereo) { const auto mayCollapse = [&](const auto v, const auto &g, const auto &atomData, const auto &bondData) { if(withHydrogen) return false; return isCollapsible(v, g, atomData, bondData, hasImportantStereo); @@ -398,8 +405,8 @@ std::tuple makeOBMol( } return isCollapsible(v, g, atomData, bondData, hasImportantStereo); }; - obMol = makeOBMolImpl(get_graph(lr), atomData, bondData, mayCollapse, true, true, [](OpenBabel::OBMol &mol) { - }); + obMol = makeOBMolImpl(get_graph(lr), atomData, bondData, mayCollapse, true, true, + [](OpenBabel::OBMol &mol) {}); const auto &lgLeft = get_labelled_left(lr); const auto &lgRight = get_labelled_right(lr); const auto hasImportantStereoLeft = [&](const auto v) { @@ -418,7 +425,7 @@ std::tuple makeOBMol( const auto &g = get_graph(lgLeft); if(has_stereo(lr)) convertStereo(g, atomDataLeft, bondDataLeft, hasImportantStereoLeft, true, - get_stereo(lgLeft), mol); + get_stereo(lgLeft), mol); for(const auto v : asRange(vertices(g))) { const auto vId = get(boost::vertex_index_t(), g, v); const auto *aBase = obMol.p->m->GetAtomById(vId); @@ -435,7 +442,7 @@ std::tuple makeOBMol( const auto &g = get_graph(lgRight); if(has_stereo(lr)) convertStereo(g, atomDataRight, bondDataRight, hasImportantStereoRight, true, - get_stereo(lgRight), mol); + get_stereo(lgRight), mol); for(const auto v : asRange(vertices(g))) { const auto vId = get(boost::vertex_index_t(), g, v); const auto *aBase = obMol.p->m->GetAtomById(vId); @@ -449,8 +456,6 @@ std::tuple makeOBMol( return std::make_tuple(std::move(obMol), std::move(obMolLeft), std::move(obMolRight)); } -} // namespace Chem -} // namespace lib -} // namespace mod +} // namespace mod::lib::Chem #endif // MOD_HAVE_OPENBABEL \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Chem/OBabel.hpp b/libs/libmod/src/mod/lib/Chem/OBabel.hpp index 7e8f85a..80a0a61 100644 --- a/libs/libmod/src/mod/lib/Chem/OBabel.hpp +++ b/libs/libmod/src/mod/lib/Chem/OBabel.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_CHEM_OBABEL_H -#define MOD_LIB_CHEM_OBABEL_H +#ifndef MOD_LIB_CHEM_OBABEL_HPP +#define MOD_LIB_CHEM_OBABEL_HPP #include #include @@ -14,27 +14,23 @@ namespace mod { struct AtomData; enum class BondType; -namespace lib { -namespace IO { -namespace Graph { -namespace Write { +} // namespace mod +namespace mod::lib::IO::Graph::Write { enum class EdgeFake3DType; -} // namespace Write -} // namespace Graph -} // namespace IO -namespace Graph { +} // namespace mod::lib::IO::Graph::Write +namespace mod::lib::Graph { struct PropStereo; struct Single; -} // namespace Graph -namespace Rules { +} // namespace mod::lib::Graph +namespace mod::lib::Rules { struct PropStereoCore; -} // namespace Rules -namespace Chem { +} // namespace mod::lib::Rules +namespace mod::lib::Chem { #ifndef MOD_HAVE_OPENBABEL #define MOD_NO_OPENBABEL_ERROR \ - IO::log() << "Call to '" << __FUNCTION__ << "' failed." << std::endl; \ - IO::log() << "Open Babel features are not available. Rebuild with Open Babel enabled." << std::endl; + std::cout << "Call to '" << __FUNCTION__ << "' failed." << std::endl; \ + std::cout << "Open Babel features are not available. Rebuild with Open Babel enabled." << std::endl; #else struct OBMolHandle { @@ -77,8 +73,6 @@ std::tuple makeOBMol(const lib::Rules::La const bool withHydrogen); #endif -} // namespace Chem -} // namespace lib -} // namespace mod +} // namespace mod::lib::Chem -#endif /* MOD_LIB_CHEM_OBABEL_H */ +#endif // MOD_LIB_CHEM_OBABEL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Chem/Smiles.hpp b/libs/libmod/src/mod/lib/Chem/Smiles.hpp index 364bb65..6156b50 100644 --- a/libs/libmod/src/mod/lib/Chem/Smiles.hpp +++ b/libs/libmod/src/mod/lib/Chem/Smiles.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_CHEM_SMILES_H -#define MOD_LIB_CHEM_SMILES_H +#ifndef MOD_LIB_CHEM_SMILES_HPP +#define MOD_LIB_CHEM_SMILES_HPP #include @@ -7,12 +7,12 @@ namespace mod { struct AtomId; -namespace lib { -namespace Graph { +} // namespace mod +namespace mod::lib::Graph { struct PropMolecule; struct PropString; -} // namespace Graph -namespace Chem { +} // namespace mod::lib::Graph +namespace mod::lib::Chem { std::string getSmiles(const lib::Graph::GraphType &g, const lib::Graph::PropMolecule &molState, const std::vector *ranks, bool withIds); @@ -23,8 +23,7 @@ bool isInSmilesOrganicSubset(AtomId atomId); void addImplicitHydrogens(lib::Graph::GraphType &g, lib::Graph::PropString &pString, lib::Graph::Vertex v, AtomId atomId, std::function hydrogenAdder); -} // namespace Chem -} // namespace lib -} // namespace mod -#endif /* MOD_LIB_CHEM_SMILES_H */ +} // namespace mod::lib::Chem + +#endif // MOD_LIB_CHEM_SMILES_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Chem/SmilesRead.cpp b/libs/libmod/src/mod/lib/Chem/SmilesRead.cpp index 3c4f8e7..aa8402c 100644 --- a/libs/libmod/src/mod/lib/Chem/SmilesRead.cpp +++ b/libs/libmod/src/mod/lib/Chem/SmilesRead.cpp @@ -32,10 +32,9 @@ #include #include -namespace mod { -namespace lib { -namespace Chem { -namespace Smiles { +#include + +namespace mod::lib::Chem::Smiles { using Vertex = lib::Graph::Vertex; using Edge = lib::Graph::Edge; @@ -297,11 +296,11 @@ const auto abstractSymbol = x3::rule{"abstra const auto realAtom = x3::rule{"realAtom"} = isotope >> symbol >> chiral >> hcount >> charge >> radical >> class_; const auto wildcardAtom = x3::rule{"wildcardAtom"} - = x3::attr(0) >> x3::string("*") + = (x3::attr(0) >> x3::string("*")) > x3::attr(Chiral()) > hcount > x3::attr(Charge()) > x3::attr(false) > class_; // See https://github.com/boostorg/spirit/issues/523 -// We must reset the attribute, using a semnatic action, but that means the attribute +// We must reset the attribute, using a semantic action, but that means the attribute // writing gets disabled, so use semantic actions for that as well. const auto clearAtom = [](auto &ctx) { _val(ctx) = Atom(); @@ -372,7 +371,7 @@ bool addBond(lib::Graph::GraphType &g, case '/': // note: fall-through to make / and \ implicit case '\\': if(getConfig().graph.printSmilesParsingWarnings.get()) - IO::log() << "WARNING: up/down bonds are not supported, converted to '-' instead." << std::endl; + std::cout << "WARNING: up/down bonds are not supported, converted to '-' instead." << std::endl; [[fallthrough]]; case 0: if(p.isAromatic && v.isAromatic) edgeLabel += ':'; @@ -393,9 +392,9 @@ bool addBond(lib::Graph::GraphType &g, err << "Error in SMILES conversion: bond type '$' is not supported." << std::endl; return false; default: - IO::log() << "Internal error, unknown bond '" << bond << "' (" << (int) bond << ")" << std::endl; - IO::log() << "p = '" << pString[p.vertex] << "'(" << p.vertex << ")" << std::endl; - IO::log() << "v = '" << pString[v.vertex] << "'(" << v.vertex << ")" << std::endl; + std::cout << "Internal error, unknown bond '" << bond << "' (" << (int) bond << ")" << std::endl; + std::cout << "p = '" << pString[p.vertex] << "'(" << p.vertex << ")" << std::endl; + std::cout << "v = '" << pString[v.vertex] << "'(" << v.vertex << ")" << std::endl; MOD_ABORT; } const auto ePair = add_edge(v.vertex, p.vertex, g); @@ -656,14 +655,14 @@ struct StereoConverter { if(!ch.specifier.empty()) { if(getConfig().graph.ignoreStereoInSmiles.get()) { if(getConfig().graph.printSmilesParsingWarnings.get()) - IO::log() << "WARNING: ignoring stereochemical information (" << ch + std::cout << "WARNING: ignoring stereochemical information (" << ch << ") in SMILES, requested by user." << std::endl; } else { if(ch.specifier == "@" || ch.specifier == "@@") { assignTetrahedral(ch.specifier, bAtom, prev, next); } else { // not @ or @@ if(getConfig().graph.printSmilesParsingWarnings.get()) - IO::log() << "WARNING: stereochemical information (" << ch << ") in SMILES string ignored." + std::cout << "WARNING: stereochemical information (" << ch << ") in SMILES string ignored." << std::endl; } } @@ -679,7 +678,7 @@ struct StereoConverter { const std::vector oes(out_edges(v, g).first, out_edges(v, g).second); if(oes.size() != 4) { if(getConfig().graph.printSmilesParsingWarnings.get()) - IO::log() << "WARNING: Ignoring stereo information in SMILES. Can not add tetrahedral geometry to vertex (" + std::cout << "WARNING: Ignoring stereo information in SMILES. Can not add tetrahedral geometry to vertex (" << bAtom.atom << ") with degree " << oes.size() << ". Must be 4." << std::endl; return; } @@ -745,18 +744,18 @@ lib::IO::Graph::Read::Data parseSmiles(const std::string &smiles, std::ostream & std::stringstream astStr; astStr << ast; if(smiles != astStr.str()) { - IO::log() << "Converting: >>>" << smiles << "<<< " << smiles.size() << std::endl; - IO::log() << "Ast: >>>" << astStr.str() << "<<< " << astStr.str().size() << std::endl; + std::cout << "Converting: >>>" << smiles << "<<< " << smiles.size() << std::endl; + std::cout << "Ast: >>>" << astStr.str() << "<<< " << astStr.str().size() << std::endl; for(auto c : smiles) { - if(std::isprint(c)) IO::log() << c << ' '; - else IO::log() << int(c) << ' '; + if(std::isprint(c)) std::cout << c << ' '; + else std::cout << int(c) << ' '; } - IO::log() << std::endl; + std::cout << std::endl; for(auto c : astStr.str()) { - if(std::isprint(c)) IO::log() << c << ' '; - else IO::log() << int(c) << ' '; + if(std::isprint(c)) std::cout << c << ' '; + else std::cout << int(c) << ' '; } - IO::log() << std::endl; + std::cout << std::endl; MOD_ABORT; } } @@ -825,7 +824,7 @@ lib::IO::Graph::Read::Data parseSmiles(const std::string &smiles, std::ostream & break; case lib::Stereo::DeductionResult::Warning: if(!getConfig().stereo.silenceDeductionWarnings.get()) - IO::log() << finalizeErr.str(); + std::cout << finalizeErr.str(); break; case lib::Stereo::DeductionResult::Error: err << finalizeErr.str(); @@ -840,16 +839,15 @@ lib::IO::Graph::Read::Data parseSmiles(const std::string &smiles, std::ostream & } } // namespace -} // namespace Smiles +} // namespace mod::lib::Chem::Smiles +namespace mod::lib::Chem { lib::IO::Graph::Read::Data readSmiles(const std::string &smiles, std::ostream &err, const bool allowAbstract, SmilesClassPolicy classPolicy) { return Smiles::parseSmiles(smiles, err, allowAbstract, classPolicy); } -} // namespace Chem -} // namespace lib -} // namespace mod +} // namespace mod::lib::Chem BOOST_FUSION_ADAPT_STRUCT(mod::lib::Chem::Smiles::Chiral, (std::string, specifier) diff --git a/libs/libmod/src/mod/lib/Chem/SmilesWrite.cpp b/libs/libmod/src/mod/lib/Chem/SmilesWrite.cpp index 7cf6557..e6731a6 100644 --- a/libs/libmod/src/mod/lib/Chem/SmilesWrite.cpp +++ b/libs/libmod/src/mod/lib/Chem/SmilesWrite.cpp @@ -16,117 +16,90 @@ #include #include +#include -namespace mod { -namespace lib { -namespace Chem { +namespace mod::lib::Chem { namespace { using Vertex = lib::Graph::Vertex; using Edge = lib::Graph::Edge; using VSizeType = lib::Graph::GraphType::vertices_size_type; const unsigned int primesLength = 1001; -const unsigned int primes[primesLength] = {1 - , 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 - , 31, 37, 41, 43, 47, 53, 59, 61, 67, 71 - , 73, 79, 83, 89, 97, 101, 103, 107, 109, 113 - , 127, 131, 137, 139, 149, 151, 157, 163, 167, 173 - , 179, 181, 191, 193, 197, 199, 211, 223, 227, 229 - , 233, 239, 241, 251, 257, 263, 269, 271, 277, 281 - , 283, 293, 307, 311, 313, 317, 331, 337, 347, 349 - , 353, 359, 367, 373, 379, 383, 389, 397, 401, 409 - , 419, 421, 431, 433, 439, 443, 449, 457, 461, 463 - , 467, 479, 487, 491, 499, 503, 509, 521, 523, 541 - , 547, 557, 563, 569, 571, 577, 587, 593, 599, 601 - , 607, 613, 617, 619, 631, 641, 643, 647, 653, 659 - , 661, 673, 677, 683, 691, 701, 709, 719, 727, 733 - , 739, 743, 751, 757, 761, 769, 773, 787, 797, 809 - , 811, 821, 823, 827, 829, 839, 853, 857, 859, 863 - , 877, 881, 883, 887, 907, 911, 919, 929, 937, 941 - , 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013 - , 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069 - , 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151 - , 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223 - , 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291 - , 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373 - , 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451 - , 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511 - , 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583 - , 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657 - , 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733 - , 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811 - , 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889 - , 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987 - , 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053 - , 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129 - , 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213 - , 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287 - , 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357 - , 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423 - , 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531 - , 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617 - , 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687 - , 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741 - , 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819 - , 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903 - , 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999 - , 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079 - , 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181 - , 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257 - , 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331 - , 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413 - , 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511 - , 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571 - , 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643 - , 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727 - , 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821 - , 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907 - , 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989 - , 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057 - , 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139 - , 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231 - , 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297 - , 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409 - , 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493 - , 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583 - , 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657 - , 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751 - , 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831 - , 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937 - , 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003 - , 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087 - , 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179 - , 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279 - , 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387 - , 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443 - , 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521 - , 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639 - , 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693 - , 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791 - , 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857 - , 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939 - , 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053 - , 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133 - , 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221 - , 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301 - , 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367 - , 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473 - , 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571 - , 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673 - , 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761 - , 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833 - , 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917 - , 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997 - , 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103 - , 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207 - , 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297 - , 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411 - , 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499 - , 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561 - , 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643 - , 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723 - , 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829 - , 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919}; +const unsigned int primes[primesLength] = {1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, + 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, + 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, + 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, + 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, + 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, + 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, + 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, + 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, + 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, + 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, + 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, + 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, + 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, + 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, + 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, + 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, + 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, + 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, + 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, + 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, + 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, + 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, + 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, + 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, + 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, + 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, + 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, + 2789, 2791, 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, + 2887, 2897, 2903, 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, + 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, + 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, + 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, + 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449, + 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539, + 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, + 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733, + 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851, + 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943, + 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, + 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, + 4273, 4283, 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, + 4409, 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, + 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, + 4639, 4643, 4649, 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, + 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, + 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, + 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, + 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, + 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, + 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, + 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, + 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, + 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, + 5743, 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, + 5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, + 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, + 6091, 6101, 6113, 6121, 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, + 6211, 6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, + 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379, 6389, + 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481, 6491, 6521, 6529, 6547, 6551, + 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, + 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779, + 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, 6863, 6869, 6871, + 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, + 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109, + 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, + 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, + 7369, 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, + 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, + 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, + 7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, + 7829, 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919}; unsigned int prime(unsigned int number) { // check if already precalculated @@ -154,8 +127,9 @@ unsigned int prime(unsigned int number) { return prime; } -unsigned long long int combineNeighbours(Vertex v, const std::vector &ranks, const lib::Graph::GraphType &g, - const lib::Graph::PropMolecule &molState) { +unsigned long long int +combineNeighbours(Vertex v, const std::vector &ranks, const lib::Graph::GraphType &g, + const lib::Graph::PropMolecule &molState) { // The bondFactor is an attempt to propagate the bond type. unsigned long long int combinedRank = 1; for(Edge eOut : asRange(out_edges(v, g))) { @@ -182,12 +156,17 @@ unsigned long long int combineNeighbours(Vertex v, const std::vector *ranks, bool withIds) - : g(g), molState(molState), auxData(g, molState), visited(num_vertices(g), false), withIds(withIds), - nextOrder(1), vOrder(num_vertices(g), 0), ringIds(num_vertices(g)), branches(num_vertices(g)) { + SmilesWriter(const lib::Graph::GraphType &g, const lib::Graph::PropMolecule &molState, const std::vector *ranks, + bool withIds) + : g(g), molState(molState), auxData(g, molState), visited(num_vertices(g), false), withIds(withIds), + nextOrder(1), vOrder(num_vertices(g), 0), ringIds(num_vertices(g)), branches(num_vertices(g)) { if(!molState.getIsMolecule()) MOD_ABORT; #ifdef DO_DEBUG std::cerr << "getSMILES" << std::endl; @@ -298,7 +278,7 @@ struct SmilesWriter { if(molState[e] == BondType::Single) { if(withIds) { output = "[H:" + boost::lexical_cast(get(boost::vertex_index_t(), g, v1)) + "]" - + "[H:" + boost::lexical_cast(get(boost::vertex_index_t(), g, v2)) + "]"; + + "[H:" + boost::lexical_cast(get(boost::vertex_index_t(), g, v2)) + "]"; } else { output = "[H][H]"; } @@ -320,13 +300,14 @@ struct SmilesWriter { if(ranks) { this->ranks = ranks; // find the minimum vertex by rank, which has not been visited (i.e., is not a clean hydrogen) - const auto vStartIter = std::min_element(vertices(g).first, vertices(g).second, [this, &idx](Vertex a, Vertex b) { - const auto ia = idx[a], ib = idx[b]; - const auto va = visited[ia], vb = visited[ib]; - if(va) return false; - if(vb) return true; - return getRank(ia) < getRank(ib); - }); + const auto vStartIter = std::min_element(vertices(g).first, vertices(g).second, + [this, &idx](Vertex a, Vertex b) { + const auto ia = idx[a], ib = idx[b]; + const auto va = visited[ia], vb = visited[ib]; + if(va) return false; + if(vb) return true; + return getRank(ia) < getRank(ib); + }); assert(vStartIter != vertices(g).second); start = *vStartIter; } else { @@ -358,7 +339,7 @@ struct SmilesWriter { #endif } - std::vector canonicalise() { + std::vector canonicalise() { auto idx = get(boost::vertex_index_t(), g); VSizeType numNonVisitedVertices = 0; // the number of vertices except for clen hydrogens #ifdef DO_DEBUG @@ -372,7 +353,7 @@ struct SmilesWriter { assert(numNonVisitedVertices > 0); // The rank/invariant for each vertex. We actually only need it for non-hydrogens, but we want constant time lookup - std::vector vertexValue(num_vertices(g), 0); + std::vector vertexValue(num_vertices(g), 0); // Non-hydrogen vertices, sorted by vertexValue std::vector sortedVertices; sortedVertices.reserve(numNonVisitedVertices); @@ -380,12 +361,12 @@ struct SmilesWriter { for(Vertex v : asRange(vertices(g))) { vertexValue[idx[v]] = auxData.getInvariant(v); // if(vertexValue[idx[v]] != nodeData[idx[v]].getInvariant()) { - // IO::log() << "Diff invariant for vertex " << idx[v] << " with label '" << vname(v) << "'" << std::endl; - // IO::log() << "\tnew: " << vertexValue[idx[v]] << std::endl; - // IO::log() << "\told: " << nodeData[idx[v]].getInvariant() << std::endl; - // IO::log() << "\tadjacency:" << std::endl; + // std::cout << "Diff invariant for vertex " << idx[v] << " with label '" << vname(v) << "'" << std::endl; + // std::cout << "\tnew: " << vertexValue[idx[v]] << std::endl; + // std::cout << "\told: " << nodeData[idx[v]].getInvariant() << std::endl; + // std::cout << "\tadjacency:" << std::endl; // for(Edge e : asRange(out_edges(v, g))) { - // IO::log() << "\t\t" << bondToString(molState(e)) << getAtomList()[molState(target(e, g)).getAtomId()] << std::endl; + // std::cout << "\t\t" << bondToString(molState(e)) << getAtomList()[molState(target(e, g)).getAtomId()] << std::endl; // } // } if(!visited[idx[v]]) sortedVertices.push_back(v); @@ -393,9 +374,9 @@ struct SmilesWriter { // set consecutive ranks starting from 1 std::sort(sortedVertices.begin(), sortedVertices.end(), - [&vertexValue, &idx](Vertex u, Vertex v) { - return vertexValue[idx[u]] < vertexValue[idx[v]]; - }); + [&vertexValue, &idx](Vertex u, Vertex v) { + return vertexValue[idx[u]] < vertexValue[idx[v]]; + }); #ifdef DO_DEBUG std::cerr << "\tinitial values" << std::endl; for(Vertex v : sortedVertices) { @@ -422,7 +403,7 @@ struct SmilesWriter { // iterate rank setup until each node has a unique rank while(vertexValue[idx[sortedVertices.back()]] != numNonVisitedVertices) { // still tied ranks - std::vector prevVertexValue = vertexValue; // copy is needed so we can do swaps in inner loop + std::vector prevVertexValue = vertexValue; // copy is needed so we can do swaps in inner loop do { // change vertex value using neighbours swap(prevVertexValue, vertexValue); // relies on the initial copying outside the loop // calculate new ranks based on multiples of prime numbers @@ -433,10 +414,11 @@ struct SmilesWriter { // sort the vertices according to the vertexValue, but retain stability with prevVertexValue std::sort(sortedVertices.begin(), sortedVertices.end(), - [&prevVertexValue, &vertexValue, &idx](Vertex u, Vertex v) { - if(prevVertexValue[idx[u]] != prevVertexValue[idx[v]]) return prevVertexValue[idx[u]] < prevVertexValue[idx[v]]; - else return vertexValue[idx[u]] < vertexValue[idx[v]]; - } + [&prevVertexValue, &vertexValue, &idx](Vertex u, Vertex v) { + if(prevVertexValue[idx[u]] != prevVertexValue[idx[v]]) + return prevVertexValue[idx[u]] < prevVertexValue[idx[v]]; + else return vertexValue[idx[u]] < vertexValue[idx[v]]; + } ); // assign previous ranks, but possibly break ties with the new vertex values VSizeType rank = 1; @@ -458,7 +440,8 @@ struct SmilesWriter { } #endif } while(vertexValue[idx[sortedVertices.back()]] != numNonVisitedVertices // continue if we still have ties - && vertexValue[idx[sortedVertices.back()]] > prevVertexValue[idx[sortedVertices.back()]]); // continue if we broke any ties + && vertexValue[idx[sortedVertices.back()]] > + prevVertexValue[idx[sortedVertices.back()]]); // continue if we broke any ties // still some nodes have equal rank if(vertexValue[idx[sortedVertices.back()]] != numNonVisitedVertices) { @@ -492,7 +475,7 @@ struct SmilesWriter { auto idx = get(boost::vertex_index_t(), g); #ifdef DO_DEBUG std::cerr << "preBuildDFS: " << idx[v] << std::endl; -#endif +#endif assert(!preBuildVisited[idx[v]]); preBuildVisited[idx[v]] = true; @@ -539,37 +522,39 @@ struct SmilesWriter { void assignRingIds() { // for now, mimic the old behaviour auto idx = get(boost::vertex_index_t(), g); - std::sort(begin(ringClosures), end(ringClosures), [this, idx](const std::pair &p1, const std::pair &p2) { - Vertex vSrc1 = source(p1.first, g), vTar1 = target(p1.first, g); - Vertex vSrc2 = source(p2.first, g), vTar2 = target(p2.first, g); - if(vOrder[idx[vSrc1]] != vOrder[idx[vSrc2]]) return vOrder[idx[vSrc1]] < vOrder[idx[vSrc2]]; - return vOrder[idx[vTar1]] < vOrder[idx[vTar2]]; - // prefer double and triple bonds, otherwise use ranks - auto bt1 = molState[p1.first]; - auto bt2 = molState[p2.first]; - bool isMulti1 = bt1 == BondType::Double || bt1 == BondType::Triple; - bool isMulti2 = bt2 == BondType::Double || bt2 == BondType::Triple; - if(isMulti1 != isMulti2) return isMulti2; - return getRank(idx[vTar1]) < getRank(idx[vTar2]); - }); + std::sort(begin(ringClosures), end(ringClosures), + [this, idx](const std::pair &p1, const std::pair &p2) { + Vertex vSrc1 = source(p1.first, g), vTar1 = target(p1.first, g); + Vertex vSrc2 = source(p2.first, g), vTar2 = target(p2.first, g); + if(vOrder[idx[vSrc1]] != vOrder[idx[vSrc2]]) return vOrder[idx[vSrc1]] < vOrder[idx[vSrc2]]; + return vOrder[idx[vTar1]] < vOrder[idx[vTar2]]; + // prefer double and triple bonds, otherwise use ranks + auto bt1 = molState[p1.first]; + auto bt2 = molState[p2.first]; + bool isMulti1 = bt1 == BondType::Double || bt1 == BondType::Triple; + bool isMulti2 = bt2 == BondType::Double || bt2 == BondType::Triple; + if(isMulti1 != isMulti2) return isMulti2; + return getRank(idx[vTar1]) < getRank(idx[vTar2]); + }); if(ringClosures.size() >= 100) { - IO::log() << "ERROR in SMILES writing. Too many ring closures with current scheme." << std::endl; + std::cout << "ERROR in SMILES writing. Too many ring closures with current scheme." << std::endl; MOD_ABORT; } for(unsigned int i = 0; i < ringClosures.size(); i++) ringClosures[i].second = i + 1; // start with 1 instead of 0 auto ringClosuresCopy = ringClosures; - std::sort(begin(ringClosuresCopy), end(ringClosuresCopy), [this, idx](const std::pair &p1, const std::pair &p2) { - Vertex vSrc1 = source(p1.first, g), vTar1 = target(p1.first, g); - Vertex vSrc2 = source(p2.first, g), vTar2 = target(p2.first, g); - if(vOrder[idx[vTar1]] != vOrder[idx[vTar2]]) return vOrder[idx[vTar1]] < vOrder[idx[vTar2]]; - // prefer double and triple bonds, otherwise use ranks - auto bt1 = molState[p1.first]; - auto bt2 = molState[p2.first]; - bool isMulti1 = bt1 == BondType::Double || bt1 == BondType::Triple; - bool isMulti2 = bt2 == BondType::Double || bt2 == BondType::Triple; - if(isMulti1 != isMulti2) return isMulti2; - return getRank(idx[vSrc1]) < getRank(idx[vSrc2]); - }); + std::sort(begin(ringClosuresCopy), end(ringClosuresCopy), + [this, idx](const std::pair &p1, const std::pair &p2) { + Vertex vSrc1 = source(p1.first, g), vTar1 = target(p1.first, g); + Vertex vSrc2 = source(p2.first, g), vTar2 = target(p2.first, g); + if(vOrder[idx[vTar1]] != vOrder[idx[vTar2]]) return vOrder[idx[vTar1]] < vOrder[idx[vTar2]]; + // prefer double and triple bonds, otherwise use ranks + auto bt1 = molState[p1.first]; + auto bt2 = molState[p2.first]; + bool isMulti1 = bt1 == BondType::Double || bt1 == BondType::Triple; + bool isMulti2 = bt2 == BondType::Double || bt2 == BondType::Triple; + if(isMulti1 != isMulti2) return isMulti2; + return getRank(idx[vSrc1]) < getRank(idx[vSrc2]); + }); // open before close for(const auto &p : ringClosures) ringIds[idx[source(p.first, g)]].emplace_back(BondType::Invalid, p.second); for(const auto &p : ringClosuresCopy) ringIds[idx[target(p.first, g)]].emplace_back(molState[p.first], p.second); @@ -629,8 +614,8 @@ struct SmilesWriter { void getLabel(Vertex v) { bool hasBrackets = true; if(molState[v].getCharge() == 0 && !molState[v].getRadical() && molState[v].getIsotope() == Isotope() - && isInSmilesOrganicSubset(molState[v].getAtomId()) - && isValenceForOrganicSubsetNormal(v)) { + && isInSmilesOrganicSubset(molState[v].getAtomId()) + && isValenceForOrganicSubsetNormal(v)) { // if the hydrogen count is such that it can be deduced, then remove brackets hasBrackets = false; } @@ -684,7 +669,8 @@ struct SmilesWriter { // halogens 1 using namespace AtomIds; using BondVector = std::tuple; - BondVector numBonds{auxData.getNumSingle(v), auxData.getNumDouble(v), auxData.getNumTriple(v), auxData.getNumAromatic(v)}; + BondVector numBonds{auxData.getNumSingle(v), auxData.getNumDouble(v), auxData.getNumTriple(v), + auxData.getNumAromatic(v)}; unsigned char valence = auxData.getValenceNoAromatic(v) + auxData.getNumAromatic(v); if(auxData.getNumAromatic(v) > 0) valence++; unsigned char hCount = auxData.getNumHydrogen(v); @@ -704,9 +690,12 @@ struct SmilesWriter { [[fallthrough]]; case Phosphorus: switch(valence) { - case 3: return true; - case 5: return hCount < 2; - default: return valence > 5 && hCount == 0; + case 3: + return true; + case 5: + return hCount < 2; + default: + return valence > 5 && hCount == 0; } case Oxygen: if(valence == 2) return true; @@ -714,10 +703,13 @@ struct SmilesWriter { case Sulfur: if(numBonds == BondVector(0, 0, 0, 2) && hCount == 0) return true; switch(valence) { - case 2: return true; + case 2: + return true; case 4: - case 6: return hCount < 2; - default: return valence > 6 && hCount == 0; + case 6: + return hCount < 2; + default: + return valence > 6 && hCount == 0; } case Fluorine: case Chlorine: @@ -725,7 +717,8 @@ struct SmilesWriter { case Iodine: if(valence == 1) return true; return valence > 1 && hCount == 0; - default: MOD_ABORT; + default: + MOD_ABORT; } } private: @@ -746,11 +739,11 @@ struct SmilesWriter { } // namespace -std::string getSmiles(const lib::Graph::GraphType &g, const lib::Graph::PropMolecule &molState, const std::vector *ranks, bool withIds) { +std::string +getSmiles(const lib::Graph::GraphType &g, const lib::Graph::PropMolecule &molState, const std::vector *ranks, + bool withIds) { SmilesWriter writer(g, molState, ranks, withIds); return writer.output; } -} // namespace Chem -} // namespace lib -} // namespace mod +} // namespace mod::lib::Chem \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Dump.cpp b/libs/libmod/src/mod/lib/DG/Dump.cpp index 30dff1c..7091159 100644 --- a/libs/libmod/src/mod/lib/DG/Dump.cpp +++ b/libs/libmod/src/mod/lib/DG/Dump.cpp @@ -24,10 +24,9 @@ #include #include -namespace mod { -namespace lib { -namespace DG { -namespace Dump { +#include + +namespace mod::lib::DG::Dump { namespace { struct ConstructionData { @@ -67,7 +66,7 @@ struct NonHyperDump : public NonHyper { } std::shared_ptr r = *iter; if(printInfo) - IO::log() << "Rule linked: " << r->getName() << std::endl; + std::cout << "Rule linked: " << r->getName() << std::endl; this->rules.push_back(r); ruleMap[get<0>(t)] = r; } @@ -83,7 +82,7 @@ struct NonHyperDump : public NonHyper { const bool wasNew = trustAddGraphAsVertex(p.first); graphMap[id] = p.first; if(!p.second && printInfo) - IO::log() << "Graph linked: " << get<1>(v) << " -> " << p.first->getName() << std::endl; + std::cout << "Graph linked: " << get<1>(v) << " -> " << p.first->getName() << std::endl; // if(wasNew) giveProductStatus(p.first); (void) wasNew; iVertices++; @@ -149,7 +148,7 @@ bool parse(Iter &textFirst, bool res = IO::detail::ParseDispatch::parse(first, last, p, attr, x3::ascii::space); if(!res) { err << "Error while parsing DG dump.\n"; - IO::detail::doParserError(textFirst, first, last, lib::IO::log()); + IO::detail::doParserError(textFirst, first, last, std::cout); return false; } return res; @@ -308,7 +307,4 @@ std::unique_ptr load(const std::vector > ConstructionData{rules, std::move(vertices), std::move(rulesParsed), std::move(edges)}); } -} // namespace Dump -} // namespace DG -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::DG::Dump \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Dump.hpp b/libs/libmod/src/mod/lib/DG/Dump.hpp index 01e9819..fc40433 100644 --- a/libs/libmod/src/mod/lib/DG/Dump.hpp +++ b/libs/libmod/src/mod/lib/DG/Dump.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_DG_DUMP_H -#define MOD_LIB_DG_DUMP_H +#ifndef MOD_LIB_DG_DUMP_HPP +#define MOD_LIB_DG_DUMP_HPP #include #include @@ -9,20 +9,16 @@ #include #include -namespace mod { -namespace lib { -namespace DG { +namespace mod::lib::DG { class NonHyper; -namespace Dump { +} // namespace mod::lib::DG +namespace mod::lib::DG::Dump { std::unique_ptr load(const std::vector > &graphs, - const std::vector > &rules, - const std::string &file, - std::ostream &err); + const std::vector > &rules, + const std::string &file, + std::ostream &err); -} // namespace Dump -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG::Dump -#endif /* MOD_LIB_DG_DUMP_H */ \ No newline at end of file +#endif // MOD_LIB_DG_DUMP_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Hyper.cpp b/libs/libmod/src/mod/lib/DG/Hyper.cpp index 4c5c0b8..c65e749 100644 --- a/libs/libmod/src/mod/lib/DG/Hyper.cpp +++ b/libs/libmod/src/mod/lib/DG/Hyper.cpp @@ -267,12 +267,11 @@ void Hyper::printStats(std::ostream &s) const { s << "reverse/vert:\t" << (numReverse / ((double) numVerts)) << std::endl; s << "pairs/edge:\t" << (numEdgePairs / ((double) numEdges)) << std::endl; s << "------------------------------------------------------------------" << std::endl; - typedef std::pair P; s << "numIn histogram:" << std::endl; - for(const P &p : countNumIn) s << p.first << "\t" << p.second << std::endl; + for(const auto &p : countNumIn) s << p.first << "\t" << p.second << std::endl; s << "------------------------------------------------------------------" << std::endl; s << "numOut histogram:" << std::endl; - for(const P &p : countNumIn) s << p.first << "\t" << p.second << std::endl; + for(const auto &p : countNumIn) s << p.first << "\t" << p.second << std::endl; s << "------------------------------------------------------------------" << std::endl; s << "avgInReverseRatio\t" << avgInReverseRatio << std::endl; s << "avgInReverseRatioWithVirtual\t" << avgInReverseRatioWithVirtual << std::endl; diff --git a/libs/libmod/src/mod/lib/DG/NonHyper.cpp b/libs/libmod/src/mod/lib/DG/NonHyper.cpp index bed6681..9fe9f99 100644 --- a/libs/libmod/src/mod/lib/DG/NonHyper.cpp +++ b/libs/libmod/src/mod/lib/DG/NonHyper.cpp @@ -26,11 +26,10 @@ #include #include +#include #include -namespace mod { -namespace lib { -namespace DG { +namespace mod::lib::DG { namespace { std::size_t nextDGNum = 0; } // namespace @@ -50,7 +49,7 @@ NonHyper::NonHyper(LabelSettings labelSettings, case IsomorphismPolicy::Check: { const auto ls = LabelSettings{this->labelSettings.type, LabelRelation::Isomorphism, this->labelSettings.withStereo, LabelRelation::Isomorphism}; - for(const auto gCand : graphDatabase) { + for(const auto &gCand : graphDatabase) { if(ls.type == LabelType::Term) { const auto &term = get_term(gCand->getGraph().getLabelledGraph()); if(!isValid(term)) { @@ -292,15 +291,15 @@ HyperVertex NonHyper::findHyperEdge(const std::vector &sources, } void NonHyper::diff(const NonHyper &dg1, const NonHyper &dg2) { - std::ostream &s = IO::log(); bool headerPrinted = false; - const auto printHeader = [&headerPrinted, &dg1, &dg2, &s]() -> std::ostream & { - if(headerPrinted) return s; + const auto printHeader = [&headerPrinted, &dg1, &dg2]() -> std::ostream & { + if(headerPrinted) return std::cout; else headerPrinted = true; - s << "--- DG " << dg1.getId() << std::endl; - s << "+++ DG " << dg2.getId() << std::endl; - return s; + std::cout << "--- DG " << dg1.getId() << std::endl; + std::cout << "+++ DG " << dg2.getId() << std::endl; + return std::cout; }; + std::ostream &s = std::cout; // diff vertices std::unordered_set > vertexGraphsUnique; for(const auto v : dg1.getAPIReference()->vertices()) vertexGraphsUnique.insert(v.getGraph()); @@ -310,7 +309,7 @@ void NonHyper::diff(const NonHyper &dg1, const NonHyper &dg2) { [](std::shared_ptr g1, std::shared_ptr g2) { return g1->getName() < g2->getName(); }); - for(const auto g : vertexGraphs) { + for(const auto &g : vertexGraphs) { const bool in1 = dg1.getHyper().isVertexGraph(&g->getGraph()); const bool in2 = dg2.getHyper().isVertexGraph(&g->getGraph()); assert(in1 || in2); @@ -386,6 +385,4 @@ void NonHyper::diff(const NonHyper &dg1, const NonHyper &dg2) { } } -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG diff --git a/libs/libmod/src/mod/lib/DG/NonHyper.hpp b/libs/libmod/src/mod/lib/DG/NonHyper.hpp index 9281032..ae1282d 100644 --- a/libs/libmod/src/mod/lib/DG/NonHyper.hpp +++ b/libs/libmod/src/mod/lib/DG/NonHyper.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_DG_NONHYPER_H -#define MOD_LIB_DG_NONHYPER_H +#ifndef MOD_LIB_DG_NONHYPER_HPP +#define MOD_LIB_DG_NONHYPER_HPP #include #include @@ -18,12 +18,10 @@ #include #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropString; -} // namespace Graph -namespace DG { +} // namespace mod::lib::Graph +namespace mod::lib::DG { class HyperCreator; class NonHyper { @@ -121,8 +119,6 @@ class NonHyper { static void diff(const NonHyper &dg1, const NonHyper &dg2); }; -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG -#endif /* MOD_LIB_DG_NONHYPER_H */ +#endif // MOD_LIB_DG_NONHYPER_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/NonHyperBuilder.cpp b/libs/libmod/src/mod/lib/DG/NonHyperBuilder.cpp index 9d18f96..69df497 100644 --- a/libs/libmod/src/mod/lib/DG/NonHyperBuilder.cpp +++ b/libs/libmod/src/mod/lib/DG/NonHyperBuilder.cpp @@ -11,17 +11,14 @@ #include #include #include +#include #include #include -#include - #include #include -namespace mod { -namespace lib { -namespace DG { +namespace mod::lib::DG { ExecuteResult::ExecuteResult(NonHyperBuilder *owner, int execution) : owner(owner), execution(execution) {} @@ -32,7 +29,8 @@ const Strategies::GraphState &ExecuteResult::getResult() const { void ExecuteResult::list(bool withUniverse) const { owner->executions[execution].strategy->printInfo( - Strategies::PrintSettings(IO::log(), withUniverse)); + Strategies::PrintSettings(std::cout, withUniverse)); + std::cout << std::flush; } // ----------------------------------------------------------------------------- @@ -102,8 +100,8 @@ std::pair Builder::addDerivation(const Derivations &d, Iso } struct NonHyperBuilder::ExecutionEnv final : public Strategies::ExecutionEnv { - ExecutionEnv(NonHyperBuilder &owner, LabelSettings labelSettings) - : Strategies::ExecutionEnv(labelSettings), owner(owner) {} + ExecutionEnv(NonHyperBuilder &owner, LabelSettings labelSettings, Rules::GraphAsRuleCache &graphAsRuleCache) + : Strategies::ExecutionEnv(labelSettings, graphAsRuleCache), owner(owner) {} void tryAddGraph(std::shared_ptr gCand) override { owner.tryAddGraph(gCand); @@ -184,7 +182,7 @@ struct NonHyperBuilder::ExecutionEnv final : public Strategies::ExecutionEnv { ExecuteResult Builder::execute(std::unique_ptr strategy_, int verbosity, bool ignoreRuleLabelTypes) { NonHyperBuilder::StrategyExecution exec{ - std::make_unique(*dg, dg->getLabelSettings()), + std::make_unique(*dg, dg->getLabelSettings(), dg->graphAsRuleCache), std::make_unique(), std::move(strategy_) }; @@ -222,18 +220,16 @@ Builder::execute(std::unique_ptr strategy_, int verbosity, }); } - exec.strategy->execute(Strategies::PrintSettings(IO::log(), false, verbosity), *exec.input); + exec.strategy->execute(Strategies::PrintSettings(std::cout, false, verbosity), *exec.input); dg->executions.push_back(std::move(exec)); return ExecuteResult(dg, dg->executions.size() - 1); } std::vector> -Builder::apply(const std::vector > &graphs, +Builder::apply(const std::vector> &graphs, std::shared_ptr rOrig, int verbosity, IsomorphismPolicy graphPolicy) { - constexpr int V_RuleBinding = 2; - constexpr int V_RCMatchBase = 8; - IO::Logger logger(IO::log()); + IO::Logger logger(std::cout); dg->rules.insert(rOrig); switch(graphPolicy) { case IsomorphismPolicy::Check: @@ -246,70 +242,89 @@ Builder::apply(const std::vector > &graphs, break; } - std::vector boundRules; - { - BoundRule p; - p.rule = &rOrig->getRule(); - boundRules.push_back(p); - } - const auto ls = dg->getLabelSettings(); - if(verbosity >= V_RuleBinding) { + if(verbosity >= V_RuleApplication) { logger.indent() << "Binding " << graphs.size() << " graphs to rule '" << rOrig->getName() << "' with " << rOrig->getNumLeftComponents() << " left-hand components." << std::endl; ++logger.indentLevel; } - for(const auto &g : graphs) { - std::vector resultBoundRules; - for(const BoundRule &brp : boundRules) { - assert(brp.rule); - if(brp.rule->isOnlyRightSide()) continue; // no improper derivations - BoundRuleStorage ruleStore( - verbosity >= V_RuleBinding, IO::Logger(IO::log()), - ls.type, ls.withStereo, resultBoundRules, brp, &g->getGraph()); - const auto reporter = [&ruleStore, - assumeConfluence = getConfig().dg.applyAssumeConfluence.get() - ](std::unique_ptr r) { - ruleStore.add(r.release()); - return !assumeConfluence; // returns "make more matches" + if(graphs.empty()) return {}; + std::vector libGraphs; + libGraphs.reserve(graphs.size()); + for(const auto &g : graphs) + libGraphs.push_back(&g->getGraph()); + + std::vector resultRules; + const auto ls = dg->getLabelSettings(); + { + // we must bind each graph, so increase the span of graphs one at a time, + // and only keep bound rules that still have left-hand components + std::vector inputRules{{&rOrig->getRule(), {}, 0}}; + const auto firstGraph = libGraphs.begin(); + for(int round = 0; round != libGraphs.size(); ++round) { + const auto onOutput = [ + isLast = round + 1 == libGraphs.size(), + assumeConfluence = getConfig().dg.applyAssumeConfluence.get(), + &resultRules] + (IO::Logger logger, BoundRule br) -> bool { + if(isLast) { + // save only the fully bound ones + if(br.rule->isOnlyRightSide()) { + resultRules.push_back(std::move(br)); + return !assumeConfluence; // returns "make more matches" + } else return true; + } else { + // discard the fully bound ones + if(br.rule->isOnlyRightSide()) { + delete br.rule; + return true; + } else return !assumeConfluence; // returns "make more matches" + } }; - const lib::Rules::Real &rFirst = g->getGraph().getBindRule()->getRule(); - const lib::Rules::Real &rSecond = *brp.rule; - lib::RC::Super mm( - std::max(0, verbosity - V_RCMatchBase), IO::Logger(IO::log()), - true, true); - lib::RC::composeRuleRealByMatchMaker(rFirst, rSecond, mm, reporter, ls); - } - // we only care about proper derivations, to simply delete all intermediary results - for(BoundRule &p : boundRules) { - if(p.rule != &rOrig->getRule()) - delete p.rule; - } - if(verbosity >= V_RuleBinding) { - logger.indent() << "got " << resultBoundRules.size() << " intermediary rules after binding graph '" - << g->getName() - << "'" << std::endl; - if(getConfig().dg.calculateVerbosePrint.get()) { - postSection("CalculateVerbose"); - for(const auto &brp : resultBoundRules) - IO::Rules::Write::summary(*brp.rule); + std::vector outputRules = bindGraphs( + verbosity, logger, + round, + firstGraph, firstGraph + round + 1, inputRules, + dg->graphAsRuleCache, ls, + onOutput); + for(BoundRule &br : outputRules) { + // always go to the next graph + ++br.nextGraphOffset; } - } - boundRules = std::move(resultBoundRules); - } + if(round != 0) { + // in round 0 the inputRules is the actual original input rule, so don't delete it + for(auto &br : inputRules) + delete br.rule; + } + std::swap(inputRules, outputRules); + if(verbosity >= V_RuleApplication) { + ++logger.indentLevel; + logger.indent() << "Result after apply filtering: " << inputRules.size() << " rules" << std::endl; + --logger.indentLevel; + } + } // for each round + } // end of binding - std::vector > res; - for(const BoundRule &brp : boundRules) { + std::vector> res; + for(const BoundRule &br : resultRules) { if(getConfig().dg.applyLimit.get() == res.size()) break; - const auto &r = *brp.rule; - if(!r.isOnlyRightSide()) continue; - auto products = splitRule(r.getDPORule(), dg->getLabelSettings().type, dg->getLabelSettings().withStereo, - [this](std::unique_ptr gCand) { - return dg->checkIfNew(std::move(gCand)).first; - }, - [](auto a, auto b) { - } + const auto &r = *br.rule; + assert(r.isOnlyRightSide()); + auto products = splitRule( + r.getDPORule(), ls.type, ls.withStereo, + [this](std::unique_ptr gCand) { + return dg->checkIfNew(std::move(gCand)).first; + }, + [verbosity, &logger](std::shared_ptr gWrapped, std::shared_ptr gPrev) { + if(verbosity >= V_RuleApplication_Binding) { + ++logger.indentLevel; + logger.indent() << "Discarding product " << gWrapped->getName() + << ", isomorphic to other product " << gPrev->getName() + << "." << std::endl; + --logger.indentLevel; + } + } ); for(const auto &p : products) dg->addProduct(p); @@ -317,16 +332,117 @@ Builder::apply(const std::vector > &graphs, rightGraphs.reserve(products.size()); for(const auto &p : products) rightGraphs.push_back(&p->getGraph()); - lib::DG::GraphMultiset gmsLeft(brp.boundGraphs), gmsRight(std::move(rightGraphs)); + lib::DG::GraphMultiset gmsLeft(br.boundGraphs), gmsRight(std::move(rightGraphs)); const auto derivationRes = dg->suggestDerivation(gmsLeft, gmsRight, &rOrig->getRule()); res.push_back(derivationRes); } - if(!graphs.empty()) { // otherwise boundRules is the original BoundRule - for(const BoundRule &p : boundRules) - delete p.rule; + for(const auto &br : resultRules) + delete br.rule; + + return res; +} + +std::vector> +Builder::applyRelaxed(const std::vector> &graphs, + std::shared_ptr rOrig, + int verbosity, IsomorphismPolicy graphPolicy) { + + IO::Logger logger(std::cout); + dg->rules.insert(rOrig); + switch(graphPolicy) { + case IsomorphismPolicy::Check: + for(const auto &g : graphs) + dg->tryAddGraph(g); + break; + case IsomorphismPolicy::TrustMe: + for(const auto &g : graphs) + dg->trustAddGraph(g); + break; + } + + if(verbosity >= V_RuleApplication) { + logger.indent() << "Binding " << graphs.size() << " graphs to rule '" << rOrig->getName() << "' with " + << rOrig->getNumLeftComponents() << " left-hand components." << std::endl; + ++logger.indentLevel; } + if(graphs.empty()) return {}; + std::vector libGraphs; + libGraphs.reserve(graphs.size()); + for(const auto &g : graphs) + libGraphs.push_back(&g->getGraph()); + + const auto ls = dg->getLabelSettings(); + // we must bind each graph, so increase the span of graphs one at a time, + // and only keep bound rules that still have left-hand components + std::vector inputRules{{&rOrig->getRule(), {}, 0}}; + std::vector> res; + for(int round = 0; round != rOrig->getNumLeftComponents(); ++round) { + const auto firstGraph = libGraphs.begin(); + const auto lastGraph = libGraphs.end(); + + const auto onOutput = [this, verbosity, ls, &res, rOrig] + (IO::Logger logger, BoundRule br) -> bool { + if(!br.rule->isOnlyRightSide()) + return true; + + const auto &r = *br.rule; + if(verbosity >= V_RuleApplication_Binding) { + logger.indent() << "Splitting " << r.getName() << " into " + << r.getDPORule().numRightComponents << " graphs" << std::endl; + ++logger.indentLevel; + } + + assert(r.isOnlyRightSide()); + auto products = splitRule( + r.getDPORule(), ls.type, ls.withStereo, + [this](std::unique_ptr gCand) { + return dg->checkIfNew(std::move(gCand)).first; + }, + [verbosity, &logger](std::shared_ptr gWrapped, std::shared_ptr gPrev) { + if(verbosity >= V_RuleApplication_Binding) { + ++logger.indentLevel; + logger.indent() << "Discarding product " << gWrapped->getName() + << ", isomorphic to other product " << gPrev->getName() + << "." << std::endl; + --logger.indentLevel; + } + } + ); + for(const auto &p : products) + dg->addProduct(p); + std::vector rightGraphs; + rightGraphs.reserve(products.size()); + for(const auto &p : products) + rightGraphs.push_back(&p->getGraph()); + lib::DG::GraphMultiset gmsLeft(br.boundGraphs), gmsRight(std::move(rightGraphs)); + const auto derivationRes = dg->suggestDerivation(gmsLeft, gmsRight, &rOrig->getRule()); + res.push_back(derivationRes); + + if(verbosity >= V_RuleApplication_Binding) + --logger.indentLevel; + + delete br.rule; + return true; + }; + std::vector outputRules = bindGraphs + (verbosity, logger, + round, + firstGraph, lastGraph, inputRules, + dg->graphAsRuleCache, ls, + onOutput); + for(BoundRule &br : outputRules) { + // always go to the next graph + ++br.nextGraphOffset; + } + if(round != 0) { + // in round 0 the inputRules is the actual original input rule, so don't delete it + for(auto &br : inputRules) + delete br.rule; + } + std::swap(inputRules, outputRules); + } // for each round based on numComponents return res; } @@ -432,8 +548,8 @@ bool Builder::trustLoadDump(nlohmann::json &&j, for(auto &jv : jVertices) { Vertex v; v.id = jv[0].get(); - std::istringstream iss(jv[2].get()); - auto gData = lib::IO::Graph::Read::gml(iss, err); + const std::string &gml = jv[2].get(); + auto gData = lib::IO::Graph::Read::gml(gml, err); if(!gData.g) { err << "Error when loading graph GML in DG dump, for graph '"; err << jv[1].get() << "', in vertex " << v.id << "."; @@ -454,7 +570,8 @@ bool Builder::trustLoadDump(nlohmann::json &&j, std::vector> rules; rules.reserve(jRules.size()); const auto ls = dg->getLabelSettings(); - for(const std::string &jr : jRules) { + for(const auto &j : jRules) { + const std::string &jr = j.get(); auto rCand = rule::Rule::ruleGMLString(jr, false); const auto iter = std::find_if(ruleDatabase.begin(), ruleDatabase.end(), [rCand, ls](const auto &r) { return r->isomorphism(rCand, 1, ls) == 1; @@ -465,7 +582,7 @@ bool Builder::trustLoadDump(nlohmann::json &&j, } else { rules.push_back(*iter); if(verbosity >= V_Link) { - IO::log() << "DG loading: loaded rule '" << rCand->getName() + std::cout << "DG loading: loaded rule '" << rCand->getName() << "' isomorphic to existing rule '" << (*iter)->getName() << "'." << std::endl; } } @@ -484,7 +601,7 @@ bool Builder::trustLoadDump(nlohmann::json &&j, const bool wasNewAsVertex = dg->trustAddGraphAsVertex(v.graph); graphFromId[v.id] = &v.graph->getGraph(); if(verbosity >= V_Link && !v.wasNew) { - IO::log() << "DG loading: loaded graph '" << jVertices[iVertices][1].get() + std::cout << "DG loading: loaded graph '" << jVertices[iVertices][1].get() << "' isomorphic to existing graph '" << v.graph->getName() << "'." << std::endl; } //if(wasNewAsVertex) giveProductStatus(v.graph); @@ -560,6 +677,4 @@ Builder NonHyperBuilder::build() { return Builder(this); } -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/NonHyperBuilder.hpp b/libs/libmod/src/mod/lib/DG/NonHyperBuilder.hpp index 89e695b..98ed712 100644 --- a/libs/libmod/src/mod/lib/DG/NonHyperBuilder.hpp +++ b/libs/libmod/src/mod/lib/DG/NonHyperBuilder.hpp @@ -1,14 +1,12 @@ -#ifndef MOD_LIB_DG_NONHYPERBUILDER_H -#define MOD_LIB_DG_NONHYPERBUILDER_H +#ifndef MOD_LIB_DG_NONHYPERBUILDER_HPP +#define MOD_LIB_DG_NONHYPERBUILDER_HPP #include #include +#include +#include -#include - -namespace mod { -namespace lib { -namespace DG { +namespace mod::lib::DG { namespace Strategies { struct GraphState; } // namespace Strategies @@ -35,8 +33,11 @@ struct Builder { // pre: strategy must not have been executed before (i.e., a newly constructed strategy, or a clone) ExecuteResult execute(std::unique_ptr strategy, int verbosity, bool ignoreRuleLabelTypes); std::vector> - apply(const std::vector > &graphs, std::shared_ptr r, + apply(const std::vector> &graphs, std::shared_ptr r, int verbosity, IsomorphismPolicy graphPolicy); + std::vector> + applyRelaxed(const std::vector> &graphs, std::shared_ptr r, + int verbosity, IsomorphismPolicy graphPolicy); void addAbstract(const std::string &description); bool load(const std::vector> &ruleDatabase, const std::string &file, std::ostream &err, int verbosity); @@ -68,10 +69,9 @@ struct NonHyperBuilder : public NonHyper { std::unique_ptr strategy; }; std::vector executions; + Rules::GraphAsRuleCache graphAsRuleCache; // referenced by the ExecutionEnvs }; -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG -#endif /* MOD_LIB_DG_NONHYPERBUILDER_H */ +#endif // MOD_LIB_DG_NONHYPERBUILDER_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/RuleApplicationUtils.hpp b/libs/libmod/src/mod/lib/DG/RuleApplicationUtils.hpp index 3266b19..4f6345f 100644 --- a/libs/libmod/src/mod/lib/DG/RuleApplicationUtils.hpp +++ b/libs/libmod/src/mod/lib/DG/RuleApplicationUtils.hpp @@ -1,34 +1,149 @@ -#ifndef MOD_LIB_DG_RULEAPPLICATIONUTILS_H -#define MOD_LIB_DG_RULEAPPLICATIONUTILS_H +#ifndef MOD_LIB_DG_RULEAPPLICATIONUTILS_HPP +#define MOD_LIB_DG_RULEAPPLICATIONUTILS_HPP #include #include #include #include +#include +#include +#include #include #include -namespace mod { -namespace lib { -namespace DG { +namespace mod::lib::DG { struct BoundRule { const lib::Rules::Real *rule; std::vector boundGraphs; + int nextGraphOffset; +public: + void makeCanonical() { + std::sort(begin(boundGraphs), end(boundGraphs), [](const auto *a, const auto *b) { + return a->getId() < b->getId(); + }); + } + + // pre: this->makeCanonical() and other.makeCanonical() must have been called. + bool isomorphicTo(const BoundRule &other, LabelSettings ls) const { + if(boundGraphs != other.boundGraphs) return false; + if(nextGraphOffset != other.nextGraphOffset) return false; + ls.relation = ls.stereoRelation = LabelRelation::Isomorphism; + return 1 == lib::Rules::Real::isomorphism(*rule, *other.rule, 1, ls); + } + + friend std::ostream &operator<<(std::ostream &s, const BoundRule &br) { + s << "{rule=" << br.rule->getName() << ", boundGraphs=["; + bool first = true; + for(const auto *g : br.boundGraphs) { + if(!first) s << ", "; + else first = false; + s << g->getName(); + } + s << "], nextGraphOffset=" << br.nextGraphOffset << "}"; + return s; + } }; +constexpr int V_RuleApplication = 2; +constexpr int V_RuleApplication_Binding = 4; + +inline int toRCVerbosity(int verbosity) { + return std::max(0, verbosity - V_RuleApplication_Binding); +} + +// BoundRules are given to onOutput. It must return a boolean indicating +// whether to continue the search. +// If a rule in a BoundRule given to onOutput is only-right-side, +// then onOutput gains responsibility for it. +// Otherwise, if there are still left-hand elements, then +// bindGraphs retains responsibility, and will return a list of all these. +// This is to do isomorphism checks. +template +[[nodiscard]] std::vector bindGraphs( + const int verbosity, IO::Logger &logger, + const int bindRound, + const Iter firstGraph, const Iter lastGraph, + const std::vector &inputRules, + Rules::GraphAsRuleCache &graphAsRuleCache, + const LabelSettings labelSettings, + OnOutput onOutput) { + if(verbosity >= V_RuleApplication) { + logger.indent() << "Bind round " << (bindRound + 1) << " with " + << (lastGraph - firstGraph) << " graphs " + << "and " << inputRules.size() << " rules." << std::endl; + ++logger.indentLevel; + } + int numDup = 0; + int numUnique = 0; + std::vector outputRules; + for(const BoundRule &brInput : inputRules) { + if(verbosity >= V_RuleApplication_Binding) { + logger.indent() << "Processing input rule " << brInput << std::endl; + ++logger.indentLevel; + } + // try to bind with all graphs that haven't been tried yet + assert(brInput.nextGraphOffset <= lastGraph - firstGraph); + const auto brFirstGraph = firstGraph + brInput.nextGraphOffset; + for(auto iterGraph = brFirstGraph; iterGraph != lastGraph; ++iterGraph) { + const auto *g = *iterGraph; + if(verbosity >= V_RuleApplication_Binding) { + logger.indent() << "Trying to bind " << g->getName() << " to " << brInput << ":" << std::endl; + ++logger.indentLevel; + } + const auto reporter = + [labelSettings, &logger, &brInput, &outputRules, firstGraph, iterGraph, onOutput, &numUnique, &numDup] + (std::unique_ptr r) -> bool { + BoundRule brOutput{r.release(), brInput.boundGraphs, + static_cast(iterGraph - firstGraph)}; + brOutput.boundGraphs.push_back(*iterGraph); + if(!brOutput.rule->isOnlyRightSide()) { + // check if we have it already + brOutput.makeCanonical(); + for(const BoundRule &brStored : outputRules) { + if(brStored.isomorphicTo(brOutput, labelSettings)) { + delete brOutput.rule; + ++numDup; + return true; + } + } + // we store a copy of the bound info so the user can mess with their copy + outputRules.push_back(brOutput); + } + ++numUnique; + return onOutput(logger, std::move(brOutput)); + }; + const lib::Rules::Real &rFirst = graphAsRuleCache.getBindRule(g)->getRule(); + const lib::Rules::Real &rSecond = *brInput.rule; + lib::RC::Super mm(toRCVerbosity(verbosity), logger, true, true); + lib::RC::composeRuleRealByMatchMaker(rFirst, rSecond, mm, reporter, labelSettings); + if(verbosity >= V_RuleApplication_Binding) + --logger.indentLevel; + } + if(verbosity >= V_RuleApplication_Binding) + --logger.indentLevel; + } + if(verbosity >= V_RuleApplication) { + logger.indent() << "Result of bind round " << (bindRound + 1) << ": " + << numUnique << " rules + " << numDup << " duplicates" << std::endl; + --logger.indentLevel; + } + return outputRules; +} + + struct BoundRuleStorage { BoundRuleStorage(bool verbose, IO::Logger logger, - LabelType labelType, - bool withStereo, - std::vector &ruleStore, - const BoundRule &rule, - const lib::Graph::Single *graph) + LabelType labelType, + bool withStereo, + std::vector &ruleStore, + const BoundRule &rule, + const lib::Graph::Single *graph) : verbose(verbose), logger(logger), labelType(labelType), withStereo(withStereo), ruleStore(ruleStore), rule(rule), graph(graph) {} void add(lib::Rules::Real *r) { - BoundRule p{r, rule.boundGraphs}; + BoundRule p{r, rule.boundGraphs, -1}; p.boundGraphs.push_back(graph); bool found = false; const bool doBoundRulesDuplicateCheck = true; @@ -56,13 +171,13 @@ struct BoundRuleStorage { } if(doContinue) continue; found = 1 == lib::Rules::Real::isomorphism(*r, *rp.rule, 1, - {labelType, LabelRelation::Isomorphism, withStereo, - LabelRelation::Isomorphism}); + {labelType, LabelRelation::Isomorphism, withStereo, + LabelRelation::Isomorphism}); if(found) break; } } if(found) { - // IO::log() << "Duplicate BRP found" << std::endl; + // std::cout << "Duplicate BRP found" << std::endl; delete r; } else { ruleStore.push_back(p); @@ -71,7 +186,7 @@ struct BoundRuleStorage { for(const auto *g : p.boundGraphs) logger.s << " " << g->getName(); logger.s << " }> onlyRight: " << std::boolalpha << r->isOnlySide(lib::Rules::Membership::Right) - << std::endl; + << std::endl; } } } @@ -86,6 +201,11 @@ struct BoundRuleStorage { const lib::Graph::Single *graph; }; + +// =========================================================================== +// =========================================================================== +// =========================================================================== + struct GraphData { using SideVertex = boost::graph_traits::vertex_descriptor; public: @@ -99,11 +219,11 @@ struct GraphData { }; template -std::vector > splitRule(const lib::Rules::LabelledRule &rDPO, - const LabelType labelType, - const bool withStereo, - CheckIfNew checkIfNew, - OnDup onDup) { +std::vector> splitRule(const lib::Rules::LabelledRule &rDPO, + const LabelType labelType, + const bool withStereo, + CheckIfNew checkIfNew, + OnDup onDup) { if(rDPO.numRightComponents == 0) MOD_ABORT; // continue; using Vertex = lib::Graph::Vertex; using Edge = lib::Graph::Edge; @@ -168,16 +288,16 @@ std::vector > splitRule(const lib::Rules::Labelled } // end foreach product } // end of stereo prop // wrap them - std::vector > right; + std::vector> right; for(auto &g : products) { // check against the database auto gCand = std::make_unique(std::move(g.gPtr), std::move(g.pStringPtr), - std::move(g.pStereoPtr)); + std::move(g.pStereoPtr)); std::shared_ptr gWrapped = checkIfNew(std::move(gCand)); // checkIfNew does not add the graph, so we must check against the previous products as well for(auto gPrev : right) { const auto ls = mod::LabelSettings(labelType, LabelRelation::Isomorphism, withStereo, - LabelRelation::Isomorphism); + LabelRelation::Isomorphism); const bool iso = lib::Graph::Single::isomorphic(gPrev->getGraph(), gWrapped->getGraph(), ls); if(iso) { onDup(gWrapped, gPrev); @@ -190,8 +310,6 @@ std::vector > splitRule(const lib::Rules::Labelled return right; } -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG -#endif /* MOD_LIB_DG_RULEAPPLICATIONUTILS_H */ \ No newline at end of file +#endif // MOD_LIB_DG_RULEAPPLICATIONUTILS_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Add.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Add.cpp index 5430368..5d14912 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Add.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Add.cpp @@ -5,10 +5,9 @@ #include #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +#include + +namespace mod::lib::DG::Strategies { Add::Add(const std::vector > graphs, bool onlyUniverse, IsomorphismPolicy graphPolicy) : Strategy::Strategy(0), @@ -60,11 +59,15 @@ bool Add::isConsumed(const lib::Graph::Single *g) const { void Add::executeImpl(PrintSettings settings, const GraphState &input) { if(settings.verbosity >= PrintSettings::V_Add) { if(onlyUniverse) - settings.indent() << "AddUniverse:" << std::endl; + settings.indent() << "AddUniverse"; + else + settings.indent() << "AddSubset"; + if(generator) + settings.s << " (dynamic):" << std::endl; else - settings.indent() << "AddSubset:" << std::endl; + settings.s << " (static):" << std::endl; } - std::vector > graphsToAdd; + std::vector> graphsToAdd; if(generator) { graphsToAdd = (*generator)(); if(std::any_of(graphsToAdd.begin(), graphsToAdd.end(), [](const auto &g) { @@ -74,9 +77,21 @@ void Add::executeImpl(PrintSettings settings, const GraphState &input) { } else { graphsToAdd = graphs; } + if(settings.verbosity >= PrintSettings::V_Add) { + ++settings.indentLevel; + // print the graphs, 5 per line + for(int i = 0; i != graphsToAdd.size(); ++i) { + if(i % 5 == 0 && i != 0) settings.s << std::endl; + if(i % 5 == 0) settings.indent(); + else settings.s << " "; + settings.s << graphsToAdd[i]->getName(); + } + settings.s << std::endl; + --settings.indentLevel; + } switch(graphPolicy) { case IsomorphismPolicy::Check: - for(const std::shared_ptr g : graphsToAdd) { + for(const std::shared_ptr &g : graphsToAdd) { // TODO: we need to add it as a vertex for backwards compatibility, // do this more elegantly // TODO: actually, if this is a static add strategy, the graphs are probably already added, @@ -86,21 +101,18 @@ void Add::executeImpl(PrintSettings settings, const GraphState &input) { } break; case IsomorphismPolicy::TrustMe: - for(const std::shared_ptr g : graphsToAdd) + for(const auto &g : graphsToAdd) getExecutionEnv().trustAddGraphAsVertex(g); break; } output = new GraphState(input); if(onlyUniverse) { - for(const std::shared_ptr g : graphsToAdd) + for(const auto &g : graphsToAdd) output->addToUniverse(&g->getGraph()); } else { - for(const std::shared_ptr g : graphsToAdd) - output->addToSubset(0, &g->getGraph()); + for(const auto &g : graphsToAdd) + output->addToSubset(&g->getGraph()); } } -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::DG::Strategies \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Add.hpp b/libs/libmod/src/mod/lib/DG/Strategies/Add.hpp index f468e48..5fc1390 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Add.hpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Add.hpp @@ -1,14 +1,13 @@ -#ifndef MOD_LIB_DG_STRATEGIES_ADD_H -#define MOD_LIB_DG_STRATEGIES_ADD_H +#ifndef MOD_LIB_DG_STRATEGIES_ADD_HPP +#define MOD_LIB_DG_STRATEGIES_ADD_HPP #include namespace mod { template class Function; -namespace lib { -namespace DG { -namespace Strategies { +} // namespace mod +namespace mod::lib::DG::Strategies { struct Add : Strategy { // pre: no nullptrs in graphs @@ -30,10 +29,6 @@ struct Add : Strategy { const IsomorphismPolicy graphPolicy; }; -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_DG_STRATEGIES_ADD_H */ +} // namespace mod::lib::DG::Strategies +#endif // MOD_LIB_DG_STRATEGIES_ADD_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Execute.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Execute.cpp index ea1b8fc..d3a875a 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Execute.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Execute.cpp @@ -40,10 +40,12 @@ void Execute::executeImpl(PrintSettings settings, const GraphState &input) { printInfo(settings); dg::Strategy::GraphState gs( [&input](std::vector > &subset) { - for(const lib::Graph::Single *g : input.getSubset(0)) subset.push_back(g->getAPIReference()); + for(const lib::Graph::Single *g : input.getSubset()) + subset.push_back(g->getAPIReference()); }, [&input](std::vector > &universe) { - for(const lib::Graph::Single *g : input.getUniverse()) universe.push_back(g->getAPIReference()); + for(const lib::Graph::Single *g : input.getUniverse()) + universe.push_back(g->getAPIReference()); }); (*func)(gs); } diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Filter.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Filter.cpp index b0d002d..e7f2b2c 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Filter.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Filter.cpp @@ -11,7 +11,7 @@ namespace DG { namespace Strategies { Filter::Filter(std::shared_ptr, const dg::Strategy::GraphState &, - bool)> > filterFunc, bool filterUniverse) + bool)> > filterFunc, bool filterUniverse) : Strategy(1), filterFunc(filterFunc), filterUniverse(filterUniverse) { assert(filterFunc); } @@ -54,29 +54,25 @@ void Filter::executeImpl(PrintSettings settings, const GraphState &input) { assert(!output); dg::Strategy::GraphState graphState( [&input](std::vector > &subset) { - for(const lib::Graph::Single *g : input.getSubset(0)) subset.push_back(g->getAPIReference()); + for(const lib::Graph::Single *g : input.getSubset()) + subset.push_back(g->getAPIReference()); }, [&input](std::vector > &universe) { - for(const lib::Graph::Single *g : input.getUniverse()) universe.push_back(g->getAPIReference()); + for(const lib::Graph::Single *g : input.getUniverse()) + universe.push_back(g->getAPIReference()); }); if(!filterUniverse) { output = new GraphState(input.getUniverse()); - assert(input.getSubsets().size() == 1); // TODO: fix when filter is parameterized by subset - assert(input.hasSubset(0)); - unsigned int subsetIndex = 0; bool first = true; - for(const lib::Graph::Single *g : input.getSubset(subsetIndex)) { + for(const lib::Graph::Single *g : input.getSubset()) { // TODO: the adding to the subset could be faster as the index is the same as in the input ResultSet if((*filterFunc)(g->getAPIReference(), graphState, first)) { assert(output->isInUniverse(g)); - output->addToSubset(subsetIndex, g); + output->addToSubset(g); } first = false; } - // TODO: add the complete other subsets - assert(input.getSubsets().size() == 1); // TODO: fix when filter is parameterized by subset - assert(input.hasSubset(0)); } else { std::map copyToOutput; bool first = true; @@ -91,13 +87,11 @@ void Filter::executeImpl(PrintSettings settings, const GraphState &input) { } output = new GraphState(newUniverse); - for(const GraphState::SubsetStore::value_type &p : input.getSubsets()) { - for(const lib::Graph::Single *g : p.second) { - // TODO: this could be faster if we had access to the individual indices, as we could map old to new - if(copyToOutput[g]) { - assert(output->isInUniverse(g)); - output->addToSubset(p.first, g); - } + for(const lib::Graph::Single *g : input.getSubset()) { + // TODO: this could be faster if we had access to the individual indices, as we could map old to new + if(copyToOutput[g]) { + assert(output->isInUniverse(g)); + output->addToSubset(g); } } } diff --git a/libs/libmod/src/mod/lib/DG/Strategies/GraphState.cpp b/libs/libmod/src/mod/lib/DG/Strategies/GraphState.cpp index 9290c54..a115245 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/GraphState.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/GraphState.cpp @@ -3,112 +3,51 @@ #include #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { - -void GraphState::commonInit() { - // subset 0 is special - subsets.insert(SubsetStore::value_type(0, Subset(*this))); - assert(subsets.size() >= 1); - assert(subsets.begin()->first == 0); -} +namespace mod::lib::DG::Strategies { -GraphState::GraphState() { - commonInit(); -} +GraphState::GraphState() : subset(*this) {} -GraphState::GraphState(const GraphState &other) : universe(other.universe) { - assert(other.subsets.size() >= 1); - assert(other.subsets.begin()->first == 0); - // commonInit is not needed, as other should have subset 0 - // we need to give the subsets new owners - for(const SubsetStore::value_type &p : other.subsets) { - assert(p.first == 0); // TODO: remove - subsets.insert(SubsetStore::value_type(p.first, Subset(*this, p.second))); - } -} +GraphState::GraphState(const GraphState &other) + : universe(other.universe), subset(*this, other.subset) {} -GraphState::GraphState(const std::vector &universe) : universe(universe) { - commonInit(); -} +GraphState::GraphState(const std::vector &universe) + : universe(universe), subset(*this) {} -GraphState::GraphState(const std::vector &resultSets) { -#ifndef NDEBUG - for(const GraphState *rs : resultSets) { - assert(rs->subsets.size() >= 1); - assert(rs->subsets.begin()->first == 0); - } -#endif +GraphState::GraphState(const std::vector &resultSets) : subset(*this) { // collect universe - for(const GraphState *rs : resultSets) { GraphState::GraphList other(rs->getUniverse()); - - std::sort(other.begin(), other.end(), [](const Graph::Single *g1, const Graph::Single * g2) { + std::sort(other.begin(), other.end(), [](const Graph::Single *g1, const Graph::Single *g2) { return g1->getId() < g2->getId(); }); - GraphState::GraphList result; - std::set_union(universe.begin(), universe.end(), other.begin(), other.end(), std::back_inserter(result), lib::Graph::Single::IdLess()); + GraphState::GraphList result; + std::set_union(universe.begin(), universe.end(), other.begin(), other.end(), + std::back_inserter(result), + lib::Graph::Single::IdLess()); std::swap(result, universe); } - // collect all subsets - using NewSubsetStore = std::map >; - NewSubsetStore newSubsets; - // make sure the special 0th subset is there - newSubsets.insert(std::make_pair(0, std::set())); - for(const GraphState *rs : resultSets) { - for(const SubsetStore::value_type &p : rs->subsets) { - assert(p.first == 0); // TODO: remove - for(const Graph::Single *g : p.second) newSubsets[p.first].insert(g); - } - } + // collect the subset + std::set newSubset; + for(const GraphState *rs : resultSets) + for(const Graph::Single *g : rs->subset) + newSubset.insert(g); - using GraphToIndex = std::map; + using GraphToIndex = std::map; GraphToIndex graphToIndex; - for(unsigned int i = 0; i < universe.size(); i++) graphToIndex[universe[i]] = i; - - for(const NewSubsetStore::value_type &newSubset : newSubsets) { - assert(newSubset.first == 0); // TODO: remove - std::pair < SubsetStore::iterator, bool> p = subsets.insert(std::make_pair(newSubset.first, Subset(*this))); - assert(p.second); - Subset &subset = p.first->second; - for(const Graph::Single *g : newSubset.second) subset.indices.push_back(graphToIndex[g]); - } + for(int i = 0; i != universe.size(); i++) + graphToIndex[universe[i]] = i; - assert(subsets.size() >= 1); - assert(subsets.begin()->first == 0); + for(const Graph::Single *g : newSubset) + subset.indices.push_back(graphToIndex[g]); } -GraphState::~GraphState() { } - -//void GraphState::promoteToSubset(unsigned int subsetIndex, const lib::Graph::Single *g) { -// unsigned int oldUniverseSize = universe.size(); -// unsigned int gIndex = addUniverseGetIndex(g); -// if(gIndex != oldUniverseSize) return; -// -// SubsetStore::iterator iter = subsets.find(subsetIndex); -// if(iter == subsets.end()) iter = subsets.insert(SubsetStore::value_type(subsetIndex, Subset(*this))).first; -// Subset &subset = iter->second; -// -// for(unsigned int index : subset.indices) { -// if(index == gIndex) return; -// } -// subset.indices.push_back(gIndex); -//} - -void GraphState::addToSubset(unsigned int subsetIndex, const lib::Graph::Single *g) { - unsigned int gIndex = addUniverseGetIndex(g); - - SubsetStore::iterator iter = subsets.find(subsetIndex); - if(iter == subsets.end()) iter = subsets.insert(SubsetStore::value_type(subsetIndex, Subset(*this))).first; - Subset &subset = iter->second; - - for(unsigned int index : subset.indices) { +GraphState::~GraphState() {} + +void GraphState::addToSubset(const lib::Graph::Single *g) { + const int gIndex = addUniverseGetIndex(g); + for(int index : subset.indices) if(index == gIndex) return; - } subset.indices.push_back(gIndex); } @@ -116,21 +55,8 @@ void GraphState::addToUniverse(const Graph::Single *g) { addUniverseGetIndex(g); } -bool GraphState::hasSubset(unsigned int i) const { - return subsets.find(i) != subsets.end(); -} - -const GraphState::Subset &GraphState::getSubset(unsigned int i) const { - if(!hasSubset(i)) { - IO::log() << "WTF: hasSubset(" << i << ") == false" << std::endl; - IO::log() << "WTF: numSubsets: " << subsets.size() << std::endl; - } - assert(hasSubset(i)); - return subsets.find(i)->second; -} - -const GraphState::SubsetStore &GraphState::getSubsets() const { - return subsets; +const GraphState::Subset &GraphState::getSubset() const { + return subset; } const GraphState::GraphList &GraphState::getUniverse() const { @@ -138,54 +64,36 @@ const GraphState::GraphList &GraphState::getUniverse() const { } bool GraphState::isInUniverse(const lib::Graph::Single *g) const { - for(unsigned int i = 0; i < universe.size(); i++) { - if(universe[i] == g) return true; - } + for(int i = 0; i != universe.size(); i++) + if(universe[i] == g) + return true; return false; } bool operator==(const GraphState &a, const GraphState &b) { - typedef GraphState::SubsetStore::const_iterator Iter; - {// check sizes - if(a.universe.size() != b.universe.size()) return false; - if(a.subsets.size() != b.subsets.size()) return false; - Iter ai, ae, bi, be; - for(ai = a.subsets.begin(), ae = a.subsets.end(), - bi = b.subsets.begin(), be = b.subsets.end(); - ai != ae && bi != be; ai++, bi++) { - if(ai->first != bi->first) return false; - if(ai->second.size() != bi->second.size()) return false; - } - } + if(a.universe.size() != b.universe.size()) return false; + if(a.subset.size() != b.subset.size()) return false; GraphState aCopy(a), bCopy(b); - std::less comp; + std::less comp; aCopy.sortUniverse(comp); bCopy.sortUniverse(comp); - for(unsigned int i = 0; i < a.universe.size(); i++) { - if(aCopy.universe[i] != bCopy.universe[i]) return false; - } - Iter ai, ae, bi, be; - for(ai = aCopy.subsets.begin(), ae = aCopy.subsets.end(), - bi = bCopy.subsets.begin(), be = bCopy.subsets.end(); - ai != ae && bi != be; ai++, bi++) { - aCopy.sortSubset(ai->first, comp); - bCopy.sortSubset(bi->first, comp); - for(unsigned int i = 0; i < ai->second.size(); i++) { - if(*(ai->second.begin() + i) != *(bi->second.begin() + i)) return false; - } - } + for(int i = 0; i != a.universe.size(); i++) + if(aCopy.universe[i] != bCopy.universe[i]) + return false; + aCopy.sortSubset(comp); + bCopy.sortSubset(comp); + for(int i = 0; i != aCopy.subset.size(); i++) + if(*(aCopy.subset.begin() + i) != *(bCopy.subset.begin() + i)) + return false; return true; } -unsigned int GraphState::addUniverseGetIndex(const lib::Graph::Single *g) { - for(unsigned int i = 0; i < universe.size(); i++) { - if(universe[i] == g) return i; - } +int GraphState::addUniverseGetIndex(const lib::Graph::Single *g) { + for(int i = 0; i != universe.size(); i++) + if(universe[i] == g) + return i; universe.push_back(g); return universe.size() - 1; } -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::DG::Strategies \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/GraphState.hpp b/libs/libmod/src/mod/lib/DG/Strategies/GraphState.hpp index 32ffaa5..725b94c 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/GraphState.hpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/GraphState.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_DG_STRATEGIES_GRAPHSTATE_H -#define MOD_LIB_DG_STRATEGIES_GRAPHSTATE_H +#ifndef MOD_LIB_DG_STRATEGIES_GRAPHSTATE_HPP +#define MOD_LIB_DG_STRATEGIES_GRAPHSTATE_HPP #include @@ -8,13 +8,11 @@ #include #include -namespace mod { -namespace lib { +namespace mod::lib { namespace Graph { class Single; } // namespace Graph -namespace DG { -namespace Strategies { +namespace DG::Strategies { struct GraphState { using GraphList = std::vector; @@ -22,15 +20,15 @@ struct GraphState { struct Subset { struct Transformer { Transformer(const GraphList &graphs) : graphs(graphs) {} - GraphList::value_type operator()(unsigned int i) const { + GraphList::value_type operator()(int i) const { assert(i < graphs.size()); return graphs[i]; } private: const GraphList &graphs; }; - using const_iterator = boost::transform_iterator::const_iterator, const lib::Graph::Single *>; - using size_type = std::vector::size_type; + using const_iterator = boost::transform_iterator::const_iterator, const lib::Graph::Single *>; + using size_type = std::vector::size_type; public: explicit Subset(const GraphState &rs) : rs(rs) {} explicit Subset(const GraphState &rs, const Subset &other) : rs(rs), indices(other.indices) {} @@ -50,14 +48,15 @@ struct GraphState { bool empty() const { return indices.empty(); } + + std::vector getIndices() const { + return indices; + } private: friend class GraphState; const GraphState &rs; - std::vector indices; + std::vector indices; }; - using SubsetStore = std::unordered_map; -private: - void commonInit(); private: GraphState &operator=(const GraphState &other); // disable public: @@ -66,37 +65,33 @@ struct GraphState { explicit GraphState(const std::vector &universe); explicit GraphState(const std::vector &resultSets); ~GraphState(); - // void promoteToSubset(unsigned int subsetIndex, const lib::Graph::Single *g); - void addToSubset(unsigned int subsetIndex, const lib::Graph::Single *g); + void addToSubset(const lib::Graph::Single *g); void addToUniverse(const lib::Graph::Single *g); template struct Compare; template void sortUniverse(const T compare); template - void sortSubset(unsigned int subsetIndex, const T compare); - bool hasSubset(unsigned int subsetIndex) const; - const Subset &getSubset(unsigned int i) const; - const SubsetStore &getSubsets() const; + void sortSubset(const T compare); + const Subset &getSubset() const; const GraphList &getUniverse() const; bool isInUniverse(const lib::Graph::Single *g) const; friend bool operator==(const GraphState &a, const GraphState &b); private: - unsigned int addUniverseGetIndex(const lib::Graph::Single *g); + int addUniverseGetIndex(const lib::Graph::Single *g); private: GraphList universe; - SubsetStore subsets; + Subset subset; }; template class GraphState::Compare { Compare(); public: - explicit Compare(const GraphState::GraphList &graphs, T compare) : graphs(graphs), compare(compare) {} - bool operator()(unsigned int a, unsigned int b) { + bool operator()(int a, int b) { assert(a < graphs.size()); assert(b < graphs.size()); assert(graphs[a]); @@ -109,39 +104,34 @@ class GraphState::Compare { template void GraphState::sortUniverse(T compare) { - std::vector newToOld(universe.size()); - for(unsigned int i = 0; i < newToOld.size(); i++) newToOld[i] = i; + std::vector newToOld(universe.size()); + for(int i = 0; i != newToOld.size(); i++) newToOld[i] = i; Compare comp(universe, compare); std::stable_sort(newToOld.begin(), newToOld.end(), comp); - std::vector oldToNew(universe.size()); - for(unsigned int i = 0; i < universe.size(); i++) oldToNew[newToOld[i]] = i; + std::vector oldToNew(universe.size()); + for(int i = 0; i != universe.size(); i++) + oldToNew[newToOld[i]] = i; { GraphList newUniverse(universe.size()); - for(unsigned int i = 0; i < universe.size(); i++) newUniverse[i] = universe[newToOld[i]]; + for(int i = 0; i != universe.size(); i++) + newUniverse[i] = universe[newToOld[i]]; std::swap(newUniverse, universe); } { // TODO: remove, stupid sanity check - for(unsigned int i = 1; i < universe.size(); i++) assert(!compare(universe[i], universe[i - 1])); + for(int i = 1; i < universe.size(); i++) + assert(!compare(universe[i], universe[i - 1])); } - // substitute subset ids - for(SubsetStore::value_type &p : subsets) - for(unsigned int i = 0; i < p.second.indices.size(); i++) - p.second.indices[i] = oldToNew[p.second.indices[i]]; + for(unsigned int i = 0; i != subset.indices.size(); i++) + subset.indices[i] = oldToNew[subset.indices[i]]; } template -void GraphState::sortSubset(unsigned int subsetIndex, T compare) { - assert(hasSubset(subsetIndex)); - SubsetStore::iterator iter = subsets.find(subsetIndex); - assert(iter != subsets.end()); - Subset &subset = iter->second; +void GraphState::sortSubset(T compare) { Compare comp(universe, compare); std::stable_sort(subset.indices.begin(), subset.indices.end(), comp); } -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace DG::Strategies +} // namespace mod::lib -#endif /* MOD_LIB_DG_STRATEGIES_GRAPHSTATE_H */ \ No newline at end of file +#endif // MOD_LIB_DG_STRATEGIES_GRAPHSTATE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Parallel.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Parallel.cpp index 47ad133..8edacad 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Parallel.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Parallel.cpp @@ -81,8 +81,7 @@ void Parallel::executeImpl(PrintSettings settings, const GraphState &input) { outputs.push_back(&strat->getOutput()); output = new GraphState(outputs); output->sortUniverse(Graph::Single::nameLess); - for(const GraphState::SubsetStore::value_type &vt : output->getSubsets()) - output->sortSubset(vt.first, Graph::Single::nameLess); + output->sortSubset(Graph::Single::nameLess); } } // namespace Strategies diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Repeat.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Repeat.cpp index 6467cfa..e4c23aa 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Repeat.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Repeat.cpp @@ -3,12 +3,9 @@ #include #include -#include +#include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { Repeat::Repeat(Strategy *strat, int limit) : Strategy(strat->getMaxComponents()), strat(strat), limit(limit) { @@ -46,7 +43,7 @@ void Repeat::printInfo(PrintSettings settings) const { const GraphState &Repeat::getOutput() const { assert(!subStrats.empty()); - if(subStrats.back()->getOutput().getSubset(0).empty()) { + if(subStrats.back()->getOutput().getSubset().empty()) { if(subStrats.size() == 1) return *input; else return subStrats[subStrats.size() - 2]->getOutput(); } else return subStrats.back()->getOutput(); @@ -81,16 +78,14 @@ void Repeat::executeImpl(PrintSettings settings, const GraphState &input) { if(settings.verbosity >= PrintSettings::V_Repeat) { settings.indent() << "Round " << (i + 1) << ": Result subset has " - << subStrat->getOutput().getSubset(0).size() - << " graphs." << std::endl; + << subStrat->getOutput().getSubset().size() + << " graphs." << std::endl; } subStrats.push_back(subStrat); - if(!getConfig().dg.ignoreSubset.get()) { - if(subStrat->getOutput().getSubset(0).empty()) { - if(settings.verbosity >= PrintSettings::V_RepeatBreak) - settings.indent() << "Round " << (i + 1) << ": Breaking repeat due to empty subset." << std::endl; - break; - } + if(subStrat->getOutput().getSubset().empty()) { + if(settings.verbosity >= PrintSettings::V_RepeatBreak) + settings.indent() << "Round " << (i + 1) << ": Breaking repeat due to empty subset." << std::endl; + break; } if(!getConfig().dg.disableRepeatFixedPointCheck.get()) { if(i > 0) { @@ -104,7 +99,4 @@ void Repeat::executeImpl(PrintSettings settings, const GraphState &input) { } } -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::DG::Strategies \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Repeat.hpp b/libs/libmod/src/mod/lib/DG/Strategies/Repeat.hpp index 7b27d9c..9fa8fed 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Repeat.hpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Repeat.hpp @@ -1,12 +1,9 @@ -#ifndef MOD_LIB_DG_STRATEGIES_REPEAT_H -#define MOD_LIB_DG_STRATEGIES_REPEAT_H +#ifndef MOD_LIB_DG_STRATEGIES_REPEAT_HPP +#define MOD_LIB_DG_STRATEGIES_REPEAT_HPP #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { struct Repeat : Strategy { // pre: limit > 0 @@ -27,9 +24,6 @@ struct Repeat : Strategy { std::vector subStrats; }; -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG::Strategies -#endif /* MOD_LIB_DG_STRATEGIES_REPEAT_H */ \ No newline at end of file +#endif // MOD_LIB_DG_STRATEGIES_REPEAT_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Revive.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Revive.cpp index a88a3a6..56d1c9c 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Revive.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Revive.cpp @@ -4,12 +4,9 @@ #include #include -#include +#include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { Revive::Revive(Strategy *strat) : Strategy(strat->getMaxComponents()), strat(strat) {} @@ -56,15 +53,12 @@ void Revive::executeImpl(PrintSettings settings, const GraphState &input) { strat->execute(settings, input); output = new GraphState(strat->getOutput()); - for(const auto *g : input.getSubset(0)) { + for(const auto *g : input.getSubset()) { if(!strat->isConsumed(g) && output->isInUniverse(g)) { - output->addToSubset(0, g); + output->addToSubset(g); revivedGraphs.push_back(g); } } } -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG::Strategies \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Revive.hpp b/libs/libmod/src/mod/lib/DG/Strategies/Revive.hpp index a023107..8c50ba2 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Revive.hpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Revive.hpp @@ -1,19 +1,16 @@ -#ifndef MOD_LIB_DG_STRATEGIES_REVIVE_H -#define MOD_LIB_DG_STRATEGIES_REVIVE_H +#ifndef MOD_LIB_DG_STRATEGIES_REVIVE_HPP +#define MOD_LIB_DG_STRATEGIES_REVIVE_HPP #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { struct Revive : Strategy { Revive(Strategy *strat); virtual ~Revive() override; virtual Strategy *clone() const override; virtual void preAddGraphs(std::function, IsomorphismPolicy)> add) const override; - virtual void forEachRule(std::function f) const override; + virtual void forEachRule(std::function f) const override; virtual void printInfo(PrintSettings settings) const override; virtual bool isConsumed(const lib::Graph::Single *g) const override; private: @@ -21,13 +18,9 @@ struct Revive : Strategy { virtual void executeImpl(PrintSettings settings, const GraphState &input) override; private: Strategy *strat; - std::vector revivedGraphs; + std::vector revivedGraphs; }; -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_DG_STRATEGIES_REVIVE_H */ +} // namespace mod::lib::DG::Strategies +#endif // MOD_LIB_DG_STRATEGIES_REVIVE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Rule.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Rule.cpp index 64eada5..9b74618 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Rule.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Rule.cpp @@ -10,10 +10,7 @@ #include #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { Rule::Rule(std::shared_ptr r) : Strategy(std::max(r->getRule().getDPORule().numLeftComponents, r->getRule().getDPORule().numRightComponents)), @@ -62,73 +59,61 @@ struct Context { std::unordered_set &consumedGraphs; }; -void handleBoundRulePair(PrintSettings settings, Context context, const BoundRule &brp) { +void handleBoundRulePair(int verbosity, IO::Logger logger, Context context, const BoundRule &brp) { assert(brp.rule); - // use a smart pointer so the rule for sure is deallocated, even though we do a 'continue' + // TODO: use a smart pointer so the rule for sure is deallocated, even though we do a 'continue' const lib::Rules::Real &r = *brp.rule; const auto &rDPO = r.getDPORule(); - assert( - r.isOnlyRightSide()); // otherwise, it should have been deallocated. All max component results should be only right side + assert(r.isOnlyRightSide()); // otherwise, it should have been deallocated. + // All max component results should be only right side mod::Derivation d; d.r = context.r; for(const lib::Graph::Single *g : brp.boundGraphs) d.left.push_back(g->getAPIReference()); { // left predicate bool result = context.executionEnv.checkLeftPredicate(d); if(!result) { - if(settings.verbosity >= PrintSettings::V_DerivationPredicatesFail) - settings.indent() << "Skipping " << r.getName() << " due to leftPredicate" << std::endl; + if(verbosity >= PrintSettings::V_DerivationPredicatesFail) + logger.indent() << "Skipping " << r.getName() << " due to leftPredicate" << std::endl; return; } } - if(settings.verbosity >= PrintSettings::V_RuleApplication) - settings.indent() << "Splitting " << r.getName() << " into " - << rDPO.numRightComponents << " graphs:" << std::endl; + if(verbosity >= PrintSettings::V_RuleApplication) { + logger.indent() << "Splitting " << r.getName() << " into " + << rDPO.numRightComponents << " graphs" << std::endl; + ++logger.indentLevel; + } const std::vector &educts = brp.boundGraphs; d.right = splitRule( rDPO, context.executionEnv.labelSettings.type, context.executionEnv.labelSettings.withStereo, [&context](std::unique_ptr gCand) { return context.executionEnv.checkIfNew(std::move(gCand)); }, - [&settings](std::shared_ptr gWrapped, std::shared_ptr gPrev) { - if(settings.verbosity >= PrintSettings::V_RuleApplication) - settings.indent() << "Discarding product " << gWrapped->getName() - << ", isomorphic to other product " << gPrev->getName() - << "." << std::endl; + [verbosity, &logger](std::shared_ptr gWrapped, std::shared_ptr gPrev) { + if(verbosity >= PrintSettings::V_RuleApplication) + logger.indent() << "Discarding product " << gWrapped->getName() + << ", isomorphic to other product " << gPrev->getName() + << "." << std::endl; } ); + if(verbosity >= PrintSettings::V_RuleApplication) + --logger.indentLevel; - if(getConfig().dg.onlyProduceMolecules.get()) { - for(std::shared_ptr g : d.right) { - if(!g->getIsMolecule()) { - IO::log() << "Error: non-molecule produced; '" << g->getName() << "'" << std::endl - << "Derivation is:" << std::endl - << "\tEducts:" << std::endl; - for(const lib::Graph::Single *g : educts) - IO::log() << "\t\t'" << g->getName() << "'\t" << g->getGraphDFS().first << std::endl; - IO::log() << "\tProducts:" << std::endl; - for(std::shared_ptr g : d.right) - IO::log() << "\t\t'" << g->getName() << "'\t" << g->getGraphDFS() << std::endl; - IO::log() << "Rule is '" << context.r->getName() << "'" << std::endl; - std::exit(1); - } - } - } { // right predicates bool result = context.executionEnv.checkRightPredicate(d); if(!result) { - if(settings.verbosity >= PrintSettings::V_DerivationPredicatesFail) - settings.indent() << "Skipping " << r.getName() << " due to rightPredicate" << std::endl; + if(verbosity >= PrintSettings::V_DerivationPredicatesFail) + logger.indent() << "Skipping " << r.getName() << " due to rightPredicate" << std::endl; return; } } { // now the derivation is good, so add the products to output if(getConfig().dg.putAllProductsInSubset.get()) { for(const auto &g : d.right) - context.output->addToSubset(0, &g->getGraph()); + context.output->addToSubset(&g->getGraph()); } else { for(const auto &g : d.right) if(!context.output->isInUniverse(&g->getGraph())) - context.output->addToSubset(0, &g->getGraph()); + context.output->addToSubset(&g->getGraph()); } for(const auto &g : d.right) context.executionEnv.addProduct(g); @@ -149,7 +134,8 @@ template unsigned int bindGraphs(PrintSettings settings, Context context, const GraphRange &graphRange, const std::vector &rules, - std::vector &outputRules) { + std::vector &outputRules, + Rules::GraphAsRuleCache &graphAsRuleCache) { unsigned int processedRules = 0; for(const lib::Graph::Single *g : graphRange) { @@ -170,7 +156,7 @@ unsigned int bindGraphs(PrintSettings settings, Context context, return true; }; assert(p.rule); - const lib::Rules::Real &rFirst = g->getBindRule()->getRule(); + const lib::Rules::Real &rFirst = graphAsRuleCache.getBindRule(g)->getRule(); const lib::Rules::Real &rSecond = *p.rule; lib::RC::Super mm( std::max(0, settings.verbosity - PrintSettings::V_RCMorphismGenBase), @@ -181,7 +167,7 @@ unsigned int bindGraphs(PrintSettings settings, Context context, processedRules++; if(context.executionEnv.doExit()) delete brp.rule; else if(brp.rule->isOnlyRightSide()) { - handleBoundRulePair(settings, context, brp); + handleBoundRulePair(settings.verbosity, settings, context, brp); delete brp.rule; } else outputRules.push_back(brp); } @@ -222,58 +208,104 @@ void Rule::executeImpl(PrintSettings settings, const GraphState &input) { output = new GraphState(input.getUniverse()); if(getExecutionEnv().doExit()) { if(settings.verbosity >= PrintSettings::V_Rule) - settings.indent() << "Exit requrested, skipping." << std::endl; + settings.indent() << "Exit requested, skipping." << std::endl; return; } - std::vector > intermediaryRules(rRaw->getDPORule().numLeftComponents + 1); - { - BoundRule p; - p.rule = rRaw; - intermediaryRules[0].push_back(p); - } - Context context{r, getExecutionEnv(), output, consumedGraphs}; - const auto &subset = input.getSubset(0); - const auto &universe = input.getUniverse(); - for(unsigned int i = 1; i <= rRaw->getDPORule().numLeftComponents; i++) { - if(settings.verbosity >= PrintSettings::V_RuleBinding) { - settings.indent() << "Component bind round " << i << " with "; - ++settings.indentLevel; - if(i == 1) { - if(!getConfig().dg.ignoreSubset.get()) { - IO::log() << subset.size() << " graphs"; + + if(getConfig().dg.useOldRuleApplication.get()) { + std::vector> intermediaryRules(rRaw->getDPORule().numLeftComponents + 1); + { + BoundRule p; + p.rule = rRaw; + intermediaryRules[0].push_back(p); + } + Context context{r, getExecutionEnv(), output, consumedGraphs}; + const auto &subset = input.getSubset(); + const auto &universe = input.getUniverse(); + for(unsigned int i = 1; i <= rRaw->getDPORule().numLeftComponents; i++) { + if(settings.verbosity >= PrintSettings::V_RuleBinding) { + settings.indent() << "Component bind round " << i << " with "; + ++settings.indentLevel; + if(i == 1) { + std::cout << subset.size() << " graphs"; } else { - IO::log() << universe.size() << " graphs"; + std::cout << universe.size() << " graphs and " << intermediaryRules[i - 1].size() << " intermediaries"; } - } else { - IO::log() << universe.size() << " graphs and " << intermediaryRules[i - 1].size() << " intermediaries"; + std::cout << std::endl; } - IO::log() << std::endl; - } - std::size_t processedRules = 0; - if(i == 1) { - if(!getConfig().dg.ignoreSubset.get()) { - processedRules = bindGraphs(settings, context, subset, intermediaryRules[0], intermediaryRules[1]); + std::size_t processedRules = 0; + if(i == 1) { + processedRules = bindGraphs(settings, context, subset, intermediaryRules[0], intermediaryRules[1], + getExecutionEnv().graphAsRuleCache); } else { - processedRules = bindGraphs(settings, context, universe, intermediaryRules[0], intermediaryRules[1]); + processedRules = bindGraphs(settings, context, universe, intermediaryRules[i - 1], intermediaryRules[i], + getExecutionEnv().graphAsRuleCache); + for(BoundRule &p : intermediaryRules[i - 1]) { + delete p.rule; + p.rule = nullptr; + } } - } else { - processedRules = bindGraphs(settings, context, universe, intermediaryRules[i - 1], intermediaryRules[i]); - for(BoundRule &p : intermediaryRules[i - 1]) { - delete p.rule; - p.rule = nullptr; + if(settings.verbosity >= PrintSettings::V_RuleBinding) { + settings.indent() << "Processing of " << processedRules << " intermediary rules done" << std::endl; + --settings.indentLevel; } + if(context.executionEnv.doExit()) break; } - if(settings.verbosity >= PrintSettings::V_RuleBinding) { - settings.indent() << "Processing of " << processedRules << " intermediary rules done" << std::endl; - --settings.indentLevel; + assert(intermediaryRules.back().empty()); + } else { // new implementation + const auto &subset = input.getSubset(); + const auto &universe = input.getUniverse(); + + // partition such that the subset is first + for(int i = 0; i != subset.size(); ++i) + assert(subset.begin()[i] == universe[subset.getIndices()[i]]); + + std::vector inSubset(universe.size(), false); + for(int idx : subset.getIndices()) + inSubset[idx] = true; + + std::vector graphs = universe; + auto subsetEnd = graphs.begin(); + for(auto iter = graphs.begin(); iter != graphs.end(); ++iter) { + const auto offset = iter - graphs.begin(); + if(inSubset[offset]) { + std::iter_swap(subsetEnd, iter); + ++subsetEnd; + } } - if(context.executionEnv.doExit()) break; - } - assert(intermediaryRules.back().empty()); + assert(subsetEnd - graphs.begin() == subset.size()); + + Context context{r, getExecutionEnv(), output, consumedGraphs}; + std::vector inputRules{{rRaw, {}, 0}}; + for(int round = 0; round != rRaw->getDPORule().numLeftComponents; ++round) { + const auto firstGraph = graphs.begin(); + const auto lastGraph = round == 0 ? subsetEnd : graphs.end(); + + const auto onOutput = [verbosity = settings.verbosity, context] + (IO::Logger logger, BoundRule br) -> bool { + if(br.rule->isOnlyRightSide()) { + handleBoundRulePair(verbosity, logger, context, br); + delete br.rule; + } + return true; + }; + std::vector outputRules = bindGraphs( + settings.ruleApplicationVerbosity(), settings, + round, + firstGraph, lastGraph, inputRules, + getExecutionEnv().graphAsRuleCache, + getExecutionEnv().labelSettings, + onOutput); + if(round != 0) { + // in round 0 the inputRules is the actual original input rule, so don't delete it + for(auto &br : inputRules) + delete br.rule; + } + std::swap(inputRules, outputRules); + } // for each round based on numComponents + assert(inputRules.empty()); + } // if(getConfig().dg.useOldRuleApplication.get()) } -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG::Strategies \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Rule.hpp b/libs/libmod/src/mod/lib/DG/Strategies/Rule.hpp index 4d88fa4..ba2090c 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Rule.hpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Rule.hpp @@ -1,14 +1,11 @@ -#ifndef MOD_LIB_DG_STRATEGIES_RULE_H -#define MOD_LIB_DG_STRATEGIES_RULE_H +#ifndef MOD_LIB_DG_STRATEGIES_RULE_HPP +#define MOD_LIB_DG_STRATEGIES_RULE_HPP #include #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { struct Rule : Strategy { Rule(std::shared_ptr r); @@ -26,9 +23,6 @@ struct Rule : Strategy { std::unordered_set consumedGraphs; // all those from lhs of derivations }; -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG::Strategies -#endif /* MOD_LIB_DG_STRATEGIES_RULE_H */ \ No newline at end of file +#endif // MOD_LIB_DG_STRATEGIES_RULE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Strategy.cpp b/libs/libmod/src/mod/lib/DG/Strategies/Strategy.cpp index a04d05e..35eae8d 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Strategy.cpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Strategy.cpp @@ -33,7 +33,6 @@ void Strategy::execute(PrintSettings settings, const GraphState &input) { const GraphState &Strategy::getOutput() const { assert(output); - assert(output->hasSubset(0)); return *output; } @@ -47,12 +46,10 @@ void Strategy::printBaseInfo(PrintSettings settings) const { ++settings.indentLevel; std::ostream &s = settings.s; assert(input); - for(const auto &subset : input->getSubsets()) { - settings.indent() << "subset " << subset.first << " ="; - for(const auto *g : subset.second) - s << " " << g->getName(); - s << '\n'; - } + settings.indent() << "subset ="; + for(const auto *g : input->getSubset()) + s << " " << g->getName(); + s << '\n'; settings.indent() << "universe ="; if(settings.withUniverse) for(const auto *g : input->getUniverse()) @@ -63,13 +60,10 @@ void Strategy::printBaseInfo(PrintSettings settings) const { settings.indent() << "output:\n"; ++settings.indentLevel; // important to use getOutput(), it might be overwritten - - for(const auto &subset : getOutput().getSubsets()) { - settings.indent() << "subset " << subset.first << " ="; - for(const auto *g : subset.second) - s << " " << g->getName(); - s << '\n'; - } + settings.indent() << "subset ="; + for(const auto *g : getOutput().getSubset()) + s << " " << g->getName(); + s << '\n'; settings.indent() << "universe ="; if(settings.withUniverse) for(const auto *g : getOutput().getUniverse()) diff --git a/libs/libmod/src/mod/lib/DG/Strategies/Strategy.hpp b/libs/libmod/src/mod/lib/DG/Strategies/Strategy.hpp index f141fcf..8e2dd14 100644 --- a/libs/libmod/src/mod/lib/DG/Strategies/Strategy.hpp +++ b/libs/libmod/src/mod/lib/DG/Strategies/Strategy.hpp @@ -1,21 +1,20 @@ -#ifndef MOD_LIB_DG_STRATEGIES_STRATEGY_H -#define MOD_LIB_DG_STRATEGIES_STRATEGY_H +#ifndef MOD_LIB_DG_STRATEGIES_STRATEGY_HPP +#define MOD_LIB_DG_STRATEGIES_STRATEGY_HPP #include #include #include +#include #include #include -namespace mod { -namespace lib { -namespace DG { -namespace Strategies { +namespace mod::lib::DG::Strategies { class GraphState; struct ExecutionEnv { - ExecutionEnv(LabelSettings labelSettings) : labelSettings(labelSettings) {} + ExecutionEnv(LabelSettings labelSettings, Rules::GraphAsRuleCache &graphAsRuleCache) + : labelSettings(labelSettings), graphAsRuleCache(graphAsRuleCache) {} virtual ~ExecutionEnv() {}; // May throw LogicError if exists. virtual void tryAddGraph(std::shared_ptr g) = 0; @@ -38,12 +37,16 @@ struct ExecutionEnv { virtual void popRightPredicate() = 0; public: const LabelSettings labelSettings; + Rules::GraphAsRuleCache &graphAsRuleCache; }; struct PrintSettings : IO::Logger { explicit PrintSettings(std::ostream &s, bool withUniverse) : IO::Logger(s), withUniverse(withUniverse) {} explicit PrintSettings(std::ostream &s, bool withUniverse, int verbosity) : IO::Logger(s), withUniverse(withUniverse), verbosity(verbosity) {} + int ruleApplicationVerbosity() const { + return std::max(0, verbosity - V_DerivationPredicatesPred); + } public: bool withUniverse; // mostly used for printInfo int verbosity = 2; // mostly used for execute @@ -61,7 +64,8 @@ struct PrintSettings : IO::Logger { V_Execute = V_RepeatBreak, V_DerivationPredicatesPred = V_DerivationPredicates + 2, V_FilterPred = V_DerivationPredicatesPred, - V_RuleBinding = V_DerivationPredicatesPred + 2, + // The rest should be moved to RuleApplicationUtils + V_RuleBinding = V_DerivationPredicatesPred + 2, V_RuleApplication = V_RuleBinding + 2, V_DerivationPredicatesFail = V_RuleApplication, V_RCMorphismGenBase = 48 /* meaning 48 is no info, 50 is gen info, and 60 is rc info */; @@ -97,9 +101,6 @@ struct Strategy { static unsigned int calcMaxNumComponents(const std::vector &strats); }; -} // namespace Strategies -} // namespace DG -} // namespace lib -} // namespace mod +} // namespace mod::lib::DG::Strategies -#endif /* MOD_LIB_DG_STRATEGIES_STRATEGY_H */ +#endif // MOD_LIB_DG_STRATEGIES_STRATEGY_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/Canonicalisation.cpp b/libs/libmod/src/mod/lib/Graph/Canonicalisation.cpp index b61189e..7fdc1b8 100644 --- a/libs/libmod/src/mod/lib/Graph/Canonicalisation.cpp +++ b/libs/libmod/src/mod/lib/Graph/Canonicalisation.cpp @@ -559,7 +559,7 @@ auto getCanonForm(const Single &g, EdgeHandler eHandler, LabelType labelType, bo // canon_permutation = can(getGraph(), idx, vLess, // graph_canonicalization::make_visitor(visitor, std::ref(stats)), // eInv); - lib::IO::log() << stats; + std::cout << stats; } auto eLess = [&str](Edge lhs, Edge rhs) { diff --git a/libs/libmod/src/mod/lib/Graph/Collection.cpp b/libs/libmod/src/mod/lib/Graph/Collection.cpp index 90230e4..df35aba 100644 --- a/libs/libmod/src/mod/lib/Graph/Collection.cpp +++ b/libs/libmod/src/mod/lib/Graph/Collection.cpp @@ -35,8 +35,8 @@ struct Collection::Store { if(iso) return gCand->getAPIReference(); // if iso: // if(getConfig().dg.calculateDetailsVerbose.get()) { - // IO::log() << "Discarding product " << gCand->getName() << ", isomorphic to " << g->getName() << std::endl; - // IO::log() << "\tLabelSettings: withStereo=" << std::boolalpha << this->labelSettings.withStereo << std::endl; + // std::cout << "Discarding product " << gCand->getName() << ", isomorphic to " << g->getName() << std::endl; + // std::cout << "\tLabelSettings: withStereo=" << std::boolalpha << this->labelSettings.withStereo << std::endl; // mod::postSection("Discarded"); // mod::lib::IO::Graph::Write::Options opts, optsGraph; // opts.edgesAsBonds = opts.withIndex = true; diff --git a/libs/libmod/src/mod/lib/Graph/LabelledGraph.cpp b/libs/libmod/src/mod/lib/Graph/LabelledGraph.cpp index 4122e0c..e22128c 100644 --- a/libs/libmod/src/mod/lib/Graph/LabelledGraph.cpp +++ b/libs/libmod/src/mod/lib/Graph/LabelledGraph.cpp @@ -9,13 +9,13 @@ #include #include +#include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { -LabelledGraph::LabelledGraph(std::unique_ptr g, std::unique_ptr pString, std::unique_ptr pStereo) -: g(std::move(g)), pString(std::move(pString)), pStereo(std::move(pStereo)) { +LabelledGraph::LabelledGraph(std::unique_ptr g, std::unique_ptr pString, + std::unique_ptr pStereo) + : g(std::move(g)), pString(std::move(pString)), pStereo(std::move(pStereo)) { assert(this->g); assert(this->pString); this->pString->verify(this->g.get()); @@ -26,11 +26,11 @@ LabelledGraph::LabelledGraph(const LabelledGraph &other) { g = std::make_unique(get_graph(other)); pString = std::make_unique(get_string(other), *g); if(other.pStereo) { - IO::log() << "WARNING: missing copying of stereo info in LabelledGraph copy ctor" << std::endl; + std::cout << "WARNING: missing copying of stereo info in LabelledGraph copy ctor" << std::endl; } } -LabelledGraph::~LabelledGraph() { } +LabelledGraph::~LabelledGraph() {} GraphType &get_graph(LabelledGraph &g) { return *g.g; @@ -74,10 +74,11 @@ const LabelledGraph::PropStereoType &get_stereo(const LabelledGraph &g) { return get(boost::vertex_index_t(), get_graph(g), v); }); switch(result) { - case Stereo::DeductionResult::Success: break; + case Stereo::DeductionResult::Success: + break; case Stereo::DeductionResult::Warning: if(!getConfig().stereo.silenceDeductionWarnings.get()) - IO::log() << ssErr.str(); + std::cout << ssErr.str(); break; case Stereo::DeductionResult::Error: throw StereoDeductionError(ssErr.str()); @@ -95,7 +96,7 @@ const LabelledGraph::PropMoleculeType &get_molecule(const LabelledGraph &g) { return *g.pMolecule; } -const std::vector::vertex_descriptor>& +const std::vector::vertex_descriptor> & get_vertex_order(const LabelledGraph &g) { if(g.vertex_order.empty()) { g.vertex_order = get_vertex_order(mod::lib::GraphMorphism::DefaultFinderArgsProvider(), get_graph(g)); @@ -103,6 +104,4 @@ get_vertex_order(const LabelledGraph &g) { return g.vertex_order; } -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/LabelledGraph.hpp b/libs/libmod/src/mod/lib/Graph/LabelledGraph.hpp index d52cd35..dc3a192 100644 --- a/libs/libmod/src/mod/lib/Graph/LabelledGraph.hpp +++ b/libs/libmod/src/mod/lib/Graph/LabelledGraph.hpp @@ -1,11 +1,9 @@ -#ifndef MOD_LIB_GRAPH_LABELLED_GRAPH_H -#define MOD_LIB_GRAPH_LABELLED_GRAPH_H +#ifndef MOD_LIB_GRAPH_LABELLED_GRAPH_HPP +#define MOD_LIB_GRAPH_LABELLED_GRAPH_HPP #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropMolecule; struct PropStereo; struct PropString; @@ -19,7 +17,8 @@ struct LabelledGraph { // models a mod::lib::LabelledGraphConcept public: using PropMoleculeType = PropMolecule; public: - LabelledGraph(std::unique_ptr g, std::unique_ptr pString, std::unique_ptr pStereo); + LabelledGraph(std::unique_ptr g, std::unique_ptr pString, + std::unique_ptr pStereo); LabelledGraph(const LabelledGraph &other); ~LabelledGraph(); friend GraphType &get_graph(LabelledGraph &g); @@ -32,7 +31,7 @@ struct LabelledGraph { // models a mod::lib::LabelledGraphConcept friend const PropStereoType &get_stereo(const LabelledGraph &g); friend const PropMoleculeType &get_molecule(const LabelledGraph &g); public: - friend const std::vector::vertex_descriptor>& + friend const std::vector::vertex_descriptor> & get_vertex_order(const LabelledGraph &g); private: // intrinsic data std::unique_ptr g; @@ -45,8 +44,6 @@ struct LabelledGraph { // models a mod::lib::LabelledGraphConcept mutable std::vector::vertex_descriptor> vertex_order; }; -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph -#endif /* MOD_LIB_GRAPH_LABELLED_GRAPH_H */ +#endif // MOD_LIB_GRAPH_LABELLED_GRAPH_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/MultisetIO.hpp b/libs/libmod/src/mod/lib/Graph/MultisetIO.hpp index a857a7b..47d5395 100644 --- a/libs/libmod/src/mod/lib/Graph/MultisetIO.hpp +++ b/libs/libmod/src/mod/lib/Graph/MultisetIO.hpp @@ -1,13 +1,11 @@ -#ifndef MOD_LIB_GRAPH_MULTISETIO_H -#define MOD_LIB_GRAPH_MULTISETIO_H +#ifndef MOD_LIB_GRAPH_MULTISETIO_HPP +#define MOD_LIB_GRAPH_MULTISETIO_HPP #include -#include +#include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { template std::ostream &operator<<(std::ostream &s, const Multiset &ms) { @@ -17,8 +15,6 @@ std::ostream &operator<<(std::ostream &s, const Multiset &ms) { return s << "}"; } -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph -#endif /* MOD_LIB_GRAPH_MULTISETIO_H */ \ No newline at end of file +#endif // MOD_LIB_GRAPH_MULTISETIO_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/Properties/Molecule.cpp b/libs/libmod/src/mod/lib/Graph/Properties/Molecule.cpp index df3cde1..b70a17c 100644 --- a/libs/libmod/src/mod/lib/Graph/Properties/Molecule.cpp +++ b/libs/libmod/src/mod/lib/Graph/Properties/Molecule.cpp @@ -8,9 +8,9 @@ #include -namespace mod { -namespace lib { -namespace Graph { +#include + +namespace mod::lib::Graph { PropMolecule::PropMolecule(const GraphType &g, const PropString &pString) : Base(g), isMolecule(true) { // atomData @@ -21,7 +21,7 @@ PropMolecule::PropMolecule(const GraphType &g, const PropString &pString) : Base Charge charge; bool radical; std::tie(atomId, isotope, charge, radical) = Chem::decodeVertexLabel(pString[v]); - // IO::log() << "Decode(" << pString[v] << "): " << atomId << ", " << isotope << ", " << charge << ", " << radical << std::endl; + // std::cout << "Decode(" << pString[v] << "): " << atomId << ", " << isotope << ", " << charge << ", " << radical << std::endl; this->vertexState[get(boost::vertex_index_t(), g, v)] = AtomData(atomId, isotope, charge, radical); if(atomId == AtomIds::Invalid) isMolecule = false; } @@ -46,12 +46,12 @@ bool PropMolecule::getIsMolecule() const { const lib::Chem::OBMolHandle &PropMolecule::getOBMol() const { if(!isMolecule) { - IO::log() << "MoleculeState: Trying to create OpenBabel::OBMol from non-molecule." << std::endl - << "Should DepictionData be used instead?" << std::endl; + std::cout << "MoleculeState: Trying to create OpenBabel::OBMol from non-molecule." << std::endl + << "Should DepictionData be used instead?" << std::endl; MOD_ABORT; } if(!obMol) { - obMol = Chem::makeOBMol(this->g, [this](Vertex v) -> const AtomData& { + obMol = Chem::makeOBMol(this->g, [this](Vertex v) -> const AtomData & { return (*this)[v]; }, [this](Edge e) { return (*this)[e]; @@ -78,8 +78,8 @@ double PropMolecule::getEnergy() const { if(!energy) { #ifndef MOD_HAVE_OPENBABEL MOD_NO_OPENBABEL_ERROR - IO::log() << "Energy calculation is not possible without Open Babel." << std::endl; - IO::log() << "Energy values can be manually cached on graphs if calculation is not desired." << std::endl; + std::cout << "Energy calculation is not possible without Open Babel." << std::endl; + std::cout << "Energy values can be manually cached on graphs if calculation is not desired." << std::endl; std::exit(1); #else energy = getOBMol().getEnergy(); @@ -90,12 +90,10 @@ double PropMolecule::getEnergy() const { void PropMolecule::cacheEnergy(double value) const { if(energy) { - IO::log() << "Can not cache energy on graph already with energy." << std::endl; + std::cout << "Can not cache energy on graph already with energy." << std::endl; MOD_ABORT; } energy = value; } -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/Properties/Molecule.hpp b/libs/libmod/src/mod/lib/Graph/Properties/Molecule.hpp index 0ffdf8f..b66fe3e 100644 --- a/libs/libmod/src/mod/lib/Graph/Properties/Molecule.hpp +++ b/libs/libmod/src/mod/lib/Graph/Properties/Molecule.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_GRAPH_PROP_MOLECULE_H -#define MOD_LIB_GRAPH_PROP_MOLECULE_H +#ifndef MOD_LIB_GRAPH_PROP_MOLECULE_HPP +#define MOD_LIB_GRAPH_PROP_MOLECULE_HPP #include #include @@ -8,9 +8,7 @@ #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropString; struct PropMolecule : Prop { @@ -33,8 +31,6 @@ struct PropMolecule : Prop { mutable boost::optional energy; }; -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph -#endif /* MOD_LIB_GRAPH_PROP_MOLECULE_H */ +#endif // MOD_LIB_GRAPH_PROP_MOLECULE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/Properties/Property.cpp b/libs/libmod/src/mod/lib/Graph/Properties/Property.cpp new file mode 100644 index 0000000..43c8e64 --- /dev/null +++ b/libs/libmod/src/mod/lib/Graph/Properties/Property.cpp @@ -0,0 +1,27 @@ +#include "Property.hpp" + +#include + +namespace mod::lib::Graph::detail { + +void PropVerify(const GraphType *g, const GraphType *gOther, + std::size_t nGraph, std::size_t nOther, + std::size_t mGraph, std::size_t mOther) { + if(g != gOther) { + std::cout << "Different graphs: g = " << (std::uintptr_t) g + << ", &this->g = " << (std::uintptr_t) gOther << std::endl; + MOD_ABORT; + } + if(nGraph != nOther) { + std::cout << "Different sizes: num_vertices(this->g) = " << nGraph + << ", vertexLabels.size() = " << nOther << std::endl; + MOD_ABORT; + } + if(mGraph != mOther) { + std::cout << "Different sizes: num_edges(this->g) = " << mGraph + << ", edgeLabels.size() = " << mOther << std::endl; + MOD_ABORT; + } +} + +} // namespace mod::lib::Graph::detail \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/Properties/Property.hpp b/libs/libmod/src/mod/lib/Graph/Properties/Property.hpp index 7b0fb19..07118c9 100644 --- a/libs/libmod/src/mod/lib/Graph/Properties/Property.hpp +++ b/libs/libmod/src/mod/lib/Graph/Properties/Property.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_GRAPH_PROPERTY_H -#define MOD_LIB_GRAPH_PROPERTY_H +#ifndef MOD_LIB_GRAPH_PROPERTY_HPP +#define MOD_LIB_GRAPH_PROPERTY_HPP #include #include @@ -8,9 +8,7 @@ #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { template struct Prop { @@ -48,23 +46,15 @@ auto get(const Prop &p, VertexOrEdge ve) -> declt // Implementation //------------------------------------------------------------------------------ +namespace detail { +void PropVerify(const GraphType *g, const GraphType *gOther, + std::size_t nGraph, std::size_t nOther, + std::size_t mGraph, std::size_t mOther); +} // namespace detail + template void Prop::verify(const GraphType *g) const { - if(g != &this->g) { - IO::log() << "Different graphs: g = " << (std::uintptr_t) g << ", &this->g = " << (std::uintptr_t) &this->g - << std::endl; - MOD_ABORT; - } - if(num_vertices(this->g) != vertexState.size()) { - IO::log() << "Different sizes: num_vertices(this->g) = " << num_vertices(this->g) << ", vertexLabels.size() = " - << vertexState.size() << std::endl; - MOD_ABORT; - } - if(num_edges(this->g) != edgeState.size()) { - IO::log() << "Different sizes: num_edges(this->g) = " << num_edges(this->g) << ", edgeLabels.size() = " - << edgeState.size() << std::endl; - MOD_ABORT; - } + detail::PropVerify(g, &this->g, num_vertices(*g), vertexState.size(), num_edges(*g), edgeState.size()); } template @@ -111,8 +101,6 @@ const Derived &Prop::getDerived() const { return static_cast (*this); } -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph -#endif /* MOD_LIB_GRAPH_PROPERTY_H */ +#endif // MOD_LIB_GRAPH_PROPERTY_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Graph/Properties/Stereo.hpp b/libs/libmod/src/mod/lib/Graph/Properties/Stereo.hpp index f39aa7c..f61de83 100644 --- a/libs/libmod/src/mod/lib/Graph/Properties/Stereo.hpp +++ b/libs/libmod/src/mod/lib/Graph/Properties/Stereo.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_GRAPH_STATE_STEREO_H -#define MOD_LIB_GRAPH_STATE_STEREO_H +#ifndef MOD_LIB_GRAPH_STATE_STEREO_HPP +#define MOD_LIB_GRAPH_STATE_STEREO_HPP #include #include @@ -7,14 +7,11 @@ #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropStereo : Prop, Stereo::EdgeCategory> { using Base = Prop, Stereo::EdgeCategory>; public: - template explicit PropStereo(const GraphType &g, Inference &&inference) : Base(g) { vertexState.reserve(num_vertices(g)); @@ -31,8 +28,6 @@ struct PropStereo : Prop -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropString : Prop { using Base = Prop; public: - explicit PropString(const GraphType &g) : Base(g) { Base::verify(&g); } @@ -20,8 +17,6 @@ struct PropString : Prop { } }; -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph -#endif /* MOD_LIB_GRAPH_PROP_LABEL_H */ +#endif // MOD_LIB_GRAPH_PROP_LABEL_HPP diff --git a/libs/libmod/src/mod/lib/Graph/Single.cpp b/libs/libmod/src/mod/lib/Graph/Single.cpp index 587aa0e..2da27e4 100644 --- a/libs/libmod/src/mod/lib/Graph/Single.cpp +++ b/libs/libmod/src/mod/lib/Graph/Single.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -19,8 +18,6 @@ #include #include #include -#include -#include #include #include @@ -55,7 +52,7 @@ bool sanityCheck(const GraphType &g, const PropString &pString, std::ostream &s) // check loop if(e.first == e.second) { s << "Graph::sanityCheck:\tloop edge found on vertex " - << get(boost::vertex_index_t(), g, e.first) << "('" << pString[e.first] << "')" << std::endl; + << get(boost::vertex_index_t(), g, e.first) << "('" << pString[e.first] << "')" << std::endl; return false; } // check parallelness @@ -63,8 +60,9 @@ bool sanityCheck(const GraphType &g, const PropString &pString, std::ostream &s) auto ep = edgesSorted[i - 1]; if(e == ep) { s << "Graph::sanityCheck:\tparallel edges found between " - << get(boost::vertex_index_t(), g, e.first) << "('" << pString[e.first] - << "') and " << get(boost::vertex_index_t(), g, e.second) << " ('" << pString[e.second] << "')" << std::endl; + << get(boost::vertex_index_t(), g, e.first) << "('" << pString[e.first] + << "') and " << get(boost::vertex_index_t(), g, e.second) << " ('" << pString[e.second] << "')" + << std::endl; return false; } } @@ -82,15 +80,15 @@ bool sanityCheck(const GraphType &g, const PropString &pString, std::ostream &s) } // namespace Single::Single(std::unique_ptr g, std::unique_ptr pString, std::unique_ptr pStereo) -: g(std::move(g), std::move(pString), std::move(pStereo)), -id(nextGraphNum++), name(getGraphName(id)) { - if(!sanityCheck(getGraph(), getStringState(), IO::log())) { - IO::log() << "Graph::sanityCheck\tfailed in graph '" << getName() << "'" << std::endl; + : g(std::move(g), std::move(pString), std::move(pStereo)), + id(nextGraphNum++), name(getGraphName(id)) { + if(!sanityCheck(getGraph(), getStringState(), std::cout)) { + std::cout << "Graph::sanityCheck\tfailed in graph '" << getName() << "'" << std::endl; MOD_ABORT; } } -Single::~Single() { } +Single::~Single() {} const LabelledGraph &Single::getLabelledGraph() const { return g; @@ -119,9 +117,9 @@ void Single::setName(std::string name) { this->name = name; } -const std::pair Single::getGraphDFS() const { +const std::pair Single::getGraphDFS() const { if(!dfs) std::tie(dfs, dfsHasNonSmilesRingClosure) = DFSEncoding::write(getGraph(), getStringState(), false); - return std::pair(*dfs, dfsHasNonSmilesRingClosure); + return std::pair(*dfs, dfsHasNonSmilesRingClosure); } const std::string &Single::getGraphDFSWithIds() const { @@ -142,7 +140,8 @@ const std::string &Single::getSmiles() const { return *smiles; } else { std::string text; - text += "Graph " + boost::lexical_cast(getId()) + " with name '" + getName() + "' is not a molecule.\n"; + text += "Graph " + boost::lexical_cast(getId()) + " with name '" + getName() + + "' is not a molecule.\n"; text += "Can not generate SMILES string. GraphDFS is\n\t" + getGraphDFS().first + "\n"; throw LogicError(std::move(text)); } @@ -161,27 +160,13 @@ const std::string &Single::getSmilesWithIds() const { return *smilesWithIds; } else { std::string text; - text += "Graph " + boost::lexical_cast(getId()) + " with name '" + getName() + "' is not a molecule.\n"; + text += "Graph " + boost::lexical_cast(getId()) + " with name '" + getName() + + "' is not a molecule.\n"; text += "Can not generate SMILES string. GraphDFS is\n\t" + getGraphDFS().first + "\n"; throw LogicError(std::move(text)); } } -std::shared_ptr Single::getBindRule() const { - if(!bindRule) bindRule = rule::Rule::makeRule(lib::Rules::graphToRule(g, lib::Rules::Membership::Right, getName())); - return bindRule; -} - -std::shared_ptr Single::getIdRule() const { - if(!idRule) idRule = rule::Rule::makeRule(lib::Rules::graphToRule(g, lib::Rules::Membership::Context, getName())); - return idRule; -} - -std::shared_ptr Single::getUnbindRule() const { - if(!unbindRule) unbindRule = rule::Rule::makeRule(lib::Rules::graphToRule(g, lib::Rules::Membership::Left, getName())); - return unbindRule; -} - unsigned int Single::getVertexLabelCount(const std::string &label) const { unsigned int count = 0; @@ -235,7 +220,8 @@ const Single::CanonForm &Single::getCanonForm(LabelType labelType, bool withSter throw LogicError("Can not canonicalise stereo."); if(!canon_form_string) { assert(!aut_group_string); - std::tie(canon_perm_string, canon_form_string, aut_group_string) = lib::Graph::getCanonForm(*this, labelType, withStereo); + std::tie(canon_perm_string, canon_form_string, aut_group_string) = lib::Graph::getCanonForm(*this, labelType, + withStereo); } assert(canon_form_string); assert(aut_group_string); @@ -257,9 +243,12 @@ namespace GM = jla_boost::GraphMorphism; namespace GM_MOD = lib::GraphMorphism; template -std::size_t morphism(const Single &gDomain, const Single &gCodomain, std::size_t maxNumMatches, LabelSettings labelSettings, Finder finder) { +std::size_t +morphism(const Single &gDomain, const Single &gCodomain, std::size_t maxNumMatches, LabelSettings labelSettings, + Finder finder) { auto mr = GM::makeLimit(maxNumMatches); - lib::GraphMorphism::morphismSelectByLabelSettings(gDomain.getLabelledGraph(), gCodomain.getLabelledGraph(), labelSettings, finder, std::ref(mr)); + lib::GraphMorphism::morphismSelectByLabelSettings(gDomain.getLabelledGraph(), gCodomain.getLabelledGraph(), + labelSettings, finder, std::ref(mr)); return mr.getNumHits(); } @@ -267,7 +256,8 @@ std::size_t isomorphismSmilesOrCanonOrVF2(const Single &gDom, const Single &gCod const auto &ggDom = gDom.getLabelledGraph(); const auto &ggCodom = gCodom.getLabelledGraph(); // first try if we can compare canonical SMILES strings - if(get_molecule(ggDom).getIsMolecule() && get_molecule(ggCodom).getIsMolecule() && !getConfig().graph.useWrongSmilesCanonAlg.get()) + if(get_molecule(ggDom).getIsMolecule() && get_molecule(ggCodom).getIsMolecule() && + !getConfig().graph.useWrongSmilesCanonAlg.get()) return gDom.getSmiles() == gCodom.getSmiles() ? 1 : 0; // otherwise maybe we can still do canonical form comparison @@ -281,7 +271,8 @@ std::size_t isomorphismSmilesOrCanonOrVF2(const Single &gDom, const Single &gCod } // namespace -std::size_t Single::isomorphismVF2(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings) { +std::size_t Single::isomorphismVF2(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, + LabelSettings labelSettings) { return morphism(gDom, gCodom, maxNumMatches, labelSettings, GM_MOD::VF2Isomorphism()); } @@ -310,7 +301,8 @@ bool Single::isomorphic(const Single &gDom, const Single &gCodom, LabelSettings MOD_ABORT; } -std::size_t Single::isomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings) { +std::size_t +Single::isomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings) { ++getConfig().graph.numIsomorphismCalls(); if(maxNumMatches == 1) return isomorphic(gDom, gCodom, labelSettings) ? 1 : 0; @@ -324,7 +316,8 @@ std::size_t Single::isomorphism(const Single &gDom, const Single &gCodom, std::s return isomorphismVF2(gDom, gCodom, maxNumMatches, labelSettings); } -std::size_t Single::monomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings) { +std::size_t +Single::monomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings) { return morphism(gDom, gCodom, maxNumMatches, labelSettings, GM_MOD::VF2Monomorphism()); } @@ -344,30 +337,33 @@ Single makePermutation(const Single &g) { throw mod::FatalError("Can not (yet) permute graphs with stereo information."); std::unique_ptr pString; auto gBoost = lib::makePermutedGraph(g.getGraph(), - [&pString](GraphType & gNew) { - pString.reset(new PropString(gNew)); - }, - [&g, &pString](Vertex vOld, const GraphType &gOld, Vertex vNew, GraphType & gNew) { - pString->addVertex(vNew, g.getStringState()[vOld]); - }, - [&g, &pString](Edge eOld, const GraphType &gOld, Edge eNew, GraphType & gNew) { - pString->addEdge(eNew, g.getStringState()[eOld]); - } + [&pString](GraphType &gNew) { + pString.reset(new PropString(gNew)); + }, + [&g, &pString](Vertex vOld, const GraphType &gOld, Vertex vNew, + GraphType &gNew) { + pString->addVertex(vNew, g.getStringState()[vOld]); + }, + [&g, &pString](Edge eOld, const GraphType &gOld, Edge eNew, GraphType &gNew) { + pString->addEdge(eNew, g.getStringState()[eOld]); + } ); Single gPerm(std::move(gBoost), std::move(pString), nullptr); if(getConfig().graph.checkIsoInPermutation.get()) { const bool iso = 1 == Single::isomorphismVF2(g, gPerm, 1, - {LabelType::String, LabelRelation::Isomorphism, false, LabelRelation::Isomorphism}); + {LabelType::String, LabelRelation::Isomorphism, false, + LabelRelation::Isomorphism}); if(!iso) { IO::Graph::Write::Options graphLike, molLike; graphLike.EdgesAsBonds(true).RaiseCharges(true).CollapseHydrogens(true).WithIndex(true); - molLike.CollapseHydrogens(true).EdgesAsBonds(true).RaiseCharges(true).SimpleCarbons(true).WithColour(true).WithIndex(true); + molLike.CollapseHydrogens(true).EdgesAsBonds(true).RaiseCharges(true).SimpleCarbons(true).WithColour( + true).WithIndex(true); IO::Graph::Write::summary(g, graphLike, molLike); IO::Graph::Write::summary(gPerm, graphLike, molLike); IO::Graph::Write::gml(g, false); IO::Graph::Write::gml(gPerm, false); - IO::log() << "g: " << g.getSmiles() << std::endl; - IO::log() << "gPerm: " << gPerm.getSmiles() << std::endl; + std::cout << "g: " << g.getSmiles() << std::endl; + std::cout << "gPerm: " << gPerm.getSmiles() << std::endl; MOD_ABORT; } } diff --git a/libs/libmod/src/mod/lib/Graph/Single.hpp b/libs/libmod/src/mod/lib/Graph/Single.hpp index e21d170..0e5d7fa 100644 --- a/libs/libmod/src/mod/lib/Graph/Single.hpp +++ b/libs/libmod/src/mod/lib/Graph/Single.hpp @@ -1,9 +1,8 @@ -#ifndef MOD_LIB_GRAPH_SINGLE_H -#define MOD_LIB_GRAPH_SINGLE_H +#ifndef MOD_LIB_GRAPH_SINGLE_HPP +#define MOD_LIB_GRAPH_SINGLE_HPP #include #include -#include #include #include @@ -18,15 +17,13 @@ #include #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropMolecule; struct DepictionData; struct Single { using CanonIdxMap = boost::iterator_property_map::const_iterator, - decltype(get(boost::vertex_index_t(), GraphType()))>; + decltype(get(boost::vertex_index_t(), GraphType()))>; using CanonForm = graph_canon::ordered_graph; using AutGroup = perm_group::generated_group > >; public: @@ -42,13 +39,10 @@ struct Single { void setAPIReference(std::shared_ptr g); const std::string &getName() const; void setName(std::string name); - const std::pair getGraphDFS() const; + const std::pair getGraphDFS() const; const std::string &getGraphDFSWithIds() const; const std::string &getSmiles() const; const std::string &getSmilesWithIds() const; - std::shared_ptr getBindRule() const; - std::shared_ptr getIdRule() const; - std::shared_ptr getUnbindRule() const; unsigned int getVertexLabelCount(const std::string &label) const; unsigned int getEdgeLabelCount(const std::string &label) const; DepictionData &getDepictionData(); @@ -68,17 +62,19 @@ struct Single { mutable boost::optional dfs, dfsWithIds; mutable bool dfsHasNonSmilesRingClosure; mutable boost::optional smiles, smilesWithIds; - mutable std::shared_ptr bindRule, idRule, unbindRule; - mutable std::unique_ptr > vertexOrder; + mutable std::unique_ptr> vertexOrder; mutable std::vector canon_perm_string; mutable std::unique_ptr canon_form_string; mutable std::unique_ptr aut_group_string; mutable std::unique_ptr depictionData; public: - static std::size_t isomorphismVF2(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings); + static std::size_t + isomorphismVF2(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings); static bool isomorphic(const Single &gDom, const Single &gCodom, LabelSettings labelSettings); - static std::size_t isomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings); - static std::size_t monomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings); + static std::size_t + isomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings); + static std::size_t + monomorphism(const Single &gDom, const Single &gCodom, std::size_t maxNumMatches, LabelSettings labelSettings); static bool nameLess(const Single *g1, const Single *g2); static bool canonicalCompare(const Single &g1, const Single &g2, LabelType labelType, bool withStereo); public: @@ -95,7 +91,7 @@ namespace detail { struct IsomorphismPredicate { IsomorphismPredicate(LabelType labelType, bool withStereo) - : settings(labelType, LabelRelation::Isomorphism, withStereo, LabelRelation::Isomorphism) { } + : settings(labelType, LabelRelation::Isomorphism, withStereo, LabelRelation::Isomorphism) {} bool operator()(const Single *gDom, const Single *gCodom) const { return Single::isomorphic(*gDom, *gCodom, settings); @@ -110,8 +106,6 @@ inline detail::IsomorphismPredicate makeIsomorphismPredicate(LabelType labelType return detail::IsomorphismPredicate(labelType, withStereo); } -} // namespace Graph -} // namespace lib -} // namespace mod +} // namespace mod::lib::Graph -#endif /* MOD_LIB_GRAPH_SINGLE_H */ +#endif // MOD_LIB_GRAPH_SINGLE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/GraphMorphism/Constraints/Constraint.hpp b/libs/libmod/src/mod/lib/GraphMorphism/Constraints/Constraint.hpp index b5c6a89..e512771 100644 --- a/libs/libmod/src/mod/lib/GraphMorphism/Constraints/Constraint.hpp +++ b/libs/libmod/src/mod/lib/GraphMorphism/Constraints/Constraint.hpp @@ -1,17 +1,12 @@ -#ifndef MOD_LIB_GRAPHMORPHISM_CONSTRAINT_H -#define MOD_LIB_GRAPHMORPHISM_CONSTRAINT_H +#ifndef MOD_LIB_GRAPHMORPHISM_CONSTRAINT_HPP +#define MOD_LIB_GRAPHMORPHISM_CONSTRAINT_HPP #include #include #include -#include - -namespace mod { -namespace lib { -namespace GraphMorphism { -namespace Constraints { +namespace mod::lib::GraphMorphism::Constraints { // inspired by https://stackoverflow.com/questions/7876168/using-the-visitor-pattern-with-template-derived-classes template @@ -23,33 +18,29 @@ struct Constraint { virtual std::string name() const = 0; virtual bool supportsTerm() const = 0; protected: - template static void acceptDispatch(C &c, BaseVisitorNonConst &visitor) { - dynamic_cast&> (visitor) (c); + dynamic_cast &> (visitor)(c); } template static void acceptDispatch(C &c, BaseVisitor &visitor) { - dynamic_cast&> (visitor) (c); + dynamic_cast &> (visitor)(c); } #define MOD_VISITABLE() \ - virtual void accept(BaseVisitorNonConst &v) override { \ - Constraint::acceptDispatch(*this, v); \ - } \ - virtual void accept(BaseVisitor &v) const override { \ - Constraint::acceptDispatch(*this, v); \ - } + virtual void accept(BaseVisitorNonConst &v) override { \ + Constraint::acceptDispatch(*this, v); \ + } \ + virtual void accept(BaseVisitor &v) const override { \ + Constraint::acceptDispatch(*this, v); \ + } }; enum class Operator { EQ, LT, GT, LEQ, GEQ }; -} // namespace Constraints -} // namespace GraphMorphism -} // namespace lib -} // namespace mod +} // namespace mod::lib::GraphMorphism::Constraints -#endif /* MOD_LIB_GRAPHMORPHISM_CONSTRAINT_H */ \ No newline at end of file +#endif // MOD_LIB_GRAPHMORPHISM_CONSTRAINT_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/GraphMorphism/TermVertexMap.hpp b/libs/libmod/src/mod/lib/GraphMorphism/TermVertexMap.hpp index 757afab..63fdae7 100644 --- a/libs/libmod/src/mod/lib/GraphMorphism/TermVertexMap.hpp +++ b/libs/libmod/src/mod/lib/GraphMorphism/TermVertexMap.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_GRAPHMORPHISM_TERMVERTEXMAP_H -#define MOD_LIB_GRAPHMORPHISM_TERMVERTEXMAP_H +#ifndef MOD_LIB_GRAPHMORPHISM_TERMVERTEXMAP_HPP +#define MOD_LIB_GRAPHMORPHISM_TERMVERTEXMAP_HPP #include #include @@ -15,77 +15,81 @@ // for debugging #include #include +#include -namespace mod { -namespace lib { -namespace GraphMorphism { +namespace mod::lib::GraphMorphism { // TermPredConstants (compare terms, variables are equal to everything) //------------------------------------------------------------------------------ template struct TermPredConstants { - - TermPredConstants(Next next) : next(next) { } + TermPredConstants(Next next) : next(next) {} template - bool operator()(const VEDom &veDom, const VECodom &veCodom, const LabGraphDom &gDom, const LabGraphCodom &gCodom) const { + bool + operator()(const VEDom &veDom, const VECodom &veCodom, const LabGraphDom &gDom, const LabGraphCodom &gCodom) const { const auto &pDom = get_term(gDom); const auto &pCodom = get_term(gCodom); const auto aDom = get(pDom, veDom); const auto aCodom = get(pCodom, veCodom); using Handler = typename LabGraphDom::PropTermType::Handler; - const bool res = Handler::reduce(std::logical_and<>(), + const bool res = Handler::reduce( + std::logical_and<>(), Handler::fmap2(aDom, aCodom, gDom, gCodom, - [this, &pDom, &pCodom](std::size_t l, std::size_t r, auto&&... args) { - // note: the parameter pack _must_ be named because of fucked up rules with varargs - // http://lbrandy.com/blog/2013/02/c11s-six-dots/ - // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0281r0.html - return this->compare(l, r, getMachine(pDom), getMachine(pCodom)); - })); + [this, &pDom, &pCodom](std::size_t l, std::size_t r, + auto &&... args) { + // note: the parameter pack _must_ be named because of fucked up rules with varargs + // http://lbrandy.com/blog/2013/02/c11s-six-dots/ + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0281r0.html + return this->compare(l, r, getMachine(pDom), + getMachine(pCodom)); + })); return res && next(veDom, veCodom, gDom, gCodom); } private: - - bool compare(std::size_t addrLeft, std::size_t addrRight, const lib::Term::Wam &machineLeft, const lib::Term::Wam &machineRight) const { + bool compare(std::size_t addrLeft, std::size_t addrRight, const lib::Term::Wam &machineLeft, + const lib::Term::Wam &machineRight) const { assert(stack.empty()); - constexpr bool DEBUG = false; + // maybe_unused to silence warnings on GCC < 9 + // (perhaps this bug? https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85827) + // TODO: remove attribute when GCC 9 is required + [[maybe_unused]] constexpr bool DEBUG = false; stack.emplace_back(addrLeft, addrRight); - auto &s = lib::IO::log(); - if(DEBUG) { - s << "TermConstEqual:\n"; - lib::IO::Term::Write::wam(machineLeft, lib::Term::getStrings(), s); - lib::IO::Term::Write::wam(machineRight, lib::Term::getStrings(), s); + if constexpr(DEBUG) { + std::cout << "TermConstEqual:\n"; + lib::IO::Term::Write::wam(machineLeft, lib::Term::getStrings(), std::cout); + lib::IO::Term::Write::wam(machineRight, lib::Term::getStrings(), std::cout); } while(!stack.empty()) { std::size_t l, r; std::tie(l, r) = stack.back(); stack.pop_back(); - if(DEBUG) s << "comp(" << l << ", " << r << ")\n"; + if constexpr(DEBUG) std::cout << "comp(" << l << ", " << r << ")\n"; using AddressType = lib::Term::AddressType; using Address = lib::Term::Address; using Cell = lib::Term::Cell; using CellTag = lib::Term::CellTag; Address addrLhs = machineLeft.deref({AddressType::Heap, l}); Address addrRhs = machineRight.deref({AddressType::Heap, r}); - if(DEBUG) s << "compDeref(" << addrLhs.addr << ", " << addrRhs.addr << ")\n"; + if constexpr(DEBUG) std::cout << "compDeref(" << addrLhs.addr << ", " << addrRhs.addr << ")\n"; Cell lhs = machineLeft.getCell(addrLhs); Cell rhs = machineRight.getCell(addrRhs); // if at least one is a variable we can't decide if(lhs.tag == CellTag::REF || rhs.tag == CellTag::REF) { - if(DEBUG) s << "maybe, refs involved\n"; + if constexpr(DEBUG) std::cout << "maybe, refs involved\n"; continue; } // they should be dereferenced assert(lhs.tag == CellTag::Structure); assert(rhs.tag == CellTag::Structure); if(lhs.Structure.arity != rhs.Structure.arity) { - if(DEBUG) s << "FALSE, arity\n"; + if constexpr(DEBUG) std::cout << "FALSE, arity\n"; stack.clear(); return false; } if(lhs.Structure.name != rhs.Structure.name) { - if(DEBUG) s << "FALSE, name\n"; + if constexpr(DEBUG) std::cout << "FALSE, name\n"; stack.clear(); return false; } @@ -93,7 +97,7 @@ struct TermPredConstants { stack.emplace_back(addrLhs.addr + i, addrRhs.addr + i); } } - if(DEBUG) s << "TRUE\n"; + if constexpr(DEBUG) std::cout << "TRUE\n"; return true; } private: @@ -120,18 +124,18 @@ struct TermData { }; struct TermAssociationHandlerUnify { - template - bool operator()(std::size_t l, std::size_t r, const OuterGraphDom &gDom, const OuterGraphCodom &gCodom, lib::Term::Wam &res, lib::Term::MGU &mgu) const { + bool operator()(std::size_t l, std::size_t r, const OuterGraphDom &gDom, const OuterGraphCodom &gCodom, + lib::Term::Wam &res, lib::Term::MGU &mgu) const { constexpr bool DEBUG = false; if(DEBUG) { - auto &s = lib::IO::log(); + auto &s = std::cout; s << "TermAssociationHandlerUnify:\n"; lib::IO::Term::Write::wam(res, lib::Term::getStrings(), s); } res.unifyHeapTemp(r, l, mgu); if(DEBUG) { - auto &s = lib::IO::log(); + auto &s = std::cout; s << "\tunifyHeapTemp(" << r << ", " << l << ")\n"; switch(mgu.status) { case lib::Term::MGU::Status::Exists: @@ -152,9 +156,8 @@ struct TermAssociationHandlerUnify { template struct ToTermVertexMap { - ToTermVertexMap(const LabGraphDom &gDom, const LabGraphCodom &gCodom, Next next) - : lgDom(gDom), lgCodom(gCodom), next(next) { + : lgDom(gDom), lgCodom(gCodom), next(next) { if(!isValid(get_term(gDom))) MOD_ABORT; if(!isValid(get_term(gCodom))) MOD_ABORT; } @@ -177,9 +180,10 @@ struct ToTermVertexMap { for(const auto vDom : asRange(vertices(gDom))) { const auto vCodom = get(m, gDom, gCodom, vDom); if(vCodom == boost::graph_traits::null_vertex()) continue; - const bool ok = Handler::reduce(std::logical_and<>(), + const bool ok = Handler::reduce( + std::logical_and<>(), Handler::fmap2(get(pDomain, vDom), get(pCodomain, vCodom), lgDom, lgCodom, - TermAssociationHandlerUnify(), machine, mgu + TermAssociationHandlerUnify(), machine, mgu )); if(!ok) return true; } @@ -193,9 +197,10 @@ struct ToTermVertexMap { const auto peCodom = edge(vCodomSrc, vCodomTar, gCodom); assert(peCodom.second); const auto eCodom = peCodom.first; - const bool ok = Handler::reduce(std::logical_and<>(), + const bool ok = Handler::reduce( + std::logical_and<>(), Handler::fmap2(get(pDomain, eDom), get(pCodomain, eCodom), lgDom, lgCodom, - TermAssociationHandlerUnify(), machine, mgu + TermAssociationHandlerUnify(), machine, mgu )); if(!ok) return true; } @@ -217,7 +222,6 @@ auto makeToTermVertexMap(const LabGraphDom &gDom, const LabGraphCodom &gCodom, N //------------------------------------------------------------------------------ struct TermFilterRenaming { - template bool operator()(const VertexMap &m, const GraphDom &gDom, const GraphCodom &gCodom) const { // lib::IO::Term::Write::wam(m.machine, lib::Term::getStrings(), std::cout); @@ -230,7 +234,6 @@ struct TermFilterRenaming { }; struct TermFilterSpecialisation { - template bool operator()(const VertexMap &m, const GraphDom &gDom, const GraphCodom &gCodom) const { // lib::IO::Term::Write::wam(m.machine, lib::Term::getStrings(), std::cout); @@ -242,8 +245,6 @@ struct TermFilterSpecialisation { } }; -} // namespace GraphMorphism -} // namespace lib -} // namespace mod +} // namespace mod::lib::GraphMorphism -#endif /* MOD_LIB_GRAPHMORPHISM_TERMVERTEXMAP_H */ +#endif // MOD_LIB_GRAPHMORPHISM_TERMVERTEXMAP_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/GraphPimpl.hpp b/libs/libmod/src/mod/lib/GraphPimpl.hpp index 1afad2b..142fd5e 100644 --- a/libs/libmod/src/mod/lib/GraphPimpl.hpp +++ b/libs/libmod/src/mod/lib/GraphPimpl.hpp @@ -1,16 +1,28 @@ -#ifndef MOD_LIB_GRAPHPIMPL_H -#define MOD_LIB_GRAPHPIMPL_H +#ifndef MOD_LIB_GRAPHPIMPL_HPP +#define MOD_LIB_GRAPHPIMPL_HPP #include #include -namespace mod { -namespace lib { +namespace mod::lib { -#define MOD_GRAPHPIMPL_Define_Vertex(Graph, OwnerLowerCase, getMacroGraph, g, Owner) \ +#define MOD_GRAPHPIMPL_Define_Vertex( \ + GraphClass, GraphName, GetGraphType, \ + getMacroGraph, g, OwnerImpl) \ + MOD_GRAPHPIMPL_Define_Vertex_noGraph(GraphClass, GraphName, \ + getMacroGraph, g, OwnerImpl) \ \ -Graph::Vertex::Vertex(std::shared_ptr g, std::size_t vId) : g(g), vId(vId) { \ +GetGraphType GraphClass::Vertex::getGraph() const { \ + if(!g) throw LogicError("Can not get graph on a null vertex."); \ + return g; \ +} + +#define MOD_GRAPHPIMPL_Define_Vertex_noGraph(GraphClass, GraphName, \ + getMacroGraph, g, OwnerImpl) \ + \ +GraphClass::Vertex::Vertex(std::shared_ptr g, std::size_t vId) \ + : g(g), vId(vId) { \ assert(g); \ using boost::vertices; \ const auto &graph = getMacroGraph; \ @@ -21,57 +33,52 @@ Graph::Vertex::Vertex(std::shared_ptr g, std::size_t vId) : g(g), vId(vId } \ } \ \ -Graph::Vertex::Vertex() : vId(0) { } \ +GraphClass::Vertex::Vertex() : vId(0) { } \ \ -std::ostream &operator<<(std::ostream &s, const Graph::Vertex &v) { \ - s << #Graph "Vertex("; \ - if(!v.get ## Owner()) s << "null"; \ - else s << *v.get ## Owner() << ", " << v.getId(); \ +std::ostream &operator<<(std::ostream &s, const GraphClass::Vertex &v) { \ + s << #GraphName "Vertex("; \ + if(!v) s << "null"; \ + else s << *v.g << ", " << v.getId(); \ return s << ")"; \ } \ \ -bool operator==(const Graph::Vertex &v1, const Graph::Vertex &v2) { \ +bool operator==(const GraphClass::Vertex &v1, const GraphClass::Vertex &v2) { \ return v1.g == v2.g && v1.vId == v2.vId; \ } \ \ -bool operator!=(const Graph::Vertex &v1, const Graph::Vertex &v2) { \ +bool operator!=(const GraphClass::Vertex &v1, const GraphClass::Vertex &v2) { \ return !(v1 == v2); \ } \ \ -bool operator<(const Graph::Vertex &v1, const Graph::Vertex &v2) { \ +bool operator<(const GraphClass::Vertex &v1, const GraphClass::Vertex &v2) { \ return std::tie(v1.g, v1.vId) < std::tie(v2.g, v2.vId); \ } \ \ -std::size_t Graph::Vertex::hash() const { \ +std::size_t GraphClass::Vertex::hash() const { \ if(g) return getId(); \ - else return -1; \ + else return -1; \ } \ \ -Graph::Vertex::operator bool() const { \ +GraphClass::Vertex::operator bool() const { \ return !isNull(); \ } \ \ -bool Graph::Vertex::isNull() const { \ - return *this == Graph::Vertex(); \ +bool GraphClass::Vertex::isNull() const { \ + return *this == GraphClass::Vertex(); \ } \ \ -std::size_t Graph::Vertex::getId() const { \ +std::size_t GraphClass::Vertex::getId() const { \ if(!g) throw LogicError("Can not get id on a null vertex."); \ const auto &graph = getMacroGraph; \ using boost::vertices; \ auto v = *std::next(vertices(graph).first, vId); \ return get(boost::vertex_index_t(), graph, v); \ -} \ - \ -std::shared_ptr Graph::Vertex::get ## Owner() const { \ - if(!g) throw LogicError("Can not get " #OwnerLowerCase " on a null vertex."); \ - return g; \ } -#define MOD_GRAPHPIMPL_Define_Vertex_Undirected(Graph, GraphLowerCase, getMacroGraph, g) \ +#define MOD_GRAPHPIMPL_Define_Vertex_Undirected(GraphClass, getMacroGraph, g) \ \ -std::size_t Graph::Vertex::getDegree() const { \ +std::size_t GraphClass::Vertex::getDegree() const { \ if(!g) throw LogicError("Can not get degree on a null vertex."); \ const auto &graph = getMacroGraph; \ using boost::vertices; \ @@ -79,15 +86,15 @@ std::size_t Graph::Vertex::getDegree() const { return out_degree(v, graph); \ } \ \ -Graph::IncidentEdgeRange Graph::Vertex::incidentEdges() const { \ +GraphClass::IncidentEdgeRange GraphClass::Vertex::incidentEdges() const { \ if(!g) throw LogicError("Can not get incident edges on a null vertex."); \ return IncidentEdgeRange(g, vId); \ } -#define MOD_GRAPHPIMPL_Define_Vertex_Directed(Graph, GraphLowerCase, getMacroGraph, g) \ +#define MOD_GRAPHPIMPL_Define_Vertex_Directed(GraphClass, getMacroGraph, g) \ \ -std::size_t Graph::Vertex::inDegree() const { \ +std::size_t GraphClass::Vertex::inDegree() const { \ if(!g) throw LogicError("Can not get in-degree on a null vertex."); \ const auto &graph = getMacroGraph; \ using boost::vertices; \ @@ -95,7 +102,7 @@ std::size_t Graph::Vertex::inDegree() const { return in_degree(v, graph); \ } \ \ -std::size_t Graph::Vertex::outDegree() const { \ +std::size_t GraphClass::Vertex::outDegree() const { \ if(!g) throw LogicError("Can not get out-degree on a null vertex."); \ const auto &graph = getMacroGraph; \ using boost::vertices; \ @@ -104,13 +111,13 @@ std::size_t Graph::Vertex::outDegree() const { } -#define MOD_GRAPHPIMPL_Define_Indices(Graph, OwnerLowerCase, getMacroGraph, g, getGraph, Owner) \ +#define MOD_GRAPHPIMPL_Define_Indices(GraphClass, GraphName, GetGraphType, getMacroGraph, g, OwnerImpl) \ \ /*----------------------------------------------------------------------------*/ \ /* Edge */ \ /*----------------------------------------------------------------------------*/ \ \ -Graph::Edge::Edge(std::shared_ptr g, std::size_t vId, std::size_t eId) : g(g), vId(vId), eId(eId) { \ +GraphClass::Edge::Edge(std::shared_ptr g, std::size_t vId, std::size_t eId) : g(g), vId(vId), eId(eId) { \ assert(g); \ using boost::vertices; \ const auto &graph = getMacroGraph; \ @@ -123,16 +130,16 @@ Graph::Edge::Edge(std::shared_ptr g, std::size_t vId, std::size_t eId) : } \ } \ \ -Graph::Edge::Edge() : vId(0), eId(0) { } \ +GraphClass::Edge::Edge() : vId(0), eId(0) { } \ \ -std::ostream &operator<<(std::ostream &s, const Graph::Edge &e) { \ - s << #Graph "Edge("; \ - if(e.g) s << *e.getGraph() << ", " << e.source().getId() << ", " << e.target().getId(); \ +std::ostream &operator<<(std::ostream &s, const GraphClass::Edge &e) { \ + s << #GraphName "Edge("; \ + if(e.g) s << *e.g << ", " << e.source().getId() << ", " << e.target().getId(); \ else s << "null"; \ return s << ")"; \ } \ \ -bool operator==(const Graph::Edge &e1, const Graph::Edge &e2) { \ +bool operator==(const GraphClass::Edge &e1, const GraphClass::Edge &e2) { \ if(e1.g && e2.g) \ return (e1.source() == e2.source() && e1.target() == e2.target()) \ || (e1.source() == e2.target() && e1.target() == e2.source()); \ @@ -140,33 +147,33 @@ bool operator==(const Graph::Edge &e1, const Graph::Edge &e2) { else return false; \ } \ \ -bool operator!=(const Graph::Edge &e1, const Graph::Edge &e2) { \ +bool operator!=(const GraphClass::Edge &e1, const GraphClass::Edge &e2) { \ return !(e1 == e2); \ } \ \ -bool operator<(const Graph::Edge &e1, const Graph::Edge &e2) { \ +bool operator<(const GraphClass::Edge &e1, const GraphClass::Edge &e2) { \ return std::tie(e1.g, e1.vId, e1.eId) < std::tie(e2.g, e2.vId, e2.eId); \ } \ \ -Graph::Edge::operator bool() const { \ +GraphClass::Edge::operator bool() const { \ return !isNull(); \ } \ \ -bool Graph::Edge::isNull() const { \ - return *this == Graph::Edge(); \ +bool GraphClass::Edge::isNull() const { \ + return *this == GraphClass::Edge(); \ } \ \ -std::shared_ptr Graph::Edge::getGraph() const { \ +GetGraphType GraphClass::Edge::getGraph() const { \ if(!g) throw LogicError("Can not get graph on a null edge."); \ return g; \ } \ \ -Graph::Vertex Graph::Edge::source() const { \ +GraphClass::Vertex GraphClass::Edge::source() const { \ if(!g) throw LogicError("Can not get source on a null edge."); \ return Vertex(g, vId); \ } \ \ -Graph::Vertex Graph::Edge::target() const { \ +GraphClass::Vertex GraphClass::Edge::target() const { \ if(!g) throw LogicError("Can not get target on a null edge."); \ const auto &graph = getMacroGraph; \ using boost::vertices; \ @@ -183,7 +190,7 @@ Graph::Vertex Graph::Edge::target() const { /* VertexIterator */ \ /*----------------------------------------------------------------------------*/ \ \ -Graph::VertexIterator::VertexIterator(std::shared_ptr g) : g(g), vId(0) { \ +GraphClass::VertexIterator::VertexIterator(std::shared_ptr g) : g(g), vId(0) { \ assert(g); \ using boost::vertices; \ const auto &graph = getMacroGraph; \ @@ -192,18 +199,18 @@ Graph::VertexIterator::VertexIterator(std::shared_ptr g) : g(g), vId(0) { this->g = nullptr; \ } \ \ -Graph::VertexIterator::VertexIterator() : g(nullptr), vId(0) { } \ +GraphClass::VertexIterator::VertexIterator() : g(nullptr), vId(0) { } \ \ -Graph::Vertex Graph::VertexIterator::dereference() const { \ - return Graph::Vertex(g, vId); \ +GraphClass::Vertex GraphClass::VertexIterator::dereference() const { \ + return GraphClass::Vertex(g, vId); \ } \ \ -bool Graph::VertexIterator::equal(const VertexIterator &iter) const { \ +bool GraphClass::VertexIterator::equal(const VertexIterator &iter) const { \ if(g) return g == iter.g && vId == iter.vId; \ else return g == iter.g; \ } \ \ -void Graph::VertexIterator::increment() { \ +void GraphClass::VertexIterator::increment() { \ ++this->vId; \ using boost::vertices; \ const auto &graph = getMacroGraph; \ @@ -215,31 +222,31 @@ void Graph::VertexIterator::increment() { } \ \ /*----------------------------------------------------------------------------*/ \ -/* EdgeIterator */ \ +/* EdgeIterator */ \ /*----------------------------------------------------------------------------*/ \ \ -Graph::EdgeIterator::EdgeIterator(std::shared_ptr g) : g(g), vId(0), eId(0) { \ +GraphClass::EdgeIterator::EdgeIterator(std::shared_ptr g) : g(g), vId(0), eId(0) { \ assert(g); \ advanceToValid(); \ } \ \ -Graph::EdgeIterator::EdgeIterator() : g(nullptr), vId(0), eId(0) { } \ +GraphClass::EdgeIterator::EdgeIterator() : g(nullptr), vId(0), eId(0) { } \ \ -Graph::Edge Graph::EdgeIterator::dereference() const { \ +GraphClass::Edge GraphClass::EdgeIterator::dereference() const { \ return Edge(g, vId, eId); \ } \ \ -bool Graph::EdgeIterator::equal(const EdgeIterator &iter) const { \ +bool GraphClass::EdgeIterator::equal(const EdgeIterator &iter) const { \ if(g) return g == iter.g && vId == iter.vId && eId == iter.eId; \ else return g == iter.g; \ } \ \ -void Graph::EdgeIterator::increment() { \ +void GraphClass::EdgeIterator::increment() { \ eId++; \ advanceToValid(); \ } \ \ -void Graph::EdgeIterator::advanceToValid() { \ +void GraphClass::EdgeIterator::advanceToValid() { \ assert(g); \ using boost::vertices; \ const auto &graph = getMacroGraph; \ @@ -262,7 +269,7 @@ void Graph::EdgeIterator::advanceToValid() { /* IncidentEdgeIterator */ \ /*----------------------------------------------------------------------------*/ \ \ -Graph::IncidentEdgeIterator::IncidentEdgeIterator(std::shared_ptr g, std::size_t vId) : g(g), vId(vId), eId(0) { \ +GraphClass::IncidentEdgeIterator::IncidentEdgeIterator(std::shared_ptr g, std::size_t vId) : g(g), vId(vId), eId(0) { \ assert(g); \ const auto &graph = getMacroGraph; \ using boost::vertices; \ @@ -273,18 +280,18 @@ Graph::IncidentEdgeIterator::IncidentEdgeIterator(std::shared_ptr g, std: } \ } \ \ -Graph::IncidentEdgeIterator::IncidentEdgeIterator() : g(nullptr), vId(0), eId(0) { } \ +GraphClass::IncidentEdgeIterator::IncidentEdgeIterator() : g(nullptr), vId(0), eId(0) { } \ \ -Graph::Edge Graph::IncidentEdgeIterator::dereference() const { \ - return Graph::Edge(g, vId, eId); \ +GraphClass::Edge GraphClass::IncidentEdgeIterator::dereference() const { \ + return GraphClass::Edge(g, vId, eId); \ } \ \ -bool Graph::IncidentEdgeIterator::equal(const IncidentEdgeIterator &iter) const { \ +bool GraphClass::IncidentEdgeIterator::equal(const IncidentEdgeIterator &iter) const { \ if(g) return g == iter.g && vId == iter.vId && eId == iter.eId; \ else return g == iter.g; \ } \ \ -void Graph::IncidentEdgeIterator::increment() { \ +void GraphClass::IncidentEdgeIterator::increment() { \ ++this->eId; \ const auto &graph = getMacroGraph; \ using boost::vertices; \ @@ -295,7 +302,6 @@ void Graph::IncidentEdgeIterator::increment() { } \ } -} // namespace lib -} // namespace mod +} // namespace mod::lib -#endif /* MOD_LIB_GRAPHPIMPL_H */ \ No newline at end of file +#endif // MOD_LIB_GRAPHPIMPL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Config.hpp b/libs/libmod/src/mod/lib/IO/Config.hpp index d51088f..72c992c 100644 --- a/libs/libmod/src/mod/lib/IO/Config.hpp +++ b/libs/libmod/src/mod/lib/IO/Config.hpp @@ -2,8 +2,7 @@ #define MOD_LIB_IO_CONFIG_HPP #include - -#include +#include namespace mod { diff --git a/libs/libmod/src/mod/lib/IO/DG.hpp b/libs/libmod/src/mod/lib/IO/DG.hpp index 79e98ac..99dcec3 100644 --- a/libs/libmod/src/mod/lib/IO/DG.hpp +++ b/libs/libmod/src/mod/lib/IO/DG.hpp @@ -1,26 +1,21 @@ -#ifndef MOD_LIB_IO_DG_H -#define MOD_LIB_IO_DG_H +#ifndef MOD_LIB_IO_DG_HPP +#define MOD_LIB_IO_DG_HPP +#include #include -#include #include #include - -#include +#include #include #include #include -namespace mod { -namespace lib { -namespace DG { +namespace mod::lib::DG { class Hyper; class NonHyper; -} // namespace DG -namespace IO { -namespace DG { -namespace Read { +} // namespace mod::lib::DG +namespace mod::lib::IO::DG::Read { struct AbstractDerivation { using List = std::vector>; @@ -42,8 +37,8 @@ std::unique_ptr dump(const std::vector> abstract(const std::string &s, std::ostream &err); -} // namespace Read -namespace Write { +} // namespace mod::lib::IO::DG::Read +namespace mod::lib::IO::DG::Write { using Vertex = lib::DG::HyperVertex; using Edge = lib::DG::HyperEdge; @@ -89,7 +84,7 @@ struct SyntaxPrinter { lib::DG::HyperVertex, const std::string &)> getImageCreator() = 0; public: - FileHandle s; + post::FileHandle s; }; struct TikzPrinter : SyntaxPrinter { @@ -388,11 +383,6 @@ std::pair summary(const Data &data, Printer &printer, const IO::Graph::Write::Options &graphOptions); -} // namespace Write -} // namespace DG -} // namespace IO -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_IO_DG_H */ +} // namespace mod::lib::IO::DG::Write +#endif // MOD_LIB_IO_DG_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/DGWrite.cpp b/libs/libmod/src/mod/lib/IO/DGWrite.cpp index d14c852..0d18c73 100644 --- a/libs/libmod/src/mod/lib/IO/DGWrite.cpp +++ b/libs/libmod/src/mod/lib/IO/DGWrite.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -117,7 +118,8 @@ std::string dumpToFile(const lib::DG::NonHyper &dg) { } std::string dotNonHyper(const lib::DG::NonHyper &nonHyper) { - FileHandle s(getUniqueFilePrefix() + "dgNonHyper_" + boost::lexical_cast(nonHyper.getId()) + ".dot"); + post::FileHandle s( + getUniqueFilePrefix() + "dgNonHyper_" + boost::lexical_cast(nonHyper.getId()) + ".dot"); { // printing using Vertex = lib::DG::NonHyperVertex; using Edge = lib::DG::NonHyperEdge; @@ -680,8 +682,7 @@ Options Printer::prePrint(const Data &data) { } if(withRuleId) { // we want the rule id before its name pushEdgeLabel([this](Vertex v, const lib::DG::Hyper &dg) -> std::string { - const auto &g = dg.getGraph(); - assert(g[v].kind == lib::DG::HyperVertexKind::Edge); + assert(dg.getGraph()[v].kind == lib::DG::HyperVertexKind::Edge); std::string res; bool first = true; for(auto *r : dg.getRulesFromEdge(v)) { @@ -696,8 +697,7 @@ Options Printer::prePrint(const Data &data) { } if(withRuleName) { pushEdgeLabel([this](Vertex v, const lib::DG::Hyper &dg) -> std::string { - const auto &g = dg.getGraph(); - assert(g[v].kind == lib::DG::HyperVertexKind::Edge); + assert(dg.getGraph()[v].kind == lib::DG::HyperVertexKind::Edge); std::string res; bool first = true; for(auto *r : dg.getRulesFromEdge(v)) { diff --git a/libs/libmod/src/mod/lib/IO/DGWriteDetail.hpp b/libs/libmod/src/mod/lib/IO/DGWriteDetail.hpp index ab450c9..9e0b9be 100644 --- a/libs/libmod/src/mod/lib/IO/DGWriteDetail.hpp +++ b/libs/libmod/src/mod/lib/IO/DGWriteDetail.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_IO_DGWRITEDETAIL_H -#define MOD_LIB_IO_DGWRITEDETAIL_H +#ifndef MOD_LIB_IO_DGWRITEDETAIL_HPP +#define MOD_LIB_IO_DGWRITEDETAIL_HPP #include #include @@ -8,11 +8,7 @@ #include -namespace mod { -namespace lib { -namespace IO { -namespace DG { -namespace Write { +namespace mod::lib::IO::DG::Write { template std::string toStr(const T &t) { @@ -33,8 +29,8 @@ forEachVertex(const lib::DG::Hyper &dg, const Options &options, SyntaxPrinter &p const auto &g = dg.getGraph(); const auto &dupGraph = options.dupGraph; DupVertex prevVertex = dupGraph.null_vertex(); - for(DupVertex vDup : asRange(vertices(dupGraph))) { - Vertex v = dupGraph[vDup].v; + for(const DupVertex vDup : asRange(vertices(dupGraph))) { + const Vertex v = dupGraph[vDup].v; if(g[v].kind != lib::DG::HyperVertexKind::Vertex) continue; unsigned int vId = get(boost::vertex_index_t(), g, v); const auto &graph = *g[v].graph; @@ -57,8 +53,8 @@ void forEachExplicitHyperEdge(const lib::DG::Hyper &dg, const Options &options, const auto &g = dg.getGraph(); const auto &dupGraph = options.dupGraph; DupVertex prevVertex = dupGraph.null_vertex(); - for(DupVertex vDup : asRange(vertices(dupGraph))) { - Vertex v = dupGraph[vDup].v; + for(const DupVertex vDup : asRange(vertices(dupGraph))) { + const Vertex v = dupGraph[vDup].v; if(g[v].kind != lib::DG::HyperVertexKind::Edge) continue; if(!options.isHyperedgeVisible(v, dg)) continue; unsigned int inDegreeVisible = options.inDegreeVisible(vDup, dg).first; @@ -67,7 +63,7 @@ void forEachExplicitHyperEdge(const lib::DG::Hyper &dg, const Options &options, // if all sources and targets are hidden, then hide this edge if(inDegreeVisible == 0 && outDegreeVisible == 0) continue; - bool isShortcutEdge = options.isShortcutEdge(vDup, dg, inDegreeVisible, outDegreeVisible); + const bool isShortcutEdge = options.isShortcutEdge(vDup, dg, inDegreeVisible, outDegreeVisible); if(!isShortcutEdge) { if(prevVertex == dupGraph.null_vertex() || dupGraph[prevVertex].v != dupGraph[vDup].v) { print.comment(hyperEdgeComment(dg, v)); @@ -85,8 +81,8 @@ void forEachConnector(const lib::DG::Hyper &dg, const Options &options, SyntaxPr const auto &g = dg.getGraph(); const auto &dupGraph = options.dupGraph; DupVertex prevVertex = dupGraph.null_vertex(); - for(DupVertex vDup : asRange(vertices(dupGraph))) { - Vertex v = dupGraph[vDup].v; + for(const DupVertex vDup : asRange(vertices(dupGraph))) { + const Vertex v = dupGraph[vDup].v; if(g[v].kind != lib::DG::HyperVertexKind::Edge) continue; if(prevVertex == dupGraph.null_vertex() || dupGraph[prevVertex].v != dupGraph[vDup].v) { print.comment(detail::hyperEdgeComment(dg, v)); @@ -105,43 +101,41 @@ void forEachConnector(const lib::DG::Hyper &dg, const Options &options, SyntaxPr // if all sources and targets are hidden, then hide this edge if(inDegreeVisible == 0 && outDegreeVisible == 0) continue; - bool isShortcutEdge = options.isShortcutEdge(vDup, dg, inDegreeVisible, outDegreeVisible); + const bool isShortcutEdge = options.isShortcutEdge(vDup, dg, inDegreeVisible, outDegreeVisible); if(!isShortcutEdge) { // dupVertex -> count std::map tailCount, headCount; - for(DupVertex vDupIn : asRange(inv_adjacent_vertices(vDup, dupGraph))) { + for(const DupVertex vDupIn : asRange(inv_adjacent_vertices(vDup, dupGraph))) { auto iter = tailCount.find(vDupIn); if(iter == end(tailCount)) tailCount[vDupIn] = 1; else iter->second++; } - for(DupVertex vDupOut : asRange(adjacent_vertices(vDup, dupGraph))) { + for(const DupVertex vDupOut : asRange(adjacent_vertices(vDup, dupGraph))) { auto iter = headCount.find(vDupOut); if(iter == end(headCount)) headCount[vDupOut] = 1; else iter->second++; } - for(const auto p : tailCount) { - DupVertex vDupAdj = p.first; - Vertex vAdj = options.dupGraph[vDupAdj].v; + for(const auto[vDupAdj, count] : tailCount) { + const Vertex vAdj = options.dupGraph[vDupAdj].v; if(!options.isVertexVisible(vAdj, dg)) continue; const auto invIter = headCount.find(vDupAdj); - int maxCount = p.second; + int maxCount = count; if(invIter != end(headCount)) maxCount += invIter->second; - tailBody(vDup, vDupAdj, p.second, maxCount); + tailBody(vDup, vDupAdj, count, maxCount); } - for(const auto p : headCount) { - DupVertex vDupAdj = p.first; - Vertex vAdj = options.dupGraph[vDupAdj].v; + for(const auto[vDupAdj, count] : headCount) { + const Vertex vAdj = options.dupGraph[vDupAdj].v; if(!options.isVertexVisible(vAdj, dg)) continue; const auto invIter = tailCount.find(vDupAdj); - int maxCount = p.second; + int maxCount = count; if(invIter != end(tailCount)) maxCount += invIter->second; - headBody(vDup, vDupAdj, p.second, maxCount); + headBody(vDup, vDupAdj, count, maxCount); } } else { const auto vReverse = dg.getReverseEdge(v); - bool hasReverse = vReverse != g.null_vertex() - && options.isHyperedgeVisible(vReverse, dg); + const bool hasReverse = vReverse != g.null_vertex() + && options.isHyperedgeVisible(vReverse, dg); if(hasReverse) { // check if the reverse goes between the same vertex incarnations // TODO @@ -152,10 +146,6 @@ void forEachConnector(const lib::DG::Hyper &dg, const Options &options, SyntaxPr } } // namespace detail -} // namespace Write -} // namespace DG -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace namespace mod::lib::IO::DG::Write -#endif /* MOD_LIB_IO_DGWRITEDETAIL_H */ \ No newline at end of file +#endif // MOD_LIB_IO_DGWRITEDETAIL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Derivation.cpp b/libs/libmod/src/mod/lib/IO/Derivation.cpp index cc2ca72..55a6bf4 100644 --- a/libs/libmod/src/mod/lib/IO/Derivation.cpp +++ b/libs/libmod/src/mod/lib/IO/Derivation.cpp @@ -1,6 +1,7 @@ #include "Derivation.hpp" #include +#include #include #include #include @@ -9,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -53,10 +53,10 @@ std::vector findCompleteRules(const lib::DG::NonHyper &dg, std::vector matchingL; { if(getConfig().dg.derivationDebugOutput.get()) { - IO::log() << "Derivation: compose identifyL -> rReal" << std::endl; - IO::log() << "Derivation: eductUnion:" << std::endl; + std::cout << "Derivation: compose identifyL -> rReal" << std::endl; + std::cout << "Derivation: eductUnion:" << std::endl; for(const auto vAdj : asRange(inv_adjacent_vertices(v, dgGraph))) - IO::log() << "Derivation: " << dgGraph[vAdj].graph->getName() << std::endl; + std::cout << "Derivation: " << dgGraph[vAdj].graph->getName() << std::endl; } auto reporter = [&matchingL, &dg](std::unique_ptr r) { auto *rPtr = r.release(); @@ -69,29 +69,29 @@ std::vector findCompleteRules(const lib::DG::NonHyper &dg, if(getConfig().dg.derivationDebugOutput.get()) lib::IO::Rules::Write::termState(rReal); lib::RC::Super mm( - getConfig().dg.derivationVerbosity.get(), IO::Logger(IO::log()), + getConfig().dg.derivationVerbosity.get(), IO::Logger(std::cout), false, true); lib::RC::composeRuleRealByMatchMaker(*identifyL, rReal, mm, reporter, dg.getLabelSettings()); } for(auto *r : matchingL) { if(getConfig().dg.derivationDebugOutput.get()) - IO::log() << "Derivation: compose matchingL -> identifyR" << std::endl; + std::cout << "Derivation: compose matchingL -> identifyR" << std::endl; auto reporter = [&matchingLR, &dg](std::unique_ptr r) { if(getConfig().dg.derivationDebugOutput.get()) - IO::log() << "Derivation: got result" << std::endl; + std::cout << "Derivation: got result" << std::endl; auto *rPtr = r.release(); auto labelType = dg.getLabelSettings().type; auto withStereo = dg.getLabelSettings().withStereo; auto p = findAndInsert(matchingLR, rPtr, lib::Rules::makeIsomorphismPredicate(labelType, withStereo)); if(getConfig().dg.derivationDebugOutput.get()) - IO::log() << "Derivation: findAndInsert = " << std::boolalpha << p.second << std::endl; + std::cout << "Derivation: findAndInsert = " << std::boolalpha << p.second << std::endl; if(!p.second) delete rPtr; return true; }; assert(r); // TODO: we should do isomorphism here instead lib::RC::Sub mm( - getConfig().dg.derivationVerbosity.get(), IO::Logger(IO::log()), + getConfig().dg.derivationVerbosity.get(), IO::Logger(std::cout), false); lib::RC::composeRuleRealByMatchMaker(*r, *identifyR, mm, reporter, dg.getLabelSettings()); delete r; @@ -122,11 +122,11 @@ void forEachMatch(const lib::DG::NonHyper &dg, lib::DG::HyperVertex v, const lib // options.withIndex = true; // lib::IO::Rules::Write::summary(rReal, options, options); // lib::IO::Rules::Write::summary(*rLower, options, options); - // IO::log() << "morphismSelectByLabelSettings: " << dg.getLabelSettings() << std::endl; + // std::cout << "morphismSelectByLabelSettings: " << dg.getLabelSettings() << std::endl; lib::GraphMorphism::morphismSelectByLabelSettings(rReal.getDPORule(), rLower->getDPORule(), dg.getLabelSettings(), lib::GraphMorphism::VF2Monomorphism(), std::ref(mr), lib::Rules::MembershipPredWrapper()); - // IO::log() << "morphismSelectByLabelSettings done" << std::endl; + // std::cout << "morphismSelectByLabelSettings done" << std::endl; delete rLower; } if(!derivationFound) { @@ -170,7 +170,7 @@ summary(const lib::DG::NonHyper &dg, IO::post() << "\\}\"" << std::endl; { std::string file = getUniqueFilePrefix() + "der_constraints.tex"; - FileHandle s(file); + post::FileHandle s(file); auto vis = lib::IO::MatchConstraint::Write::makeTexPrintVisitor(s, get_left(rReal.getDPORule())); for(const auto &c : rReal.getDPORule().leftMatchConstraints) { c->accept(vis); diff --git a/libs/libmod/src/mod/lib/IO/FileHandle.cpp b/libs/libmod/src/mod/lib/IO/FileHandle.cpp deleted file mode 100644 index 9afef42..0000000 --- a/libs/libmod/src/mod/lib/IO/FileHandle.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "FileHandle.hpp" - -#include -#include - -#include - -namespace mod { -namespace lib { -namespace IO { - -FileHandle::FileHandle(std::string name) : name(name) { - // at most 1 dot - if(1 < std::count(name.begin(), name.end(), '.')) MOD_ABORT; - stream.open(name.c_str()); - if(!stream) { - IO::log() << "Could not open file '" << name << "'." << std::endl; - IO::log() << "Does 'out/' exist?" << std::endl; - std::exit(1); - } -} -} // namespace IO -} // namespace lib -} // namespace mod \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/FileHandle.hpp b/libs/libmod/src/mod/lib/IO/FileHandle.hpp deleted file mode 100644 index 7bd4595..0000000 --- a/libs/libmod/src/mod/lib/IO/FileHandle.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MOD_LIB_IO_FILEHANDLE_H -#define MOD_LIB_IO_FILEHANDLE_H - -#include -#include -#include - -namespace mod { -namespace lib { -namespace IO { - -struct FileHandle { - explicit FileHandle(std::string name); - - operator std::ostream &() { - return stream; - } - - operator std::string() { - return name; - } - - template - friend std::ostream &operator<<(FileHandle &s, T &&t) { - return s.stream << std::forward(t); - } -public: - std::ofstream stream; - std::string name; -}; - -} // namespace IO -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_IO_FILEHANDLE_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/GMLUtil.cpp b/libs/libmod/src/mod/lib/IO/GMLUtil.cpp index 986e513..a15c605 100644 --- a/libs/libmod/src/mod/lib/IO/GMLUtil.cpp +++ b/libs/libmod/src/mod/lib/IO/GMLUtil.cpp @@ -1,20 +1,14 @@ #include -#include +#include -namespace mod { -namespace lib { -namespace IO { -namespace GML { +namespace mod::lib::IO::GML { - std::ostream &operator<<(std::ostream &s, const Edge &e) { - s << "edge [ source " << e.source << " target " << e.target; - if(e.label) s << " label \"" << *e.label << "\""; - if(e.stereo) s << " stereo \"" << *e.stereo << "\""; - return s << " ]"; - } +std::ostream &operator<<(std::ostream &s, const Edge &e) { + s << "edge [ source " << e.source << " target " << e.target; + if(e.label) s << " label \"" << *e.label << "\""; + if(e.stereo) s << " stereo \"" << *e.stereo << "\""; + return s << " ]"; +} -} // namespace GML -} // namespace IO -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::IO::GML \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/GMLUtils.hpp b/libs/libmod/src/mod/lib/IO/GMLUtils.hpp index a065e66..40d8fbb 100644 --- a/libs/libmod/src/mod/lib/IO/GMLUtils.hpp +++ b/libs/libmod/src/mod/lib/IO/GMLUtils.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_IO_GMLUTILS_H -#define MOD_LIB_IO_GMLUTILS_H +#ifndef MOD_LIB_IO_GMLUTILS_HPP +#define MOD_LIB_IO_GMLUTILS_HPP #include @@ -12,10 +12,7 @@ #include -namespace mod { -namespace lib { -namespace IO { -namespace GML { +namespace mod::lib::IO::GML { struct Vertex { int id; @@ -68,8 +65,7 @@ static const auto makeVertexConverter = [](std::size_t lowerBound) { return list("node", &Graph::vertices) (int_("id", &Vertex::id), 1, 1) (string("label", &Vertex::label), lowerBound, 1) - (cStereo, 0, 1) - ; + (cStereo, 0, 1); }; static const auto makeEdgeConverter = [](std::size_t lowerBound) { @@ -79,13 +75,9 @@ static const auto makeEdgeConverter = [](std::size_t lowerBound) { (int_("source", &Edge::source), 1, 1) (int_("target", &Edge::target), 1, 1) (string("label", &Edge::label), lowerBound, 1) - (cStereo, 0, 1) - ; + (cStereo, 0, 1); }; -} // namespace GML -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::GML -#endif /* MOD_LIB_IO_GMLUTILS_H */ \ No newline at end of file +#endif // MOD_LIB_IO_GMLUTILS_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Graph.hpp b/libs/libmod/src/mod/lib/IO/Graph.hpp index 8b368d1..0a056a4 100644 --- a/libs/libmod/src/mod/lib/IO/Graph.hpp +++ b/libs/libmod/src/mod/lib/IO/Graph.hpp @@ -1,26 +1,24 @@ -#ifndef MOD_LIB_IO_GRAPH_H -#define MOD_LIB_IO_GRAPH_H +#ifndef MOD_LIB_IO_GRAPH_HPP +#define MOD_LIB_IO_GRAPH_HPP #include -#include #include #include #include +#include namespace mod { enum class SmilesClassPolicy; -namespace lib { -namespace Graph { +} // namespace mod +namespace mod::lib::Graph { struct DepictionData; struct LabelledGraph; struct PropStereo; struct PropString; struct Single; -} // namespace Graph -namespace IO { -namespace Graph { -namespace Read { +} // namespace mod::lib::Graph +namespace mod::lib::IO::Graph::Read { struct Data { Data(); @@ -34,11 +32,11 @@ struct Data { std::map externalToInternalIds; }; -Data gml(std::istream &s, std::ostream &err); +Data gml(std::string_view src, std::ostream &err); Data dfs(const std::string &dfs, std::ostream &err); Data smiles(const std::string &smiles, std::ostream &err, bool allowAbstract, SmilesClassPolicy classPolicy); -} // namespace Read -namespace Write { +} // namespace mod::lib::IO::Graph::Read +namespace mod::lib::IO::Graph::Write { enum class EdgeFake3DType { None, WedgeSL, WedgeLS, HashSL, HashLS @@ -204,11 +202,6 @@ std::string tikz(const lib::Graph::Single &g, const Options &options, bool asInl std::string pdf(const lib::Graph::Single &g, const Options &options); std::string svg(const lib::Graph::Single &g, const Options &options); -} // namespace Write -} // namespace Graph -} // namespace IO -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_IO_GRAPH_H */ +} // namespace mod::lib::IO::Graph::Write +#endif // MOD_LIB_IO_GRAPH_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/GraphRead.cpp b/libs/libmod/src/mod/lib/IO/GraphRead.cpp index ec77f3c..ef38c37 100644 --- a/libs/libmod/src/mod/lib/IO/GraphRead.cpp +++ b/libs/libmod/src/mod/lib/IO/GraphRead.cpp @@ -18,11 +18,9 @@ #include -namespace mod { -namespace lib { -namespace IO { -namespace Graph { -namespace Read { +#include + +namespace mod::lib::IO::Graph::Read { Data::Data() {} @@ -30,19 +28,17 @@ Data::Data(Data &&other) : g(std::move(other.g)), pString(std::move(other.pStrin externalToInternalIds(std::move(other.externalToInternalIds)) {} Data::~Data() { - if(std::uncaught_exception()) return; // TODO: update to the plural version when C++17 is required + if(std::uncaught_exceptions() != 0) return; if(g) MOD_ABORT; if(pString) MOD_ABORT; if(pStereo) MOD_ABORT; } -namespace { - -Data parseGML(std::istream &s, std::ostream &err) { +Data gml(std::string_view src, std::ostream &err) { GML::Graph gGML; { gml::ast::KeyValue ast; - bool res = gml::parser::parse(s, ast, err); + bool res = gml::parser::parse(src, ast, err); if(!res) return Data(); using namespace gml::converter::edsl; auto cVertex = GML::makeVertexConverter(1); @@ -244,7 +240,7 @@ Data parseGML(std::istream &s, std::ostream &err) { break; case lib::Stereo::DeductionResult::Warning: if(!getConfig().stereo.silenceDeductionWarnings.get()) - IO::log() << ssErr.str(); + std::cout << ssErr.str(); break; case lib::Stereo::DeductionResult::Error: err << ssErr.str(); @@ -255,12 +251,6 @@ Data parseGML(std::istream &s, std::ostream &err) { return data; } -} // namespace - -Data gml(std::istream &s, std::ostream &err) { - return parseGML(s, err); -} - Data dfs(const std::string &dfs, std::ostream &err) { return lib::Graph::DFSEncoding::parse(dfs, err); } @@ -269,8 +259,4 @@ Data smiles(const std::string &smiles, std::ostream &err, const bool allowAbstra return lib::Chem::readSmiles(smiles, err, allowAbstract, classPolicy); } -} // namespace Read -} // namespace Graph -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::Graph::Read \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/GraphWrite.cpp b/libs/libmod/src/mod/lib/IO/GraphWrite.cpp index f7dfa75..3f8f1dc 100644 --- a/libs/libmod/src/mod/lib/IO/GraphWrite.cpp +++ b/libs/libmod/src/mod/lib/IO/GraphWrite.cpp @@ -2,13 +2,13 @@ #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -18,11 +18,9 @@ #include -namespace mod { -namespace lib { -namespace IO { -namespace Graph { -namespace Write { +#include + +namespace mod::lib::IO::Graph::Write { namespace { // returns the filename _without_ extension @@ -89,7 +87,7 @@ std::string gml(const lib::Graph::Single &g, bool withCoords) { std::string fileNoExt = getFilePrefix(g.getId(), true); if(iter != end(cache)) return fileNoExt; cache.emplace(g.getId(), withCoords); - FileHandle s(fileNoExt + ".gml"); + post::FileHandle s(fileNoExt + ".gml"); gml(g.getLabelledGraph(), g.getDepictionData(), g.getId(), withCoords, s); return s; } @@ -100,7 +98,7 @@ std::string dot(const lib::Graph::LabelledGraph &gLabelled, const std::size_t gI std::string file = getFilePrefix(gId, true) + ".dot"; if(iter != end(cache)) return file; cache.insert(gId); - FileHandle s(file); + post::FileHandle s(file); const auto &g = get_graph(gLabelled); const auto &pString = get_string(gLabelled); { @@ -175,7 +173,7 @@ std::string coords(const lib::Graph::LabelledGraph &gLabelled, const lib::Graph: if(options.rotation != 0) f += "_r" + std::to_string(options.rotation); if(options.mirror) f += "_m" + std::to_string(options.mirror); if(asInline) f += "i"; - FileHandle s(f + "_coord.tex"); + post::FileHandle s(f + "_coord.tex"); s << "% dummy\n"; for(const auto v : asRange(vertices(g))) { const auto vId = get(boost::vertex_index_t(), g, v); @@ -215,7 +213,7 @@ tikz(const lib::Graph::LabelledGraph &gLabelled, const lib::Graph::DepictionData if(iter != end(cache)) return std::make_pair(file, fileCoordsExt); cache.insert(std::make_pair(gId, strOptions)); } - FileHandle s(file); + post::FileHandle s(file); tikz(s, options, get_graph(gLabelled), depict, fileCoordsExt, asInline, idPrefix); return std::make_pair(file, fileCoordsExt); } @@ -231,7 +229,7 @@ pdf(const lib::Graph::LabelledGraph &gLabelled, const lib::Graph::DepictionData if(image) { std::string imageNoExt = (*image)(); if(imageNoExt.empty()) { - IO::log() << "User-specified depiction file for graph with id " << gId << " can not be empty." << std::endl; + std::cout << "User-specified depiction file for graph with id " << gId << " can not be empty." << std::endl; throw 0; } std::string cmd = depict.getImageCommand(); @@ -290,7 +288,7 @@ void termState(const lib::Graph::Single &g) { using Edge = lib::Graph::Edge; using namespace lib::Term; IO::post() << "summarySubsection \"Term State for " << g.getName() << "\"" << std::endl; - FileHandle s(getUniqueFilePrefix() + "termState.tex"); + post::FileHandle s(getUniqueFilePrefix() + "termState.tex"); s << "\\begin{verbatim}\n"; const auto &termState = get_term(g.getLabelledGraph()); if(isValid(termState)) { @@ -351,8 +349,4 @@ std::string svg(const lib::Graph::Single &g, const Options &options) { return svg(g.getLabelledGraph(), g.getDepictionData(), g.getId(), options); } -} // namespace Write -} // namespace Graph -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::Graph::Write \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/GraphWriteDetail.hpp b/libs/libmod/src/mod/lib/IO/GraphWriteDetail.hpp index ebbb5f0..cf1677c 100644 --- a/libs/libmod/src/mod/lib/IO/GraphWriteDetail.hpp +++ b/libs/libmod/src/mod/lib/IO/GraphWriteDetail.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_IO_GRAPHWRITEDETAIL_H -#define MOD_LIB_IO_GRAPHWRITEDETAIL_H +#ifndef MOD_LIB_IO_GRAPHWRITEDETAIL_HPP +#define MOD_LIB_IO_GRAPHWRITEDETAIL_HPP #include #include @@ -46,9 +46,7 @@ static constexpr unsigned int } // namespace Loc } // namespace -namespace mod { -namespace lib { -namespace IO { +namespace mod::lib::IO { constexpr double pi = 3.14159265358979323846; @@ -66,8 +64,8 @@ inline std::pair pointTransform(double xRaw, double yRaw, int ro return pointRotation(xRaw, yRaw, rotation); } -namespace Graph { -namespace Write { +} // mod::lib::IO +namespace mod::lib::IO::Graph::Write { template void tikz(std::ostream &s, const Options &options, const Graph &g, const Depict &depict, @@ -747,11 +745,6 @@ void tikz(std::ostream &s, const Options &options, const Graph &g, const Depict }, idPrefix); } -} // namespace Write -} // namespace Graph -} // namespace IO -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_IO_GRAPHWRITEDETAIL_H */ +} // namespace mod::lib::IO::Graph::Write +#endif // MOD_LIB_IO_GRAPHWRITEDETAIL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/IO.cpp b/libs/libmod/src/mod/lib/IO/IO.cpp index f427b5b..d232106 100644 --- a/libs/libmod/src/mod/lib/IO/IO.cpp +++ b/libs/libmod/src/mod/lib/IO/IO.cpp @@ -1,22 +1,17 @@ #include "IO.hpp" -#include - #include #include #include #include -namespace mod { -namespace lib { -namespace IO { +namespace mod::lib::IO { namespace { const std::string prefix = "out/"; struct PostStream { - PostStream() { std::string postFile = prefix + "post.sh"; s.open(postFile.c_str()); @@ -25,16 +20,24 @@ struct PostStream { ~PostStream() {} + void resetStream() { + std::string postFile = prefix + "post.sh"; + s.close(); + s.open(postFile.c_str()); + enabled = s.is_open(); + } + std::ofstream &getStream() { if(enabled) return s; std::cerr << "ERROR: can not write to '" << prefix + "post.sh'" << std::endl; std::cerr << "Does '" << prefix << "' exist?" << std::endl; std::exit(1); } - private: bool enabled; std::ofstream s; +public: + bool dynamicallyEnabled = true; }; PostStream postStream; @@ -94,18 +97,30 @@ std::string asLatexMath(const std::string &str) { } std::ostream &nullStream() { - static std::ofstream s("/dev/null"); + // https://stackoverflow.com/questions/11826554/standard-no-op-output-stream/11826787 + struct NullBuffer : public std::streambuf { + int overflow(int c) { return c; } + }; + struct NullStream : public std::ostream { + NullStream() : std::ostream(&buffer) {} + private: + NullBuffer buffer; + }; + static NullStream s; return s; } std::ostream &post() { + if(!postStream.dynamicallyEnabled) return nullStream(); return postStream.getStream(); } -std::ostream &log() { - std::cout.flush(); - bool log = true; - return log ? std::cout : nullStream(); +void postReset() { + postStream.resetStream(); +} + +void postDisable() { + postStream.dynamicallyEnabled = false; } std::ostream &Logger::indent() const { @@ -118,6 +133,4 @@ std::ostream &Logger::sep(char c) const { return s << std::string(std::max(10, 80 - indentLevel * 2), c) << '\n'; } -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO diff --git a/libs/libmod/src/mod/lib/IO/IO.hpp b/libs/libmod/src/mod/lib/IO/IO.hpp index f100ef8..94db330 100644 --- a/libs/libmod/src/mod/lib/IO/IO.hpp +++ b/libs/libmod/src/mod/lib/IO/IO.hpp @@ -1,12 +1,10 @@ -#ifndef MOD_LIB_IO_IO_H -#define MOD_LIB_IO_IO_H +#ifndef MOD_LIB_IO_IO_HPP +#define MOD_LIB_IO_IO_HPP #include #include -namespace mod { -namespace lib { -namespace IO { +namespace mod::lib::IO { std::string getUniqueFilePrefix(); std::string escapeForLatex(const std::string &str); @@ -14,11 +12,12 @@ std::string asLatexMath(const std::string &str); std::ostream &nullStream(); std::ostream &post(); -std::ostream &log(); + +void postReset(); +void postDisable(); struct Logger { explicit Logger(std::ostream &s) : s(s) {} - std::ostream &indent() const; std::ostream &sep(char c) const; public: @@ -26,8 +25,6 @@ struct Logger { int indentLevel = 0; }; -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO -#endif /* MOD_LIB_IO_IO_H */ +#endif // MOD_LIB_IO_IO_HPP diff --git a/libs/libmod/src/mod/lib/IO/JsonUtils.cpp b/libs/libmod/src/mod/lib/IO/JsonUtils.cpp index 60b9d0a..540326e 100644 --- a/libs/libmod/src/mod/lib/IO/JsonUtils.cpp +++ b/libs/libmod/src/mod/lib/IO/JsonUtils.cpp @@ -1,6 +1,6 @@ #include "JsonUtils.hpp" -#include +#include #include #include @@ -16,7 +16,7 @@ std::string writeJsonFile(const std::string &name, const nlohmann::json &j) { const std::uint32_t checksum = result.checksum(); const char version = 1; - FileHandle s(getUniqueFilePrefix() + name); + post::FileHandle s(getUniqueFilePrefix() + name); s.stream.write(reinterpret_cast(bytes.data()), bytes.size()); s.stream.write(reinterpret_cast(&checksum), sizeof(checksum)); s.stream.write(&version, 1); diff --git a/libs/libmod/src/mod/lib/IO/JsonUtils.hpp b/libs/libmod/src/mod/lib/IO/JsonUtils.hpp index dfc75f4..38e9f70 100644 --- a/libs/libmod/src/mod/lib/IO/JsonUtils.hpp +++ b/libs/libmod/src/mod/lib/IO/JsonUtils.hpp @@ -3,11 +3,16 @@ #include +// We don't control the symbol visibility of the json library and json-schema library, +// so we need to restore the default when using their header files. +// For example typeinfo objects for exceptions _must_ be exported. +#pragma GCC visibility push(default) + #include -namespace mod { -namespace lib { -namespace IO { +#pragma GCC visibility pop + +namespace mod::lib::IO { // returns the full filename std::string writeJsonFile(const std::string &name, const nlohmann::json &j); @@ -18,8 +23,6 @@ bool validateJson(const nlohmann::json &j, std::ostream &err, const std::string &msg); -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO #endif // MOD_LIB_IO_JSONUTILS_HPP diff --git a/libs/libmod/src/mod/lib/IO/RC.cpp b/libs/libmod/src/mod/lib/IO/RC.cpp index 50895fd..fa6321b 100644 --- a/libs/libmod/src/mod/lib/IO/RC.cpp +++ b/libs/libmod/src/mod/lib/IO/RC.cpp @@ -1,7 +1,7 @@ #include "RC.hpp" #include -#include +#include #include #include #include @@ -9,19 +9,13 @@ #include #include -namespace mod { -namespace lib { -namespace IO { -namespace RC { -namespace Read { -} // namespace Read -namespace Write { +namespace mod::lib::IO::RC::Write { std::string dot(const lib::RC::Evaluator &rc) { typedef lib::RC::Evaluator::Vertex Vertex; typedef lib::RC::Evaluator::Edge Edge; const lib::RC::Evaluator::GraphType &rcg = rc.getGraph(); - FileHandle s(getUniqueFilePrefix() + "rc.dot"); + post::FileHandle s(getUniqueFilePrefix() + "rc.dot"); std::string fileNoExt = s; fileNoExt.erase(end(fileNoExt) - 4, end(fileNoExt)); s << "digraph g {" << std::endl; @@ -41,7 +35,7 @@ std::string dot(const lib::RC::Evaluator &rc) { for(Edge e : asRange(edges(rcg))) { s << "\t" << get(boost::vertex_index_t(), rcg, source(e, rcg)) - << " -> " << get(boost::vertex_index_t(), rcg, target(e, rcg)) << " ["; + << " -> " << get(boost::vertex_index_t(), rcg, target(e, rcg)) << " ["; switch(rcg[e].kind) { case lib::RC::Evaluator::EdgeKind::First: s << " label=1"; @@ -70,7 +64,47 @@ std::string pdf(const lib::RC::Evaluator &rc) { return fileNoExt; } -void test(const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, const CoreCoreMap &match, const lib::Rules::Real &rNew) { +void test(const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, const CoreCoreMap &match, + const lib::Rules::Real &rNew) { + if(getConfig().rc.printMatchesOnlyHaxChem.get()) { + const auto &lg = get_labelled_left(rNew.getDPORule()); + const auto &g = get_graph(lg); + const auto &mol = get_molecule(lg); + for(const auto v : asRange(vertices(g))) { + const auto ad = mol[v]; + if(ad.getRadical()) continue; + if(ad.getCharge() != 0) continue; + if(ad.getIsotope() != Isotope()) continue; + int valence = 0; + for(const auto e : asRange(out_edges(v, g))) { + switch(mol[e]) { + case BondType::Single: + valence += 1; + break; + case BondType::Double: + valence += 2; + break; + case BondType::Triple: + valence += 3; + break; + default: + valence -= 100; + break; + } + } + switch(ad.getAtomId()) { + case AtomIds::H: + if(valence > 1) return; + break; + case AtomIds::C: + if(valence > 4) return; + break; + case AtomIds::O: + if(valence > 2) return; + break; + } + } + } using CoreVertex = lib::Rules::Vertex; using CoreEdge = lib::Rules::Edge; IO::Rules::Write::Options options; @@ -78,13 +112,13 @@ void test(const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, const options.EdgesAsBonds(true); if(getConfig().rc.matchesWithIndex.get()) options.WithIndex(true); - auto visible = [](CoreVertex) { + const auto visible = [](CoreVertex) { return true; }; - auto vColour = [](CoreVertex) { + const auto vColour = [](CoreVertex) { return std::string(); }; - auto eColour = [](CoreEdge) { + const auto eColour = [](CoreEdge) { return std::string(); }; // make a fake rule with all the vertices and edges, just for coords @@ -92,41 +126,43 @@ void test(const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, const lib::Rules::LabelledRule dpoCommon(rFirst.getDPORule(), false); lib::Rules::GraphType &gComon = get_graph(dpoCommon); lib::Rules::PropStringCore &pStringCommon = *dpoCommon.pString; - for(CoreVertex v : asRange(vertices(rFirst.getGraph()))) vFirstToCommon[v] = v; + for(const CoreVertex v : asRange(vertices(rFirst.getGraph()))) + vFirstToCommon[v] = v; // TODO: this will completely break if vertices are deleted in the composed rule - for(CoreVertex v : asRange(vertices(rNew.getGraph()))) + for(const CoreVertex v : asRange(vertices(rNew.getGraph()))) vNewToCommon[v] = v; // copy rSecond vertices - for(CoreVertex v : asRange(vertices(rSecond.getGraph()))) { - auto rightIter = match.right.find(v); - if(rightIter != match.right.end()) vSecondToCommon[v] = rightIter->second; - else { - CoreVertex vCommon = add_vertex(gComon); + for(const CoreVertex v : asRange(vertices(rSecond.getGraph()))) { + const auto rightIter = match.right.find(v); + if(rightIter != match.right.end()) { + vSecondToCommon[v] = rightIter->second; + } else { + const CoreVertex vCommon = add_vertex(gComon); vSecondToCommon[v] = vCommon; gComon[vCommon].membership = lib::Rules::Membership::Context; const std::string &label = rSecond.getGraph()[v].membership == lib::Rules::Membership::Left - ? rSecond.getStringState().getLeft()[v] - : rSecond.getStringState().getRight()[v]; + ? rSecond.getStringState().getLeft()[v] + : rSecond.getStringState().getRight()[v]; pStringCommon.add(vCommon, label, label); } } // copy rSecond edges - for(CoreEdge e : asRange(edges(rSecond.getGraph()))) { - CoreVertex vSrcSecond = source(e, rSecond.getGraph()); - CoreVertex vTarSecond = target(e, rSecond.getGraph()); - auto iterSrc = vSecondToCommon.find(vSrcSecond); - auto iterTar = vSecondToCommon.find(vTarSecond); + for(const CoreEdge e : asRange(edges(rSecond.getGraph()))) { + const CoreVertex vSrcSecond = source(e, rSecond.getGraph()); + const CoreVertex vTarSecond = target(e, rSecond.getGraph()); + const auto iterSrc = vSecondToCommon.find(vSrcSecond); + const auto iterTar = vSecondToCommon.find(vTarSecond); assert(iterSrc != end(vSecondToCommon)); assert(iterTar != end(vSecondToCommon)); - CoreVertex vSrc = iterSrc->second; - CoreVertex vTar = iterTar->second; + const CoreVertex vSrc = iterSrc->second; + const CoreVertex vTar = iterTar->second; auto pEdge = edge(vSrc, vTar, gComon); if(pEdge.second) continue; pEdge = add_edge(vSrc, vTar, gComon); gComon[pEdge.first].membership = lib::Rules::Membership::Context; const std::string &label = rSecond.getGraph()[e].membership == lib::Rules::Membership::Left - ? rSecond.getStringState().getLeft()[e] - : rSecond.getStringState().getRight()[e]; + ? rSecond.getStringState().getLeft()[e] + : rSecond.getStringState().getRight()[e]; pStringCommon.add(pEdge.first, label, label); } lib::Rules::Real rCommon(std::move(dpoCommon), rFirst.getLabelType()); @@ -137,98 +173,80 @@ void test(const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, const rSecondCopy.getDepictionData().copyCoords(rCommon.getDepictionData(), vSecondToCommon); rNewCopy.getDepictionData().copyCoords(rCommon.getDepictionData(), vNewToCommon); - unsigned int secondIdOffset = num_vertices(rFirst.getGraph()); + const auto secondIdOffset = num_vertices(rFirst.getGraph()); std::set matchVerticesInCommon; - for(CoreVertex v : asRange(vertices(rFirst.getGraph()))) { + for(const CoreVertex v : asRange(vertices(rFirst.getGraph()))) { if(match.left.find(v) == match.left.end()) continue; - auto iter = vFirstToCommon.find(v); + const auto iter = vFirstToCommon.find(v); assert(iter != end(vFirstToCommon)); matchVerticesInCommon.insert(iter->second); } - auto disallowCollapseFirst = [&matchVerticesInCommon, &vFirstToCommon](CoreVertex v) { - auto iter = vFirstToCommon.find(v); + const auto disallowCollapseFirst = [&matchVerticesInCommon, &vFirstToCommon](CoreVertex v) { + const auto iter = vFirstToCommon.find(v); assert(iter != end(vFirstToCommon)); return matchVerticesInCommon.find(iter->second) != end(matchVerticesInCommon); }; - auto disallowCollapseSecond = [&matchVerticesInCommon, &vSecondToCommon](CoreVertex v) { - auto iter = vSecondToCommon.find(v); + const auto disallowCollapseSecond = [&matchVerticesInCommon, &vSecondToCommon](CoreVertex v) { + const auto iter = vSecondToCommon.find(v); assert(iter != end(vSecondToCommon)); return matchVerticesInCommon.find(iter->second) != end(matchVerticesInCommon); }; - auto disallowCollapseNew = [&matchVerticesInCommon, &vNewToCommon](CoreVertex v) { - auto iter = vNewToCommon.find(v); + const auto disallowCollapseNew = [&matchVerticesInCommon, &vNewToCommon](CoreVertex v) { + const auto iter = vNewToCommon.find(v); assert(iter != end(vNewToCommon)); return matchVerticesInCommon.find(iter->second) != end(matchVerticesInCommon); }; - auto rawFilesFirst = IO::Rules::Write::tikz(rFirstCopy, 0, options, "L", "K", "R", - IO::Rules::Write::BaseArgs{visible, vColour, eColour}, disallowCollapseFirst); - auto rawFilesSecond = IO::Rules::Write::tikz(rSecondCopy, secondIdOffset, options, "L", "K", "R", - IO::Rules::Write::BaseArgs{visible, vColour, eColour}, disallowCollapseSecond); - auto rawFilesNew = IO::Rules::Write::tikz(rNewCopy, 0, options, "L", "K", "R", - IO::Rules::Write::BaseArgs{visible, vColour, eColour}, disallowCollapseNew); - FileHandle s(getUniqueFilePrefix() + "rcMatch.tex"); - // IO::log() << "rFirstFiles: " << rawFilesFirst.first << ", " << rawFilesFirst.second << std::endl; - // IO::log() << "rSecondFiles: " << rawFilesSecond.first << ", " << rawFilesSecond.second << std::endl; + const auto rawFilesFirst = IO::Rules::Write::tikz(rFirstCopy, 0, options, "L", "K", "R", + IO::Rules::Write::BaseArgs{visible, vColour, eColour}, + disallowCollapseFirst); + const auto rawFilesSecond = IO::Rules::Write::tikz(rSecondCopy, secondIdOffset, options, "L", "K", "R", + IO::Rules::Write::BaseArgs{visible, vColour, eColour}, + disallowCollapseSecond); + const auto rawFilesNew = IO::Rules::Write::tikz(rNewCopy, 0, options, "L", "K", "R", + IO::Rules::Write::BaseArgs{visible, vColour, eColour}, + disallowCollapseNew); + post::FileHandle s(getUniqueFilePrefix() + "rcMatch.tex"); { - s << "\\newpage" << std::endl; - s << "\\subsection{RC Match}" << std::endl; - s << "{\\centering" << std::endl; - auto arrow = [](std::string edgeLabel) -> std::string { - return R"XXX(\begin{tikzpicture}[node distance=20pt, - baseline={([yshift={-\ht\strutbox}]A.center)}] - \node (A) {}; - \node (B) [right=of A] {}; - \draw[->, >=triangle 45] (A) to node[above] {)XXX" + edgeLabel + R"XXX(} (B); - \end{tikzpicture})XXX"; - }; - s << "\\input{\\modInputPrefix/" << rawFilesFirst.first << "_L.tex}" << std::endl; - s << arrow("$r_1$") << std::endl; - s << "\\input{\\modInputPrefix/" << rawFilesFirst.first << "_R.tex}" << std::endl; - s << "\\\\" << std::endl; - s << "\\mbox{}\\hfill"; - s << "\\input{\\modInputPrefix/" << rawFilesSecond.first << "_L.tex}" << std::endl; - { // the match lines - s << "\\begin{tikzpicture}[remember picture, overlay]" << std::endl; - for(auto m : match.left) { - CoreVertex vFirst = m.first; - CoreVertex vSecond = m.second; - unsigned int vIdFirst = get(boost::vertex_index_t(), rFirst.getGraph(), vFirst); - unsigned int vIdSecond = get(boost::vertex_index_t(), rSecond.getGraph(), vSecond); - vIdSecond += num_vertices(rFirst.getGraph()); - s << "\\path[modRCMatchEdge] (v-" << vIdFirst << ") to[modRCMatchEdgeTo] (v-" << vIdSecond << ");" << std::endl; - } - s << "\\end{tikzpicture}" << std::endl; + s << "\\rcMatchFig"; + s << '{' << rawFilesFirst.first << '}' + << '{' << rFirst.getId() << '}'; + s << '{'; + bool first = true; + for(const auto[vFirst, vSecond] : match.left) { + const auto vIdFirst = get(boost::vertex_index_t(), rFirst.getGraph(), vFirst); + auto vIdSecond = get(boost::vertex_index_t(), rSecond.getGraph(), vSecond); + vIdSecond += num_vertices(rFirst.getGraph()); + if(first) first = false; + else s << ", "; + s << vIdFirst << "/" << vIdSecond; } - s << arrow("$r_2$") << std::endl; - s << "\\input{\\modInputPrefix/" << rawFilesSecond.first << "_R.tex}" << std::endl; - s << "\\\\" << std::endl; - s << "\\input{\\modInputPrefix/" << rawFilesNew.first << "_L.tex}" << std::endl; - s << arrow("$r$") << std::endl; - s << "\\input{\\modInputPrefix/" << rawFilesNew.first << "_R.tex}" << std::endl; - s << "}" << std::endl; + s << '}'; + s << '{' << rawFilesSecond.first << '}' + << '{' << rSecond.getId() << '}'; + s << '{' << rawFilesNew.first << '}' + << '{' << rNew.getId() << '}'; + s << '\n'; } - FileHandle sAux(getUniqueFilePrefix() + "rcMatch_aux.tex"); + post::FileHandle sAux(getUniqueFilePrefix() + "rcMatch_aux.tex"); { - sAux << "\\\\" << std::endl; - sAux << "Files: \\texttt{" << IO::escapeForLatex(rawFilesFirst.first) - << "}, \\texttt{" << IO::escapeForLatex(rawFilesSecond.first) - << "}, \\texttt{" << IO::escapeForLatex(s) - << "}, \\texttt{" << IO::escapeForLatex(sAux) << "}" << std::endl; - sAux << "\\\\" << std::endl; - sAux << "Match: " << std::endl; + sAux << "\\\\\n"; + sAux << "Files:\\\\\n \\texttt{" << IO::escapeForLatex(rawFilesFirst.first) + << "},\\\\\n \\texttt{" << IO::escapeForLatex(rawFilesSecond.first) + << "},\\\\\n \\texttt{" << IO::escapeForLatex(rawFilesNew.first) + << "},\\\\\n \\texttt{" << IO::escapeForLatex(s) + << "},\\\\\n \\texttt{" << IO::escapeForLatex(sAux) + << "}\\\\\n"; + sAux << "Match: \n"; bool first = true; - for(auto m : match.left) { + for(const auto[vFirst, vSecond] : match.left) { if(!first) sAux << ", "; - sAux << "$" << m.first << "\\rightarrow " << m.second << "$" << std::endl; + sAux << "$" << vFirst << "\\rightarrow " << vSecond << "$\n"; first = false; } } - IO::post() << "summaryInput \"" << std::string(s) << "\"" << std::endl; - IO::post() << "summaryInput \"" << std::string(sAux) << "\"" << std::endl; + IO::post() << "summaryInput \"" << std::string(s) << "\"\n"; + IO::post() << "summaryInput \"" << std::string(sAux) << "\"\n"; + IO::post() << std::flush; } -} // namespace Write -} // namespace RC -} // namespace IO -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::IO::RC::Write \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/RC.hpp b/libs/libmod/src/mod/lib/IO/RC.hpp index cc62f7f..31cb488 100644 --- a/libs/libmod/src/mod/lib/IO/RC.hpp +++ b/libs/libmod/src/mod/lib/IO/RC.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_IO_RC_H -#define MOD_LIB_IO_RC_H +#ifndef MOD_LIB_IO_RC_HPP +#define MOD_LIB_IO_RC_HPP #include @@ -7,16 +7,10 @@ #include -namespace mod { -namespace lib { -namespace RC { -class Evaluator; -} // namespace RC -namespace IO { -namespace RC { -namespace Read { -} // namespace Read -namespace Write { +namespace mod::lib::RC { +struct Evaluator; +} // namespace mod::lib::RC +namespace mod::lib::IO::RC::Write { std::string dot(const lib::RC::Evaluator &rc); std::string svg(const lib::RC::Evaluator &rc); std::string pdf(const lib::RC::Evaluator &rc); @@ -39,10 +33,6 @@ void test(const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, const test(rFirst, rSecond, match, rNew); } -} // namespace Write -} // namespace RC -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::RC::Write -#endif /* MOD_LIB_IO_RC_H */ \ No newline at end of file +#endif // MOD_LIB_IO_RC_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Rule.hpp b/libs/libmod/src/mod/lib/IO/Rule.hpp index 034d8b3..adba6fc 100644 --- a/libs/libmod/src/mod/lib/IO/Rule.hpp +++ b/libs/libmod/src/mod/lib/IO/Rule.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_IO_RULE_H -#define MOD_LIB_IO_RULE_H +#ifndef MOD_LIB_IO_RULE_HPP +#define MOD_LIB_IO_RULE_HPP #include #include // to make sure the write options are defined @@ -7,15 +7,14 @@ #include +#include #include +#include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { struct Real; -} // namespace Rules -namespace IO { -namespace Rules { +} // namespace mod::lib::Rules +namespace mod::lib::IO::Rules { namespace Read { struct Data { @@ -25,7 +24,7 @@ struct Data { std::map externalToInternalIds; }; -Data gml(std::istream &s, std::ostream &err); +Data gml(std::string_view src, std::ostream &err); } // namespace Read namespace Write { using Options = IO::Graph::Write::Options; @@ -33,9 +32,9 @@ using CoreVertex = lib::Rules::Vertex; using CoreEdge = lib::Rules::Edge; struct BaseArgs { - std::function visible; - std::function vColour; - std::function eColour; + std::function visible; + std::function vColour; + std::function eColour; }; // returns the filename _with_ extension @@ -47,30 +46,33 @@ std::string svgCombined(const lib::Rules::Real &r); std::string pdfCombined(const lib::Rules::Real &r); // returns the filename _without_ extension std::string dot(const lib::Rules::Real &r); // does not handle labels correctly, is for coordinate generation -std::string coords(const lib::Rules::Real &r, unsigned int idOffset, const Options &options, std::function disallowCollapse_); -std::pair tikz(const std::string &fileCoordsNoExt, const lib::Rules::Real &r, unsigned int idOffset, const Options &options, - const std::string &suffixL, const std::string &suffixK, const std::string &suffixR, const BaseArgs &args, - std::function disallowCollapse); +std::string coords(const lib::Rules::Real &r, unsigned int idOffset, const Options &options, + std::function disallowCollapse_); +std::pair +tikz(const std::string &fileCoordsNoExt, const lib::Rules::Real &r, unsigned int idOffset, const Options &options, + const std::string &suffixL, const std::string &suffixK, const std::string &suffixR, const BaseArgs &args, + std::function disallowCollapse); std::pair tikz(const lib::Rules::Real &r, unsigned int idOffset, const Options &options, - const std::string &suffixL, const std::string &suffixK, const std::string &suffixR, const BaseArgs &args, - std::function disallowCollapse); + const std::string &suffixL, const std::string &suffixK, + const std::string &suffixR, const BaseArgs &args, + std::function disallowCollapse); std::string pdf(const lib::Rules::Real &r, const Options &options, - const std::string &suffixL, const std::string &suffixK, const std::string &suffixR, const BaseArgs &args); -std::pair tikzTransitionState(const std::string &fileCoordsNoExt, const lib::Rules::Real &r, unsigned int idOffset, const Options &options, - const std::string &suffix, const BaseArgs &args); -std::pair tikzTransitionState(const lib::Rules::Real &r, unsigned int idOffset, const Options &options, - const std::string &suffix, const BaseArgs &args); + const std::string &suffixL, const std::string &suffixK, const std::string &suffixR, + const BaseArgs &args); +std::pair +tikzTransitionState(const std::string &fileCoordsNoExt, const lib::Rules::Real &r, unsigned int idOffset, + const Options &options, + const std::string &suffix, const BaseArgs &args); +std::pair +tikzTransitionState(const lib::Rules::Real &r, unsigned int idOffset, const Options &options, + const std::string &suffix, const BaseArgs &args); std::string pdfTransitionState(const lib::Rules::Real &r, const Options &options, - const std::string &suffix, const BaseArgs &args); + const std::string &suffix, const BaseArgs &args); //std::string pdfCombined(const lib::Rules::Real &r, const Options &options); // TODO std::pair summary(const lib::Rules::Real &r); std::pair summary(const lib::Rules::Real &r, const Options &first, const Options &second); void termState(const lib::Rules::Real &r); } // namespace Write -} // namespace Rules -} // namespace IO -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_IO_RULE_H */ +} // namespace mod::lib::IO::Rules +#endif // MOD_LIB_IO_RULE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/RuleRead.cpp b/libs/libmod/src/mod/lib/IO/RuleRead.cpp index 5f3e0ef..8a9d4c1 100644 --- a/libs/libmod/src/mod/lib/IO/RuleRead.cpp +++ b/libs/libmod/src/mod/lib/IO/RuleRead.cpp @@ -14,11 +14,7 @@ #include #include -namespace mod { -namespace lib { -namespace IO { -namespace Rules { -namespace Read { +namespace mod::lib::IO::Rules::Read { namespace { template @@ -26,35 +22,34 @@ struct Label { boost::optional left, context, right; }; -Data parseGML(std::istream &s, std::ostream &err) { +} // namespace + +Data gml(std::string_view src, std::ostream &err) { GML::Rule rule; { gml::ast::KeyValue ast; - bool res = gml::parser::parse(s, ast, err); + bool res = gml::parser::parse(src, ast, err); if(!res) return Data(); using namespace gml::converter::edsl; auto cVertex = GML::makeVertexConverter(0); auto cEdge = GML::makeEdgeConverter(0); auto nodeLabels = list("nodeLabels") - (string("label", &GML::AdjacencyConstraint::nodeLabels)) - ; + (string("label", &GML::AdjacencyConstraint::nodeLabels)); auto edgeLabels = list("edgeLabels") - (string("label", &GML::AdjacencyConstraint::edgeLabels)) - ; + (string("label", &GML::AdjacencyConstraint::edgeLabels)); auto constrainAdj = list("constrainAdj", &GML::Rule::matchConstraints) (int_("id", &GML::AdjacencyConstraint::id), 1, 1) (string("op", &GML::AdjacencyConstraint::op), 1, 1) (int_("count", &GML::AdjacencyConstraint::count), 1, 1) - (nodeLabels) (edgeLabels) - ; - auto constrainShortestPath = list("constrainShortestPath", &GML::Rule::matchConstraints) + (nodeLabels)(edgeLabels); + auto constrainShortestPath = list("constrainShortestPath", + &GML::Rule::matchConstraints) (int_("source", &GML::ShortestPathConstraint::source), 1, 1) (int_("target", &GML::ShortestPathConstraint::target), 1, 1) (string("op", &GML::ShortestPathConstraint::op), 1, 1) - (int_("length", &GML::ShortestPathConstraint::length), 1, 1) - ; + (int_("length", &GML::ShortestPathConstraint::length), 1, 1); auto makeSide = [&](std::string name, GML::Graph GML::Rule::*side) { - return list(name, side)(cVertex) (cEdge); + return list(name, side)(cVertex)(cEdge); }; auto cRule = list("rule") (string("ruleID", &GML::Rule::id), 0, 1) @@ -62,8 +57,7 @@ Data parseGML(std::istream &s, std::ostream &err) { (makeSide("left", &GML::Rule::left), 0, 1) (makeSide("context", &GML::Rule::context), 0, 1) (makeSide("right", &GML::Rule::right), 0, 1) - (constrainAdj) (constrainShortestPath) - ; + (constrainAdj)(constrainShortestPath); auto iterBegin = * auto iterEnd = iterBegin + 1; res = gml::converter::convert(iterBegin, iterEnd, cRule, err, rule); @@ -238,11 +232,13 @@ Data parseGML(std::istream &s, std::ostream &err) { int src = p.first.first; int tar = p.first.second; if(idMapVertex.find(src) == end(idMapVertex)) { - err << "Error in rule GML. Edge endpoint '" << src << "' does not exist for edge (" << src << ", " << tar << ")."; + err << "Error in rule GML. Edge endpoint '" << src << "' does not exist for edge (" << src << ", " << tar + << ")."; return Data(); } if(idMapVertex.find(tar) == end(idMapVertex)) { - err << "Error in rule GML. Edge endpoint '" << tar << "' does not exist for edge (" << src << ", " << tar << ")."; + err << "Error in rule GML. Edge endpoint '" << tar << "' does not exist for edge (" << src << ", " << tar + << ")."; return Data(); } Vertex vSrc = idMapVertex[src].v, vTar = idMapVertex[tar].v; @@ -308,8 +304,9 @@ Data parseGML(std::istream &s, std::ostream &err) { struct MatchConstraintConverter : boost::static_visitor { - MatchConstraintConverter(lib::Rules::LabelledRule &dpoResult, const std::map &idMapVertex, std::ostream &err) - : dpoResult(dpoResult), idMapVertex(idMapVertex), err(err) { } + MatchConstraintConverter(lib::Rules::LabelledRule &dpoResult, const std::map &idMapVertex, + std::ostream &err) + : dpoResult(dpoResult), idMapVertex(idMapVertex), err(err) {} bool operator()(const GML::AdjacencyConstraint &cGML) { auto iter = idMapVertex.find(cGML.id); @@ -332,8 +329,9 @@ Data parseGML(std::istream &s, std::ostream &err) { return false; } } - auto c = std::make_unique >( - vConstrained, op, cGML.count); + auto c = std::make_unique< + lib::GraphMorphism::Constraints::VertexAdjacency < lib::Rules::LabelledRule::LeftGraphType> > ( + vConstrained, op, cGML.count); for(const auto &s : cGML.nodeLabels) c->vertexLabels.insert(s); for(const auto &s : cGML.edgeLabels) c->edgeLabels.insert(s); dpoResult.leftMatchConstraints.push_back(std::move(c)); @@ -370,12 +368,14 @@ Data parseGML(std::istream &s, std::ostream &err) { auto compSrc = dpoResult.leftComponents[get(boost::vertex_index_t(), get_graph(dpoResult), vSrc)]; auto compTar = dpoResult.leftComponents[get(boost::vertex_index_t(), get_graph(dpoResult), vTar)]; if(compSrc != compTar) { - err << "Error in rule GML. Vertex " << cGML.source << " and " << cGML.target << " are in different connected components of the left graph. " - << "This is currently not supported for the shortest path constraint." << std::endl; + err << "Error in rule GML. Vertex " << cGML.source << " and " << cGML.target + << " are in different connected components of the left graph. " + << "This is currently not supported for the shortest path constraint." << std::endl; return false; } - auto c = std::make_unique >( - vSrc, vTar, op, cGML.length); + auto c = std::make_unique< + lib::GraphMorphism::Constraints::ShortestPath < lib::Rules::LabelledRule::LeftGraphType> > ( + vSrc, vTar, op, cGML.length); dpoResult.leftMatchConstraints.push_back(std::move(c)); return true; } @@ -414,26 +414,31 @@ Data parseGML(std::istream &s, std::ostream &err) { // Set the explicitly defined edge categories. //---------------------------------------------------------------------------- for(const auto &p : idMapEdge) { - const auto handleSide = [&err, &ssErr, &p](const boost::optional &os, const std::string &side, auto &inference) { + const auto handleSide = [&err, &ssErr, &p](const boost::optional &os, const std::string &side, + auto &inference) { if(!os) return true; const std::string &s = *os; if(s.size() != 1) { - err << "Error in stereo data for edge (" << p.first.first << ", " << p.first.second << ") in " << side << ". "; + err << "Error in stereo data for edge (" << p.first.first << ", " << p.first.second << ") in " << side + << ". "; err << "Parsing error in stereo data '" << s << "'."; return false; } lib::Stereo::EdgeCategory cat; switch(s.front()) { - case '*': cat = lib::Stereo::EdgeCategory::Any; + case '*': + cat = lib::Stereo::EdgeCategory::Any; break; default: - err << "Error in stereo data for edge (" << p.first.first << ", " << p.first.second << ") in " << side << ". "; + err << "Error in stereo data for edge (" << p.first.first << ", " << p.first.second << ") in " << side + << ". "; err << "Parsing error in stereo data '" << s << "'."; return false; } bool res = inference.assignEdgeCategory(p.second.e, cat, ssErr); if(!res) { - err << "Error in stereo data for edge (" << p.first.first << ", " << p.first.second << ") in " << side << ". "; + err << "Error in stereo data for edge (" << p.first.first << ", " << p.first.second << ") in " << side + << ". "; err << ssErr.str(); return false; } @@ -445,7 +450,8 @@ Data parseGML(std::istream &s, std::ostream &err) { // Set the explicitly stereo data. //---------------------------------------------------------------------------- for(auto &p : idMapVertex) { - const auto handleSide = [&](const boost::optional &os, const std::string &side, auto &inference, auto &parsedEmbedding, const auto &gSide) { + const auto handleSide = [&](const boost::optional &os, const std::string &side, auto &inference, + auto &parsedEmbedding, const auto &gSide) { if(!os) return true; const auto &v = p.second.v; parsedEmbedding = lib::IO::Stereo::Read::parseEmbedding(os.get(), ssErr); @@ -460,7 +466,8 @@ Data parseGML(std::istream &s, std::ostream &err) { if(embGML.geometry) { auto vGeo = gGeometry.findGeometry(*embGML.geometry); if(vGeo == gGeometry.nullGeometry()) { - err << "Error in stereo data for vertex " << p.first << " in " << side << ". Invalid gGeometry '" << *embGML.geometry << "'." << std::endl; + err << "Error in stereo data for vertex " << p.first << " in " << side << ". Invalid gGeometry '" + << *embGML.geometry << "'." << std::endl; return false; } bool res = inference.assignGeometry(v, vGeo, ssErr); @@ -477,12 +484,14 @@ Data parseGML(std::istream &s, std::ostream &err) { if(const int *idPtr = boost::get(&e)) { int idNeighbour = *idPtr; if(idMapVertex.find(idNeighbour) == end(idMapVertex)) { - err << "Error in graph GML. Neighbour vertex " << idNeighbour << " in stereo embedding for vertex " << p.first << " in " << side << " does not exist." << std::endl; + err << "Error in graph GML. Neighbour vertex " << idNeighbour << " in stereo embedding for vertex " + << p.first << " in " << side << " does not exist." << std::endl; return false; } auto ePair = edge(v, vFromVertexId(idNeighbour), gSide); if(!ePair.second) { - err << "Error in graph GML. Vertex " << idNeighbour << " in stereo embedding for vertex " << p.first << " in " << side << " is not a neighbour." << std::endl; + err << "Error in graph GML. Vertex " << idNeighbour << " in stereo embedding for vertex " + << p.first << " in " << side << " is not a neighbour." << std::endl; return false; } inference.addEdge(v, ePair.first); @@ -512,16 +521,17 @@ Data parseGML(std::istream &s, std::ostream &err) { if(!handleSide(p.second.stereo.right, "R", rightInference, p.second.parsedEmbeddingRight, gRight)) return Data(); } // for each vertex - auto finalize = [&err, &ssErr, &vertexMapId](auto &inference, const std::string & side) { + auto finalize = [&err, &ssErr, &vertexMapId](auto &inference, const std::string &side) { auto stereoResult = inference.finalize(ssErr, [&vertexMapId, &side](Vertex v) { auto iter = vertexMapId.find(v); assert(iter != vertexMapId.end()); return std::to_string(iter->second) + " in " + side; }); switch(stereoResult) { - case lib::Stereo::DeductionResult::Success: return true; + case lib::Stereo::DeductionResult::Success: + return true; case lib::Stereo::DeductionResult::Warning: - IO::log() << ssErr.str(); + std::cout << ssErr.str(); return true; case lib::Stereo::DeductionResult::Error: err << ssErr.str(); @@ -564,18 +574,10 @@ Data parseGML(std::istream &s, std::ostream &err) { else // otherwise, default to be in context return true; }; - dpoResult.pStereo = std::make_unique(g, std::move(leftInference), std::move(rightInference), vertexInContext, edgeInContext); + dpoResult.pStereo = std::make_unique(g, std::move(leftInference), + std::move(rightInference), vertexInContext, + edgeInContext); return data; } -} // namespace - -Data gml(std::istream &s, std::ostream &err) { - return parseGML(s, err); -} - -} // namespace Read -} // namespace Rules -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::Rules::Read \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/RuleWrite.cpp b/libs/libmod/src/mod/lib/IO/RuleWrite.cpp index 8d42d70..0fb5472 100644 --- a/libs/libmod/src/mod/lib/IO/RuleWrite.cpp +++ b/libs/libmod/src/mod/lib/IO/RuleWrite.cpp @@ -1,10 +1,10 @@ #include "Rule.hpp" #include +#include #include #include #include -#include #include #include #include @@ -16,11 +16,7 @@ #include -namespace mod { -namespace lib { -namespace IO { -namespace Rules { -namespace Write { +namespace mod::lib::IO::Rules::Write { namespace { // returns the filename _without_ extension @@ -160,7 +156,7 @@ void gml(const lib::Rules::Real &r, bool withCoords, std::ostream &s) { } std::string gml(const lib::Rules::Real &r, bool withCoords) { - FileHandle s(getFilePrefix(r) + ".gml"); + post::FileHandle s(getFilePrefix(r) + ".gml"); gml(r, withCoords, s); return s; } @@ -168,7 +164,7 @@ std::string gml(const lib::Rules::Real &r, bool withCoords) { std::string dotCombined(const lib::Rules::Real &r) { std::stringstream fileName; fileName << "r_" << r.getId() << "_combined.dot"; - FileHandle s(getUniqueFilePrefix() + fileName.str()); + post::FileHandle s(getUniqueFilePrefix() + fileName.str()); std::string fileNoExt = s; fileNoExt.erase(fileNoExt.end() - 4, fileNoExt.end()); using Vertex = lib::Rules::Vertex; @@ -262,7 +258,7 @@ std::string dot(const lib::Rules::Real &r) { const lib::Rules::GraphType &g = r.getGraph(); const lib::Rules::PropStringCore &labelState = r.getStringState(); - FileHandle s(fileNoExt + ".dot"); + post::FileHandle s(fileNoExt + ".dot"); s << "graph g {" << std::endl; s << getConfig().io.dotCoordOptions.get() << std::endl; for(Vertex v : asRange(vertices(g))) { @@ -310,7 +306,6 @@ struct CoordsCacheEntry { int rotation; bool mirror; public: - friend bool operator<(const CoordsCacheEntry &a, const CoordsCacheEntry &b) { return std::tie(a.id, a.collapseHydrogens, a.rotation, a.mirror) < std::tie(b.id, b.collapseHydrogens, b.rotation, b.mirror); @@ -343,7 +338,7 @@ std::string coords(const lib::Rules::Real &r, unsigned int idOffset, const Optio const auto &depict = r.getDepictionData(); if(!depict.getHasCoordinates()) { if(idOffset != 0) { - IO::log() << "Blame the lazy programmer. Offset " << idOffset << " not yet supported in dot coords." + std::cout << "Blame the lazy programmer. Offset " << idOffset << " not yet supported in dot coords." << std::endl; MOD_ABORT; } @@ -359,7 +354,7 @@ std::string coords(const lib::Rules::Real &r, unsigned int idOffset, const Optio const auto &g = r.getGraph(); const std::string molString = options.collapseHydrogens ? "_mol" : ""; const std::string fileNoExt = getFilePrefix(r) + molString + "_coord"; - FileHandle s(fileNoExt + ".tex"); + post::FileHandle s(fileNoExt + ".tex"); s << "% dummy\n"; const bool useCollapsedCoords = [&]() { if(!options.collapseHydrogens) return false; @@ -405,7 +400,6 @@ struct AdvOptions { std::function disallowCollapse) : idOffset(idOffset), changeColour(changeColourFromMembership()), r(r), args(args), disallowCollapse_(disallowCollapse) {} - private: static std::string changeColourFromMembership() { std::string side = []() { @@ -574,14 +568,14 @@ tikz(const std::string &fileCoordsNoExt, const lib::Rules::Real &r, unsigned int std::string fileCoords = fileCoordsNoExt + ".tex"; { // left - FileHandle s(fileNoExt + "_" + suffixL + ".tex"); + post::FileHandle s(fileNoExt + "_" + suffixL + ".tex"); const auto &g = get_left(r.getDPORule()); const auto &depict = r.getDepictionData().getLeft(); const auto adv = AdvOptions(r, idOffset, args, disallowCollapse); IO::Graph::Write::tikz(s, options, g, depict, fileCoords, adv, jla_boost::Nop<>(), ""); } { // context - FileHandle s(fileNoExt + "_" + suffixK + ".tex"); + post::FileHandle s(fileNoExt + "_" + suffixK + ".tex"); const auto &g = get_context(r.getDPORule()); const auto &depict = r.getDepictionData().getContext(); @@ -603,7 +597,7 @@ tikz(const std::string &fileCoordsNoExt, const lib::Rules::Real &r, unsigned int IO::Graph::Write::tikz(s, options, gFiltered, depict, fileCoords, adv, jla_boost::Nop<>(), ""); } { // right - FileHandle s(fileNoExt + "_" + suffixR + ".tex"); + post::FileHandle s(fileNoExt + "_" + suffixR + ".tex"); const auto &g = get_right(r.getDPORule()); const auto &depict = r.getDepictionData().getRight(); const auto adv = AdvOptions(r, idOffset, args, disallowCollapse); @@ -680,7 +674,7 @@ std::pair summary(const lib::Rules::Real &r, const Opt std::string constraints = getUniqueFilePrefix() + "r_" + boost::lexical_cast(r.getId()) + "_constraints.tex"; { - FileHandle s(constraints); + post::FileHandle s(constraints); auto printer = lib::IO::MatchConstraint::Write::makeTexPrintVisitor(s, get_left(r.getDPORule())); for(const auto &c : r.getDPORule().leftMatchConstraints) { c->accept(printer); @@ -701,7 +695,7 @@ void termState(const lib::Rules::Real &r) { using Membership = lib::Rules::Membership; using namespace lib::Term; IO::post() << "summarySubsection \"Term State for " << r.getName() << "\"" << std::endl; - FileHandle s(getUniqueFilePrefix() + "termState.tex"); + post::FileHandle s(getUniqueFilePrefix() + "termState.tex"); s << "\\begin{verbatim}\n"; const auto &termState = r.getTermState(); if(isValid(termState)) { @@ -746,7 +740,6 @@ void termState(const lib::Rules::Real &r) { } struct Visitor : lib::GraphMorphism::Constraints::AllVisitor { - Visitor(std::unordered_map > &addrMap, const lib::Rules::GraphType &g) : addrMap(addrMap), g(g) {} @@ -767,8 +760,6 @@ void termState(const lib::Rules::Real &r) { virtual void operator()(const lib::GraphMorphism::Constraints::ShortestPath &c) override {} - private: - int counter = 0; public: std::unordered_map > &addrMap; const lib::Rules::GraphType &g; @@ -837,8 +828,4 @@ void termState(const lib::Rules::Real &r) { IO::post() << "summaryInput \"" << std::string(s) << "\"" << std::endl; } -} // namespace Write -} // namespace Rules -} // namespace IO -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::IO::Rules::Write \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Stereo.hpp b/libs/libmod/src/mod/lib/IO/Stereo.hpp index 2f9e4b1..92e1fb4 100644 --- a/libs/libmod/src/mod/lib/IO/Stereo.hpp +++ b/libs/libmod/src/mod/lib/IO/Stereo.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_IO_STEREO_H -#define MOD_LIB_IO_STEREO_H +#ifndef MOD_LIB_IO_STEREO_HPP +#define MOD_LIB_IO_STEREO_HPP #include #include @@ -8,18 +8,14 @@ #include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { struct PropStereoCore; -} // namespace Rules -namespace Stereo { +} // namespace mod::lib::Rules +namespace mod::lib::Stereo { struct Configuration; struct GeometryGraph; -} // namespace Stereo -namespace IO { -namespace Stereo { -namespace Read { +} // namespace mod::lib::Stereo +namespace mod::lib::IO::Stereo::Read { using ParsedEmbeddingEdge = boost::variant; struct ParsedEmbedding { @@ -30,20 +26,18 @@ struct ParsedEmbedding { boost::optional parseEmbedding(const std::string &str, std::ostream &err); -} // namesapce Read -namespace Write { +} // namesapce mod::lib::IO::Stereo::Read +namespace mod::lib::IO::Stereo::Write { -std::string summary(const lib::Graph::Single &g, lib::Graph::Vertex v, const lib::Stereo::Configuration &conf, const IO::Graph::Write::Options &options); -std::string summary(const lib::Rules::Real &r, lib::Rules::Vertex v, lib::Rules::Membership m, const IO::Graph::Write::Options &options); +std::string summary(const lib::Graph::Single &g, lib::Graph::Vertex v, const lib::Stereo::Configuration &conf, + const IO::Graph::Write::Options &options, int shownIdOffset, const std::string &nameSuffix); +std::string summary(const lib::Rules::Real &r, lib::Rules::Vertex v, lib::Rules::Membership m, + const IO::Graph::Write::Options &options); // old/new delimiter void summary(const lib::Stereo::GeometryGraph &g); -} // namesapce Write -} // namesapce Stereo -} // namesapce IO -} // namesapce lib -} // namesapce mod +} // namesapce mod::lib::IO::Stereo::Write -#endif /* MOD_LIB_IO_STEREO_H */ \ No newline at end of file +#endif // MOD_LIB_IO_STEREO_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/StereoWrite.cpp b/libs/libmod/src/mod/lib/IO/StereoWrite.cpp index b3e8dc7..3739d83 100644 --- a/libs/libmod/src/mod/lib/IO/StereoWrite.cpp +++ b/libs/libmod/src/mod/lib/IO/StereoWrite.cpp @@ -1,9 +1,9 @@ #include "Stereo.hpp" +#include #include #include #include -#include #include #include #include @@ -16,18 +16,16 @@ #include -namespace mod { -namespace lib { -namespace Stereo { +namespace mod::lib::Stereo { namespace { #define MOD_anyPrintCoords() \ - Configuration::printCoords(s, vIds); \ - if(vIds.size() == 1) return; \ - auto centerId = vIds.back(); \ - double angle = 360.0 / (vIds.size() - 1); \ - for(std::size_t i = 0; i < vIds.size() - 1; i++) \ - printSateliteCoord(s, centerId, angle * i + 90, vIds[i]); + Configuration::printCoords(s, vIds); \ + if(vIds.size() == 1) return; \ + auto centerId = vIds.back(); \ + double angle = 360.0 / (vIds.size() - 1); \ + for(std::size_t i = 0; i < vIds.size() - 1; i++) \ + printSateliteCoord(s, centerId, angle * i + 90, vIds[i]); void printSateliteCoord(std::ostream &s, std::size_t centerId, double angle, std::size_t id) { s << "\\coordinate[overlay, at=($(v-coord-" << centerId << ")+(" << angle << ":1)"; @@ -90,10 +88,14 @@ std::string TrigonalPlanar::getEdgeAnnotation(std::size_t i) const { IO::Graph::Write::EdgeFake3DType Tetrahedral::getEdgeDepiction(std::size_t i) const { switch(i) { case 0: - case 1: return lib::IO::Graph::Write::EdgeFake3DType::None; - case 2: return lib::IO::Graph::Write::EdgeFake3DType::WedgeSL; - case 3: return lib::IO::Graph::Write::EdgeFake3DType::HashSL; - default: MOD_ABORT; + case 1: + return lib::IO::Graph::Write::EdgeFake3DType::None; + case 2: + return lib::IO::Graph::Write::EdgeFake3DType::WedgeSL; + case 3: + return lib::IO::Graph::Write::EdgeFake3DType::HashSL; + default: + MOD_ABORT; } } @@ -110,18 +112,16 @@ std::string Tetrahedral::getEdgeAnnotation(std::size_t i) const { else return "?"; } -} // namespace Stereo -namespace IO { -namespace Stereo { -namespace Read { -} // namesapce Read -namespace Write { +} // namespace mod::lib::Stereo +namespace mod::lib::IO::Stereo::Read { +} // namesapce mod::lib::IO::Stereo::Read +namespace mod::lib::IO::Stereo::Write { namespace { template std::string coords(const GraphInner &gStereo, const lib::Stereo::Configuration &conf, const std::string &name, - std::map::vertex_descriptor, int> &vMap) { - FileHandle s(getUniqueFilePrefix() + name + "_coord.tex"); + std::map::vertex_descriptor, int> &vMap) { + post::FileHandle s(getUniqueFilePrefix() + name + "_coord.tex"); std::vector vIds(num_vertices(gStereo)); using SVertex = typename boost::graph_traits::vertex_descriptor; for(SVertex vStereo : asRange(vertices(gStereo))) { @@ -135,9 +135,11 @@ std::string coords(const GraphInner &gStereo, const lib::Stereo::Configuration & return s; } -template -std::pair tikz(const GraphPrint &g, typename boost::graph_traits::vertex_descriptor v, - const lib::Stereo::Configuration &conf, const std::string &name, const Depict &depict, const IO::Graph::Write::Options &options) { +template +std::pair +tikz(const GraphPrint &g, typename boost::graph_traits::vertex_descriptor v, + const lib::Stereo::Configuration &conf, const std::string &name, const Depict &depict, + const IO::Graph::Write::Options &options, ShownId shownId) { const bool printLonePairs = true; using GVertex = typename boost::graph_traits::vertex_descriptor; using GEdge = typename boost::graph_traits::edge_descriptor; @@ -161,16 +163,18 @@ std::pair tikz(const GraphPrint &g, typename boost::gr } std::string coordFile = coords(gStereo, conf, name, vMap); - FileHandle s(getUniqueFilePrefix() + name + ".tex"); + post::FileHandle s(getUniqueFilePrefix() + name + ".tex"); struct DepictorAndAdvOptions { - DepictorAndAdvOptions(const GraphPrint &gOuter, GVertex vOuterCenter, const lib::Graph::GraphType &g, - const Depict &depict, bool printLonePairs, const std::map &vMap, - const lib::Stereo::Configuration &conf, - const std::map, IO::Graph::Write::EdgeFake3DType> &edgeDepiction) - : gOuter(gOuter), vOuterCenter(vOuterCenter), nullVertexOuter(boost::graph_traits::null_vertex()), gInner(g), - depict(depict), printLonePairs(printLonePairs), vMap(vMap), conf(conf), edgeDepiction(edgeDepiction) { } + const Depict &depict, bool printLonePairs, const std::map &vMap, + const lib::Stereo::Configuration &conf, + const std::map, IO::Graph::Write::EdgeFake3DType> &edgeDepiction, + ShownId shownId) + : gOuter(gOuter), vOuterCenter(vOuterCenter), + nullVertexOuter(boost::graph_traits::null_vertex()), gInner(g), + depict(depict), printLonePairs(printLonePairs), vMap(vMap), conf(conf), edgeDepiction(edgeDepiction), + shownId(shownId) {} GVertex getOuterVertexFromInnerVertex(SVertex vInner) const { auto iter = vMap.find(vInner); @@ -244,9 +248,12 @@ std::pair tikz(const GraphPrint &g, typename boost::gr assert(iter->second != -1); const auto &emb = conf.begin()[iter->second]; switch(emb.type) { - case lib::Stereo::EmbeddingEdge::Type::Edge: MOD_ABORT; - case lib::Stereo::EmbeddingEdge::Type::LonePair: return "e"; - case lib::Stereo::EmbeddingEdge::Type::Radical: return "r"; + case lib::Stereo::EmbeddingEdge::Type::Edge: + MOD_ABORT; + case lib::Stereo::EmbeddingEdge::Type::LonePair: + return "e"; + case lib::Stereo::EmbeddingEdge::Type::Radical: + return "r"; } MOD_ABORT; } @@ -276,7 +283,8 @@ std::pair tikz(const GraphPrint &g, typename boost::gr bool isVisible(SVertex v) const { if(printLonePairs) return true; - else MOD_ABORT; + else + MOD_ABORT; return true; } @@ -291,7 +299,7 @@ std::pair tikz(const GraphPrint &g, typename boost::gr std::string getShownId(SVertex vInner) const { GVertex vOuter = getOuterVertexFromInnerVertex(vInner); if(vOuter == nullVertexOuter) MOD_ABORT; - else return boost::lexical_cast(get(boost::vertex_index_t(), gOuter, vOuter)); + else return boost::lexical_cast(shownId(gOuter, vOuter)); } bool overwriteWithIndex(SVertex vInner) const { @@ -375,17 +383,20 @@ std::pair tikz(const GraphPrint &g, typename boost::gr const std::map &vMap; const lib::Stereo::Configuration &conf; const std::map, IO::Graph::Write::EdgeFake3DType> &edgeDepiction; - } depictAndAdvOptions(g, v, gStereo, depict, printLonePairs, vMap, conf, edgeDepiction); - auto bonusWriter = [&](std::ostream & s) { + ShownId shownId; + } depictAndAdvOptions(g, v, gStereo, depict, printLonePairs, vMap, conf, edgeDepiction, shownId); + auto bonusWriter = [&](std::ostream &s) { }; - lib::IO::Graph::Write::tikz(s, options, gStereo, depictAndAdvOptions, coordFile, depictAndAdvOptions, bonusWriter, ""); + lib::IO::Graph::Write::tikz(s, options, gStereo, depictAndAdvOptions, coordFile, depictAndAdvOptions, bonusWriter, + ""); return std::pair(s, coordFile); } -template +template std::string pdf(const Graph &g, typename boost::graph_traits::vertex_descriptor v, - const lib::Stereo::Configuration &conf, const std::string &name, const Depict &depict, const IO::Graph::Write::Options &options) { - auto p = tikz(g, v, conf, name, depict, options); + const lib::Stereo::Configuration &conf, const std::string &name, const Depict &depict, + const IO::Graph::Write::Options &options, ShownId shownId) { + const auto p = tikz(g, v, conf, name, depict, options, shownId); std::string fileTikz = p.first, fileCoords = p.second; std::string fileNoExt = fileTikz.substr(0, fileTikz.size() - 4); std::string fileCoordsNoExt = fileCoords.substr(0, fileCoords.size() - 4); @@ -395,12 +406,18 @@ std::string pdf(const Graph &g, typename boost::graph_traits::vertex_desc } // namespace -std::string summary(const lib::Graph::Single &gLib, lib::Graph::Vertex v, const lib::Stereo::Configuration &conf, const IO::Graph::Write::Options &options) { +std::string summary(const lib::Graph::Single &gLib, lib::Graph::Vertex v, const lib::Stereo::Configuration &conf, + const IO::Graph::Write::Options &options, int shownIdOffset, const std::string &nameSuffix) { const auto &g = gLib.getGraph(); - std::string name = "g_" + boost::lexical_cast(gLib.getId()) + "_stereo_" + boost::lexical_cast(get(boost::vertex_index_t(), g, v)); - IO::post() << "summarySubsection \"Stereo, g " << gLib.getId() << ", v " << get(boost::vertex_index_t(), g, v) << "\"\n"; - std::string f = pdf(g, v, conf, name, gLib.getDepictionData(), options); - FileHandle s(getUniqueFilePrefix() + "stereo.tex"); + const auto vId = get(boost::vertex_index_t(), g, v); + std::string name = "g_" + boost::lexical_cast(gLib.getId()) + "_stereo_" + + boost::lexical_cast(vId); + IO::post() << "summarySubsection \"Stereo, g " << gLib.getId() << ", v " << vId + << nameSuffix << "\"\n"; + std::string f = pdf(g, v, conf, name, gLib.getDepictionData(), options, [shownIdOffset](const auto &g, const auto v) { + return get(boost::vertex_index_t(), g, v) + shownIdOffset; + }); + post::FileHandle s(getUniqueFilePrefix() + "stereo.tex"); s << "\\begin{center}\n"; s << "\\includegraphics{" << f << "}\\\\\n"; s << "File: \\texttt{" << escapeForLatex(f) << "}\n"; @@ -409,22 +426,27 @@ std::string summary(const lib::Graph::Single &gLib, lib::Graph::Vertex v, const return f; } -std::string summary(const lib::Rules::Real &r, lib::Rules::Vertex v, lib::Rules::Membership m, const IO::Graph::Write::Options &options) { +std::string summary(const lib::Rules::Real &r, lib::Rules::Vertex v, lib::Rules::Membership m, + const IO::Graph::Write::Options &options) { assert(m != lib::Rules::Membership::Context); if(m == lib::Rules::Membership::Left) assert(membership(r.getDPORule(), v) != lib::Rules::Membership::Right); if(m == lib::Rules::Membership::Right) assert(membership(r.getDPORule(), v) != lib::Rules::Membership::Left); const std::string side = m == lib::Rules::Membership::Left ? "L" : "R"; const auto &g = get_graph(r.getDPORule()); - std::string name = "r_" + std::to_string(r.getId()) + "_" + side + "_stereo_" + std::to_string(get(boost::vertex_index_t(), g, v)); - IO::post() << "summarySubsection \"Stereo, r " << r.getId() << ", v " << get(boost::vertex_index_t(), g, v) << " " << side << "\"" << std::endl; + std::string name = "r_" + std::to_string(r.getId()) + "_" + side + "_stereo_" + + std::to_string(get(boost::vertex_index_t(), g, v)); + IO::post() << "summarySubsection \"Stereo, r " << r.getId() << ", v " << get(boost::vertex_index_t(), g, v) << " " + << side << "\"" << std::endl; const auto handler = [&](const auto &gLabelled, const auto &depict) { const auto &g = get_graph(gLabelled); - return pdf(g, v, *get_stereo(gLabelled)[v], name, depict, options); + return pdf(g, v, *get_stereo(gLabelled)[v], name, depict, options, [](const auto &g, const auto v) { + return get(boost::vertex_index_t(), g, v); + }); }; std::string f = m == lib::Rules::Membership::Left - ? handler(get_labelled_left(r.getDPORule()), r.getDepictionData().getLeft()) - : handler(get_labelled_right(r.getDPORule()), r.getDepictionData().getRight()); - FileHandle s(getUniqueFilePrefix() + "stereo.tex"); + ? handler(get_labelled_left(r.getDPORule()), r.getDepictionData().getLeft()) + : handler(get_labelled_right(r.getDPORule()), r.getDepictionData().getRight()); + post::FileHandle s(getUniqueFilePrefix() + "stereo.tex"); s << "\\begin{center}\n"; s << "\\includegraphics{" << f << "}\\\\\n"; s << "File: \\texttt{" << escapeForLatex(f) << "}\n"; @@ -439,7 +461,7 @@ void summary(const lib::Stereo::GeometryGraph &graph) { const auto &g = graph.getGraph(); const auto n = num_vertices(g); std::string fileDot = [&]() { - FileHandle s(IO::getUniqueFilePrefix() + "geometryGraph.dot"); + post::FileHandle s(IO::getUniqueFilePrefix() + "geometryGraph.dot"); s << "digraph g {\nrankdir=LR;\n"; for(auto v : asRange(vertices(g))) { s << get(boost::vertex_index_t(), g, v) << " [ label=\"" << g[v].name << "\" ];\n"; @@ -470,7 +492,7 @@ void summary(const lib::Stereo::GeometryGraph &graph) { IO::post() << "coordsFromGV dgHyperDot \"" << fileDot << "\"\n"; std::string fileCoords = fileDot + "_coord"; std::string fileFig = [&]() { - FileHandle s(IO::getUniqueFilePrefix() + "geometryGraph.tex"); + post::FileHandle s(IO::getUniqueFilePrefix() + "geometryGraph.tex"); s << "\\begin{tikzpicture}[scale=\\modDGHyperScale]\n"; s << "\\input{" << fileCoords << ".tex}\n"; for(auto v : asRange(vertices(g))) { @@ -483,8 +505,8 @@ void summary(const lib::Stereo::GeometryGraph &graph) { auto vSrc = source(e, g); auto vTar = target(e, g); s << "\\path[draw, ->, >=stealth] (v-" << get(boost::vertex_index_t(), g, vSrc) - << ") to (v-" << get(boost::vertex_index_t(), g, vTar) - << ");\n"; + << ") to (v-" << get(boost::vertex_index_t(), g, vTar) + << ");\n"; } for(std::size_t i = 0; i < graph.chemValids.size(); ++i) { auto &cv = graph.chemValids[i]; @@ -510,7 +532,7 @@ void summary(const lib::Stereo::GeometryGraph &graph) { return std::string(f.begin(), f.end() - 4); }(); std::string fileTex = [&]() { - FileHandle s(IO::getUniqueFilePrefix() + "geometryGraphSummary.tex"); + post::FileHandle s(IO::getUniqueFilePrefix() + "geometryGraphSummary.tex"); s << "\\begin{center}\n" << "\\includegraphics{" << fileFig << "}\n\n" @@ -533,7 +555,8 @@ void summary(const lib::Stereo::GeometryGraph &graph) { if(std::abs(cv.charge) != 1) s << std::abs(cv.charge); s << "}$"; } - for(auto cat :{lib::Stereo::EdgeCategory::Single, lib::Stereo::EdgeCategory::Double, lib::Stereo::EdgeCategory::Triple, lib::Stereo::EdgeCategory::Aromatic}) { + for(auto cat :{lib::Stereo::EdgeCategory::Single, lib::Stereo::EdgeCategory::Double, + lib::Stereo::EdgeCategory::Triple, lib::Stereo::EdgeCategory::Aromatic}) { s << " & "; if(auto count = cv.catCount[cat]) { s << int(count); @@ -546,8 +569,7 @@ void summary(const lib::Stereo::GeometryGraph &graph) { s << "\\bottomrule\n" << "\\end{longtable}\n" - << "\\end{center}\n" - ; + << "\\end{center}\n"; return std::string(s); }(); @@ -556,8 +578,4 @@ void summary(const lib::Stereo::GeometryGraph &graph) { IO::post() << "summaryInput \"" << fileTex << "\"" << std::endl; } -} // namesapce Write -} // namesapce Stereo -} // namesapce IO -} // namesapce lib -} // namesapce mod \ No newline at end of file +} // namesapce mod::lib::IO::Stereo::Write \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Term.cpp b/libs/libmod/src/mod/lib/IO/Term.cpp index 6ab9054..deccc04 100644 --- a/libs/libmod/src/mod/lib/IO/Term.cpp +++ b/libs/libmod/src/mod/lib/IO/Term.cpp @@ -22,11 +22,9 @@ #include #include -namespace mod { -namespace lib { -namespace IO { -namespace Term { -namespace Read { +#include + +namespace mod::lib::IO::Term::Read { namespace detail { struct Structure; @@ -67,10 +65,10 @@ BOOST_SPIRIT_DEFINE(term, function, termList, variable, identifier); } // namespace struct Converter : public boost::static_visitor { - Converter(const Converter&) = delete; - Converter &operator=(const Converter&) = delete; + Converter(const Converter &) = delete; + Converter &operator=(const Converter &) = delete; - Converter(const StringStore &stringStore) : stringStore(stringStore) { } + Converter(const StringStore &stringStore) : stringStore(stringStore) {} lib::Term::RawTerm operator()(const Variable &var) { std::size_t stringId; @@ -102,7 +100,8 @@ struct Converter : public boost::static_visitor { } // namespace detail -boost::optional rawTerm(const std::string &data, const StringStore &stringStore, std::ostream &errorStream) { +boost::optional +rawTerm(const std::string &data, const StringStore &stringStore, std::ostream &errorStream) { detail::Term term; bool res = parse(data.begin(), data.end(), detail::parser::term, term, errorStream, x3::space); if(!res) return boost::none; @@ -111,8 +110,8 @@ boost::optional rawTerm(const std::string &data, const Strin return libTerm; } -} // namespace Read -namespace Write { +} // namespace mod::lib::IO::Term::Read +namespace mod::lib::IO::Term::Write { namespace { std::ostream &rawVarFromCell(std::ostream &s, lib::Term::Cell cell) { @@ -130,10 +129,8 @@ std::ostream &rawVarFromCell(std::ostream &s, lib::Term::Cell cell) { } // namespace std::ostream &rawTerm(const lib::Term::RawTerm &term, const StringStore &strings, std::ostream &s) { - struct Printer : public boost::static_visitor { - - Printer(std::ostream &s, const StringStore &strings) : s(s), strings(strings) { } + Printer(std::ostream &s, const StringStore &strings) : s(s), strings(strings) {} void operator()(lib::Term::RawVariable v) const { s << "_" << strings.getString(v.name); @@ -176,12 +173,12 @@ std::ostream &element(lib::Term::Cell cell, const StringStore &strings, std::ost } void wam(const lib::Term::Wam &machine, const StringStore &strings, std::ostream &s) { - wam(machine, strings, s, [](lib::Term::Address, std::ostream&) { + wam(machine, strings, s, [](lib::Term::Address, std::ostream &) { }); } void wam(const lib::Term::Wam &machine, const StringStore &strings, std::ostream &s, - std::function addressCallback) { + std::function addressCallback) { using namespace lib::Term; s << "Heap:" << std::endl; for(std::size_t i = 0; i < machine.getHeap().size(); i++) { @@ -203,20 +200,23 @@ void wam(const lib::Term::Wam &machine, const StringStore &strings, std::ostream s << "-------------------------------------------------" << std::endl; } -std::ostream &term(const lib::Term::Wam &machine, lib::Term::Address addr, const StringStore &strings, std::ostream &s) { +std::ostream & +term(const lib::Term::Wam &machine, lib::Term::Address addr, const StringStore &strings, std::ostream &s) { using namespace lib::Term; struct Printer { - Printer(const Wam &machine, const StringStore &strings, std::ostream &s) - : machine(machine), strings(strings), s(s) { } + : machine(machine), strings(strings), s(s) { + occurred[0].resize(machine.getHeap().size(), 0); + occurred[1].resize(machine.getTemp().size(), 0); + } void operator()(Address addr) { Cell cell = machine.getCell(addr); switch(cell.tag) { case CellTag::REF: if(cell.REF.addr == addr - || occurred.find(cell.REF.addr) != end(occurred) + || occurred[static_cast(cell.REF.addr.type)][cell.REF.addr.addr] != 0 ) { rawVarFromCell(s, cell); } else (*this)(cell.REF.addr); @@ -225,10 +225,21 @@ std::ostream &term(const lib::Term::Wam &machine, lib::Term::Address addr, const (*this)(cell.STR.addr); break; case CellTag::Structure: - assert(occurred.find(addr) == end(occurred)); - occurred.insert(addr); + if(occurred[static_cast(addr.type)][addr.addr] != 0) { + wam(machine, strings, std::cout); + std::cout << "addr.addr = " << addr.addr << std::endl; + std::cout << "occurred:" << std::endl; + for(int aType : {0, 1}) { + for(const auto o : occurred[aType]) { + if(o == 0) continue; + std::cout << " [" << aType << "]: " << o << std::endl; + } + } + } + assert(occurred[static_cast(addr.type)][addr.addr] == 0); s << strings.getString(cell.Structure.name); if(cell.Structure.arity > 0) { + ++occurred[static_cast(addr.type)][addr.addr]; s << "("; (*this)(addr + 1); for(std::size_t i = 2; i <= cell.Structure.arity; i++) { @@ -236,6 +247,7 @@ std::ostream &term(const lib::Term::Wam &machine, lib::Term::Address addr, const (*this)(addr + i); } s << ")"; + --occurred[static_cast(addr.type)][addr.addr]; } break; } @@ -244,14 +256,14 @@ std::ostream &term(const lib::Term::Wam &machine, lib::Term::Address addr, const const Wam &machine; const StringStore &strings; std::ostream &s; - //std::size_t occursBase; - std::unordered_set
occurred; + std::array, 2> occurred; }; Printer(machine, strings, s)(addr); return s; } -std::ostream &mgu(const lib::Term::Wam &machine, const lib::Term::MGU &mgu, const StringStore &strings, std::ostream &s) { +std::ostream & +mgu(const lib::Term::Wam &machine, const lib::Term::MGU &mgu, const StringStore &strings, std::ostream &s) { using namespace lib::Term; switch(mgu.status) { case MGU::Status::Exists: @@ -276,10 +288,8 @@ std::ostream &mgu(const lib::Term::Wam &machine, const lib::Term::MGU &mgu, cons return s; } -} // namespace Write -} // namespace Term -} // namespace IO -namespace Term { +} // namespace mod::lib::IO::Term::Write +namespace mod::lib::Term { std::ostream &operator<<(std::ostream &s, Address addr) { switch(addr.type) { @@ -293,13 +303,10 @@ std::ostream &operator<<(std::ostream &s, Address addr) { return s << "[" << addr.addr << "]"; } -} // namespace Term -} // namespace lib -} // namespace mod +} // namespace mod::lib::Term BOOST_FUSION_ADAPT_STRUCT(mod::lib::IO::Term::Read::detail::Variable, - (std::string, name)) + (std::string, name)) BOOST_FUSION_ADAPT_STRUCT(mod::lib::IO::Term::Read::detail::Structure, - (std::string, name) - (std::vector, arguments) - ) \ No newline at end of file + (std::string, name) + (std::vector, arguments)) \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/IO/Term.hpp b/libs/libmod/src/mod/lib/IO/Term.hpp index 95d01b0..a6dc021 100644 --- a/libs/libmod/src/mod/lib/IO/Term.hpp +++ b/libs/libmod/src/mod/lib/IO/Term.hpp @@ -1,20 +1,18 @@ -#ifndef MOD_LIB_IO_TERM_H -#define MOD_LIB_IO_TERM_H +#ifndef MOD_LIB_IO_TERM_HPP +#define MOD_LIB_IO_TERM_HPP #include #include #include -namespace mod { -namespace lib { +namespace mod::lib { struct StringStore; -namespace IO { -namespace Term { -namespace Read { +} // namespace mod::lib +namespace mod::lib::IO::Term::Read { boost::optional rawTerm(const std::string &data, const StringStore &stringStore, std::ostream &errorStream); -} // namespace Read -namespace Write { +} // namespace mod::lib::IO::Term::Read +namespace mod::lib::IO::Term::Write { std::ostream &rawTerm(const lib::Term::RawTerm &term, const StringStore &strings, std::ostream &s); std::ostream &element(lib::Term::Cell cell, const StringStore &strings, std::ostream &s); void wam(const lib::Term::Wam &machine, const StringStore &strings, std::ostream &s); @@ -22,10 +20,6 @@ void wam(const lib::Term::Wam &machine, const StringStore &strings, std::ostream std::function addressCallback); std::ostream &term(const lib::Term::Wam &machine, lib::Term::Address addr, const StringStore &strings, std::ostream &s); std::ostream &mgu(const lib::Term::Wam &machine, const lib::Term::MGU &mgu, const StringStore &strings, std::ostream &s); -} // namespace Write -} // namespace Term -} // namespace IO -} // namespace lib -} // namespace mod +} // namespace mod::lib::IO::Term::Write -#endif /* MOD_LIB_IO_TERM_H */ \ No newline at end of file +#endif // MOD_LIB_IO_TERM_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/LabelledGraph.hpp b/libs/libmod/src/mod/lib/LabelledGraph.hpp index c3cbd8d..90b6178 100644 --- a/libs/libmod/src/mod/lib/LabelledGraph.hpp +++ b/libs/libmod/src/mod/lib/LabelledGraph.hpp @@ -1,10 +1,9 @@ -#ifndef MOD_LIB_LABELLEDGRAPH_H -#define MOD_LIB_LABELLEDGRAPH_H +#ifndef MOD_LIB_LABELLEDGRAPH_HPP +#define MOD_LIB_LABELLEDGRAPH_HPP #include -namespace mod { -namespace lib { +namespace mod::lib { template struct LabelledGraphTraits { @@ -19,7 +18,6 @@ struct LabelledGraphConcept { using PropStringType = typename LabelledGraphTraits::PropStringType; using PropTermType = typename LabelledGraphTraits::PropTermType; public: - BOOST_CONCEPT_USAGE(LabelledGraphConcept) { const G &gOuterConst = gOuter; @@ -47,7 +45,6 @@ struct LabelledGraphConcept { //}; struct IdentityPropertyHandler { - template static auto fmap2(const VEProp &l, const VEProp &r, const LabGraphDom &gDom, const LabGraphCodom &gCodom, F &&f, Args&&... args) { return f(l, r, gDom, gCodom, std::forward(args)...); @@ -59,7 +56,6 @@ struct IdentityPropertyHandler { } }; -} // namespace lib -} // namespace mod +} // namespace mod::lib -#endif /* MOD_LIB_LABELLEDGRAPH_H */ +#endif // MOD_LIB_LABELLEDGRAPH_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/LabelledUnionGraph.hpp b/libs/libmod/src/mod/lib/LabelledUnionGraph.hpp index e66fbeb..fb3b089 100644 --- a/libs/libmod/src/mod/lib/LabelledUnionGraph.hpp +++ b/libs/libmod/src/mod/lib/LabelledUnionGraph.hpp @@ -1,12 +1,11 @@ -#ifndef MOD_LIB_LABELLEDUNIONGRAPH_H -#define MOD_LIB_LABELLEDUNIONGRAPH_H +#ifndef MOD_LIB_LABELLEDUNIONGRAPH_HPP +#define MOD_LIB_LABELLEDUNIONGRAPH_HPP #include #include -namespace mod { -namespace lib { +namespace mod::lib { namespace detail { template @@ -95,7 +94,6 @@ struct LabelledUnionGraph { GraphType ug; }; -} // namesapce lib -} // namespace mod +} // namesapce mod::lib -#endif /* MOD_LIB_LABELLEDUNIONGRAPH_H */ +#endif // MOD_LIB_LABELLEDUNIONGRAPH_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/RC/Evaluator.cpp b/libs/libmod/src/mod/lib/RC/Evaluator.cpp index d0f6b5b..76ad734 100644 --- a/libs/libmod/src/mod/lib/RC/Evaluator.cpp +++ b/libs/libmod/src/mod/lib/RC/Evaluator.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -14,47 +13,44 @@ #include -namespace mod { -namespace lib { -namespace RC { +namespace mod::lib::RC { namespace { -struct EvalVisitor : public boost::static_visitor > > { - +struct EvalVisitor : public boost::static_visitor>> { EvalVisitor(int verbosity, IO::Logger logger, Evaluator &evaluator) : verbosity(verbosity), logger(logger), evaluator(evaluator) {} // Nullary/unary //---------------------------------------------------------------------- - std::unordered_set > operator()(std::shared_ptr r) { - return std::unordered_set >{r}; + std::vector > operator()(std::shared_ptr r) { + return {r}; } - std::unordered_set > operator()(const rule::RCExp::Union &par) { - std::unordered_set > result; + std::vector> operator()(const rule::RCExp::Union &par) { + std::vector> result; for(const auto &subExp : par.getExpressions()) { auto subRes = subExp.applyVisitor(*this); - result.insert(begin(subRes), end(subRes)); + result.insert(end(result), begin(subRes), end(subRes)); } return result; } - std::unordered_set > operator()(const rule::RCExp::Bind &bind) { - std::unordered_set > result; - result.insert(bind.getGraph()->getGraph().getBindRule()); + std::vector> operator()(const rule::RCExp::Bind &bind) { + std::vector> result; + result.push_back(evaluator.graphAsRuleCache.getBindRule(&bind.getGraph()->getGraph())); return result; } - std::unordered_set > operator()(const rule::RCExp::Id &id) { - std::unordered_set > result; - result.insert(id.getGraph()->getGraph().getIdRule()); + std::vector > operator()(const rule::RCExp::Id &id) { + std::vector > result; + result.push_back(evaluator.graphAsRuleCache.getIdRule(&id.getGraph()->getGraph())); return result; } - std::unordered_set > operator()(const rule::RCExp::Unbind &unbind) { - std::unordered_set > result; - result.insert(unbind.getGraph()->getGraph().getUnbindRule()); + std::vector > operator()(const rule::RCExp::Unbind &unbind) { + std::vector > result; + result.push_back(evaluator.graphAsRuleCache.getUnbindRule(&unbind.getGraph()->getGraph())); return result; } @@ -62,11 +58,11 @@ struct EvalVisitor : public boost::static_visitor - std::unordered_set > composeTemplate( + std::vector> composeTemplate( const rule::RCExp::ComposeBase &compose, Composer composer) { auto firstResult = compose.getFirst().applyVisitor(*this); auto secondResult = compose.getSecond().applyVisitor(*this); - std::unordered_set > result; + std::vector > result; for(auto rFirst : firstResult) { for(auto rSecond : secondResult) { std::vector resultVec; @@ -84,43 +80,43 @@ struct EvalVisitor : public boost::static_visitorgetRule(), &rSecond->getRule(), &rWrapped->getRule()); - result.insert(rWrapped); + result.push_back(rWrapped); } } } return result; } - std::unordered_set > operator()(const rule::RCExp::ComposeCommon &common) { + std::vector> operator()(const rule::RCExp::ComposeCommon &common) { const auto composer = [&common, this](const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, - std::function)> reporter) { + std::function)> reporter) { RC::Common mm(matchMakerVerbosity(), logger, common.getMaxmimum(), common.getConnected()); lib::RC::composeRuleRealByMatchMaker(rFirst, rSecond, mm, reporter, evaluator.labelSettings); }; return composeTemplate(common, composer); } - std::unordered_set > operator()(const rule::RCExp::ComposeParallel &common) { + std::vector> operator()(const rule::RCExp::ComposeParallel &common) { const auto composer = [this](const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, - std::function)> reporter) { + std::function)> reporter) { lib::RC::composeRuleRealByMatchMaker(rFirst, rSecond, lib::RC::Parallel(verbosity, logger), - reporter, evaluator.labelSettings); + reporter, evaluator.labelSettings); }; return composeTemplate(common, composer); } - std::unordered_set > operator()(const rule::RCExp::ComposeSub &sub) { + std::vector> operator()(const rule::RCExp::ComposeSub &sub) { const auto composer = [&sub, this](const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, - std::function)> reporter) { + std::function)> reporter) { RC::Sub mm(matchMakerVerbosity(), logger, sub.getAllowPartial()); lib::RC::composeRuleRealByMatchMaker(rFirst, rSecond, mm, reporter, evaluator.labelSettings); }; return composeTemplate(sub, composer); } - std::unordered_set > operator()(const rule::RCExp::ComposeSuper &super) { + std::vector> operator()(const rule::RCExp::ComposeSuper &super) { const auto composer = [&super, this](const lib::Rules::Real &rFirst, const lib::Rules::Real &rSecond, - std::function)> reporter) { + std::function)> reporter) { RC::Super mm(matchMakerVerbosity(), logger, super.getAllowPartial(), super.getEnforceConstraints()); lib::RC::composeRuleRealByMatchMaker(rFirst, rSecond, mm, reporter, evaluator.labelSettings); }; @@ -130,7 +126,6 @@ struct EvalVisitor : public boost::static_visitor > database, LabelSettings labelSettings) +Evaluator::Evaluator(std::unordered_set> database, LabelSettings labelSettings) : labelSettings(labelSettings), database(database) { if(labelSettings.type == LabelType::Term) { - for(const auto r : database) { + for(const auto &r : database) { const auto &term = get_term(r->getRule().getDPORule()); if(!isValid(term)) { std::string msg = "Parsing failed for rule '" + r->getName() + "'. " + term.getParsingError(); @@ -156,11 +151,11 @@ const std::unordered_set > &Evaluator::getRuleDataba return database; } -const std::unordered_set > &Evaluator::getProducts() const { +const std::unordered_set> &Evaluator::getProducts() const { return products; } -std::unordered_set > Evaluator::eval(const rule::RCExp::Expression &exp, int verbosity) { +std::vector> Evaluator::eval(const rule::RCExp::Expression &exp, int verbosity) { struct PreEvalVisitor : public boost::static_visitor { PreEvalVisitor(Evaluator &evaluator) : evaluator(evaluator) {} @@ -183,15 +178,15 @@ std::unordered_set > Evaluator::eval(const rule::RCE } void operator()(const rule::RCExp::Bind &bind) { - evaluator.addRule(bind.getGraph()->getGraph().getBindRule()); + evaluator.addRule(evaluator.graphAsRuleCache.getBindRule(&bind.getGraph()->getGraph())); } void operator()(const rule::RCExp::Id &id) { - evaluator.addRule(id.getGraph()->getGraph().getIdRule()); + evaluator.addRule(evaluator.graphAsRuleCache.getIdRule(&id.getGraph()->getGraph())); } void operator()(const rule::RCExp::Unbind &unbind) { - evaluator.addRule(unbind.getGraph()->getGraph().getUnbindRule()); + evaluator.addRule(evaluator.graphAsRuleCache.getUnbindRule(&unbind.getGraph()->getGraph())); } // Binary @@ -221,7 +216,7 @@ std::unordered_set > Evaluator::eval(const rule::RCE Evaluator &evaluator; }; exp.applyVisitor(PreEvalVisitor(*this)); - auto result = exp.applyVisitor(EvalVisitor(verbosity, IO::Logger(IO::log()), *this)); + auto result = exp.applyVisitor(EvalVisitor(verbosity, IO::Logger(std::cout), *this)); return result; } @@ -254,8 +249,8 @@ std::shared_ptr Evaluator::checkIfNew(lib::Rules::Real *rCand) const } void Evaluator::suggestComposition(const lib::Rules::Real *rFirst, - const lib::Rules::Real *rSecond, - const lib::Rules::Real *rResult) { + const lib::Rules::Real *rSecond, + const lib::Rules::Real *rResult) { Vertex vComp = getVertexFromArgs(rFirst, rSecond); Vertex vResult = getVertexFromRule(rResult); for(Vertex vOut : asRange(adjacent_vertices(vComp, rcg))) { @@ -296,6 +291,4 @@ Evaluator::Vertex Evaluator::getVertexFromArgs(const lib::Rules::Real *rFirst, c return vComp; } -} // namespace RC -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::RCd \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/RC/Evaluator.hpp b/libs/libmod/src/mod/lib/RC/Evaluator.hpp index 30bde70..aa143c7 100644 --- a/libs/libmod/src/mod/lib/RC/Evaluator.hpp +++ b/libs/libmod/src/mod/lib/RC/Evaluator.hpp @@ -1,8 +1,9 @@ -#ifndef MOD_LIB_RC_EVALCONTEXT_H -#define MOD_LIB_RC_EVALCONTEXT_H +#ifndef MOD_LIB_RC_EVALCONTEXT_HPP +#define MOD_LIB_RC_EVALCONTEXT_HPP #include #include +#include #include @@ -10,12 +11,9 @@ #include #include -namespace mod { -namespace lib { -namespace RC { +namespace mod::lib::RC { struct Evaluator { - enum class VertexKind { Rule, Composition }; @@ -40,7 +38,7 @@ struct Evaluator { Evaluator(std::unordered_set> database, LabelSettings labelSettings); const std::unordered_set> &getRuleDatabase() const; const std::unordered_set> &getProducts() const; - std::unordered_set> eval(const rule::RCExp::Expression &exp, int verbosity); + std::vector> eval(const rule::RCExp::Expression &exp, int verbosity); void print() const; const GraphType &getGraph() const; public: // evalutation interface @@ -55,13 +53,14 @@ struct Evaluator { std::shared_ptr checkIfNew(lib::Rules::Real *rCand) const; // records a composition void suggestComposition(const lib::Rules::Real *rFirst, - const lib::Rules::Real *rSecond, - const lib::Rules::Real *rResult); + const lib::Rules::Real *rSecond, + const lib::Rules::Real *rResult); private: // graph interface Vertex getVertexFromRule(const lib::Rules::Real *r); Vertex getVertexFromArgs(const lib::Rules::Real *rFirst, const lib::Rules::Real *rSecond); public: const LabelSettings labelSettings; + Rules::GraphAsRuleCache graphAsRuleCache; private: std::unordered_set > database, products; private: @@ -70,8 +69,6 @@ struct Evaluator { std::map, Vertex> argsToVertex; }; -} // namespace RC -} // namespace lib -} // namespace mod +} // namespace mod::lib::RC -#endif /* MOD_LIB_RC_EVALCONTEXT_H */ \ No newline at end of file +#endif // MOD_LIB_RC_EVALCONTEXT_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/RC/MatchMaker/Common.hpp b/libs/libmod/src/mod/lib/RC/MatchMaker/Common.hpp index c1a98f1..862a3dc 100644 --- a/libs/libmod/src/mod/lib/RC/MatchMaker/Common.hpp +++ b/libs/libmod/src/mod/lib/RC/MatchMaker/Common.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RC_COMMONSG_H -#define MOD_LIB_RC_COMMONSG_H +#ifndef MOD_LIB_RC_COMMONSG_HPP +#define MOD_LIB_RC_COMMONSG_HPP #include #include @@ -9,21 +9,26 @@ #include #include -namespace mod { -namespace lib { -namespace RC { +namespace mod::lib::RC { struct Common { - Common(int verbosity, IO::Logger logger, bool maximum, bool connected) : verbosity(verbosity), logger(logger), maximum(maximum), connected(connected) {} template void makeMatches(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - Callback callback, - LabelSettings labelSettings) { - const auto mr = [&rFirst, &rSecond, &callback, this](auto &&m, const auto &gSecond, const auto &gFirst) -> bool { + const lib::Rules::Real &rSecond, + Callback callback, + LabelSettings labelSettings) { + using MapImpl = std::vector; + std::vector maps; + const auto mr = [&rFirst, &rSecond, &callback, this, &maps](auto &&m, const auto &gSecond, const auto &gFirst) -> bool { + MapImpl map(num_vertices(gFirst)); + for(const auto v : asRange(vertices(gFirst))) + map[get(boost::vertex_index_t(), gFirst, v)] = get_inverse(m, gSecond, gFirst, v); + if(std::find(begin(maps), end(maps), map) != end(maps)) + return true; + maps.push_back(std::move(map)); return callback(rFirst, rSecond, std::move(m), verbosity, logger); }; const auto &lgDom = get_labelled_left(rSecond.getDPORule()); @@ -37,7 +42,6 @@ struct Common { } lib::GraphMorphism::morphismSelectByLabelSettings(lgDom, lgCodom, labelSettings, finder, mr); } - private: const int verbosity; IO::Logger logger; @@ -45,9 +49,6 @@ struct Common { const bool connected; }; -} // namespace RC -} // namespace lib -} // namespace mod - -#endif /* MOD_LIB_RC_COMMONSG_H */ +} // namespace mod::lib::RC +#endif // MOD_LIB_RC_COMMONSG_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/RC/MatchMaker/ComponentWiseUtil.hpp b/libs/libmod/src/mod/lib/RC/MatchMaker/ComponentWiseUtil.hpp index 74c2cc2..6824c61 100644 --- a/libs/libmod/src/mod/lib/RC/MatchMaker/ComponentWiseUtil.hpp +++ b/libs/libmod/src/mod/lib/RC/MatchMaker/ComponentWiseUtil.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -77,8 +78,8 @@ struct WrappedComponentGraph { template WrappedComponentGraph makeWrappedComponentGraph(const typename Rule::ComponentGraph &g, - std::size_t i, - const Rule &r) { + std::size_t i, + const Rule &r) { return WrappedComponentGraph(g, i, r); } @@ -88,67 +89,74 @@ struct RuleRuleComponentMonomorphism { public: RuleRuleComponentMonomorphism(const RuleSideDom &rsDom, - const RuleSideCodom &rsCodom, - bool enforceConstraints, - LabelSettings labelSettings, - bool verbose, IO::Logger &logger) + const RuleSideCodom &rsCodom, + bool enforceConstraints, + LabelSettings labelSettings, + bool verbose, IO::Logger &logger) : rsDom(rsDom), rsCodom(rsCodom), enforceConstraints(enforceConstraints), labelSettings(labelSettings), - verbose(verbose), logger(logger) {} + verbose(verbose), logger(logger), haxMorphismLimit(getConfig().rc.componentWiseMorphismLimit.get()) {} std::vector operator()(const std::size_t idDom, const std::size_t idCodom) const { - std::vector morphisms; - auto mrStore = GM::makeStore(std::back_inserter(morphisms)); - const auto &gDom = get_component_graph(idDom, rsDom); - const auto &gCodom = get_component_graph(idCodom, rsCodom); - auto wgDom = makeWrappedComponentGraph(gDom, idDom, rsDom); - auto wgCodom = makeWrappedComponentGraph(gCodom, idCodom, rsCodom); - - auto makeCheckConstraints = [&](auto &&mrNext) { - const auto &constraints = get_match_constraints(rsDom); - auto constraintsIterEnd = enforceConstraints ? constraints.end() : constraints.begin(); - if(verbose) - logger.indent() << "RuleRuleComponentMonomorphism(" << idDom << ", " << idCodom - << ")::makeCheckConstraints: " - << std::distance(constraints.begin(), constraintsIterEnd) << std::endl; - return GraphMorphism::Constraints::makeChecker( - asRange(std::make_pair(constraints.begin(), constraintsIterEnd)), - rsCodom, labelSettings, mrNext); + const auto doIt = [this, idDom, idCodom](auto mrStore) { + const auto &gDom = get_component_graph(idDom, rsDom); + const auto &gCodom = get_component_graph(idCodom, rsCodom); + auto wgDom = makeWrappedComponentGraph(gDom, idDom, rsDom); + auto wgCodom = makeWrappedComponentGraph(gCodom, idCodom, rsCodom); + + auto makeCheckConstraints = [&](auto &&mrNext) { + const auto &constraints = get_match_constraints(rsDom); + auto constraintsIterEnd = enforceConstraints ? constraints.end() : constraints.begin(); + if(verbose) + logger.indent() << "RuleRuleComponentMonomorphism(" << idDom << ", " << idCodom + << ")::makeCheckConstraints: " + << std::distance(constraints.begin(), constraintsIterEnd) << std::endl; + return GraphMorphism::Constraints::makeChecker( + asRange(std::make_pair(constraints.begin(), constraintsIterEnd)), + rsCodom, labelSettings, mrNext); + }; + // First reinterpret the vertex descriptors from the reindexed graphs to their parent graphs. + auto mrWrapper = FilteredWrapperReinterpretMRWrapper(); + // Then do whatever checked is needed by the labelled morphisms (morphismSelectByLabelSettings injects those). + // And now process the final morphisms: + auto mr = + // The next two unwrappings will increase the domain and codomain, + // so we first need to capture the mapping: + // Store them in a vector (which runs through the domain graph): + GM::makeTransform(GM::ToVectorVertexMap(), + // Unwrap the filtering by connected component, so we get side graphs: + GM::makeUnwrapperDom( + GM::makeUnwrapperCodom( + // Check constraints using the side graphs: + makeCheckConstraints( + // // Unwrap the filtering by rule side, so we get to core graphs: + // GM::makeUnwrapperLeft ( + // GM::makeUnwrapperRight ( + // Slice away the properties, the user must recreate that. + GM::makeSliceProps( + // And finally push it into our storage: + mrStore + )))))//)) + ; + auto predWrapper = lib::GraphMorphism::IdentityWrapper(); + + // auto mrPrinter = GraphMorphism::Callback::makePrint(std::cout, patternWrapped, targetWrapped, mrCheckConstraints); + lib::GraphMorphism::morphismSelectByLabelSettings(wgDom, wgCodom, labelSettings, GM_MOD::VF2Monomorphism(), mr, + predWrapper, mrWrapper); }; - // First reinterpret the vertex descriptors from the reindexed graphs to their parent graphs. - auto mrWrapper = FilteredWrapperReinterpretMRWrapper(); - // Then do whatever checked is needed by the labelled morphisms (morphismSelectByLabelSettings injects those). - // And now process the final morphisms: - auto mr = - // The next two unwrappings will increase the domain and codomain, - // so we first need to capture the mapping: - // Store them in a vector (which runs through the domain graph): - GM::makeTransform(GM::ToVectorVertexMap(), - // Unwrap the filtering by connected component, so we get side graphs: - GM::makeUnwrapperDom( - GM::makeUnwrapperCodom( - // Check constraints using the side graphs: - makeCheckConstraints( - // // Unwrap the filtering by rule side, so we get to core graphs: - // GM::makeUnwrapperLeft ( - // GM::makeUnwrapperRight ( - // Slice away the properties, the user must recreate that. - GM::makeSliceProps( - // And finally push it into our storage: - mrStore - )))))//)) - ; - auto predWrapper = lib::GraphMorphism::IdentityWrapper(); - - // auto mrPrinter = GraphMorphism::Callback::makePrint(IO::log(), patternWrapped, targetWrapped, mrCheckConstraints); - lib::GraphMorphism::morphismSelectByLabelSettings(wgDom, wgCodom, labelSettings, GM_MOD::VF2Monomorphism(), mr, - predWrapper, mrWrapper); - if(verbose) - logger.indent() << "RuleRuleComponentMonomorphism(" << idDom << ", " << idCodom << "): got " - << morphisms.size() - << std::endl; + std::vector morphisms; + if(haxMorphismLimit == 0) { + doIt(GM::makeStore(std::back_inserter(morphisms))); + } else { + auto limit = GM::makeLimit(haxMorphismLimit, GM::makeStore(std::back_inserter(morphisms))); + doIt(std::ref(limit)); + } + if(verbose) { + logger.indent() << "RuleRuleComponentMonomorphism(" << idDom << ", " << idCodom; + if(haxMorphismLimit != 0) std::cout << ", limit=" << haxMorphismLimit; + std::cout << "): got " << morphisms.size() << std::endl; + } return morphisms; } - private: const RuleSideDom &rsDom; const RuleSideCodom &rsCodom; @@ -156,16 +164,17 @@ struct RuleRuleComponentMonomorphism { const LabelSettings labelSettings; const bool verbose; IO::Logger &logger; + int haxMorphismLimit; }; template auto makeRuleRuleComponentMonomorphism(const RuleSideDom &rsDom, - const RuleSideCodom &rsCodom, - bool enforceConstraints, - LabelSettings labelSettings, - bool verbose, IO::Logger &logger) { - return RuleRuleComponentMonomorphism(rsDom, rsCodom, enforceConstraints, labelSettings, - verbose, logger); + const RuleSideCodom &rsCodom, + bool enforceConstraints, + LabelSettings labelSettings, + bool verbose, IO::Logger &logger) { + return RuleRuleComponentMonomorphism( + rsDom, rsCodom, enforceConstraints, labelSettings, verbose, logger); } } // namespace RC diff --git a/libs/libmod/src/mod/lib/RC/MatchMaker/LabelledMatch.hpp b/libs/libmod/src/mod/lib/RC/MatchMaker/LabelledMatch.hpp index 9bb7448..dfe6d4a 100644 --- a/libs/libmod/src/mod/lib/RC/MatchMaker/LabelledMatch.hpp +++ b/libs/libmod/src/mod/lib/RC/MatchMaker/LabelledMatch.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RC_MATCH_MAKER_LABELLED_MATCH_H -#define MOD_LIB_RC_MATCH_MAKER_LABELLED_MATCH_H +#ifndef MOD_LIB_RC_MATCH_MAKER_LABELLED_MATCH_HPP +#define MOD_LIB_RC_MATCH_MAKER_LABELLED_MATCH_HPP #include #include @@ -11,9 +11,7 @@ #include -namespace mod { -namespace lib { -namespace RC { +namespace mod::lib::RC { constexpr int V_MorphismGen = 2; constexpr int V_Composition = 12; namespace detail { @@ -141,8 +139,8 @@ bool handleMapToTerm(const RFirst &rFirst, const RSecond &rSecond, machine.verify(); // lib::IO::Rules::Write::termState(rFirst); // lib::IO::Rules::Write::termState(rSecond); - // lib::IO::Term::Write::wam(termFirst.getMachine(), lib::Term::getStrings(), lib::IO::log() << "MachineFirst:\n"); - // lib::IO::Term::Write::wam(termSecond.getMachine(), lib::Term::getStrings(), lib::IO::log() << "MachineSecond:\n"); + // lib::IO::Term::Write::wam(termFirst.getMachine(), lib::Term::getStrings(), std::cout << "MachineFirst:\n"); + // lib::IO::Term::Write::wam(termSecond.getMachine(), lib::Term::getStrings(), std::cout << "MachineSecond:\n"); lib::GraphMorphism::TermData data{std::move(machine), std::move(mgu)}; auto mTerm = GM::addProp(std::move(m), lib::GraphMorphism::TermDataT(), std::move(data)); return handleMapToStereo(rFirst, rSecond, std::move(mTerm), mr, labelSettings, verbosity, logger); @@ -173,8 +171,6 @@ bool handleMapByLabelSettings(const RFirst &rFirst, const RSecond &rSecond, labelSettings, verbosity, logger); } -} // namespace RC -} // namespace lib -} // namespace mod +} // namespace mod::lib::RC -#endif /* MOD_LIB_RC_MATCH_MAKER_LABELLED_MATCH_H */ \ No newline at end of file +#endif // MOD_LIB_RC_MATCH_MAKER_LABELLED_MATCH_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/RC/MatchMaker/Sub.hpp b/libs/libmod/src/mod/lib/RC/MatchMaker/Sub.hpp index 23a08ba..36a4648 100644 --- a/libs/libmod/src/mod/lib/RC/MatchMaker/Sub.hpp +++ b/libs/libmod/src/mod/lib/RC/MatchMaker/Sub.hpp @@ -31,9 +31,9 @@ struct Sub { template void makeMatches(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - MR mr, - LabelSettings labelSettings) const { + const lib::Rules::Real &rSecond, + MR mr, + LabelSettings labelSettings) const { if(allowPartial) makeMatchesInternal(rFirst, rSecond, mr, labelSettings); else @@ -44,15 +44,15 @@ struct Sub { template void makeMatchesInternal(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - MR mr, - LabelSettings labelSettings) const { + const lib::Rules::Real &rSecond, + MR mr, + LabelSettings labelSettings) const { initByLabelSettings(rFirst, rSecond, labelSettings); const auto &lgCodomPatterns = get_labelled_right(rFirst.getDPORule()); const auto &lgDomHosts = get_labelled_left(rSecond.getDPORule()); - IO::Logger logger(IO::log()); + IO::Logger logger(std::cout); auto mp = makeRuleRuleComponentMonomorphism(lgCodomPatterns, lgDomHosts, false, labelSettings, - false, logger); + false, logger); auto mm = makeMultiDimSelector( get_num_connected_components(lgCodomPatterns), get_num_connected_components(lgDomHosts), mp); @@ -61,7 +61,7 @@ struct Sub { if(!maybeMap) continue; auto map = *std::move(maybeMap); bool continue_ = handleMapByLabelSettings(rFirst, rSecond, std::move(map), mr, labelSettings, - verbosity, logger); + verbosity, logger); if(!continue_) break; } } @@ -69,8 +69,8 @@ struct Sub { public: template boost::optional matchFromPosition(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - const std::vector &position) const; + const lib::Rules::Real &rSecond, + const std::vector &position) const; private: const int verbosity; IO::Logger logger; @@ -80,8 +80,8 @@ struct Sub { template inline boost::optional Sub::matchFromPosition(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - const std::vector &position) const { + const lib::Rules::Real &rSecond, + const std::vector &position) const { const auto &gDom = get_graph(get_labelled_left(rSecond.getDPORule())); const auto &lgCodom = get_labelled_right(rFirst.getDPORule()); const auto &gCodom = get_graph(lgCodom); diff --git a/libs/libmod/src/mod/lib/RC/MatchMaker/Super.hpp b/libs/libmod/src/mod/lib/RC/MatchMaker/Super.hpp index 9c24cfb..8445851 100644 --- a/libs/libmod/src/mod/lib/RC/MatchMaker/Super.hpp +++ b/libs/libmod/src/mod/lib/RC/MatchMaker/Super.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RC_SUPER_H -#define MOD_LIB_RC_SUPER_H +#ifndef MOD_LIB_RC_SUPER_HPP +#define MOD_LIB_RC_SUPER_HPP #include #include @@ -16,16 +16,15 @@ #include -namespace mod { -namespace lib { -namespace RC { +#include + +namespace mod::lib::RC { struct Super { using GraphDom = lib::Rules::LabelledRule::LeftGraphType; using GraphCodom = lib::Rules::LabelledRule::RightGraphType; using VertexMapType = jla_boost::GraphMorphism::InvertibleVectorVertexMap; public: - Super(int verbosity, IO::Logger logger, bool allowPartial, bool enforceConstraints) : verbosity(verbosity), logger(logger), allowPartial(allowPartial), enforceConstraints(enforceConstraints) {} @@ -36,9 +35,7 @@ struct Super { else makeMatchesInternal(rFirst, rSecond, mr, labelSettings); } - private: - template void makeMatchesInternal(const RFirst &rFirst, const RSecond &rSecond, MR &&mr, LabelSettings labelSettings) const { if(verbosity >= V_MorphismGen) { @@ -50,37 +47,37 @@ struct Super { const auto &lgDomPatterns = get_labelled_left(rSecond.getDPORule()); const auto &lgCodomHosts = get_labelled_right(rFirst.getDPORule()); if(get_num_connected_components(lgDomPatterns) == 0) { - IO::log() << "RCSuper: rSecond L has no vertices, rule = " << rSecond.getName() << std::endl; + std::cout << "RCSuper: rSecond L has no vertices, rule = " << rSecond.getName() << std::endl; MOD_ABORT; } if(get_num_connected_components(lgCodomHosts) == 0) { - IO::log() << "RCSuper: rFirst R has no vertices, rule = " << rFirst.getName() << std::endl; + std::cout << "RCSuper: rFirst R has no vertices, rule = " << rFirst.getName() << std::endl; MOD_ABORT; } - // IO::log() << "rFirstRight:\n"; + // std::cout << "rFirstRight:\n"; // for(auto v : asRange(vertices(get_graph(rFirstRight)))) { - // IO::log() << v << ":"; + // std::cout << v << ":"; // for(auto vOut : asRange(adjacent_vertices(v, get_graph(rFirstRight)))) - // IO::log() << " " << vOut; - // IO::log() << "\n"; + // std::cout << " " << vOut; + // std::cout << "\n"; // } - // IO::log() << "\n"; - // IO::log() << "rSecondLeft:\n"; + // std::cout << "\n"; + // std::cout << "rSecondLeft:\n"; // for(auto v : asRange(vertices(get_graph(rSecondLeft)))) { - // IO::log() << v << ":"; + // std::cout << v << ":"; // for(auto vOut : asRange(adjacent_vertices(v, get_graph(rSecondLeft)))) - // IO::log() << " " << vOut; - // IO::log() << "\n"; + // std::cout << " " << vOut; + // std::cout << "\n"; // } - // IO::log() << std::endl; + // std::cout << std::endl; auto mp = makeRuleRuleComponentMonomorphism(lgDomPatterns, lgCodomHosts, enforceConstraints, labelSettings, - verbosity >= V_MorphismGen, logger); + verbosity >= V_MorphismGen, logger); auto mm = makeMultiDimSelector( get_num_connected_components(lgDomPatterns), get_num_connected_components(lgCodomHosts), mp); if(verbosity >= V_MorphismGen) { logger.indent() << "Super: " << "Match matrix, " - << mm.morphisms.size() << " x " << mm.morphisms.front().size() << std::endl; + << mm.morphisms.size() << " x " << mm.morphisms.front().size() << std::endl; ++logger.indentLevel; for(int i = 0; i != mm.morphisms.size(); ++i) { logger.indent(); @@ -98,12 +95,12 @@ struct Super { auto maybeMap = matchFromPosition(rFirst, rSecond, position); if(!maybeMap) { if(verbosity >= V_MorphismGen) - IO::log() << "Super: matchFromPosition returned none." << std::endl; + std::cout << "Super: matchFromPosition returned none." << std::endl; continue; } auto map = *std::move(maybeMap); bool continue_ = handleMapByLabelSettings(rFirst, rSecond, std::move(map), mr, labelSettings, - verbosity, logger); + verbosity, logger); if(!continue_) break; } } @@ -111,8 +108,8 @@ struct Super { public: template boost::optional matchFromPosition(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - const std::vector &position) const; + const lib::Rules::Real &rSecond, + const std::vector &position) const; private: const int verbosity; mutable IO::Logger logger; @@ -123,8 +120,8 @@ struct Super { template inline boost::optional Super::matchFromPosition(const lib::Rules::Real &rFirst, - const lib::Rules::Real &rSecond, - const std::vector &position) const { + const lib::Rules::Real &rSecond, + const std::vector &position) const { const auto &lgDom = get_labelled_left(rSecond.getDPORule()); const auto &gDom = get_graph(lgDom); const auto &gCodom = get_graph(get_labelled_right(rFirst.getDPORule())); @@ -143,16 +140,16 @@ Super::matchFromPosition(const lib::Rules::Real &rFirst, auto &&morphism = *position[pId].iterMorphism; assert(morphism.size() == num_vertices(gDomPattern)); // { - // IO::log() << "from:"; - // for(unsigned int i = 0; i < subMatch.size(); i++) IO::log() << "\t" << i; - // IO::log() << std::endl; - // IO::log() << "to: "; + // std::cout << "from:"; + // for(unsigned int i = 0; i < subMatch.size(); i++) std::cout << "\t" << i; + // std::cout << std::endl; + // std::cout << "to: "; // for(unsigned int i = 0; i < subMatch.size(); i++) { - // IO::log() << "\t"; - // if(subMatch[i] == boost::graph_traits::null_vertex()) IO::log() << "-"; - // else IO::log() << get(boost::vertex_index_t(), patterns[pattern], subMatch[i]); + // std::cout << "\t"; + // if(subMatch[i] == boost::graph_traits::null_vertex()) std::cout << "-"; + // else std::cout << get(boost::vertex_index_t(), patterns[pattern], subMatch[i]); // } - // IO::log() << std::endl; + // std::cout << std::endl; // } for(const auto vDomPattern : asRange(vertices(gDomPattern))) { assert(get(map, gDom, gCodom, vDomPattern) == vNullCodom); @@ -166,8 +163,6 @@ Super::matchFromPosition(const lib::Rules::Real &rFirst, return map; } -} // namespace RC -} // namespace lib -} // namespace mod +} // namespace mod::lib::RC -#endif /* MOD_LIB_RC_SUPER_H */ +#endif // MOD_LIB_RC_SUPER_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/RC/Visitor/MatchConstraints.hpp b/libs/libmod/src/mod/lib/RC/Visitor/MatchConstraints.hpp index 9e9d58b..1f85ee1 100644 --- a/libs/libmod/src/mod/lib/RC/Visitor/MatchConstraints.hpp +++ b/libs/libmod/src/mod/lib/RC/Visitor/MatchConstraints.hpp @@ -48,7 +48,7 @@ struct ConvertFirst : public ConstraintVisitor::null_vertex()); cResult->vConstrained = vResult; - // IO::log() << "WARNING: check transfered constraint for " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; + // std::cout << "WARNING: check transfered constraint for " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; this->cResult = std::move(cResult); } @@ -84,18 +84,18 @@ struct ConvertSecond : public ConstraintVisitor::null_vertex()) { - // IO::log() << "WARNING: constrained vertex " << vSecondId << " deleted in " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; + // std::cout << "WARNING: constrained vertex " << vSecondId << " deleted in " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; return; } auto mResult = membership(result.rResult, vResult); if(mResult == jla_boost::GraphDPO::Membership::Right) { - // IO::log() << "WARNING: constrained vertex " << vSecondId << " changed to right side in " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; + // std::cout << "WARNING: constrained vertex " << vSecondId << " changed to right side in " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; return; } if(get(match, get_graph(get_labelled_left(rSecond)), get_graph(get_labelled_right(rFirst)), vSecond) != boost::graph_traits::null_vertex()) { - // IO::log() << "WARNING: maybe missing constraint on " << vNew << " for " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; + // std::cout << "WARNING: maybe missing constraint on " << vNew << " for " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; return; } @@ -119,9 +119,9 @@ struct ConvertSecond : public ConstraintVisitorcResult = std::move(cResult); - // IO::log() << "WARNING: check converted constraint on vertex " << vNew << " for " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; + // std::cout << "WARNING: check converted constraint on vertex " << vNew << " for " << rFirst.getName() << " -> " << rSecond.getName() << std::endl; } -private: public: virtual void operator()(const ConstraintSP &c) override { diff --git a/libs/libmod/src/mod/lib/RC/Visitor/Stereo.hpp b/libs/libmod/src/mod/lib/RC/Visitor/Stereo.hpp index df705e3..d3d7c8c 100644 --- a/libs/libmod/src/mod/lib/RC/Visitor/Stereo.hpp +++ b/libs/libmod/src/mod/lib/RC/Visitor/Stereo.hpp @@ -85,7 +85,7 @@ struct Stereo { auto &data = vData[vResultId]; const auto &conf = *get_stereo(glSide)[vInput]; data.vGeometry = conf.getGeometryVertex(); - if(Verbose) IO::log() << "\tGeometry: " << getGeoName(data.vGeometry) << "\n"; + if(Verbose) std::cout << "\tGeometry: " << getGeoName(data.vGeometry) << "\n"; for(const auto &emb : conf) { switch(emb.type) { case lib::Stereo::EmbeddingEdge::Type::LonePair: @@ -101,7 +101,7 @@ struct Stereo { const auto eInput = emb.getEdge(vInput, get_graph(glSide)); const auto vAdjInput = target(eInput, gInput); if(Verbose) { - IO::log() << "\tmapping edge: (" + std::cout << "\tmapping edge: (" << get(boost::vertex_index_t(), gInput, vInput) << ", " << get(boost::vertex_index_t(), gInput, vAdjInput) << ")\n"; } @@ -109,7 +109,7 @@ struct Stereo { if(safe) assert(vAdjResult != NullVertex(gResult)); else if(vAdjResult == NullVertex(gResult)) { // the vertex is deleted, so let's skip it - if(Verbose) IO::log() << "\tdeleted\n"; + if(Verbose) std::cout << "\tdeleted\n"; partial = true; break; // the case statement } @@ -123,7 +123,7 @@ struct Stereo { return std::distance(oeResult.first, oeIter); }(); if(Verbose) { - IO::log() << "\tto edge: (" + std::cout << "\tto edge: (" << get(boost::vertex_index_t(), gResult, vResult) << ", " << get(boost::vertex_index_t(), gResult, vAdjResult) << "), offset = " << eResultOffset << " (of " << out_degree(vResult, gResultSide) << ")\n"; @@ -139,10 +139,10 @@ struct Stereo { if(partial) { // let it remain free MOD_ABORT; // TODO assert(data.fix == lib::Stereo::Fixation::free()); - if(Verbose) IO::log() << "\tfix: remain free (" << data.fix << ")\n"; + if(Verbose) std::cout << "\tfix: remain free (" << data.fix << ")\n"; } else { // copy from conf data.fix = conf.getFixation(); - if(Verbose) IO::log() << "\tfix: copy (" << data.fix << ")\n"; + if(Verbose) std::cout << "\tfix: copy (" << data.fix << ")\n"; } return partial; }; @@ -152,14 +152,14 @@ struct Stereo { const auto m = membership(result.rResult, vResult); if(m != Membership::Right) { // copy left - if(Verbose) IO::log() << "\tLeft:\n"; + if(Verbose) std::cout << "\tLeft:\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_left(rInput), vInput, gInput, mInputToResult, vResult, get_left(result.rResult), vDataLeft, eDataLeft); (void) partial; assert(!partial); } if(m != Membership::Left) { // copy right - if(Verbose) IO::log() << "\tRight:\n"; + if(Verbose) std::cout << "\tRight:\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_right(rInput), vInput, gInput, mInputToResult, vResult, get_right(result.rResult), vDataRight, eDataRight); (void) partial; assert(!partial); @@ -223,36 +223,36 @@ struct Stereo { const auto &confL1 = *get_stereo(get_labelled_left(rFirst))[vFirst]; const auto geoL1 = confL1.getGeometryVertex(); if(Verbose) - IO::log() << "\tHandling L\n" + std::cout << "\tHandling L\n" << "\t\tGeo L1: " << getGeoName(geoL1) << "\n" << "\t\tGeo R1: " << getGeoName(geoR1) << "\n" << "\t\tGeo L2: " << getGeoName(geoL2) << "\n"; if(firstInContext) { - if(Verbose) IO::log() << "\t\tFirst stereo in context\n"; + if(Verbose) std::cout << "\t\tFirst stereo in context\n"; if(secondToFirstSubgraph) { - if(Verbose) IO::log() << "\t\tSecond-to-first subgraph: copy and map L1/R1 to L\n"; + if(Verbose) std::cout << "\t\tSecond-to-first subgraph: copy and map L1/R1 to L\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_left(rFirst), vFirst, gFirst, result.mFirstToResult, vResult, get_left(result.rResult), vDataLeft, eDataLeft); (void) partial; assert(!partial); } else if(firstToSecondSubgraph) { - if(Verbose) IO::log() << "\t\tFirst-to-second subgraph: copy and map L2 to L\n"; + if(Verbose) std::cout << "\t\tFirst-to-second subgraph: copy and map L2 to L\n"; MOD_ABORT; } else { - if(Verbose) IO::log() << "\t\tNon-subgraph: do a merge\n"; + if(Verbose) std::cout << "\t\tNon-subgraph: do a merge\n"; MOD_ABORT; } } else { // !firstInContext - if(Verbose) IO::log() << "\t\tFirst stereo changes\n"; + if(Verbose) std::cout << "\t\tFirst stereo changes\n"; if(secondToFirstSubgraph) { - if(Verbose) IO::log() << "\t\tSecond-to-first subgraph: copy and map L1 to L\n"; + if(Verbose) std::cout << "\t\tSecond-to-first subgraph: copy and map L1 to L\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_left(rFirst), vFirst, gFirst, result.mFirstToResult, vResult, get_left(result.rResult), vDataLeft, eDataLeft); (void) partial; assert(!partial); } else if(firstToSecondSubgraph) { - if(Verbose) IO::log() << "\t\tFirst-to-second subgraph: hmm\n"; + if(Verbose) std::cout << "\t\tFirst-to-second subgraph: hmm\n"; MOD_ABORT; } else { - if(Verbose) IO::log() << "\t\tNon-subgraph: do a merge\n"; + if(Verbose) std::cout << "\t\tNon-subgraph: do a merge\n"; MOD_ABORT; } } @@ -265,41 +265,41 @@ struct Stereo { const auto &confR2 = *get_stereo(get_labelled_right(rSecond))[vSecond]; const auto geoR2 = confR2.getGeometryVertex(); if(Verbose) - IO::log() << "\tHandling R\n" + std::cout << "\tHandling R\n" << "\t\tGeo R1: " << getGeoName(geoR1) << "\n" << "\t\tGeo L2: " << getGeoName(geoL2) << "\n" << "\t\tGeo R2: " << getGeoName(geoR2) << "\n"; if(secondInContext) { - if(Verbose) IO::log() << "\t\tSecond stereo in context\n"; + if(Verbose) std::cout << "\t\tSecond stereo in context\n"; if(firstToSecondSubgraph) { - if(Verbose) IO::log() << "\t\tFirst-to-second subgraph: copy and map L2/R2 to R\n"; + if(Verbose) std::cout << "\t\tFirst-to-second subgraph: copy and map L2/R2 to R\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_right(rSecond), vSecond, gSecond, result.mSecondToResult, vResult, get_right(result.rResult), vDataRight, eDataRight); (void) partial; assert(!partial); } else if(secondToFirstSubgraph) { - if(Verbose) IO::log() << "\t\tSecond-to-first subgraph: copy and map R1 to R\n"; + if(Verbose) std::cout << "\t\tSecond-to-first subgraph: copy and map R1 to R\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_right(rFirst), vFirst, gFirst, result.mFirstToResult, vResult, get_right(result.rResult), vDataRight, eDataRight); (void) partial; assert(!partial); } else { - if(Verbose) IO::log() << "\t\tNon-subgraph: do a merge\n"; + if(Verbose) std::cout << "\t\tNon-subgraph: do a merge\n"; MOD_ABORT; } } else { // !secondInContext - if(Verbose) IO::log() << "\t\tSecond stereo changes\n"; + if(Verbose) std::cout << "\t\tSecond stereo changes\n"; if(firstToSecondSubgraph) { - if(Verbose) IO::log() << "\t\tFirst-to-second subgraph: copy and map R2 to R\n"; + if(Verbose) std::cout << "\t\tFirst-to-second subgraph: copy and map R2 to R\n"; const bool partial = copyAllFromSide(std::true_type(), get_labelled_right(rSecond), vSecond, gSecond, result.mSecondToResult, vResult, get_right(result.rResult), vDataRight, eDataRight); (void) partial; assert(!partial); } else if(secondToFirstSubgraph) { if(Verbose) { - IO::log() << "\t\tSecond-to-first subgraph:\n" + std::cout << "\t\tSecond-to-first subgraph:\n" << "\t\t\t- Copy all from R2.\n" << "\t\t\t- Copy unmatched from R1.\n" << "\t\t\t- Match R2 stereo onto the result and check if the pushout is valid.\n" ; - IO::log() << "\tCopying all from R2\n"; + std::cout << "\tCopying all from R2\n"; } const bool partial = copyAllFromSide(std::true_type(), get_labelled_right(rSecond), vSecond, gSecond, result.mSecondToResult, vResult, get_right(result.rResult), vDataRight, eDataRight); (void) partial; @@ -307,7 +307,7 @@ struct Stereo { const auto sizeAfterR2 = data.edges.size(); (void) sizeAfterR2; { // copy unmatched from R1 - if(Verbose) IO::log() << "\tCopying unmatched from R1\n"; + if(Verbose) std::cout << "\tCopying unmatched from R1\n"; const auto vInput = vFirst; const auto &gBaseInput = get_graph(rFirst); const auto &glSide = get_labelled_right(rFirst); @@ -332,14 +332,14 @@ struct Stereo { const auto eInput = emb.getEdge(vInput, gInput); const auto vAdjInput = target(eInput, gInput); if(Verbose) { - IO::log() << "\tmapping edge: (" + std::cout << "\tmapping edge: (" << get(boost::vertex_index_t(), gInput, vInput) << ", " << get(boost::vertex_index_t(), gInput, vAdjInput) << ")\n"; } const auto vAdjResult = get(mInputToResult, gBaseInput, gResult, vAdjInput); if(vAdjResult == NullVertex(gResult)) { // the vertex is deleted, so let's skip it - if(Verbose) IO::log() << "\tdeleted\n"; + if(Verbose) std::cout << "\tdeleted\n"; break; // the case statement } // is it mapped? @@ -347,35 +347,35 @@ struct Stereo { const auto vAdjInputOther = mapToOtherInput(vAdjInput); const bool isMatched = [&]() { if(vInputOther == NullVertex(gInput)) { - if(Verbose) IO::log() << "\tnot matched, due to vInputOther = null\n"; + if(Verbose) std::cout << "\tnot matched, due to vInputOther = null\n"; return false; } if(vAdjInputOther == NullVertex(gInput)) { - if(Verbose) IO::log() << "\tnot matched, due to vAdjInputOther = null\n"; + if(Verbose) std::cout << "\tnot matched, due to vAdjInputOther = null\n"; return false; } for(auto eInputOther : asRange(out_edges(vInputOther, gInputOther))) { if(target(eInputOther, gInputOther) != vAdjInputOther) { if(Verbose) { - IO::log() << "\tcand = (" + std::cout << "\tcand = (" << get(boost::vertex_index_t(), gInputOther, vInputOther) << ", " << get(boost::vertex_index_t(), gInputOther, vAdjInputOther) << ") not it\n"; } continue; } if(Verbose) { - IO::log() << "\tcand = (" + std::cout << "\tcand = (" << get(boost::vertex_index_t(), gInputOther, vInputOther) << ", " << get(boost::vertex_index_t(), gInputOther, vAdjInputOther) << ") is it\n"; } // TODO: shouldn't we check the membership as well? return true; } - if(Verbose) IO::log() << "\tnot matched, due to no edge found\n"; + if(Verbose) std::cout << "\tnot matched, due to no edge found\n"; return false; }(); if(isMatched) { - if(Verbose) IO::log() << "\tmatched\n"; + if(Verbose) std::cout << "\tmatched\n"; break; } @@ -389,7 +389,7 @@ struct Stereo { return std::distance(oeResult.first, oeIter); }(); if(Verbose) { - IO::log() << "\tto edge: (" + std::cout << "\tto edge: (" << get(boost::vertex_index_t(), gResult, vResult) << ", " << get(boost::vertex_index_t(), gResult, vAdjResult) << "), offset = " << eResultOffset << " (of " << out_degree(vResult, gResultSide) << ")\n"; @@ -408,7 +408,7 @@ struct Stereo { MOD_ABORT; // bah, we need to do something, or reject the pushout } } else { - if(Verbose) IO::log() << "\t\tNon-subgraph: do a merge\n"; + if(Verbose) std::cout << "\t\tNon-subgraph: do a merge\n"; MOD_ABORT; } } @@ -418,18 +418,18 @@ struct Stereo { if(data.edges.size() > prevEmbSize) { // we the fixation must be free - if(Verbose) IO::log() << "\tfix: data.edges.size() = " << data.edges.size() << " > " << prevEmbSize << " = prevEmbSize, so set free (was " << data.fix << ")\n"; + if(Verbose) std::cout << "\tfix: data.edges.size() = " << data.edges.size() << " > " << prevEmbSize << " = prevEmbSize, so set free (was " << data.fix << ")\n"; data.fix = lib::Stereo::Fixation::free(); } else { - if(Verbose) IO::log() << "\tfix: not changing it (" << data.fix << ")\n"; + if(Verbose) std::cout << "\tfix: not changing it (" << data.fix << ")\n"; } } // if false, old code } // if vResult in R }; // handleBoth() - if(Verbose) IO::log() << "Stereo Finalization\n" << std::string(80, '-') << '\n'; + if(Verbose) std::cout << "Stereo Finalization\n" << std::string(80, '-') << '\n'; const auto &gGeometry = lib::Stereo::getGeometryGraph().getGraph(); for(auto vResult : asRange(vertices(gResult))) { - if(Verbose) IO::log() << "Result vertex: " << get(boost::vertex_index_t(), gResult, vResult) << "\n"; + if(Verbose) std::cout << "Result vertex: " << get(boost::vertex_index_t(), gResult, vResult) << "\n"; const auto m = membership(result.rResult, vResult); const auto vResultId = get(boost::vertex_index_t(), gResult, vResult); // If vResult is in only first or only second, we should be able to just copy the embedding. @@ -438,15 +438,15 @@ struct Stereo { assert(vFirst != NullVertex() || vSecond != NullVertex()); std::stringstream ssErr; const auto instantiateConfs = [&]() { - if(Verbose) IO::log() << "\tinstantiating configurations\n"; + if(Verbose) std::cout << "\tinstantiating configurations\n"; // TODO: we should probably correct LonePair and Radical offsets here if(m != Membership::Right) { auto &data = vDataLeft[vResultId]; data.configuration = gGeometry[data.vGeometry].constructor( data.edges.data(), data.edges.data() + data.edges.size(), data.fix, ssErr); if(!data.configuration) { - IO::log() << "Error in configuration construction in L.\n"; - IO::log() << ssErr.str(); + std::cout << "Error in configuration construction in L.\n"; + std::cout << ssErr.str(); MOD_ABORT; } } @@ -455,22 +455,22 @@ struct Stereo { data.configuration = gGeometry[data.vGeometry].constructor( data.edges.data(), data.edges.data() + data.edges.size(), data.fix, ssErr); if(!data.configuration) { - IO::log() << "Error in configuration construction in R.\n"; - IO::log() << ssErr.str(); + std::cout << "Error in configuration construction in R.\n"; + std::cout << ssErr.str(); MOD_ABORT; } } }; if(vFirst == NullVertex()) { - if(Verbose) IO::log() << "\tnot in First, copy only from Second\n"; + if(Verbose) std::cout << "\tnot in First, copy only from Second\n"; handleOnly(vResult, vSecond, rSecond, result.mSecondToResult); instantiateConfs(); } else if(vSecond == NullVertex()) { - if(Verbose) IO::log() << "\tnot in Second, copy only from First\n"; + if(Verbose) std::cout << "\tnot in Second, copy only from First\n"; handleOnly(vResult, vFirst, rFirst, result.mFirstToResult); instantiateConfs(); } else { - if(Verbose) IO::log() << "\tin both\n"; + if(Verbose) std::cout << "\tin both\n"; handleBoth(vResult, vFirst, vSecond); instantiateConfs(); } diff --git a/libs/libmod/src/mod/lib/RC/Visitor/Term.hpp b/libs/libmod/src/mod/lib/RC/Visitor/Term.hpp index 9990b30..39392cb 100644 --- a/libs/libmod/src/mod/lib/RC/Visitor/Term.hpp +++ b/libs/libmod/src/mod/lib/RC/Visitor/Term.hpp @@ -29,8 +29,8 @@ struct Term { machine.verify(); result.rResult.pTerm = std::make_unique (get_graph(result.rResult), std::move(machine)); if(Verbose) { - lib::IO::log() << "New machine:\n"; - lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), lib::IO::log()); + std::cout << "New machine:\n"; + lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), std::cout); } return true; } @@ -63,8 +63,8 @@ struct Term { break; } if(Verbose) { - lib::IO::log() << "Cur machine:\n"; - lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), lib::IO::log()); + std::cout << "Cur machine:\n"; + lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), std::cout); } } @@ -91,8 +91,8 @@ struct Term { break; } if(Verbose) { - lib::IO::log() << "Cur machine:\n"; - lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), lib::IO::log()); + std::cout << "Cur machine:\n"; + lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), std::cout); } } @@ -117,8 +117,8 @@ struct Term { break; } if(Verbose) { - lib::IO::log() << "Cur machine:\n"; - lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), lib::IO::log()); + std::cout << "Cur machine:\n"; + lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), std::cout); } } @@ -145,8 +145,8 @@ struct Term { break; } if(Verbose) { - lib::IO::log() << "Cur machine:\n"; - lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), lib::IO::log()); + std::cout << "Cur machine:\n"; + lib::IO::Term::Write::wam(getMachine(*result.rResult.pTerm), lib::Term::getStrings(), std::cout); } } public: @@ -236,10 +236,10 @@ struct Term { auto &m = getMachine(*result.rResult.pTerm); m.verify(); if(Verbose) - lib::IO::Term::Write::wam(m, lib::Term::getStrings(), lib::IO::log() << "Copy " << addr << "\n"); + lib::IO::Term::Write::wam(m, lib::Term::getStrings(), std::cout << "Copy " << addr << "\n"); m.copyFromTemp(addr); if(Verbose) - lib::IO::Term::Write::wam(m, lib::Term::getStrings(), lib::IO::log() << "After copy " << addr << "\n"); + lib::IO::Term::Write::wam(m, lib::Term::getStrings(), std::cout << "After copy " << addr << "\n"); m.verify(); } diff --git a/libs/libmod/src/mod/lib/RC/detail/CompositionHelper.hpp b/libs/libmod/src/mod/lib/RC/detail/CompositionHelper.hpp index 27a94c0..beed57e 100644 --- a/libs/libmod/src/mod/lib/RC/detail/CompositionHelper.hpp +++ b/libs/libmod/src/mod/lib/RC/detail/CompositionHelper.hpp @@ -35,11 +35,11 @@ struct CompositionHelper { : rFirst(rFirst), rSecond(rSecond), match(match), visitor(std::move(visitor)) {} boost::optional operator()() &&{ - if(Verbose) IO::log() << std::string(80, '=') << std::endl; + if(Verbose) std::cout << std::string(80, '=') << std::endl; Result result(rFirst, rSecond); bool resInit = visitor.template init(rFirst, rSecond, match, result); if(!resInit) { - if(Verbose) IO::log() << std::string(80, '=') << std::endl; + if(Verbose) std::cout << std::string(80, '=') << std::endl; return boost::none; } // Vertices @@ -50,12 +50,12 @@ struct CompositionHelper { //-------------------------------------------------------------------------- bool resFirst = copyEdgesFirstUnmatched(result); if(!resFirst) { - if(Verbose) IO::log() << std::string(80, '=') << std::endl; + if(Verbose) std::cout << std::string(80, '=') << std::endl; return boost::none; } bool resSecond = composeEdgesSecond(result); if(!resSecond) { - if(Verbose) IO::log() << std::string(80, '=') << std::endl; + if(Verbose) std::cout << std::string(80, '=') << std::endl; return boost::none; } @@ -63,10 +63,10 @@ struct CompositionHelper { //-------------------------------------------------------------------------- bool resFinal = visitor.template finalize(rFirst, rSecond, match, result); if(!resFinal) { - if(Verbose) IO::log() << std::string(80, '=') << std::endl; + if(Verbose) std::cout << std::string(80, '=') << std::endl; return boost::none; } - if(Verbose) IO::log() << std::string(80, '=') << std::endl; + if(Verbose) std::cout << std::string(80, '=') << std::endl; return boost::optional(std::move(result)); // something strange is going on with just "return result;" } @@ -101,19 +101,19 @@ struct CompositionHelper { private: void copyVerticesFirst(Result &result) { - if(Verbose) IO::log() << "copyVerticesFirst\n" << std::string(80, '-') << std::endl; + if(Verbose) std::cout << "copyVerticesFirst\n" << std::string(80, '-') << std::endl; auto &rResult = result.rResult; auto &gResult = get_graph(rResult); const auto &gFirst = get_graph(rFirst); const auto &gSecond = get_graph(rSecond); for(const auto vFirst : asRange(vertices(gFirst))) { if(Verbose) { - IO::log() << "rFirst node:\t" + std::cout << "rFirst node:\t" << get(boost::vertex_index_t(), gFirst, vFirst) << "(" << membership(rFirst, vFirst) << ")" << "("; - visitor.template printVertexFirst(rFirst, rSecond, match, result, IO::log(), vFirst); - IO::log() << ")" << std::endl; + visitor.template printVertexFirst(rFirst, rSecond, match, result, std::cout, vFirst); + std::cout << ")" << std::endl; } const bool getsDeleted = [&]() { // must be only in R to be deleted @@ -126,7 +126,7 @@ struct CompositionHelper { }(); if(getsDeleted) { put(result.mFirstToResult, gFirst, gResult, vFirst, getNullResult()); - if(Verbose) IO::log() << "gets deleted" << std::endl; + if(Verbose) std::cout << "gets deleted" << std::endl; } else { const auto vResult = add_vertex(gResult); result.mFirstToResult.resizeRight(gFirst, gResult); @@ -135,18 +135,18 @@ struct CompositionHelper { put_membership(rResult, vResult, membership(rFirst, vFirst)); visitor.template copyVertexFirst(rFirst, rSecond, match, result, vFirst, vResult); if(Verbose) { - IO::log() << "new node:\t" + std::cout << "new node:\t" << get(boost::vertex_index_t(), gResult, vResult) << "(" << membership(rResult, vResult) << ")("; - visitor.template printVertexResult(rFirst, rSecond, match, result, IO::log(), vResult); - IO::log() << ")" << std::endl; + visitor.template printVertexResult(rFirst, rSecond, match, result, std::cout, vResult); + std::cout << ")" << std::endl; } } } } void composeVerticesSecond(Result &result) { - if(Verbose) IO::log() << "composeVerticesSecond\n" << std::string(80, '-') << std::endl; + if(Verbose) std::cout << "composeVerticesSecond\n" << std::string(80, '-') << std::endl; const auto &gFirst = get_graph(rFirst); const auto &gSecond = get_graph(rSecond); auto &rResult = result.rResult; @@ -154,12 +154,12 @@ struct CompositionHelper { // copy nodes from second, but compose the matched ones which has already been created for(const auto vSecond : asRange(vertices(gSecond))) { if(Verbose) { - IO::log() << "rSecond node:\t" + std::cout << "rSecond node:\t" << get(boost::vertex_index_t(), gSecond, vSecond) << "(" << membership(rSecond, vSecond) << ")" << "("; - visitor.template printVertexSecond(rFirst, rSecond, match, result, IO::log(), vSecond); - IO::log() << ")" << std::endl; + visitor.template printVertexSecond(rFirst, rSecond, match, result, std::cout, vSecond); + std::cout << ")" << std::endl; } // check if the vertex is matched const auto vFirst = getVertexFirstChecked(vSecond); @@ -172,24 +172,24 @@ struct CompositionHelper { put_membership(rResult, vResult, membership(rSecond, vSecond)); visitor.template copyVertexSecond(rFirst, rSecond, match, result, vSecond, vResult); if(Verbose) { - IO::log() << "new node:\t" << get(boost::vertex_index_t(), gResult, vResult) + std::cout << "new node:\t" << get(boost::vertex_index_t(), gResult, vResult) << "(" << membership(rResult, vResult) << ")" << "("; - visitor.template printVertexResult(rFirst, rSecond, match, result, IO::log(), vResult); - IO::log() << ")" << std::endl; + visitor.template printVertexResult(rFirst, rSecond, match, result, std::cout, vResult); + std::cout << ")" << std::endl; } } else { // vertex matched const auto vResult = get(result.mFirstToResult, gFirst, gResult, vFirst); put(result.mSecondToResult, gSecond, gResult, vSecond, vResult); if(vResult == getNullResult()) { - if(Verbose) IO::log() << "deleted" << std::endl; + if(Verbose) std::cout << "deleted" << std::endl; } else { if(Verbose) { - IO::log() << "match to:\t" << get(boost::vertex_index_t(), gResult, vResult) + std::cout << "match to:\t" << get(boost::vertex_index_t(), gResult, vResult) << "(" << membership(rResult, vResult) << ")" << "("; - visitor.template printVertexResult(rFirst, rSecond, match, result, IO::log(), vResult); - IO::log() << ")" << std::endl; + visitor.template printVertexResult(rFirst, rSecond, match, result, std::cout, vResult); + std::cout << ")" << std::endl; } // now we calculate the new membership for the node const auto mFirst = membership(rResult, vResult); // should be a copy of the one from rFirst @@ -224,7 +224,7 @@ struct CompositionHelper { } bool copyEdgesFirstUnmatched(Result &result) { - if(Verbose) IO::log() << "copyEdgesFirstUnmatched\n" << std::string(80, '-') << std::endl; + if(Verbose) std::cout << "copyEdgesFirstUnmatched\n" << std::string(80, '-') << std::endl; const auto &gFirst = get_graph(rFirst); const auto &gSecond = get_graph(rSecond); auto &rResult = result.rResult; @@ -238,12 +238,12 @@ struct CompositionHelper { const auto vSrcResult = get(result.mFirstToResult, gFirst, gResult, vSrcFirst); const auto vTarResult = get(result.mFirstToResult, gFirst, gResult, vTarFirst); // vSrcResult/vTarResult may be null_vertex - IO::log() << "Edge first:\t(" << vSrcFirst << ", " << vTarFirst << ") maybe copy to new (" << vSrcResult + std::cout << "Edge first:\t(" << vSrcFirst << ", " << vTarFirst << ") maybe copy to new (" << vSrcResult << ", " << vTarResult << ")" << "(" << meFirst << ")" << "("; - visitor.template printEdgeFirst(rFirst, rSecond, match, result, IO::log(), eFirst); - IO::log() << ")" << std::endl; + visitor.template printEdgeFirst(rFirst, rSecond, match, result, std::cout, eFirst); + std::cout << ")" << std::endl; } const auto makeCopy = [&]() { const auto vSrcResult = get(result.mFirstToResult, gFirst, gResult, vSrcFirst); @@ -251,7 +251,7 @@ struct CompositionHelper { // vResultSrc/vResultTar should be valid at this point assert(vSrcResult != getNullResult()); assert(vTarResult != getNullResult()); - if(Verbose) IO::log() << "\tCopy eFirst" << std::endl; + if(Verbose) std::cout << "\tCopy eFirst" << std::endl; const auto peResult = add_edge(vSrcResult, vTarResult, gResult); // adding shouldn't fail assert(peResult.second); @@ -265,17 +265,17 @@ struct CompositionHelper { }; // and now the actual case analysis if(meFirst == Membership::Left) { - if(Verbose) IO::log() << "\teFirst in LEFT, clean copy" << std::endl; + if(Verbose) std::cout << "\teFirst in LEFT, clean copy" << std::endl; makeCopy(); return true; } - if(Verbose) IO::log() << "\teFirst in RIGHT or CONTEXT" << std::endl; + if(Verbose) std::cout << "\teFirst in RIGHT or CONTEXT" << std::endl; const auto vSrcSecond = getVertexSecond(vSrcFirst); const auto vTarSecond = getVertexSecond(vTarFirst); const bool isSrcMatched = vSrcSecond != getNullSecond(); const bool isTarMatched = vTarSecond != getNullSecond(); if(isSrcMatched && isTarMatched) { - if(Verbose) IO::log() << "\tBoth ends matched" << std::endl; + if(Verbose) std::cout << "\tBoth ends matched" << std::endl; const auto oeSecond = out_edges(vSrcSecond, gSecond); const auto eSecondIter = std::find_if(oeSecond.first, oeSecond.second, [&gSecond, vTarSecond, this](const auto &eSecond) { @@ -288,12 +288,12 @@ struct CompositionHelper { if(isEdgeMatched) { const auto eSecond = *eSecondIter; if(meFirst == Membership::Right) { - if(Verbose) IO::log() << "\teFirst matched and in RIGHT, skipping" << std::endl; + if(Verbose) std::cout << "\teFirst matched and in RIGHT, skipping" << std::endl; return true; } if(Verbose) - IO::log() << "\teFirst matched and in CONTEXT, copying to LEFT or CONTEXT (depending on eSecond (" + std::cout << "\teFirst matched and in CONTEXT, copying to LEFT or CONTEXT (depending on eSecond (" << membership(rSecond, eSecond) << "))" << std::endl; const auto vSrcResult = get(result.mFirstToResult, gFirst, gResult, vSrcFirst); const auto vTarResult = get(result.mFirstToResult, gFirst, gResult, vTarFirst); @@ -318,7 +318,7 @@ struct CompositionHelper { // vSrcResult/vTarResult may be null_vertex const bool endPointDeleted = vSrcResult == getNullResult() || vTarResult == getNullResult(); if(endPointDeleted) { - if(Verbose) IO::log() << "\tComposition failure: at least one matched vertex deleted" << std::endl; + if(Verbose) std::cout << "\tComposition failure: at least one matched vertex deleted" << std::endl; return false; } @@ -327,43 +327,43 @@ struct CompositionHelper { const auto mvTarResult = membership(rResult, vTarResult); if(mvSrcResult == Membership::Left || mvTarResult == Membership::Left) { if(Verbose) - IO::log() << "\tComposition failure: at least one matched vertex has inconsistent context (" + std::cout << "\tComposition failure: at least one matched vertex has inconsistent context (" << mvSrcResult << " and " << mvTarResult << "), eFirst is (" << meFirst << ")" << std::endl; return false; } - if(Verbose) IO::log() << "\teFirst not matched and not dangling" << std::endl; + if(Verbose) std::cout << "\teFirst not matched and not dangling" << std::endl; makeCopy(); return true; } // at most 1 end matched if(isSrcMatched != isTarMatched) { - if(Verbose) IO::log() << "\tOne end matched" << std::endl; + if(Verbose) std::cout << "\tOne end matched" << std::endl; const auto vSrcResult = get(result.mFirstToResult, gFirst, gResult, vSrcFirst); const auto vTarResult = get(result.mFirstToResult, gFirst, gResult, vTarFirst); // vResultSrc/vResultTar may be null_vertex const auto vResultMatched = isSrcMatched ? vSrcResult : vTarResult; const bool matchedDeleted = vResultMatched == boost::graph_traits::null_vertex(); if(matchedDeleted) { - if(Verbose) IO::log() << "\tComposition failure: matched vertex deleted" << std::endl; + if(Verbose) std::cout << "\tComposition failure: matched vertex deleted" << std::endl; return false; } // matched, but is it consistent? const auto mvMatchedResult = membership(rResult, vResultMatched); if(mvMatchedResult == Membership::Left) { if(Verbose) - IO::log() << "\tComposition failure: matched vertex has inconsistent context (" + std::cout << "\tComposition failure: matched vertex has inconsistent context (" << mvMatchedResult << "), eFirst is (" << meFirst << ")" << std::endl; return false; } - if(Verbose) IO::log() << "\teFirst not matched and not dangling" << std::endl; + if(Verbose) std::cout << "\teFirst not matched and not dangling" << std::endl; makeCopy(); return true; } - if(Verbose) IO::log() << "\tNo ends matched" << std::endl; + if(Verbose) std::cout << "\tNo ends matched" << std::endl; makeCopy(); return true; }; @@ -375,7 +375,7 @@ struct CompositionHelper { } bool composeEdgesSecond(Result &result) { - if(Verbose) IO::log() << "composeEdgesSecond\n" << std::string(80, '-') << std::endl; + if(Verbose) std::cout << "composeEdgesSecond\n" << std::string(80, '-') << std::endl; // const auto &gFirst = get_graph(rFirst); const auto &gSecond = get_graph(rSecond); auto &rResult = result.rResult; @@ -387,12 +387,12 @@ struct CompositionHelper { auto vResultTar = get(result.mSecondToResult, gSecond, gResult, vSecondTar); if(Verbose) { // vSrcNew/vTarNew may be null_vertex - IO::log() << "Edge second:\t(" << vSecondSrc << ", " << vSecondTar << ")\tmapped to (" << vResultSrc << ", " + std::cout << "Edge second:\t(" << vSecondSrc << ", " << vSecondTar << ")\tmapped to (" << vResultSrc << ", " << vResultTar << ")" << ", (" << membership(rSecond, eSecond) << ")" << "("; - visitor.template printEdgeSecond(rFirst, rSecond, match, result, IO::log(), eSecond); - IO::log() << ")" << std::endl; + visitor.template printEdgeSecond(rFirst, rSecond, match, result, std::cout, eSecond); + std::cout << ")" << std::endl; } // vResultSrc/vResultTar may be null_vertex // check for match on vFirstSrc and vFirstTar @@ -402,7 +402,7 @@ struct CompositionHelper { bool isTarMatched = vFirstTar != boost::graph_traits::null_vertex(); if(!isSrcMatched || !isTarMatched) { // new edge if(!isSrcMatched && !isTarMatched) { - if(Verbose) IO::log() << "No ends matched. Copy eSecond." << std::endl; + if(Verbose) std::cout << "No ends matched. Copy eSecond." << std::endl; // vResultSrc/vResultTar can not be null_vertex assert(vResultSrc != boost::graph_traits::null_vertex()); assert(vResultTar != boost::graph_traits::null_vertex()); @@ -438,7 +438,7 @@ struct CompositionHelper { bool isTarMatched) { auto &rResult = result.rResult; auto &gResult = get_graph(rResult); - if(Verbose) IO::log() << "One end matched, eSecond should be copied" << std::endl; + if(Verbose) std::cout << "One end matched, eSecond should be copied" << std::endl; assert(isSrcMatched ^ isTarMatched); // at most one of vResultSrc and vResultTar may be null_vertex assert(vResultSrc != boost::graph_traits::null_vertex() @@ -453,19 +453,19 @@ struct CompositionHelper { assert(mvResultOther == Membership::Context || mvResultOther == meSecond); if(vResultMatched == boost::graph_traits::null_vertex()) { - if(Verbose) IO::log() << "\tComposition failure: matched vertex deleted" << std::endl; + if(Verbose) std::cout << "\tComposition failure: matched vertex deleted" << std::endl; return false; } auto mvResultMatched = membership(rResult, vResultMatched); if(mvResultMatched != Membership::Context && mvResultMatched != meSecond) { if(Verbose) - IO::log() << "\tComposition failure: matched vertex has inconsistent context (" + std::cout << "\tComposition failure: matched vertex has inconsistent context (" << mvResultMatched << "), eSecond is (" << meSecond << ")" << std::endl; return false; } - if(Verbose) IO::log() << "\tCopy edge" << std::endl; + if(Verbose) std::cout << "\tCopy edge" << std::endl; auto peResult = add_edge(vResultSrc, vResultTar, gResult); // adding shouldn't fail assert(peResult.second); @@ -484,7 +484,7 @@ struct CompositionHelper { const auto &gFirst = get_graph(rFirst); auto &rResult = result.rResult; auto &gResult = get_graph(rResult); - if(Verbose) IO::log() << "Both ends matched" << std::endl; + if(Verbose) std::cout << "Both ends matched" << std::endl; // vResultSrc/vResultTar may be null_vertex boost::optional omeFirst; // we search in coreFirst, because it has the matched edges @@ -513,24 +513,24 @@ struct CompositionHelper { // -> vs. | -> // -> vs. -> | // -> vs. | -> | - if(Verbose) IO::log() << "\tSimple copy of eSecond" << std::endl; + if(Verbose) std::cout << "\tSimple copy of eSecond" << std::endl; if(meSecond == Membership::Left) { - if(Verbose) IO::log() << "\t\teSecond in LEFT, check ends" << std::endl; + if(Verbose) std::cout << "\t\teSecond in LEFT, check ends" << std::endl; // vResultSrc/vResultTar may be null_vertex if(vResultSrc == boost::graph_traits::null_vertex()) { - if(Verbose) IO::log() << "\tComposition failure: vResultSrc deleted" << std::endl; + if(Verbose) std::cout << "\tComposition failure: vResultSrc deleted" << std::endl; return false; } if(vResultTar == boost::graph_traits::null_vertex()) { - if(Verbose) IO::log() << "\tComposition failure: vResultTar deleted" << std::endl; + if(Verbose) std::cout << "\tComposition failure: vResultTar deleted" << std::endl; return false; } if(membership(rResult, vResultSrc) == Membership::Right) { - if(Verbose) IO::log() << "\tComposition failure: vResultSrc not in LEFT or CONTEXT" << std::endl; + if(Verbose) std::cout << "\tComposition failure: vResultSrc not in LEFT or CONTEXT" << std::endl; return false; } if(membership(rResult, vResultTar) == Membership::Right) { - if(Verbose) IO::log() << "\tComposition failure: vResultTar not in LEFT or CONTEXT" << std::endl; + if(Verbose) std::cout << "\tComposition failure: vResultTar not in LEFT or CONTEXT" << std::endl; return false; } } @@ -553,7 +553,7 @@ struct CompositionHelper { // creating parallel in left // | -> vs. | -> // | -> vs. | -> | - if(Verbose) IO::log() << "\tComposition failure: duplicate edge in L" << std::endl; + if(Verbose) std::cout << "\tComposition failure: duplicate edge in L" << std::endl; return false; } if(meFirst != Membership::Left && meSecond == Membership::Right) { @@ -561,7 +561,7 @@ struct CompositionHelper { // -> | vs. -> | // | -> | vs. -> | if(Verbose) - IO::log() << "\tComposition failure: eSecond in RIGHT, eFirst in CONTEXT or RIGHT, i.e., parallel edge in R" + std::cout << "\tComposition failure: eSecond in RIGHT, eFirst in CONTEXT or RIGHT, i.e., parallel edge in R" << std::endl; return false; } @@ -576,7 +576,7 @@ struct CompositionHelper { // -> | vs. | -> first not in result // | -> | vs. | -> first in result as LEFT if(Verbose) - IO::log() << "\teSecond matched in (" << meSecond << ")" + std::cout << "\teSecond matched in (" << meSecond << ")" << ", either in LEFT or both eSecond and eFirst in CONTEXT" << std::endl; return true; } @@ -591,7 +591,7 @@ struct CompositionHelper { // copy eSecond as RIGHT to result assert(meSecond == Membership::Context); // -> | vs. | -> | - if(Verbose) IO::log() << "\t -> | vs. | -> |, copy to RIGHT" << std::endl; + if(Verbose) std::cout << "\t -> | vs. | -> |, copy to RIGHT" << std::endl; auto peResult = add_edge(vResultSrc, vResultTar, gResult); // adding shouldn't fail assert(peResult.second); @@ -612,7 +612,7 @@ struct CompositionHelper { assert(edgeIter != edgesResult.second); auto eResult = *edgeIter; if(Verbose) - IO::log() + std::cout << "\t'| -> vs. -> |' or '| -> | vs. | -> |', promote eNew to CONTEXT and set right from second right" << std::endl; put_membership(rResult, eResult, Membership::Context); diff --git a/libs/libmod/src/mod/lib/Random.cpp b/libs/libmod/src/mod/lib/Random.cpp index 0b787ae..dce94f7 100644 --- a/libs/libmod/src/mod/lib/Random.cpp +++ b/libs/libmod/src/mod/lib/Random.cpp @@ -3,9 +3,9 @@ #include #include +#include -namespace mod { -namespace lib { +namespace mod::lib { Random::Random() { reseed(std::random_device()()); @@ -18,7 +18,7 @@ std::mt19937 &Random::getEngine() { void Random::reseed(unsigned int seed) { this->seed = seed; engine.seed(this->seed); - IO::log() << "RNG seed: " << this->seed << std::endl; + std::cout << "RNG seed: " << this->seed << std::endl; } Random &Random::getInstance() { @@ -47,5 +47,4 @@ std::vector invertPermutation(const std::vector &p) { return pInverted; } -} // namespace lib -} // namespace mod +} // namespace mod::lib \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Random.hpp b/libs/libmod/src/mod/lib/Random.hpp index 29663ab..2ac4b6a 100644 --- a/libs/libmod/src/mod/lib/Random.hpp +++ b/libs/libmod/src/mod/lib/Random.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RANDOM_H -#define MOD_LIB_RANDOM_H +#ifndef MOD_LIB_RANDOM_HPP +#define MOD_LIB_RANDOM_HPP #include @@ -10,11 +10,9 @@ #include #include -namespace mod { -namespace lib { +namespace mod::lib { -class Random { -public: +struct Random { using Engine = std::mt19937; private: Random(); @@ -73,7 +71,6 @@ std::unique_ptr makePermutedGraph(const Graph &g, Initialiser initialize, return gPermutedPtr; } -} // namespace lib -} // namespace mod +} // namespace mnod::lib -#endif /* MOD_LIB_RANDOM_H */ \ No newline at end of file +#endif // MOD_LIB_RANDOM_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/GraphAsRuleCache.cpp b/libs/libmod/src/mod/lib/Rules/GraphAsRuleCache.cpp new file mode 100644 index 0000000..9b3edda --- /dev/null +++ b/libs/libmod/src/mod/lib/Rules/GraphAsRuleCache.cpp @@ -0,0 +1,31 @@ +#include "GraphAsRuleCache.hpp" + +#include +#include +#include +#include +#include + +namespace mod::lib::Rules { + +std::shared_ptr GraphAsRuleCache::getBindRule(const lib::Graph::Single *g) { + return getRule(g, Membership::Right); +} + +std::shared_ptr GraphAsRuleCache::getIdRule(const lib::Graph::Single *g) { + return getRule(g, Membership::Context); +} + +std::shared_ptr GraphAsRuleCache::getUnbindRule(const lib::Graph::Single *g) { + return getRule(g, Membership::Left); +} + +std::shared_ptr GraphAsRuleCache::getRule(const lib::Graph::Single *g, jla_boost::GraphDPO::Membership m) { + const auto iter = storage.find({g, m}); + if(iter != end(storage)) return iter->second; + auto r = rule::Rule::makeRule(graphToRule(g->getLabelledGraph(), m, g->getName())); + storage.emplace(std::make_pair(g, m), r); + return r; +} + +} // namespace mod::lib::Rules \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/GraphAsRuleCache.hpp b/libs/libmod/src/mod/lib/Rules/GraphAsRuleCache.hpp new file mode 100644 index 0000000..f80c00e --- /dev/null +++ b/libs/libmod/src/mod/lib/Rules/GraphAsRuleCache.hpp @@ -0,0 +1,28 @@ +#ifndef MOD_LIB_RULES_GRAPHASRULECACHE_HPP +#define MOD_LIB_RULES_GRAPHASRULECACHE_HPP + +#include + +#include + +#include +#include + +namespace mod::lib::Graph { +struct Single; +} // namespace mod::lib::Graph +namespace mod::lib::Rules { + +struct GraphAsRuleCache { + std::shared_ptr getBindRule(const lib::Graph::Single *g); + std::shared_ptr getIdRule(const lib::Graph::Single *g); + std::shared_ptr getUnbindRule(const lib::Graph::Single *g); +private: + std::shared_ptr getRule(const lib::Graph::Single *g, jla_boost::GraphDPO::Membership m); +private: + std::map, std::shared_ptr> storage; +}; + +} // namespace mod::lib::Rules + +#endif // MOD_LIB_RULES_GRAPHASRULECACHE_HPP diff --git a/libs/libmod/src/mod/lib/Rules/GraphToRule.hpp b/libs/libmod/src/mod/lib/Rules/GraphToRule.hpp index d63dbd5..cc7af3a 100644 --- a/libs/libmod/src/mod/lib/Rules/GraphToRule.hpp +++ b/libs/libmod/src/mod/lib/Rules/GraphToRule.hpp @@ -1,14 +1,12 @@ -#ifndef MOD_LIB_RULES_GRAPHTORULE_H -#define MOD_LIB_RULES_GRAPHTORULE_H +#ifndef MOD_LIB_RULES_GRAPHTORULE_HPP +#define MOD_LIB_RULES_GRAPHTORULE_HPP #include #include -#include +#include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { template std::unique_ptr graphToRule(const LGraph &lg, Membership membership, const std::string &name) { @@ -84,7 +82,8 @@ std::unique_ptr graphToRule(const LGraph &lg, Membership membership, const return e; }; const auto inf = Stereo::makeCloner(lg, gCore, vertexMap, edgeMap); - rule.pStereo = std::make_unique(gCore, inf, inf, jla_boost::AlwaysTrue(), jla_boost::AlwaysTrue()); + rule.pStereo = std::make_unique(gCore, inf, inf, jla_boost::AlwaysTrue(), + jla_boost::AlwaysTrue()); } rule.initComponents(); @@ -111,8 +110,6 @@ std::unique_ptr graphToRule(const LGraph &lg, Membership membership, const return res; } -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules -#endif /* MOD_LIB_RULES_GRAPHTORULE_H */ +#endif // MOD_LIB_RULES_GRAPHTORULE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/LabelledRule.cpp b/libs/libmod/src/mod/lib/Rules/LabelledRule.cpp index 2e0f403..690822d 100644 --- a/libs/libmod/src/mod/lib/Rules/LabelledRule.cpp +++ b/libs/libmod/src/mod/lib/Rules/LabelledRule.cpp @@ -7,14 +7,14 @@ #include -namespace mod { -namespace lib { -namespace Rules { +#include + +namespace mod::lib::Rules { // LabelledRule //------------------------------------------------------------------------------ -LabelledRule::LabelledRule() : g(new GraphType()) { } +LabelledRule::LabelledRule() : g(new GraphType()) {} LabelledRule::LabelledRule(const LabelledRule &other, bool withConstraints) : LabelledRule() { auto &g = *this->g; @@ -124,7 +124,7 @@ const LabelledRule::PropTermType &get_term(const LabelledRule &r) { r.pTerm.reset(new LabelledRule::PropTermType( get_graph(r), r.leftMatchConstraints, r.rightMatchConstraints, get_string(r), lib::Term::getStrings() - )); + )); } return *r.pTerm; } @@ -146,10 +146,11 @@ const LabelledRule::PropStereoType &get_stereo(const LabelledRule &r) { return std::to_string(get(boost::vertex_index_t(), get_graph(r), v)) + " left"; }); switch(leftResult) { - case Stereo::DeductionResult::Success: break; + case Stereo::DeductionResult::Success: + break; case Stereo::DeductionResult::Warning: if(!getConfig().stereo.silenceDeductionWarnings.get()) - IO::log() << ssErr.str(); + std::cout << ssErr.str(); break; case Stereo::DeductionResult::Error: throw StereoDeductionError(ssErr.str()); @@ -159,16 +160,18 @@ const LabelledRule::PropStereoType &get_stereo(const LabelledRule &r) { return std::to_string(get(boost::vertex_index_t(), get_graph(r), v)) + " right"; }); switch(rightResult) { - case Stereo::DeductionResult::Success: break; + case Stereo::DeductionResult::Success: + break; case Stereo::DeductionResult::Warning: if(!getConfig().stereo.silenceDeductionWarnings.get()) - IO::log() << ssErr.str(); + std::cout << ssErr.str(); break; case Stereo::DeductionResult::Error: throw StereoDeductionError(ssErr.str()); } r.pStereo.reset(new PropStereoCore(get_graph(r), - std::move(leftInference), std::move(rightInference), jla_boost::AlwaysTrue(), jla_boost::AlwaysTrue())); + std::move(leftInference), std::move(rightInference), jla_boost::AlwaysTrue(), + jla_boost::AlwaysTrue())); } return *r.pStereo; } @@ -220,9 +223,9 @@ LabelledRule::LabelledRightType get_labelled_right(const LabelledRule &r) { } LabelledRule::Projections::Projections(const LabelledRule &r) -: left(get_graph(r), Membership::Left), -context(get_graph(r), Membership::Context), -right(get_graph(r), Membership::Right) { } + : left(get_graph(r), Membership::Left), + context(get_graph(r), Membership::Context), + right(get_graph(r), Membership::Right) {} // LabelledSideGraph @@ -231,7 +234,7 @@ right(get_graph(r), Membership::Right) { } namespace detail { LabelledSideGraph::LabelledSideGraph(const LabelledRule &r, jla_boost::GraphDPO::Membership m) -: r(r), m(m) { } + : r(r), m(m) {} } // namespace detail @@ -239,7 +242,7 @@ LabelledSideGraph::LabelledSideGraph(const LabelledRule &r, jla_boost::GraphDPO: //------------------------------------------------------------------------------ LabelledLeftGraph::LabelledLeftGraph(const LabelledRule &r) -: Base(r, jla_boost::GraphDPO::Membership::Left) { } + : Base(r, jla_boost::GraphDPO::Membership::Left) {} const LabelledLeftGraph::GraphType &get_graph(const LabelledLeftGraph &g) { return get_left(g.r); @@ -281,7 +284,7 @@ get_component_graph(std::size_t i, const LabelledLeftGraph &g) { return LabelledLeftGraph::Base::ComponentGraph(get_graph(g), filter, filter); } -const std::vector::vertex_descriptor>& +const std::vector::vertex_descriptor> & get_vertex_order_component(std::size_t i, const LabelledLeftGraph &g) { assert(i < get_num_connected_components(g)); // the number of connected components is initialized externally after construction, so we have this annoying hax @@ -296,7 +299,7 @@ get_vertex_order_component(std::size_t i, const LabelledLeftGraph &g) { //------------------------------------------------------------------------------ LabelledRightGraph::LabelledRightGraph(const LabelledRule &r) -: Base(r, jla_boost::GraphDPO::Membership::Right) { } + : Base(r, jla_boost::GraphDPO::Membership::Right) {} const LabelledRightGraph::GraphType &get_graph(const LabelledRightGraph &g) { return get_right(g.r); @@ -338,7 +341,7 @@ LabelledRightGraph::PropMoleculeType get_molecule(const LabelledRightGraph &g) { return get_molecule(g.r).getRight(); } -const std::vector::vertex_descriptor>& +const std::vector::vertex_descriptor> & get_vertex_order_component(std::size_t i, const LabelledRightGraph &g) { assert(i < get_num_connected_components(g)); // the number of connected components is initialized externally after construction, so we have this annoying hax @@ -349,6 +352,4 @@ get_vertex_order_component(std::size_t i, const LabelledRightGraph &g) { return g.vertex_orders[i]; } -} // namespace Rules -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::Rules \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/LabelledRule.hpp b/libs/libmod/src/mod/lib/Rules/LabelledRule.hpp index e2cfbf7..a7461c3 100644 --- a/libs/libmod/src/mod/lib/Rules/LabelledRule.hpp +++ b/libs/libmod/src/mod/lib/Rules/LabelledRule.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RULES_LABELLED_RULE_H -#define MOD_LIB_RULES_LABELLED_RULE_H +#ifndef MOD_LIB_RULES_LABELLED_RULE_HPP +#define MOD_LIB_RULES_LABELLED_RULE_HPP #include #include @@ -11,9 +11,7 @@ #include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { struct LabelledLeftGraph; struct LabelledRightGraph; @@ -63,7 +61,6 @@ class LabelledRule { friend LabelledLeftType get_labelled_left(const LabelledRule &r); friend LabelledRightType get_labelled_right(const LabelledRule &r); private: - struct Projections { Projections(const LabelledRule &r); public: @@ -78,7 +75,7 @@ class LabelledRule { mutable std::unique_ptr pTerm; mutable std::unique_ptr pStereo; std::vector > leftMatchConstraints; - std::vector >rightMatchConstraints; + std::vector > rightMatchConstraints; private: mutable std::unique_ptr pMolecule; public: @@ -127,7 +124,7 @@ struct LabelledLeftGraph : detail::LabelledSideGraph { public: friend PropMoleculeType get_molecule(const LabelledLeftGraph &g); public: - friend const std::vector::vertex_descriptor>& + friend const std::vector::vertex_descriptor> & get_vertex_order_component(std::size_t i, const LabelledLeftGraph &g); }; @@ -154,12 +151,10 @@ struct LabelledRightGraph : detail::LabelledSideGraph { public: friend PropMoleculeType get_molecule(const LabelledRightGraph &g); public: - friend const std::vector::vertex_descriptor>& + friend const std::vector::vertex_descriptor> & get_vertex_order_component(std::size_t i, const LabelledRightGraph &g); }; -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules -#endif /* MOD_LIB_RULES_LABELLED_RULE_H */ +#endif // MOD_LIB_RULES_LABELLED_RULE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Properties/Depiction.cpp b/libs/libmod/src/mod/lib/Rules/Properties/Depiction.cpp index 71a29b2..619bb65 100644 --- a/libs/libmod/src/mod/lib/Rules/Properties/Depiction.cpp +++ b/libs/libmod/src/mod/lib/Rules/Properties/Depiction.cpp @@ -11,18 +11,17 @@ #include +#include #include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { //------------------------------------------------------------------------------ // template DepictionData //------------------------------------------------------------------------------ template -DepictionDataCore::DepictionData::DepictionData(const DepictionDataCore &depict) : depict(depict) { } +DepictionDataCore::DepictionData::DepictionData(const DepictionDataCore &depict) : depict(depict) {} template AtomId DepictionDataCore::DepictionData::getAtomId(Vertex v) const { @@ -111,17 +110,16 @@ std::string DepictionDataCore::DepictionData::getVertexLabelNoIsotop return Chem::symbolFromAtomId(atomId); switch(membership) { case Membership::Left: - case Membership::Right: - { - const auto &nonAtomToPhonyAtom = membership == Membership::Left ? depict.nonAtomToPhonyAtomLeft : depict.nonAtomToPhonyAtomRight; + case Membership::Right: { + const auto &nonAtomToPhonyAtom = + membership == Membership::Left ? depict.nonAtomToPhonyAtomLeft : depict.nonAtomToPhonyAtomRight; auto nonAtomIter = nonAtomToPhonyAtom.find(v); assert(nonAtomIter != end(nonAtomToPhonyAtom)); auto labelIter = depict.phonyAtomToString.find(nonAtomIter->second.getAtomId()); assert(labelIter != end(depict.phonyAtomToString)); return labelIter->second; } - case Membership::Context: - { + case Membership::Context: { const auto &pMol = get_molecule(depict.lr); auto nonAtomIterLeft = depict.nonAtomToPhonyAtomLeft.find(v); auto nonAtomIterRight = depict.nonAtomToPhonyAtomRight.find(v); @@ -155,16 +153,14 @@ std::string DepictionDataCore::DepictionData::getEdgeLabel(Edge e) c return std::string(1, Chem::bondToChar(bt)); switch(membership) { case Membership::Left: - case Membership::Right: - { + case Membership::Right: { const auto &nonBondEdges = membership == Membership::Left ? depict.nonBondEdgesLeft : depict.nonBondEdgesRight; auto iter = nonBondEdges.find(e); - if(iter == end(nonBondEdges)) IO::log() << "WTF: " << e << std::endl; + if(iter == end(nonBondEdges)) std::cout << "WTF: " << e << std::endl; assert(iter != end(nonBondEdges)); return iter->second; } - case Membership::Context: - { + case Membership::Context: { std::string left, right; auto iterLeft = depict.nonBondEdgesLeft.find(e); auto iterRight = depict.nonBondEdgesRight.find(e); @@ -212,14 +208,12 @@ template bool DepictionDataCore::DepictionData::hasImportantStereo(Vertex v) const { const auto &lr = depict.lr; switch(membership) { - case Membership::Left: - { + case Membership::Left: { const auto &lg = get_labelled_left(lr); if(!has_stereo(lg)) return false; return !get_stereo(lg)[v]->morphismDynamicOk(); } - case Membership::Right: - { + case Membership::Right: { const auto &lg = get_labelled_right(lr); if(!has_stereo(lg)) return false; return !get_stereo(lg)[v]->morphismDynamicOk(); @@ -246,7 +240,8 @@ double DepictionDataCore::DepictionData::getY(Vertex v, bool withHyd } template -lib::IO::Graph::Write::EdgeFake3DType DepictionDataCore::DepictionData::getEdgeFake3DType(Edge e, bool withHydrogen) const { +lib::IO::Graph::Write::EdgeFake3DType +DepictionDataCore::DepictionData::getEdgeFake3DType(Edge e, bool withHydrogen) const { #ifndef MOD_HAVE_OPENBABEL MOD_NO_OPENBABEL_ERROR #else @@ -296,14 +291,15 @@ lib::IO::Graph::Write::EdgeFake3DType DepictionDataCore::DepictionData atomUsed(AtomIds::Max + 1, false); Chem::markSpecialAtomsUsed(atomUsed); - std::vector < std::pair > verticesToProcess; // vertex x {Left, Right} + std::vector> verticesToProcess; // vertex x {Left, Right} for(Vertex v : asRange(vertices(g))) { auto m = g[v].membership; if(m != Membership::Right) { @@ -325,7 +321,7 @@ DepictionDataCore::DepictionDataCore(const LabelledRule &lr) : lr(lr), hasMolecu assert(m != Membership::Context); std::string label = std::get<0>(Chem::extractIsotopeChargeRadical( m == Membership::Left ? pString.getLeft()[v] : pString.getRight()[v] - )); + )); auto iter = labelToAtomId.find(label); if(iter == end(labelToAtomId)) { unsigned char atomId = 1; @@ -369,9 +365,12 @@ DepictionDataCore::DepictionDataCore(const LabelledRule &lr) : lr(lr), hasMolecu if(hasMoleculeEncoding) { #ifdef MOD_HAVE_OPENBABEL - const auto doIt = [&](CoordData & cData, const bool withHydrogen) { + const auto doIt = [&](CoordData &cData, const bool withHydrogen) { std::tie(cData.obMol, cData.obMolLeft, cData.obMolRight) - = Chem::makeOBMol(lr, std::cref(*this), std::cref(*this), getLeft(), getLeft(), getRight(), getRight(), withHydrogen); + = Chem::makeOBMol(lr, std::cref(*this), std::cref(*this), + getLeft(), getLeft(), + getRight(), getRight(), + withHydrogen); cData.x.resize(num_vertices(g)); cData.y.resize(num_vertices(g)); for(const auto v : asRange(vertices(g))) { @@ -420,19 +419,16 @@ const AtomData &DepictionDataCore::operator()(Vertex v) const { BondType DepictionDataCore::operator()(Edge e) const { const auto &g = get_graph(lr); const auto &pMol = get_molecule(lr); - // if there is agreement, return that, otherwise prefer single bonds + // if there is agreement, return that, otherwise prefer invalid bonds // this should give a bit more freedom in bond angles const auto m = g[e].membership; BondType l = BondType::Single, r = BondType::Single; - if(m != Membership::Right) { - const auto bt = pMol.getLeft()[e]; - l = bt == BondType::Invalid ? BondType::Single : bt; - } else { - const auto bt = pMol.getRight()[e]; - r = bt == BondType::Invalid ? BondType::Single : bt; - } + if(m != Membership::Right) + l = pMol.getLeft()[e]; + if(m != Membership::Left) + r = pMol.getRight()[e]; if(l == r) return l; - else return BondType::Single; + else return BondType::Invalid; } bool DepictionDataCore::hasImportantStereo(Vertex v) const { @@ -451,7 +447,7 @@ bool DepictionDataCore::getHasCoordinates() const { else return false; #else return false; -#endif +#endif } double DepictionDataCore::getX(Vertex v, bool withHydrogen) const { @@ -474,7 +470,7 @@ double DepictionDataCore::getY(Vertex v, bool withHydrogen) const { void DepictionDataCore::copyCoords(const DepictionDataCore &other, const std::map &vMap) { if(!other.getHasCoordinates()) { - IO::log() << "Can not copy coordinates from depiction without coordinates." << std::endl; + std::cout << "Can not copy coordinates from depiction without coordinates." << std::endl; MOD_ABORT; } const auto &g = get_graph(lr); @@ -484,11 +480,12 @@ void DepictionDataCore::copyCoords(const DepictionDataCore &other, const std::ma for(const Vertex v : asRange(vertices(g))) { const auto iter = vMap.find(v); if(iter == end(vMap)) { - IO::log() << "Vertex " << v << " (id=" << get(boost::vertex_index_t(), g, v) << ") not mapped." << std::endl; - IO::log() << "Map:" << std::endl; - for(auto p : vMap) IO::log() << "\t" << p.first << " => " << p.second << std::endl; - IO::log() << "num_vertices: " << num_vertices(g) << std::endl; - IO::log() << "other.num_vertices: " << num_vertices(get_graph(other.lr)) << std::endl; + std::cout << "Vertex " << v << " (id=" << get(boost::vertex_index_t(), g, v) << ") not mapped." + << std::endl; + std::cout << "Map:" << std::endl; + for(auto p : vMap) std::cout << "\t" << p.first << " => " << p.second << std::endl; + std::cout << "num_vertices: " << num_vertices(g) << std::endl; + std::cout << "other.num_vertices: " << num_vertices(get_graph(other.lr)) << std::endl; MOD_ABORT; } const Vertex vOther = iter->second; @@ -524,10 +521,11 @@ DepictionDataCore::DepictionData DepictionDataCore::getRight( return DepictionData(*this); } -template struct DepictionDataCore::DepictionData; -template struct DepictionDataCore::DepictionData; -template struct DepictionDataCore::DepictionData; +template +struct DepictionDataCore::DepictionData; +template +struct DepictionDataCore::DepictionData; +template +struct DepictionDataCore::DepictionData; -} // namespace Rules -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::Rules \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Properties/Depiction.hpp b/libs/libmod/src/mod/lib/Rules/Properties/Depiction.hpp index ed6057d..0bbfacc 100644 --- a/libs/libmod/src/mod/lib/Rules/Properties/Depiction.hpp +++ b/libs/libmod/src/mod/lib/Rules/Properties/Depiction.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RULES_STATE_DEPICTION_H -#define MOD_LIB_RULES_STATE_DEPICTION_H +#ifndef MOD_LIB_RULES_STATE_DEPICTION_HPP +#define MOD_LIB_RULES_STATE_DEPICTION_HPP #include #include @@ -14,8 +14,8 @@ struct AtomId; struct Charge; struct AtomData; enum class BondType; -namespace lib { -namespace Rules { +} // namespace mod +namespace mod::lib::Rules { struct PropStringCore; struct PropMoleculeCore; @@ -75,8 +75,6 @@ struct DepictionDataCore { } cDataAll, cDataNoHydrogen; }; -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules -#endif /* MOD_LIB_RULES_STATE_DEPICTION_H */ \ No newline at end of file +#endif // MOD_LIB_RULES_STATE_DEPICTION_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Properties/Property.cpp b/libs/libmod/src/mod/lib/Rules/Properties/Property.cpp new file mode 100644 index 0000000..cb3e3f0 --- /dev/null +++ b/libs/libmod/src/mod/lib/Rules/Properties/Property.cpp @@ -0,0 +1,27 @@ +#include "Property.hpp" + +#include + +namespace mod::lib::Rules::detail { + +void PropVerify(const void *g, const void *gOther, + std::size_t nGraph, std::size_t nOther, + std::size_t mGraph, std::size_t mOther) { + if(g != gOther) { + std::cout << "Different graphs: g = " << (std::uintptr_t) g + << ", &this->g = " << (std::uintptr_t) gOther << std::endl; + MOD_ABORT; + } + if(nGraph != nOther) { + std::cout << "Different sizes: num_vertices(this->g) = " << nGraph + << ", vertexLabels.size() = " << nOther << std::endl; + MOD_ABORT; + } + if(mGraph != mOther) { + std::cout << "Different sizes: num_edges(this->g) = " << mGraph + << ", edgeLabels.size() = " << mOther << std::endl; + MOD_ABORT; + } +} + +} // namespace mod::lib::Rules::detail \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Properties/Property.hpp b/libs/libmod/src/mod/lib/Rules/Properties/Property.hpp index 590646a..00ff229 100644 --- a/libs/libmod/src/mod/lib/Rules/Properties/Property.hpp +++ b/libs/libmod/src/mod/lib/Rules/Properties/Property.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RULES_PROP_H -#define MOD_LIB_RULES_PROP_H +#ifndef MOD_LIB_RULES_PROP_HPP +#define MOD_LIB_RULES_PROP_HPP #include #include @@ -13,9 +13,7 @@ #include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { using jla_boost::GraphDPO::Membership; #define MOD_RULE_STATE_TEMPLATE_PARAMS \ @@ -193,24 +191,15 @@ auto get(const RightState &p, const VertexOrEdge & // Implementation //------------------------------------------------------------------------------ +namespace detail { +void PropVerify(const void *g, const void *gOther, + std::size_t nGraph, std::size_t nOther, + std::size_t mGraph, std::size_t mOther); +} // namespace detail + MOD_RULE_STATE_TEMPLATE_PARAMS void PropCore::verify(const Graph *g) const { - if(g != &this->g) { - IO::log() << "Different graphs (" << reinterpret_cast (this) << "): g = " - << static_cast (g) << ", &this->g = " << static_cast (&this->g) - << std::endl; - MOD_ABORT; - } - if(num_vertices(this->g) != vertexState.size()) { - IO::log() << "Different sizes (" << reinterpret_cast (this) << "): num_vertices(this->g) = " - << num_vertices(this->g) << ", vertexState.size() = " << vertexState.size() << std::endl; - MOD_ABORT; - } - if(num_edges(this->g) != edgeState.size()) { - IO::log() << "Different sizes (" << reinterpret_cast (this) << "): num_edges(this->g) = " - << num_edges(this->g) << ", edgeState.size() = " << edgeState.size() << std::endl; - MOD_ABORT; - } + detail::PropVerify(g, &this->g, num_vertices(*g), vertexState.size(), num_edges(*g), edgeState.size()); } MOD_RULE_STATE_TEMPLATE_PARAMS @@ -356,8 +345,6 @@ const Derived &PropCore::getDerived() const { return static_cast (*this); } -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules -#endif /* MOD_LIB_RULES_PROP_H */ +#endif // MOD_LIB_RULES_PROP_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Properties/Stereo.hpp b/libs/libmod/src/mod/lib/Rules/Properties/Stereo.hpp index 29d5c9a..4fbe550 100644 --- a/libs/libmod/src/mod/lib/Rules/Properties/Stereo.hpp +++ b/libs/libmod/src/mod/lib/Rules/Properties/Stereo.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RULE_PROP_STEREO_H -#define MOD_LIB_RULE_PROP_STEREO_H +#ifndef MOD_LIB_RULE_PROP_STEREO_HPP +#define MOD_LIB_RULE_PROP_STEREO_HPP #include #include @@ -7,9 +7,7 @@ #include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { struct PropStereoCore : private PropCore, lib::Stereo::EdgeCategory> { @@ -50,13 +48,12 @@ struct PropStereoCore if(g[v].membership != Membership::Right) l = leftInference.extractConfiguration(v); if(g[v].membership != Membership::Left) r = rightInference.extractConfiguration(v); { // verify - const auto verify = [&g, &v](const lib::Stereo::Configuration &conf, const auto m) { #ifndef NDEBUG + const auto verify = [&g, &v](const lib::Stereo::Configuration &conf, const auto m) { const auto oe = out_edges(v, g); const auto d = std::count_if(oe.first, oe.second, [&g, m](const auto &e) { return g[e].membership != m; }); -#endif int dConf = 0; for(const auto &emb : conf) { if(emb.type != lib::Stereo::EmbeddingEdge::Type::Edge) { @@ -71,12 +68,13 @@ struct PropStereoCore if(l) verify(*l, Membership::Right); if(r) verify(*r, Membership::Left); assert(bool(l) || bool(r)); +#endif } // end verify vertexState.emplace_back(std::move(l), std::move(r)); const bool inContext = [&]() { if(g[v].membership != Membership::Context) return false; if(!vCallback(v)) return false; - for(const auto &eOut : asRange(out_edges(v, g))) { + for(const auto eOut : asRange(out_edges(v, g))) { if(g[eOut].membership != Membership::Context) return false; } assert(bool(vertexState.back().left)); @@ -192,8 +190,6 @@ auto get(const PropStereoCore &p, const VertexOrEdge &ve) -> decltype(p[ve]) { return p[ve]; } -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules -#endif /* MOD_LIB_RULE_PROP_STEREO_H */ \ No newline at end of file +#endif // MOD_LIB_RULE_PROP_STEREO_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Properties/String.cpp b/libs/libmod/src/mod/lib/Rules/Properties/String.cpp index d9b6bcf..1a36999 100644 --- a/libs/libmod/src/mod/lib/Rules/Properties/String.cpp +++ b/libs/libmod/src/mod/lib/Rules/Properties/String.cpp @@ -1,7 +1,7 @@ #include "String.hpp" #include -#include +#include #include #include diff --git a/libs/libmod/src/mod/lib/Rules/Real.cpp b/libs/libmod/src/mod/lib/Rules/Real.cpp index 90ba699..cb962f4 100644 --- a/libs/libmod/src/mod/lib/Rules/Real.cpp +++ b/libs/libmod/src/mod/lib/Rules/Real.cpp @@ -21,9 +21,7 @@ #include -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { BOOST_CONCEPT_ASSERT((LabelledGraphConcept)); BOOST_CONCEPT_ASSERT((LabelledGraphConcept)); BOOST_CONCEPT_ASSERT((LabelledGraphConcept)); @@ -84,8 +82,8 @@ Real::Real(LabelledRule &&rule, boost::optional labelType) // only one of propString and propTerm should be defined assert(this->dpoRule.pString || this->dpoRule.pTerm); assert(!this->dpoRule.pString || !this->dpoRule.pTerm); - if(!sanityChecks(getGraph(), getStringState(), IO::log())) { - IO::log() << "Rule::sanityCheck\tfailed in rule '" << getName() << "'" << std::endl; + if(!sanityChecks(getGraph(), getStringState(), std::cout)) { + std::cout << "Rule::sanityCheck\tfailed in rule '" << getName() << "'" << std::endl; MOD_ABORT; } } @@ -228,6 +226,4 @@ bool Real::isomorphicLeftRight(const Real &rDom, const Real &rCodom, LabelSettin return mrRight.getNumHits() == 1; } -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Rules/Real.hpp b/libs/libmod/src/mod/lib/Rules/Real.hpp index 392022c..f99c1ff 100644 --- a/libs/libmod/src/mod/lib/Rules/Real.hpp +++ b/libs/libmod/src/mod/lib/Rules/Real.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_RULES_REAL_H -#define MOD_LIB_RULES_REAL_H +#ifndef MOD_LIB_RULES_REAL_HPP +#define MOD_LIB_RULES_REAL_HPP #include #include @@ -11,14 +11,12 @@ #include -namespace mod { -namespace lib { -namespace Graph { +namespace mod::lib::Graph { struct PropStereo; struct PropString; struct Single; -} // namespace Graph -namespace Rules { +} // namespace mod::lib::Graph +namespace mod::lib::Rules { struct PropStringCore; struct PropMoleculeCore; struct DepictionDataCore; @@ -106,8 +104,6 @@ struct MembershipPredWrapper { } }; -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules -#endif /* MOD_LIB_RULES_REAL_H */ +#endif // MOD_LIB_RULES_REAL_HPP diff --git a/libs/libmod/src/mod/lib/Stereo/CloneUtil.hpp b/libs/libmod/src/mod/lib/Stereo/CloneUtil.hpp index 25a9028..4e46ba0 100644 --- a/libs/libmod/src/mod/lib/Stereo/CloneUtil.hpp +++ b/libs/libmod/src/mod/lib/Stereo/CloneUtil.hpp @@ -1,21 +1,18 @@ -#ifndef MOD_LIB_STEREO_CLONEUTIL_H -#define MOD_LIB_STEREO_CLONEUTIL_H +#ifndef MOD_LIB_STEREO_CLONEUTIL_HPP +#define MOD_LIB_STEREO_CLONEUTIL_HPP #include #include #include -namespace mod { -namespace lib { -namespace Stereo { +namespace mod::lib::Stereo { template struct Cloner { using VertexCodom = typename boost::graph_traits::vertex_descriptor; using EdgeCodom = typename boost::graph_traits::edge_descriptor; public: - Cloner(const LGraphDom &lgDom, const GraphCodom &gCodom, InverseVertexMorphism mInverseVertex, const InverseEdgeMorphism &mInverseEdge) : lgDom(lgDom), gCodom(gCodom), mInverseVertex(mInverseVertex), mInverseEdge(mInverseEdge) { } @@ -30,12 +27,12 @@ struct Cloner { std::vector offsetMap(out_degree(vDom, gDom)); assert(out_degree(vDom, gDom) == out_degree(vCodom, gCodom)); std::size_t offsetCodom = 0; - for(const auto &eOutCodom : asRange(out_edges(vCodom, gCodom))) { + for(const auto eOutCodom : asRange(out_edges(vCodom, gCodom))) { const auto vAdjDom = mInverseVertex(target(eOutCodom, gCodom)); // we don't use find_if as we want the distance, also for forward iterators std::size_t offsetDom = [&]() { std::size_t i = 0; - for(const auto &eDomCand : asRange(out_edges(vDom, gDom))) { + for(const auto eDomCand : asRange(out_edges(vDom, gDom))) { if(target(eDomCand, gDom) == vAdjDom) return i; ++i; } @@ -66,8 +63,6 @@ auto makeCloner(const LGraphDom &lgDom, const GraphCodom &gCodom, InverseVertexM return Cloner(lgDom, gCodom, mInverseVertex, mInverseEdge); } -} // namespace Stereo -} // namespace lib -} // namespace mod +} // namespace mod::lib::Stereo -#endif /* MOD_LIB_STEREO_CLONEUTIL_H */ \ No newline at end of file +#endif // MOD_LIB_STEREO_CLONEUTIL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Stereo/EdgeCategory.cpp b/libs/libmod/src/mod/lib/Stereo/EdgeCategory.cpp index c9b3ee3..b59a8dd 100644 --- a/libs/libmod/src/mod/lib/Stereo/EdgeCategory.cpp +++ b/libs/libmod/src/mod/lib/Stereo/EdgeCategory.cpp @@ -2,11 +2,9 @@ #include -#include +#include -namespace mod { -namespace lib { -namespace Stereo { +namespace mod::lib::Stereo { bool carriesPlane(EdgeCategory cat) { switch(cat) { @@ -156,6 +154,4 @@ bool componentWiseLEQ(const EdgeCategoryCount &lhs, const EdgeCategoryCount &rhs return true; } -} // namespace Stereo -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib::Stereo \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Stereo/EdgeCategory.hpp b/libs/libmod/src/mod/lib/Stereo/EdgeCategory.hpp index dda7354..b781302 100644 --- a/libs/libmod/src/mod/lib/Stereo/EdgeCategory.hpp +++ b/libs/libmod/src/mod/lib/Stereo/EdgeCategory.hpp @@ -1,17 +1,15 @@ -#ifndef MOD_LIB_STEREO_EDGECATEGORY_H -#define MOD_LIB_STEREO_EDGECATEGORY_H +#ifndef MOD_LIB_STEREO_EDGECATEGORY_HPP +#define MOD_LIB_STEREO_EDGECATEGORY_HPP #include #include #include -#include +#include #include #include -namespace mod { -namespace lib { -namespace Stereo { +namespace mod::lib::Stereo { enum class EdgeCategory : unsigned char { // A partial order: Any is greater than all the others. @@ -64,8 +62,6 @@ struct EdgeCategoryCount { Storage count; }; -} // namespace Stereo -} // namespace lib -} // namespace mod +} // namespace mod::lib::Stereo -#endif /* MOD_LIB_STEREO_EDGECATEGORY_H */ \ No newline at end of file +#endif // MOD_LIB_STEREO_EDGECATEGORY_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/StringStore.cpp b/libs/libmod/src/mod/lib/StringStore.cpp index 5abc4b4..1c8d2dd 100644 --- a/libs/libmod/src/mod/lib/StringStore.cpp +++ b/libs/libmod/src/mod/lib/StringStore.cpp @@ -3,18 +3,15 @@ #include #include -namespace mod { -namespace lib { +namespace mod::lib { bool StringStore::hasString(const std::string &s) const { return index.find(s) != end(index); } std::size_t StringStore::getIndex(const std::string &s) const { - struct DoPrint { - - DoPrint(const StringStore &store, const std::string &s) : store(store), s(s) { } + DoPrint(const StringStore &store, const std::string &s) : store(store), s(s) {} ~DoPrint() { std::cout << "StringStore getIndex(" << s << ")" << std::endl; @@ -39,5 +36,4 @@ const std::string &StringStore::getString(std::size_t index) const { return strings[index]; } -} // namespace lib -} // namespace mod \ No newline at end of file +} // namespace mod::lib \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/StringStore.hpp b/libs/libmod/src/mod/lib/StringStore.hpp index d09f81d..5cfa821 100644 --- a/libs/libmod/src/mod/lib/StringStore.hpp +++ b/libs/libmod/src/mod/lib/StringStore.hpp @@ -1,12 +1,11 @@ -#ifndef MOD_LIB_STRINGSTORE_H -#define MOD_LIB_STRINGSTORE_H +#ifndef MOD_LIB_STRINGSTORE_HPP +#define MOD_LIB_STRINGSTORE_HPP #include #include #include -namespace mod { -namespace lib { +namespace mod::lib { struct StringStore { StringStore() = default; @@ -22,7 +21,6 @@ struct StringStore { mutable std::map index; }; -} // namespace lib -} // namespace mod +} // namespace mod::lib -#endif /* MOD_LIB_STRINGSTORE_H */ \ No newline at end of file +#endif // MOD_LIB_STRINGSTORE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/lib/Term/WAM.hpp b/libs/libmod/src/mod/lib/Term/WAM.hpp index 6871c58..d153072 100644 --- a/libs/libmod/src/mod/lib/Term/WAM.hpp +++ b/libs/libmod/src/mod/lib/Term/WAM.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_LIB_TERM_WAM_H -#define MOD_LIB_TERM_WAM_H +#ifndef MOD_LIB_TERM_WAM_HPP +#define MOD_LIB_TERM_WAM_HPP #include @@ -11,10 +11,10 @@ // see http://wambook.sourceforge.net/ -namespace mod { -namespace lib { +namespace mod::lib { struct StringStore; -namespace Term { +} // namespace mod::lib +namespace mod::lib::Term { const StringStore &getStrings(); @@ -25,14 +25,13 @@ enum class CellTag : int { }; enum class AddressType : int { // order matters, used in operator< - Heap, Temp + Heap = 0, Temp = 1 }; struct Address { AddressType type; std::size_t addr; public: - friend bool operator==(Address lhs, Address rhs) { return lhs.type == rhs.type && lhs.addr == rhs.addr; } @@ -56,9 +55,7 @@ struct Address { struct Cell { CellTag tag; - union { - struct { Address addr; } STR; @@ -73,7 +70,6 @@ struct Cell { } Structure; }; public: - static Cell makeSTR(Address addr) { Cell cell; cell.tag = CellTag::STR; @@ -100,14 +96,12 @@ struct Cell { struct Wam; struct MGU { - - MGU(std::size_t preHeapSize) : preHeapSize(preHeapSize) { } + MGU(std::size_t preHeapSize) : preHeapSize(preHeapSize) {} bool isRenaming(const Wam &machine) const; bool isSpecialisation(const Wam &machine) const; public: std::size_t preHeapSize; std::vector
bindings; // stack of addresses of REFs that were self-references before - enum class Status { Exists, Fail } status = Status::Exists; @@ -217,25 +211,32 @@ struct Wam { Address deref(Address addr) const { Cell cell = getCell(addr); switch(cell.tag) { - case CellTag::STR: return deref(cell.STR.addr); - case CellTag::REF: return cell.REF.addr == addr ? addr: deref(cell.REF.addr); - case CellTag::Structure: return addr; + case CellTag::STR: + return deref(cell.STR.addr); + case CellTag::REF: + return cell.REF.addr == addr ? addr : deref(cell.REF.addr); + case CellTag::Structure: + return addr; } MOD_ABORT; } Cell &getCell(Address addr) { switch(addr.type) { - case AddressType::Heap: return heap[addr.addr]; - case AddressType::Temp: return temp[addr.addr]; + case AddressType::Heap: + return heap[addr.addr]; + case AddressType::Temp: + return temp[addr.addr]; } MOD_ABORT; } const Cell &getCell(Address addr) const { switch(addr.type) { - case AddressType::Heap: return heap[addr.addr]; - case AddressType::Temp: return temp[addr.addr]; + case AddressType::Heap: + return heap[addr.addr]; + case AddressType::Temp: + return temp[addr.addr]; } MOD_ABORT; } @@ -260,7 +261,8 @@ struct Wam { assert(cell.STR.addr.type == AddressType::Heap); cell.STR.addr.type = AddressType::Temp; break; - case CellTag::Structure: break; + case CellTag::Structure: + break; } } } @@ -358,7 +360,7 @@ inline void Wam::unifyHeapHeap(std::size_t lhs, std::size_t rhs, MGU &mgu) { assert(leftCell.tag == CellTag::Structure); assert(rightCell.tag == CellTag::Structure); if(leftCell.Structure.name != rightCell.Structure.name - || leftCell.Structure.arity != rightCell.Structure.arity) { + || leftCell.Structure.arity != rightCell.Structure.arity) { mgu.status = MGU::Status::Fail; mgu.errorLeft = Address{AddressType::Heap, lhs}; mgu.errorRight = Address{AddressType::Heap, rhs}; @@ -439,7 +441,7 @@ inline void Wam::unifyHeapTemp(std::size_t lhsIndex, std::size_t rhsIndex, MGU & } } else if(lhsCell.tag == CellTag::Structure) { if(lhsCell.Structure.name == rhsCell.Structure.name && - lhsCell.Structure.arity == rhsCell.Structure.arity) { + lhsCell.Structure.arity == rhsCell.Structure.arity) { for(std::size_t i = lhsCell.Structure.arity; i > 0; i--) stack.emplace(lhsAddr + i, rhsAddr + i); // overwrite rhs to point to heap @@ -451,26 +453,22 @@ inline void Wam::unifyHeapTemp(std::size_t lhsIndex, std::size_t rhsIndex, MGU & mgu.errorRight = rhsAddr; return; } - } else MOD_ABORT; - } else MOD_ABORT; + } else + MOD_ABORT; + } else + MOD_ABORT; } } verify(); } -} // namespace Term -} // namespace lib -} // namespace mod -namespace std { +} // namespace mod::lib::Term template<> -struct hash { - +struct std::hash { std::size_t operator()(mod::lib::Term::Address addr) const { return addr.addr; // probably good enough } }; -} // namespace std - -#endif /* MOD_LIB_TERM_WAM_H */ \ No newline at end of file +#endif // MOD_LIB_TERM_WAM_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/Composer.cpp b/libs/libmod/src/mod/rule/Composer.cpp index 355dada..5ca1d55 100644 --- a/libs/libmod/src/mod/rule/Composer.cpp +++ b/libs/libmod/src/mod/rule/Composer.cpp @@ -2,13 +2,11 @@ #include -namespace mod { -namespace rule { +namespace mod::rule { struct Composer::Pimpl { Pimpl(const std::unordered_set> &database, LabelSettings labelSettings) : evaluator(database, labelSettings) {} - public: lib::RC::Evaluator evaluator; }; @@ -26,7 +24,7 @@ const std::unordered_set> &Composer::getProducts() c return p->evaluator.getProducts(); } -std::unordered_set> Composer::eval(const RCExp::Expression &exp, int verbosity) { +std::vector> Composer::eval(const RCExp::Expression &exp, int verbosity) { return p->evaluator.eval(exp, verbosity); } @@ -38,9 +36,8 @@ void Composer::print() const { //------------------------------------------------------------------------------ std::shared_ptr Composer::create(const std::unordered_set > &database, - LabelSettings labelSettings) { + LabelSettings labelSettings) { return std::shared_ptr(new Composer(database, labelSettings)); } -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/Composer.hpp b/libs/libmod/src/mod/rule/Composer.hpp index 70a73c2..a746e82 100644 --- a/libs/libmod/src/mod/rule/Composer.hpp +++ b/libs/libmod/src/mod/rule/Composer.hpp @@ -9,8 +9,7 @@ #include #include -namespace mod { -namespace rule { +namespace mod::rule { // rst-class: rule::Composer // rst: @@ -25,7 +24,6 @@ namespace rule { // rst: hyperedge vertices are labelled with 1 and 2. // rst: // rst-class-start: - class MOD_DECL Composer { Composer(const std::unordered_set > &database, LabelSettings labelSettings); Composer(Composer &&) = delete; @@ -40,9 +38,12 @@ class MOD_DECL Composer { // rst: // rst: :returns: the set of unique rules this evaluator has constructed. const std::unordered_set> &getProducts() const; - // rst: .. function:: std::unordered_set > eval(const RCExp::Expression &exp, int verbosity) + // rst: .. function:: std::vector> eval(const RCExp::Expression &exp, int verbosity) + // rst: + // rst: Evaluates a rule composition expression. + // rst: Any created rule is replaced by a rule in the database if they are isomorphic. // rst: - // rst: Evaluates a rule composition expression. Any created rule is replaced by a rule in the database if they are isomorphic. + // rst: A rule may appear multiple times in the result if multiple overlaps resulted in the same composed rule. // rst: // rst: The :var:`verbosity` has the following meaning: // rst: @@ -51,7 +52,7 @@ class MOD_DECL Composer { // rst: - 20: Print rule composition information. // rst: // rst: :returns: the result of the expression. - std::unordered_set> eval(const RCExp::Expression &exp, int verbosity); + std::vector> eval(const RCExp::Expression &exp, int verbosity); // rst: .. function:: void print() const // rst: // rst: Print the graph representing all expressions evaluated so far. @@ -70,7 +71,6 @@ class MOD_DECL Composer { }; // rst-class-end: -} // namespace rule -} // namespace mod +} // namespace mod::rule #endif /* MOD_RULE_COMPOSITION_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/CompositionExpr.cpp b/libs/libmod/src/mod/rule/CompositionExpr.cpp index f28d9fa..e227213 100644 --- a/libs/libmod/src/mod/rule/CompositionExpr.cpp +++ b/libs/libmod/src/mod/rule/CompositionExpr.cpp @@ -6,10 +6,7 @@ #include -namespace mod { -namespace rule { - -namespace RCExp { +namespace mod::rule::RCExp { // Parallel //------------------------------------------------------------------------------ @@ -207,7 +204,4 @@ std::ostream &ComposeSuper::print(std::ostream &s) const { return s << "rcSuper(allowPartial=" << std::boolalpha << allowPartial << ", enforceConstraints=" << enforceConstraints << ", "; } -} // namespace RCExp - -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule::RCExp \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/CompositionExpr.hpp b/libs/libmod/src/mod/rule/CompositionExpr.hpp index 8ce8d0a..f5e7ff9 100644 --- a/libs/libmod/src/mod/rule/CompositionExpr.hpp +++ b/libs/libmod/src/mod/rule/CompositionExpr.hpp @@ -12,10 +12,7 @@ #include #include -namespace mod { -namespace rule { - -namespace RCExp { +namespace mod::rule::RCExp { // rst: RCExp // rst: --------------------------- // rst: @@ -32,7 +29,6 @@ namespace RCExp { // rst: Return the union of the subexpressions. I.e., flatten the subresult lists into a single list. // rst: // rst-class-start: - struct MOD_DECL Union { Union(std::vector exps); MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Union &par); @@ -47,7 +43,6 @@ struct MOD_DECL Union { // rst: Return the singleton list with the rule :math:`(\emptyset, \emptyset, G)` for the given graph :math:`G`. // rst: // rst-class-start: - struct MOD_DECL Bind { Bind(std::shared_ptr g); MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Bind &b); @@ -62,7 +57,6 @@ struct MOD_DECL Bind { // rst: Return the singleton list with the rule :math:`(G, G, G)` for the given graph :math:`G`. // rst: // rst-class-start: - struct MOD_DECL Id { Id(std::shared_ptr g); MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Id &i); @@ -77,7 +71,6 @@ struct MOD_DECL Id { // rst: Return the singleton list with the rule :math:`(G, \emptyset, \emptyset)` for the given graph :math:`G`. // rst: // rst-class-start: - struct MOD_DECL Unbind { Unbind(std::shared_ptr g); MOD_DECL friend std::ostream &operator<<(std::ostream &s, const Unbind &u); @@ -91,11 +84,8 @@ struct MOD_DECL Unbind { //------------------------------------------------------------------------------ class ComposeCommon; - class ComposeParallel; - class ComposeSub; - class ComposeSuper; // rst-class: rule::RCExp::Expression @@ -103,7 +93,6 @@ class ComposeSuper; // rst: A generic rule composition expression. // rst: // rst-class-start: - struct MOD_DECL Expression { Expression(std::shared_ptr r); Expression(Union u); @@ -140,7 +129,6 @@ struct MOD_DECL Expression { // rst: The base class for the composition of two rule :math:`(L_1, K_1, R_1)` and :math:`(L_2, K_2, R_2)`. // rst: // rst-class-start: - class MOD_DECL ComposeBase { protected: ComposeBase(Expression first, Expression second, bool discardNonchemical); @@ -164,7 +152,6 @@ class MOD_DECL ComposeBase { // rst: possibly limited to connected subgraphs or to the subgraphs of maximum size. // rst: // rst-class-start: - struct MOD_DECL ComposeCommon : public ComposeBase { ComposeCommon(Expression first, Expression second, bool discardNonchemical, bool maximum, bool connected); bool getMaxmimum() const; @@ -181,7 +168,6 @@ struct MOD_DECL ComposeCommon : public ComposeBase { // rst: Compose the rules by the empty graph, i.e., create a rule representing the parallel application of two input rules. // rst: // rst-class-start: - struct MOD_DECL ComposeParallel : public ComposeBase { ComposeParallel(Expression first, Expression second, bool discardNonchemical); private: @@ -195,7 +181,6 @@ struct MOD_DECL ComposeParallel : public ComposeBase { // rst: The overlap is *partial* if not every connected component of :math:`L_2` is participating in the common subgraph. // rst: // rst-class-start: - struct MOD_DECL ComposeSub : public ComposeBase { ComposeSub(Expression first, Expression second, bool discardNonchemical, bool allowPartial); bool getAllowPartial() const; @@ -212,13 +197,9 @@ struct MOD_DECL ComposeSub : public ComposeBase { // rst: The overlap is *partial* if not every connected component of :math:`R_1` is participating in the common subgraph. // rst: // rst-class-start: - struct MOD_DECL ComposeSuper : public ComposeBase { - ComposeSuper(Expression first, - Expression second, - bool discardNonchemical, - bool allowPartial, - bool enforceConstraints); + ComposeSuper(Expression first, Expression second, + bool discardNonchemical, bool allowPartial, bool enforceConstraints); bool getAllowPartial() const; bool getEnforceConstraints() const; private: @@ -228,10 +209,7 @@ struct MOD_DECL ComposeSuper : public ComposeBase { }; // rst-class-end: -} // namespace RCExp - -} // namespace rule -} // namespace mod +} // namespace mod::rule::RCExp #endif /* MOD_RULE_COMPOSITIONEXPR_H */ diff --git a/libs/libmod/src/mod/rule/ForwardDecl.hpp b/libs/libmod/src/mod/rule/ForwardDecl.hpp index 80fb2ae..acc4cb6 100644 --- a/libs/libmod/src/mod/rule/ForwardDecl.hpp +++ b/libs/libmod/src/mod/rule/ForwardDecl.hpp @@ -1,18 +1,14 @@ #ifndef MOD_RULE_FORWARDDECL_H #define MOD_RULE_FORWARDDECL_H -namespace mod { -namespace rule { +namespace mod::rule { struct Rule; namespace RCExp { struct Expression; } // namespace RCExp -} // namespace rule -namespace lib { -namespace Rules { +} // namespace mod::rule +namespace mod::lib::Rules { struct Real; -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules #endif /* MOD_RULE_FORWARDDECL_H */ \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/GraphInterface.cpp b/libs/libmod/src/mod/rule/GraphInterface.cpp index ddb85e0..2c869f4 100644 --- a/libs/libmod/src/mod/rule/GraphInterface.cpp +++ b/libs/libmod/src/mod/rule/GraphInterface.cpp @@ -8,13 +8,16 @@ #include #include -namespace mod { -namespace rule { +namespace mod::rule { //============================================================================== // Left //============================================================================== +std::ostream &operator<<(std::ostream &s, const Rule::LeftGraph &g) { + return s << "RuleLeftGraph(" << *g.getRule() << ")"; +} + std::size_t Rule::LeftGraph::numVertices() const { using boost::vertices; const auto &graph = get_left(r->getRule().getDPORule()); @@ -33,17 +36,9 @@ std::size_t Rule::LeftGraph::numEdges() const { // Vertex //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Vertex(Rule::LeftGraph, rule, get_left(r->getRule().getDPORule()), r, Rule) -MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule::LeftGraph, rule, get_left(r->getRule().getDPORule()), r) - -Rule::Vertex Rule::LeftGraph::Vertex::getCore() const { - if(isNull()) return Rule::Vertex(); - const auto &graph = get_left(r->getRule().getDPORule()); - using boost::vertices; - auto v = *std::next(vertices(graph).first, vId); - auto vCoreId = get(boost::vertex_index_t(), graph, v); - return Rule::Vertex(r, vCoreId); -} +MOD_GRAPHPIMPL_Define_Vertex(Rule::LeftGraph, RuleLeftGraph, Rule::LeftGraph, + get_left(r->getRule().getDPORule()), r, Rule) +MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule::LeftGraph, get_left(r->getRule().getDPORule()), r) const std::string &Rule::LeftGraph::Vertex::getStringLabel() const { if(!r) throw LogicError("Can not get string label on a null vertex."); @@ -97,35 +92,38 @@ std::string Rule::LeftGraph::Vertex::printStereo() const { } std::string Rule::LeftGraph::Vertex::printStereo(const graph::Printer &p) const { - if(!r) throw LogicError("Can not get radical status on a null vertex."); + if(!r) throw LogicError("Can not print stereo on a null vertex."); const auto &graph = get_graph(get_labelled_left(r->getRule().getDPORule())); using boost::vertices; auto v = *std::next(vertices(graph).first, vId); return lib::IO::Stereo::Write::summary(r->getRule(), v, lib::Rules::Membership::Left, p.getOptions()); } +Rule::Vertex Rule::LeftGraph::Vertex::getCore() const { + if(isNull()) return Rule::Vertex(); + const auto &graph = get_left(r->getRule().getDPORule()); + using boost::vertices; + auto v = *std::next(vertices(graph).first, vId); + auto vCoreId = get(boost::vertex_index_t(), graph, v); + return Rule::Vertex(r, vCoreId); +} + +std::shared_ptr Rule::LeftGraph::Vertex::getRule() const { + if(!r) throw LogicError("Can not get rule on a null vertex."); + return r; +} + //------------------------------------------------------------------------------ // Edge //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Indices(Rule::LeftGraph, rule, get_left(r->getRule().getDPORule()), r, getRule, Rule) +MOD_GRAPHPIMPL_Define_Indices(Rule::LeftGraph, RuleLeftGraph, Rule::LeftGraph, + get_left(r->getRule().getDPORule()), r, Rule) BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); -Rule::Edge Rule::LeftGraph::Edge::getCore() const { - if(isNull()) return Rule::Edge(); - const auto &graph = get_left(r->getRule().getDPORule()); - using boost::vertices; - auto v = *std::next(vertices(graph).first, vId); - auto vCoreId = get(boost::vertex_index_t(), graph, v); - auto e = *std::next(out_edges(v, graph).first, eId); - const auto &es = out_edges(v, get_graph(r->getRule().getDPORule())); - auto eCoreId = std::distance(es.first, std::find(es.first, es.second, e)); - return Rule::Edge(r, vCoreId, eCoreId); -} - const std::string &Rule::LeftGraph::Edge::getStringLabel() const { if(!r) throw LogicError("Can not get string label on a null edge."); const auto &graph = get_left(r->getRule().getDPORule()); @@ -144,11 +142,32 @@ BondType Rule::LeftGraph::Edge::getBondType() const { return r->getRule().getMoleculeState().getLeft()[e]; } +Rule::Edge Rule::LeftGraph::Edge::getCore() const { + if(isNull()) return Rule::Edge(); + const auto &graph = get_left(r->getRule().getDPORule()); + using boost::vertices; + auto v = *std::next(vertices(graph).first, vId); + auto vCoreId = get(boost::vertex_index_t(), graph, v); + auto e = *std::next(out_edges(v, graph).first, eId); + const auto &es = out_edges(v, get_graph(r->getRule().getDPORule())); + auto eCoreId = std::distance(es.first, std::find(es.first, es.second, e)); + return Rule::Edge(r, vCoreId, eCoreId); +} + +std::shared_ptr Rule::LeftGraph::Edge::getRule() const { + if(!r) throw LogicError("Can not get rule on a null edge."); + return r; +} + //============================================================================== // Context //============================================================================== +std::ostream &operator<<(std::ostream &s, const Rule::ContextGraph &g) { + return s << "RuleContextGraph(" << *g.getRule() << ")"; +} + std::size_t Rule::ContextGraph::numVertices() const { using boost::vertices; const auto &graph = get_context(r->getRule().getDPORule()); @@ -167,8 +186,9 @@ std::size_t Rule::ContextGraph::numEdges() const { // Vertex //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Vertex(Rule::ContextGraph, rule, get_context(r->getRule().getDPORule()), r, Rule) -MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule::ContextGraph, rule, get_context(r->getRule().getDPORule()), r) +MOD_GRAPHPIMPL_Define_Vertex(Rule::ContextGraph, RuleContextGraph, Rule::ContextGraph, + get_context(r->getRule().getDPORule()), r, Rule) +MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule::ContextGraph, get_context(r->getRule().getDPORule()), r) Rule::Vertex Rule::ContextGraph::Vertex::getCore() const { if(isNull()) return Rule::Vertex(); @@ -179,11 +199,17 @@ Rule::Vertex Rule::ContextGraph::Vertex::getCore() const { return Rule::Vertex(r, vCoreId); } +std::shared_ptr Rule::ContextGraph::Vertex::getRule() const { + if(!r) throw LogicError("Can not get rule on a null vertex."); + return r; +} + //------------------------------------------------------------------------------ // Edge //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Indices(Rule::ContextGraph, rule, get_context(r->getRule().getDPORule()), r, getRule, Rule) +MOD_GRAPHPIMPL_Define_Indices(Rule::ContextGraph, RuleContextGraph, Rule::ContextGraph, + get_context(r->getRule().getDPORule()), r, Rule) BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); @@ -201,10 +227,19 @@ Rule::Edge Rule::ContextGraph::Edge::getCore() const { return Rule::Edge(r, vCoreId, eCoreId); } +std::shared_ptr Rule::ContextGraph::Edge::getRule() const { + if(!r) throw LogicError("Can not get rule on a null edge."); + return r; +} + //============================================================================== // Right //============================================================================== +std::ostream &operator<<(std::ostream &s, const Rule::RightGraph &g) { + return s << "RuleRightGraph(" << *g.getRule() << ")"; +} + std::size_t Rule::RightGraph::numVertices() const { using boost::vertices; const auto &graph = get_right(r->getRule().getDPORule()); @@ -223,17 +258,9 @@ std::size_t Rule::RightGraph::numEdges() const { // Vertex //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Vertex(Rule::RightGraph, rule, get_right(r->getRule().getDPORule()), r, Rule) -MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule::RightGraph, rule, get_right(r->getRule().getDPORule()), r) - -Rule::Vertex Rule::RightGraph::Vertex::getCore() const { - if(isNull()) return Rule::Vertex(); - const auto &graph = get_right(r->getRule().getDPORule()); - using boost::vertices; - auto v = *std::next(vertices(graph).first, vId); - auto vCoreId = get(boost::vertex_index_t(), graph, v); - return Rule::Vertex(r, vCoreId); -} +MOD_GRAPHPIMPL_Define_Vertex(Rule::RightGraph, RuleRightGraph, Rule::RightGraph, + get_right(r->getRule().getDPORule()), r, Rule) +MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule::RightGraph, get_right(r->getRule().getDPORule()), r) const std::string &Rule::RightGraph::Vertex::getStringLabel() const { if(!r) throw LogicError("Can not get string label on a null vertex."); @@ -275,6 +302,20 @@ bool Rule::RightGraph::Vertex::getRadical() const { return r->getRule().getMoleculeState().getRight()[v].getRadical(); } +Rule::Vertex Rule::RightGraph::Vertex::getCore() const { + if(isNull()) return Rule::Vertex(); + const auto &graph = get_right(r->getRule().getDPORule()); + using boost::vertices; + auto v = *std::next(vertices(graph).first, vId); + auto vCoreId = get(boost::vertex_index_t(), graph, v); + return Rule::Vertex(r, vCoreId); +} + +std::shared_ptr Rule::RightGraph::Vertex::getRule() const { + if(!r) throw LogicError("Can not get rule on a null vertex."); + return r; +} + //------------------------------------------------------------------------------ std::string Rule::RightGraph::Vertex::printStereo() const { @@ -287,7 +328,7 @@ std::string Rule::RightGraph::Vertex::printStereo() const { } std::string Rule::RightGraph::Vertex::printStereo(const graph::Printer &p) const { - if(!r) throw LogicError("Can not get radical status on a null vertex."); + if(!r) throw LogicError("Can not print stereo on a null vertex."); const auto &graph = get_graph(get_labelled_right(r->getRule().getDPORule())); using boost::vertices; auto v = *std::next(vertices(graph).first, vId); @@ -298,24 +339,13 @@ std::string Rule::RightGraph::Vertex::printStereo(const graph::Printer &p) const // Edge //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Indices(Rule::RightGraph, rule, get_right(r->getRule().getDPORule()), r, getRule, Rule) +MOD_GRAPHPIMPL_Define_Indices(Rule::RightGraph, RuleRightGraph, Rule::RightGraph, + get_right(r->getRule().getDPORule()), r, Rule) BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); -Rule::Edge Rule::RightGraph::Edge::getCore() const { - if(isNull()) return Rule::Edge(); - const auto &graph = get_right(r->getRule().getDPORule()); - using boost::vertices; - auto v = *std::next(vertices(graph).first, vId); - auto vCoreId = get(boost::vertex_index_t(), graph, v); - auto e = *std::next(out_edges(v, graph).first, eId); - const auto &es = out_edges(v, get_graph(r->getRule().getDPORule())); - auto eCoreId = std::distance(es.first, std::find(es.first, es.second, e)); - return Rule::Edge(r, vCoreId, eCoreId); -} - const std::string &Rule::RightGraph::Edge::getStringLabel() const { if(!r) throw LogicError("Can not get string label on a null edge."); const auto &graph = get_right(r->getRule().getDPORule()); @@ -338,6 +368,23 @@ BondType Rule::RightGraph::Edge::getBondType() const { return r->getRule().getMoleculeState().getRight()[e]; } +Rule::Edge Rule::RightGraph::Edge::getCore() const { + if(isNull()) return Rule::Edge(); + const auto &graph = get_right(r->getRule().getDPORule()); + using boost::vertices; + auto v = *std::next(vertices(graph).first, vId); + auto vCoreId = get(boost::vertex_index_t(), graph, v); + auto e = *std::next(out_edges(v, graph).first, eId); + const auto &es = out_edges(v, get_graph(r->getRule().getDPORule())); + auto eCoreId = std::distance(es.first, std::find(es.first, es.second, e)); + return Rule::Edge(r, vCoreId, eCoreId); +} + +std::shared_ptr Rule::RightGraph::Edge::getRule() const { + if(!r) throw LogicError("Can not get rule on a null edge."); + return r; +} + //============================================================================== // Core @@ -347,8 +394,9 @@ BondType Rule::RightGraph::Edge::getBondType() const { // Vertex //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Vertex(Rule, rule, r->getRule().getGraph(), r, Rule) -MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule, rule, r->getRule().getGraph(), r) +MOD_GRAPHPIMPL_Define_Vertex(Rule, Rule, std::shared_ptr, + r->getRule().getGraph(), r, Rule) +MOD_GRAPHPIMPL_Define_Vertex_Undirected(Rule, r->getRule().getGraph(), r) Rule::LeftGraph::Vertex Rule::Vertex::getLeft() const { if(isNull()) return LeftGraph::Vertex(); @@ -415,7 +463,8 @@ double Rule::Vertex::get2DY(bool withHydrogens) { // Edge //------------------------------------------------------------------------------ -MOD_GRAPHPIMPL_Define_Indices(Rule, rule, r->getRule().getGraph(), r, getRule, Rule) +MOD_GRAPHPIMPL_Define_Indices(Rule, Rule, std::shared_ptr, + r->getRule().getGraph(), r, Rule) BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); @@ -475,5 +524,4 @@ Rule::RightGraph::Edge Rule::Edge::getRight() const { } else return RightGraph::Edge(); } -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/GraphInterface.hpp b/libs/libmod/src/mod/rule/GraphInterface.hpp index c07b1e0..13f6c5c 100644 --- a/libs/libmod/src/mod/rule/GraphInterface.hpp +++ b/libs/libmod/src/mod/rule/GraphInterface.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_RULE_GRAPHINTERFACE_H -#define MOD_RULE_GRAPHINTERFACE_H +#ifndef MOD_RULE_GRAPHINTERFACE_HPP +#define MOD_RULE_GRAPHINTERFACE_HPP // rst: This header contains the definitions for the graph interface for :cpp:class:`rule::Rule`. // rst: @@ -15,7 +15,8 @@ struct AtomId; struct Isotope; struct Charge; enum class BondType; -namespace rule { +} // namespace mod +namespace mod::rule { // rst: ======================================================================== // rst: Left @@ -25,7 +26,6 @@ namespace rule { // rst: // rst: A proxy object representing the left graph of the rule. // rst-class-start: - struct Rule::LeftGraph { class Vertex; class Edge; @@ -39,10 +39,13 @@ struct Rule::LeftGraph { friend class Rule; LeftGraph(std::shared_ptr r); public: - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: friend bool operator==(const LeftGraph &a, const LeftGraph &b) + // rst: friend bool operator!=(const LeftGraph &a, const LeftGraph &b) + // rst: friend std::ostream &operator<<(std::ostream &s, const LeftGraph &g) // rst: - // rst: :returns: the rule where the graph belongs to. - std::shared_ptr getRule() const; + MOD_DECL friend bool operator==(const LeftGraph &a, const LeftGraph &b) { return a.r == b.r; } + MOD_DECL friend bool operator!=(const LeftGraph &a, const LeftGraph &b) { return a.r != b.r; } + MOD_DECL friend std::ostream &operator<<(std::ostream &s, const LeftGraph &g); // rst: .. function:: std::size_t numVertices() const // rst: // rst: :returns: the number of vertices in the graph. @@ -59,6 +62,10 @@ struct Rule::LeftGraph { // rst: // rst: :returns: a range of all edges in the graph. EdgeRange edges() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule where the graph belongs to. + std::shared_ptr getRule() const; private: std::shared_ptr r; }; @@ -73,7 +80,6 @@ struct Rule::LeftGraph { // rst: // rst: A descriptor of either a vertex in a rule, or a null vertex. // rst-class-start: - class Rule::LeftGraph::Vertex { friend class Rule::Vertex; friend class LeftGraph; @@ -104,15 +110,11 @@ class Rule::LeftGraph::Vertex { // rst: :returns: the index of the vertex. It will be in the range :math:`[0, numVertices[`. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. std::size_t getId() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: LeftGraph getGraph() const // rst: - // rst: :returns: the rule the vertex belongs to. + // rst: :returns: the graph the vertex belongs to. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; - // rst: .. function:: Rule::Vertex getCore() const - // rst: - // rst: :returns: the descriptor for this vertex in the core graph. - Rule::Vertex getCore() const; + LeftGraph getGraph() const; // rst: .. function:: std::size_t getDegree() const // rst: // rst: :returns: the degree of the vertex. @@ -157,6 +159,15 @@ class Rule::LeftGraph::Vertex { // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. std::string printStereo() const; std::string printStereo(const graph::Printer &p) const; + // rst: .. function:: Rule::Vertex getCore() const + // rst: + // rst: :returns: the descriptor for this vertex in the core graph. + Rule::Vertex getCore() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule the vertex belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::shared_ptr getRule() const; private: std::shared_ptr r; std::size_t vId; @@ -167,7 +178,6 @@ class Rule::LeftGraph::Vertex { // rst: // rst: A descriptor of either an edge in a rule, or a null edge. // rst-class-start: - class Rule::LeftGraph::Edge { friend class Rule::Edge; friend class EdgeIterator; @@ -190,15 +200,11 @@ class Rule::LeftGraph::Edge { // rst: // rst: :returns: whether this is a null descriptor or not. bool isNull() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: LeftGraph getGraph() const // rst: - // rst: :returns: the rule the edge belongs to. + // rst: :returns: the graph the edge belongs to. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; - // rst: .. function:: Rule::Edge getCore() const - // rst: - // rst: :returns: the descriptor for this edge in the core graph. - Rule::Edge getCore() const; + LeftGraph getGraph() const; // rst: .. function:: Vertex source() const // rst: // rst: :returns: the source vertex of the edge. @@ -219,6 +225,15 @@ class Rule::LeftGraph::Edge { // rst: :returns: the bond type of the edge. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. BondType getBondType() const; + // rst: .. function:: Rule::Edge getCore() const + // rst: + // rst: :returns: the descriptor for this edge in the core graph. + Rule::Edge getCore() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule the edge belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::shared_ptr getRule() const; private: std::shared_ptr r; std::size_t vId, eId; @@ -234,8 +249,8 @@ class Rule::LeftGraph::Edge { // rst: An iterator for traversing all vertices in a rule. // rst: It models a forward iterator. // rst-class-start: - -class Rule::LeftGraph::VertexIterator : public boost::iterator_facade { +class Rule::LeftGraph::VertexIterator + : public boost::iterator_facade { friend class Rule; VertexIterator(std::shared_ptr r); public: @@ -258,7 +273,6 @@ class Rule::LeftGraph::VertexIterator : public boost::iterator_facade { +class Rule::LeftGraph::EdgeIterator + : public boost::iterator_facade { friend class Rule; EdgeIterator(std::shared_ptr r); public: @@ -307,7 +321,6 @@ class Rule::LeftGraph::EdgeIterator : public boost::iterator_facade { +class Rule::LeftGraph::IncidentEdgeIterator + : public boost::iterator_facade { friend class Rule; IncidentEdgeIterator(std::shared_ptr r, std::size_t vId); public: @@ -355,7 +368,6 @@ class Rule::LeftGraph::IncidentEdgeIterator : public boost::iterator_facade r); public: - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: friend bool operator==(const ContextGraph &a, const ContextGraph &b) + // rst: friend bool operator!=(const ContextGraph &a, const ContextGraph &b) + // rst: friend std::ostream &operator<<(std::ostream &s, const ContextGraph &g) // rst: - // rst: :returns: the rule where the graph belongs to. - std::shared_ptr getRule() const; + MOD_DECL friend bool operator==(const ContextGraph &a, const ContextGraph &b) { return a.r == b.r; } + MOD_DECL friend bool operator!=(const ContextGraph &a, const ContextGraph &b) { return a.r != b.r; } + MOD_DECL friend std::ostream &operator<<(std::ostream &s, const ContextGraph &g); // rst: .. function:: std::size_t numVertices() const // rst: // rst: :returns: the number of vertices in the graph. @@ -415,6 +429,10 @@ struct Rule::ContextGraph { // rst: // rst: :returns: a range of all edges in the graph. EdgeRange edges() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule where the graph belongs to. + std::shared_ptr getRule() const; private: std::shared_ptr r; }; @@ -428,7 +446,6 @@ struct Rule::ContextGraph { // rst: // rst: A descriptor of either a vertex in a rule, or a null vertex. // rst-class-start: - class Rule::ContextGraph::Vertex { friend class Rule; friend class Edge; @@ -458,15 +475,11 @@ class Rule::ContextGraph::Vertex { // rst: :returns: the index of the vertex. It will be in the range :math:`[0, numVertices[`. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. std::size_t getId() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: ContextGraph getGraph() const // rst: - // rst: :returns: the rule the vertex belongs to. + // rst: :returns: the graph the vertex belongs to. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; - // rst: .. function:: Rule::Vertex getCore() const - // rst: - // rst: :returns: the descriptor for this vertex in the core graph. - Rule::Vertex getCore() const; + ContextGraph getGraph() const; // rst: .. function:: std::size_t getDegree() const // rst: // rst: :returns: the degree of the vertex. @@ -477,6 +490,15 @@ class Rule::ContextGraph::Vertex { // rst: :returns: a range of incident edges to this vertex. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. IncidentEdgeRange incidentEdges() const; + // rst: .. function:: Rule::Vertex getCore() const + // rst: + // rst: :returns: the descriptor for this vertex in the core graph. + Rule::Vertex getCore() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule the vertex belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::shared_ptr getRule() const; private: std::shared_ptr r; std::size_t vId; @@ -487,7 +509,6 @@ class Rule::ContextGraph::Vertex { // rst: // rst: A descriptor of either an edge in a rule, or a null edge. // rst-class-start: - class Rule::ContextGraph::Edge { friend class Rule::Edge; friend class EdgeIterator; @@ -510,15 +531,11 @@ class Rule::ContextGraph::Edge { // rst: // rst: :returns: whether this is a null descriptor or not. bool isNull() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: ContextGraph getGraph() const // rst: - // rst: :returns: the rule the edge belongs to. + // rst: :returns: the graph the edge belongs to. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; - // rst: .. function:: Rule::Edge getCore() const - // rst: - // rst: :returns: the descriptor for this edge in the core graph. - Rule::Edge getCore() const; + ContextGraph getGraph() const; // rst: .. function:: Vertex source() const // rst: // rst: :returns: the source vertex of the edge. @@ -529,6 +546,15 @@ class Rule::ContextGraph::Edge { // rst: :returns: the target vertex of the edge. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. Vertex target() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule the edge belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::shared_ptr getRule() const; + // rst: .. function:: Rule::Edge getCore() const + // rst: + // rst: :returns: the descriptor for this edge in the core graph. + Rule::Edge getCore() const; private: std::shared_ptr r; std::size_t vId, eId; @@ -544,8 +570,8 @@ class Rule::ContextGraph::Edge { // rst: An iterator for traversing all vertices in a rule. // rst: It models a forward iterator. // rst-class-start: - -class Rule::ContextGraph::VertexIterator : public boost::iterator_facade { +class Rule::ContextGraph::VertexIterator + : public boost::iterator_facade { friend class Rule; VertexIterator(std::shared_ptr r); public: @@ -568,7 +594,6 @@ class Rule::ContextGraph::VertexIterator : public boost::iterator_facade { +class Rule::ContextGraph::EdgeIterator + : public boost::iterator_facade { friend class Rule; EdgeIterator(std::shared_ptr r); public: @@ -617,7 +642,6 @@ class Rule::ContextGraph::EdgeIterator : public boost::iterator_facade { +class Rule::ContextGraph::IncidentEdgeIterator + : public boost::iterator_facade { friend class Rule; IncidentEdgeIterator(std::shared_ptr r, std::size_t vId); public: @@ -665,7 +689,6 @@ class Rule::ContextGraph::IncidentEdgeIterator : public boost::iterator_facade r); public: - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: friend bool operator==(const RightGraph &a, const RightGraph &b) + // rst: friend bool operator!=(const RightGraph &a, const RightGraph &b) + // rst: friend std::ostream &operator<<(std::ostream &s, const RightGraph &g); // rst: - // rst: :returns: the rule where the graph belongs to. - std::shared_ptr getRule() const; + MOD_DECL friend bool operator==(const RightGraph &a, const RightGraph &b) { return a.r == b.r; } + MOD_DECL friend bool operator!=(const RightGraph &a, const RightGraph &b) { return a.r != b.r; } + MOD_DECL friend std::ostream &operator<<(std::ostream &s, const RightGraph &g); // rst: .. function:: std::size_t numVertices() const // rst: // rst: :returns: the number of vertices in the graph. @@ -725,6 +750,10 @@ struct Rule::RightGraph { // rst: // rst: :returns: a range of all edges in the graph. EdgeRange edges() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule where the graph belongs to. + std::shared_ptr getRule() const; private: std::shared_ptr r; }; @@ -738,7 +767,6 @@ struct Rule::RightGraph { // rst: // rst: A descriptor of either a vertex in a rule, or a null vertex. // rst-class-start: - class Rule::RightGraph::Vertex { friend class Rule; friend class Edge; @@ -768,15 +796,11 @@ class Rule::RightGraph::Vertex { // rst: :returns: the index of the vertex. It will be in the range :math:`[0, numVertices[`. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. std::size_t getId() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: RightGraph getGraph() const // rst: - // rst: :returns: the rule the vertex belongs to. + // rst: :returns: the graph the vertex belongs to. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; - // rst: .. function:: Rule::Vertex getCore() const - // rst: - // rst: :returns: the descriptor for this vertex in the core graph. - Rule::Vertex getCore() const; + RightGraph getGraph() const; // rst: .. function:: std::size_t getDegree() const // rst: // rst: :returns: the degree of the vertex. @@ -821,6 +845,15 @@ class Rule::RightGraph::Vertex { // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. std::string printStereo() const; std::string printStereo(const graph::Printer &p) const; + // rst: .. function:: Rule::Vertex getCore() const + // rst: + // rst: :returns: the descriptor for this vertex in the core graph. + Rule::Vertex getCore() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule the vertex belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::shared_ptr getRule() const; private: std::shared_ptr r; std::size_t vId; @@ -831,7 +864,6 @@ class Rule::RightGraph::Vertex { // rst: // rst: A descriptor of either an edge in a rule, or a null edge. // rst-class-start: - class Rule::RightGraph::Edge { friend class Rule::Edge; friend class EdgeIterator; @@ -854,15 +886,11 @@ class Rule::RightGraph::Edge { // rst: // rst: :returns: whether this is a null descriptor or not. bool isNull() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: RightGraph getGraph() const // rst: // rst: :returns: the rule the edge belongs to. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; - // rst: .. function:: Rule::Edge getCore() const - // rst: - // rst: :returns: the descriptor for this edge in the core graph. - Rule::Edge getCore() const; + RightGraph getGraph() const; // rst: .. function:: Vertex source() const // rst: // rst: :returns: the source vertex of the edge. @@ -883,6 +911,15 @@ class Rule::RightGraph::Edge { // rst: :returns: the bond type of the edge. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. BondType getBondType() const; + // rst: .. function:: std::shared_ptr getRule() const + // rst: + // rst: :returns: the rule the edge belongs to. + // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. + std::shared_ptr getRule() const; + // rst: .. function:: Rule::Edge getCore() const + // rst: + // rst: :returns: the descriptor for this edge in the core graph. + Rule::Edge getCore() const; private: std::shared_ptr r; std::size_t vId, eId; @@ -898,8 +935,8 @@ class Rule::RightGraph::Edge { // rst: An iterator for traversing all vertices in a rule. // rst: It models a forward iterator. // rst-class-start: - -class Rule::RightGraph::VertexIterator : public boost::iterator_facade { +class Rule::RightGraph::VertexIterator + : public boost::iterator_facade { friend class Rule; VertexIterator(std::shared_ptr r); public: @@ -922,7 +959,6 @@ class Rule::RightGraph::VertexIterator : public boost::iterator_facade { +class Rule::RightGraph::EdgeIterator + : public boost::iterator_facade { friend class Rule; EdgeIterator(std::shared_ptr r); public: @@ -971,7 +1007,6 @@ class Rule::RightGraph::EdgeIterator : public boost::iterator_facade { +class Rule::RightGraph::IncidentEdgeIterator + : public boost::iterator_facade { friend class Rule; IncidentEdgeIterator(std::shared_ptr r, std::size_t vId); public: @@ -1019,7 +1054,6 @@ class Rule::RightGraph::IncidentEdgeIterator : public boost::iterator_facade getRule() const + // rst: .. function:: std::shared_ptr getGraph() const + // rst: std::shared_ptr getRule() const // rst: - // rst: :returns: the rule the vertex belongs to. + // rst: :returns: the graph the vertex belongs to, which happens to be the rule object it self. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; + std::shared_ptr getGraph() const; + std::shared_ptr getRule() const { return getGraph(); } // rst: .. function:: LeftGraph::Vertex getLeft() const // rst: // rst: :returns: a null descriptor if this vertex is not in the left graph, @@ -1133,7 +1168,6 @@ class Rule::Vertex { // rst: // rst: A descriptor of either an edge in a rule, or a null edge. // rst-class-start: - class Rule::Edge { friend class Rule::LeftGraph::Edge; friend class Rule::ContextGraph::Edge; @@ -1158,11 +1192,13 @@ class Rule::Edge { // rst: // rst: :returns: whether this is a null descriptor or not. bool isNull() const; - // rst: .. function:: std::shared_ptr getRule() const + // rst: .. function:: std::shared_ptr getGraph() const + // rst: std::shared_ptr getRule() const // rst: - // rst: :returns: the rule the edge belongs to. + // rst: :returns: the rule the edge belongs to, which happens to be the rule object it self. // rst: :throws: :cpp:class:`LogicError` if it is a null descriptor. - std::shared_ptr getRule() const; + std::shared_ptr getGraph() const; + std::shared_ptr getRule() const { return getGraph(); } // rst: .. function:: LeftGraph::Edge getLeft() const // rst: // rst: :returns: a null descriptor if this edge is not in the left graph, @@ -1203,7 +1239,6 @@ class Rule::Edge { // rst: An iterator for traversing all vertices in a rule. // rst: It models a forward iterator. // rst-class-start: - class Rule::VertexIterator : public boost::iterator_facade { friend class Rule; VertexIterator(std::shared_ptr r); @@ -1227,7 +1262,6 @@ class Rule::VertexIterator : public boost::iterator_facade { friend class Rule; EdgeIterator(std::shared_ptr r); @@ -1277,7 +1310,6 @@ class Rule::EdgeIterator : public boost::iterator_facade { +class Rule::IncidentEdgeIterator + : public boost::iterator_facade { friend class Rule; IncidentEdgeIterator(std::shared_ptr r, std::size_t vId); public: @@ -1325,7 +1357,6 @@ class Rule::IncidentEdgeIterator : public boost::iterator_facade r) : r(r) { } - -inline std::shared_ptr Rule::LeftGraph::getRule() const { - return r; -} +inline Rule::LeftGraph::LeftGraph(std::shared_ptr r) : r(r) {} inline Rule::LeftGraph::VertexRange Rule::LeftGraph::vertices() const { return VertexRange(r); @@ -1364,10 +1391,14 @@ inline Rule::LeftGraph::EdgeRange Rule::LeftGraph::edges() const { return EdgeRange(r); } +inline std::shared_ptr Rule::LeftGraph::getRule() const { + return r; +} + // VertexRange //------------------------------------------------------------------------------ -inline Rule::LeftGraph::VertexRange::VertexRange(std::shared_ptr r) : r(r) { } +inline Rule::LeftGraph::VertexRange::VertexRange(std::shared_ptr r) : r(r) {} inline Rule::LeftGraph::VertexIterator Rule::LeftGraph::VertexRange::begin() const { return VertexIterator(r); @@ -1380,7 +1411,7 @@ inline Rule::LeftGraph::VertexIterator Rule::LeftGraph::VertexRange::end() const // EdgeRange //------------------------------------------------------------------------------ -inline Rule::LeftGraph::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) { } +inline Rule::LeftGraph::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) {} inline Rule::LeftGraph::EdgeIterator Rule::LeftGraph::EdgeRange::begin() const { return EdgeIterator(r); @@ -1393,7 +1424,8 @@ inline Rule::LeftGraph::EdgeIterator Rule::LeftGraph::EdgeRange::end() const { // IncidentEdgeRange //------------------------------------------------------------------------------ -inline Rule::LeftGraph::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), vId(vId) { } +inline Rule::LeftGraph::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), + vId(vId) {} inline Rule::LeftGraph::IncidentEdgeIterator Rule::LeftGraph::IncidentEdgeRange::begin() const { return IncidentEdgeIterator(r, vId); @@ -1407,11 +1439,7 @@ inline Rule::LeftGraph::IncidentEdgeIterator Rule::LeftGraph::IncidentEdgeRange: // Context //============================================================================== -inline Rule::ContextGraph::ContextGraph(std::shared_ptr r) : r(r) { } - -inline std::shared_ptr Rule::ContextGraph::getRule() const { - return r; -} +inline Rule::ContextGraph::ContextGraph(std::shared_ptr r) : r(r) {} inline Rule::ContextGraph::VertexRange Rule::ContextGraph::vertices() const { return VertexRange(r); @@ -1421,10 +1449,14 @@ inline Rule::ContextGraph::EdgeRange Rule::ContextGraph::edges() const { return EdgeRange(r); } +inline std::shared_ptr Rule::ContextGraph::getRule() const { + return r; +} + // VertexRange //------------------------------------------------------------------------------ -inline Rule::ContextGraph::VertexRange::VertexRange(std::shared_ptr r) : r(r) { } +inline Rule::ContextGraph::VertexRange::VertexRange(std::shared_ptr r) : r(r) {} inline Rule::ContextGraph::VertexIterator Rule::ContextGraph::VertexRange::begin() const { return VertexIterator(r); @@ -1437,7 +1469,7 @@ inline Rule::ContextGraph::VertexIterator Rule::ContextGraph::VertexRange::end() // EdgeRange //------------------------------------------------------------------------------ -inline Rule::ContextGraph::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) { } +inline Rule::ContextGraph::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) {} inline Rule::ContextGraph::EdgeIterator Rule::ContextGraph::EdgeRange::begin() const { return EdgeIterator(r); @@ -1450,7 +1482,8 @@ inline Rule::ContextGraph::EdgeIterator Rule::ContextGraph::EdgeRange::end() con // IncidentEdgeRange //------------------------------------------------------------------------------ -inline Rule::ContextGraph::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), vId(vId) { } +inline Rule::ContextGraph::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), + vId(vId) {} inline Rule::ContextGraph::IncidentEdgeIterator Rule::ContextGraph::IncidentEdgeRange::begin() const { return IncidentEdgeIterator(r, vId); @@ -1464,11 +1497,7 @@ inline Rule::ContextGraph::IncidentEdgeIterator Rule::ContextGraph::IncidentEdge // Right //============================================================================== -inline Rule::RightGraph::RightGraph(std::shared_ptr r) : r(r) { } - -inline std::shared_ptr Rule::RightGraph::getRule() const { - return r; -} +inline Rule::RightGraph::RightGraph(std::shared_ptr r) : r(r) {} inline Rule::RightGraph::VertexRange Rule::RightGraph::vertices() const { return VertexRange(r); @@ -1478,11 +1507,15 @@ inline Rule::RightGraph::EdgeRange Rule::RightGraph::edges() const { return EdgeRange(r); } +inline std::shared_ptr Rule::RightGraph::getRule() const { + return r; +} + // VertexRange //------------------------------------------------------------------------------ -inline Rule::RightGraph::VertexRange::VertexRange(std::shared_ptr r) : r(r) { } +inline Rule::RightGraph::VertexRange::VertexRange(std::shared_ptr r) : r(r) {} inline Rule::RightGraph::VertexIterator Rule::RightGraph::VertexRange::begin() const { return VertexIterator(r); @@ -1495,7 +1528,7 @@ inline Rule::RightGraph::VertexIterator Rule::RightGraph::VertexRange::end() con // EdgeRange //------------------------------------------------------------------------------ -inline Rule::RightGraph::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) { } +inline Rule::RightGraph::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) {} inline Rule::RightGraph::EdgeIterator Rule::RightGraph::EdgeRange::begin() const { return EdgeIterator(r); @@ -1509,7 +1542,8 @@ inline Rule::RightGraph::EdgeIterator Rule::RightGraph::EdgeRange::end() const { // IncidentEdgeRange //------------------------------------------------------------------------------ -inline Rule::RightGraph::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), vId(vId) { } +inline Rule::RightGraph::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), + vId(vId) {} inline Rule::RightGraph::IncidentEdgeIterator Rule::RightGraph::IncidentEdgeRange::begin() const { return IncidentEdgeIterator(r, vId); @@ -1526,7 +1560,7 @@ inline Rule::RightGraph::IncidentEdgeIterator Rule::RightGraph::IncidentEdgeRang // VertexRange //------------------------------------------------------------------------------ -inline Rule::VertexRange::VertexRange(std::shared_ptr r) : r(r) { } +inline Rule::VertexRange::VertexRange(std::shared_ptr r) : r(r) {} inline Rule::VertexIterator Rule::VertexRange::begin() const { return VertexIterator(r); @@ -1543,7 +1577,7 @@ inline Rule::Vertex Rule::VertexRange::operator[](std::size_t i) const { // EdgeRange //------------------------------------------------------------------------------ -inline Rule::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) { } +inline Rule::EdgeRange::EdgeRange(std::shared_ptr r) : r(r) {} inline Rule::EdgeIterator Rule::EdgeRange::begin() const { return EdgeIterator(r); @@ -1556,7 +1590,7 @@ inline Rule::EdgeIterator Rule::EdgeRange::end() const { // IncidentEdgeRange //------------------------------------------------------------------------------ -inline Rule::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), vId(vId) { } +inline Rule::IncidentEdgeRange::IncidentEdgeRange(std::shared_ptr r, std::size_t vId) : r(r), vId(vId) {} inline Rule::IncidentEdgeIterator Rule::IncidentEdgeRange::begin() const { return IncidentEdgeIterator(r, vId); @@ -1566,42 +1600,34 @@ inline Rule::IncidentEdgeIterator Rule::IncidentEdgeRange::end() const { return IncidentEdgeIterator(); } -} // namespace rule -} // namespace mod -namespace std { +} // namespace mod::rule template<> -struct hash { - +struct std::hash { std::size_t operator()(const mod::rule::Rule::Vertex &v) const { return v.hash(); } }; template<> -struct hash { - +struct std::hash { std::size_t operator()(const mod::rule::Rule::Vertex &v) const { return v.hash(); } }; template<> -struct hash { - +struct std::hash { std::size_t operator()(const mod::rule::Rule::Vertex &v) const { return v.hash(); } }; template<> -struct hash { - +struct std::hash { std::size_t operator()(const mod::rule::Rule::Vertex &v) const { return v.hash(); } }; -} // namespace std - -#endif /* MOD_RULE_GRAPHINTERFACE_H */ +#endif // MOD_RULE_GRAPHINTERFACE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/Rule.cpp b/libs/libmod/src/mod/rule/Rule.cpp index 941c8f2..ff05b59 100644 --- a/libs/libmod/src/mod/rule/Rule.cpp +++ b/libs/libmod/src/mod/rule/Rule.cpp @@ -10,18 +10,18 @@ #include #include +#include + #include +#include #include -namespace mod { -namespace rule { +namespace mod::rule { struct Rule::Pimpl { - Pimpl(std::unique_ptr r) : r(std::move(r)) { assert(this->r); } - public: const std::unique_ptr r; std::unique_ptr > externalToInternalIds; @@ -80,7 +80,7 @@ std::shared_ptr Rule::makeInverse() const { if(getConfig().rule.ignoreConstraintsDuringInversion.get()) { if(dpoRule.leftMatchConstraints.size() > 0 || dpoRule.rightMatchConstraints.size() > 0) { - lib::IO::log() << "WARNING: inversion of rule strips constraints.\n"; + std::cout << "WARNING: inversion of rule strips constraints.\n"; } } else { if(dpoRule.leftMatchConstraints.size() > 0) { @@ -213,9 +213,9 @@ std::shared_ptr handleLoadedRule(lib::IO::Rules::Read::Data &&data, assert(data.rule->pString); if(invert) { if(!data.rule->leftMatchConstraints.empty()) { - if(getConfig().rule.ignoreConstraintsDuringInversion.get()) lib::IO::log() << "WARNING: "; + if(getConfig().rule.ignoreConstraintsDuringInversion.get()) std::cout << "WARNING: "; bool ignore = getConfig().rule.ignoreConstraintsDuringInversion.get(); - std::ostream &stream = ignore ? lib::IO::log() : err; + std::ostream &stream = ignore ? std::cout : err; stream << "The rule '"; if(data.name) stream << data.name.get(); else stream << "anon"; @@ -240,16 +240,16 @@ std::shared_ptr handleLoadedRule(lib::IO::Rules::Read::Data &&data, } // namespace std::shared_ptr Rule::ruleGMLString(const std::string &data, bool invert) { - std::istringstream ss(data); std::ostringstream err; - return handleLoadedRule(lib::IO::Rules::Read::gml(ss, err), invert, "", err); + return handleLoadedRule(lib::IO::Rules::Read::gml(data, err), invert, "", err); } std::shared_ptr Rule::ruleGML(const std::string &file, bool invert) { - std::ifstream ifs(file); + boost::iostreams::mapped_file_source ifs(file); if(!ifs) throw InputError("Could not open rule GML file '" + file + "'.\n"); std::ostringstream err; - return handleLoadedRule(lib::IO::Rules::Read::gml(ifs, err), invert, "file '" + file + "'", err); + return handleLoadedRule(lib::IO::Rules::Read::gml({ifs.begin(), ifs.size()}, err), + invert, "file '" + file + "'", err); } std::shared_ptr Rule::makeRule(std::unique_ptr r) { @@ -267,5 +267,4 @@ std::shared_ptr Rule::makeRule(std::unique_ptr r, return rWrapped; } -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/Rule.hpp b/libs/libmod/src/mod/rule/Rule.hpp index 41fcc1c..5e5fc25 100644 --- a/libs/libmod/src/mod/rule/Rule.hpp +++ b/libs/libmod/src/mod/rule/Rule.hpp @@ -1,5 +1,5 @@ -#ifndef MOD_RULE_RULE_H -#define MOD_RULE_RULE_H +#ifndef MOD_RULE_RULE_HPP +#define MOD_RULE_RULE_HPP #include #include @@ -13,8 +13,7 @@ #include #include -namespace mod { -namespace rule { +namespace mod::rule { // rst-class: rule::Rule // rst: @@ -37,8 +36,8 @@ struct MOD_DECL Rule { class ContextGraph; class RightGraph; private: - Rule(Rule&&) = delete; - Rule &operator=(Rule&&) = delete; + Rule(Rule &&) = delete; + Rule &operator=(Rule &&) = delete; private: Rule(std::unique_ptr r); public: @@ -192,7 +191,8 @@ struct MOD_DECL Rule { // rst: // rst: :returns: a rule wrapping the given internal rule object. If an id mapping is given, it will be used for the :cpp:func:`getVertexFromExternalId` function. static std::shared_ptr makeRule(std::unique_ptr r); - static std::shared_ptr makeRule(std::unique_ptr r, std::map externalToInternalIds); + static std::shared_ptr + makeRule(std::unique_ptr r, std::map externalToInternalIds); private: struct Pimpl; std::unique_ptr p; @@ -200,13 +200,11 @@ struct MOD_DECL Rule { // rst-class-end: struct RuleLess { - bool operator()(std::shared_ptr r1, std::shared_ptr r2) const { return r1->getId() < r2->getId(); } }; -} // namespace rule -} // namespace mod +} // namespace mod::rule -#endif /* MOD_RULE_RULE_H */ +#endif // MOD_RULE_RULE_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/internal/ForwardDecl.hpp b/libs/libmod/src/mod/rule/internal/ForwardDecl.hpp index b0d8d9f..d285346 100644 --- a/libs/libmod/src/mod/rule/internal/ForwardDecl.hpp +++ b/libs/libmod/src/mod/rule/internal/ForwardDecl.hpp @@ -1,12 +1,8 @@ #ifndef MOD_RULE_INTERNAL_FORWARDDECL_HPP #define MOD_RULE_INTERNAL_FORWARDDECL_HPP -namespace mod { -namespace lib { -namespace Rules { +namespace mod::lib::Rules { -} // namespace Rules -} // namespace lib -} // namespace mod +} // namespace mod::lib::Rules #endif // MOD_RULE_INTERNAL_FORWARDDECL_HPP \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/internal/Rule.cpp b/libs/libmod/src/mod/rule/internal/Rule.cpp index 37f00dc..65b450b 100644 --- a/libs/libmod/src/mod/rule/internal/Rule.cpp +++ b/libs/libmod/src/mod/rule/internal/Rule.cpp @@ -3,9 +3,7 @@ #include #include -namespace mod { -namespace rule { -namespace internal { +namespace mod::rule::internal { lib::Rules::LabelledRule makeLabelledRule() { return lib::Rules::LabelledRule(); @@ -44,6 +42,4 @@ std::shared_ptr makeRule(lib::Rules::LabelledRule &&r) { return mod::rule::Rule::makeRule(std::move(rLib)); } -} // namespace internal -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule::internal \ No newline at end of file diff --git a/libs/libmod/src/mod/rule/internal/Rule.hpp b/libs/libmod/src/mod/rule/internal/Rule.hpp index dc60722..c28e5a6 100644 --- a/libs/libmod/src/mod/rule/internal/Rule.hpp +++ b/libs/libmod/src/mod/rule/internal/Rule.hpp @@ -5,9 +5,7 @@ #include #include -namespace mod { -namespace rule { -namespace internal { +namespace mod::rule::internal { MOD_DECL lib::Rules::LabelledRule makeLabelledRule(); MOD_DECL lib::Rules::GraphType &getGraph(lib::Rules::LabelledRule &r); @@ -24,8 +22,6 @@ makePropMoleculeCore(const lib::Rules::GraphType &g, const lib::Rules::PropStrin MOD_DECL std::shared_ptr makeRule(lib::Rules::LabelledRule &&r); -} // namespace internal -} // namespace rule -} // namespace mod +} // namespace mod::rule::internal #endif // MOD_RULE_INTERNAL_RULE_HPP diff --git a/libs/post_mod/CMakeLists.txt b/libs/post_mod/CMakeLists.txt index bdbc30e..69c306b 100644 --- a/libs/post_mod/CMakeLists.txt +++ b/libs/post_mod/CMakeLists.txt @@ -10,25 +10,29 @@ install(PROGRAMS bin/mod_post DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT post_mod_run) -# commonPreamble.fmt -add_custom_target(commonPreamble ALL - pdflatex - -interaction=nonstopmode - -halt-on-error - -ini - '&pdflatex \\input{${CMAKE_CURRENT_LIST_DIR}/share/mod/commonPreamble.tex}\\usepackage{${CMAKE_CURRENT_LIST_DIR}/share/mod/mod}\\dump' - DEPENDS share/mod/commonPreamble.tex share/mod/mod.sty - BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/share/mod/commonPreamble.fmt - COMMENT "Precompiling Latex preamble (commonPreamble.fmt)") +if(BUILD_POST_MOD_FMT) + # commonPreamble.fmt + add_custom_target(commonPreamble ALL + pdflatex + -interaction=nonstopmode + -halt-on-error + -ini + '&pdflatex \\input{${CMAKE_CURRENT_LIST_DIR}/share/mod/commonPreamble.tex}\\usepackage{${CMAKE_CURRENT_LIST_DIR}/share/mod/mod}\\dump' + DEPENDS share/mod/commonPreamble.tex share/mod/mod.sty + BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/share/mod/commonPreamble.fmt + COMMENT "Pre-compiling Latex preamble (commonPreamble.fmt)") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/commonPreamble.fmt + DESTINATION ${CMAKE_INSTALL_DATADIR}/mod + COMPONENT post_mod_run) +endif() install(FILES - ${CMAKE_CURRENT_BINARY_DIR}/commonPreamble.fmt - share/mod/commonPreamble.tex - share/mod/figureTemplate.tex - share/mod/summary.tex - DESTINATION ${CMAKE_INSTALL_DATADIR}/mod - COMPONENT post_mod_run) + share/mod/commonPreamble.tex + share/mod/figureTemplate.tex + share/mod/summary.tex + DESTINATION ${CMAKE_INSTALL_DATADIR}/mod + COMPONENT post_mod_run) # Makefile template and Latex package install(FILES share/mod/mod.mk share/mod/mod.sty DESTINATION ${CMAKE_INSTALL_DATADIR}/mod - COMPONENT post_mod_run) \ No newline at end of file + COMPONENT post_mod_run) diff --git a/libs/post_mod/bin/mod_post b/libs/post_mod/bin/mod_post index dc6981c..543bb0a 100755 --- a/libs/post_mod/bin/mod_post +++ b/libs/post_mod/bin/mod_post @@ -32,6 +32,9 @@ function printHelp { echo "Options:" echo " --help, -h Show this message." echo " -j Use '-j ' as argument when calling make." + echo " --install-format, --install-format-sudo" + echo " Compile the common Latex preamble and install it." + echo " The '-sudo' version will run the copying through with sudo." echo " --mode ... Enter a magic mode for data conversion." } @@ -62,9 +65,26 @@ fi -if test "x$1" == "xclean"; then +if test "x$1" = xclean; then $this --mode clean exit $? +elif test "x$1" = "x--install-format" -o "x$1" = "x--install-format-sudo"; then + echo "Compiling common Latex preamble into format file: " + mkdir -p out + rm -f out/commonPreamble.fmt + $this --mode compileFmt + res=$? + echo "" + if [ $res -ne 0 ]; then + exit $res + fi + p=$MOD_PREFIX/share/mod/ + echo "Installing out/commonPreamble.fmt in $p" + if [ "x$1" = "x--install-format" ]; then + cp out/commonPreamble.fmt $p + else + sudo cp out/commonPreamble.fmt $p + fi elif test "x$1" != "x--mode"; then echo "PostMØD ------------------------------------------------------------" echo "Prefix: $MOD_PREFIX" @@ -162,6 +182,15 @@ else # $1 == --mode echo "include $makefileClean" >> $makefile } function initMakefileImpl { + local p=$MOD_PREFIX/share/mod/commonPreamble + if [ -f $p.fmt ]; then + if [ ! -f out/commonPreamble.fmt ]; then + ln -s $p.fmt out/commonPreamble.fmt + fi + else + echo "out/commonPreamble.fmt: $p.tex" + echo " $this --mode compileFmt" + fi echo "" } function initMakefileDep { @@ -382,6 +411,7 @@ else # $1 == --mode echo -n "$fileNoExt.pdf:" >> $makefileImpl echo -n " $fileCoordNoExt.tex" >> $makefileImpl echo -n " $fileNoExt.tex" >> $makefileImpl + echo -n " out/commonPreamble.fmt" >> $makefileImpl echo "" >> $makefileImpl echo " $this --mode compileTikz \"$fileNoExt\" \"$fileCoordNoExt\" $repeats" >> $makefileImpl echo -n " $fileNoExt.pdf" >> $makefileDep @@ -450,6 +480,15 @@ else # $1 == --mode echo '' || $latexCmd } + function compileFmt { + printStatus "$FUNCNAME" + local texArgs="-interaction=nonstopmode -halt-on-error -ini" + texArgs="$texArgs -output-directory out/ -jobname commonPreamble" + local texContent="&pdflatex \\input{$MOD_PREFIX/share/mod/commonPreamble.tex}\\usepackage{$MOD_PREFIX/share/mod/mod}\\dump" + latexCmd="pdflatex $texArgs $texContent" + $latexCmd &> /dev/null || $latexCmd + } + dimensionTooLargeString="\\dontUseTooLargeCoords" # fileNoExt fileCoordsNoExt [compilation repetitions] @@ -468,7 +507,7 @@ else # $1 == --mode fi fi local latexArgs="-interaction=nonstopmode -halt-on-error" - latexArgs="$latexArgs -jobname $fileNoExt -fmt $MOD_PREFIX/share/mod/commonPreamble.fmt \"\\newcommand{\modPrefix}{$MOD_PREFIX}\\newcommand{\modFigureInput}{$fileNoExt.tex}\input{\modPrefix/share/mod/$texFigureTemplateFile}\"" + latexArgs="$latexArgs -jobname $fileNoExt -fmt out/commonPreamble.fmt \"\\newcommand{\modPrefix}{$MOD_PREFIX}\\newcommand{\modFigureInput}{$fileNoExt.tex}\input{\modPrefix/share/mod/$texFigureTemplateFile}\"" local latexCmd="pdflatex $latexArgs" for i in $(seq $repeats); do $latexCmd &> /dev/null diff --git a/libs/post_mod/share/mod/summary.tex b/libs/post_mod/share/mod/summary.tex index 6330d8d..31b6af3 100644 --- a/libs/post_mod/share/mod/summary.tex +++ b/libs/post_mod/share/mod/summary.tex @@ -293,6 +293,43 @@ \end{figure} } + + +% ruleLabel +\newcommand\rcMatchArrow[1]{% + \begin{tikzpicture}[node distance=20pt, baseline={(A.center)}] + \node (A) {}; + \node (B) [right=of A] {}; + \draw[->, >=stealth] (A) to node[above] {#1} (B); + \end{tikzpicture}% +}% +% filePrefixFirst ruleIdFirst +% mapping +% filePrefixSecond ruleIdSecond +% filePrefixNew ruleIdNew +\newcommand\rcMatchFig[7]{% + \newpage% + \subsection{RC Match, $r_{#2} \bullet r_{#5} = r_{#7}$} + \input{\modInputPrefix/#1_L.tex}% + \rcMatchArrow{$r_{#2}$}% + \input{\modInputPrefix/#1_R.tex}% + \\ + \mbox{}\hfill% + \input{\modInputPrefix/#4_L.tex}% + \begin{tikzpicture}[remember picture, overlay] + \foreach \s/\t in {#3} + \path[modRCMatchEdge] (v-\s) to[modRCMatchEdgeTo] (v-\t); + \end{tikzpicture}% + \rcMatchArrow{$r_{#5}$}% + \input{\modInputPrefix/#4_R.tex}% + \\ + \input{\modInputPrefix/#6_L.tex}% + \rcMatchArrow{$r_{#7}$}% + \input{\modInputPrefix/#6_R.tex}% + \\ +}% + + \lstdefinelanguage{pseudo}{morekeywords={function,return,for,if,while,end,each,in,add,to,else,do,length}} \lstset{basicstyle=\small,tabsize=2,breaklines=true,numbers=left} %\lstinputlisting{fil} diff --git a/libs/pymod/CMakeLists.txt b/libs/pymod/CMakeLists.txt index f3d5bc1..8dd8f27 100644 --- a/libs/pymod/CMakeLists.txt +++ b/libs/pymod/CMakeLists.txt @@ -17,7 +17,12 @@ target_include_directories(pymod $ $) target_link_libraries(pymod PUBLIC mod::libmod Boost::${PYTHON_TARGET} Python3::Python) -target_link_libraries(pymod PRIVATE -Wl,--no-undefined) +target_link_libraries(pymod PRIVATE + $<$:-Wl,--no-undefined> + $<$:-Wl,--no-undefined> + #$<$:-Wl,--no-undefined> # TODO: is there an equivalent? + ) +set_target_properties(pymod PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") target_compile_options(pymod PRIVATE -Wall -Wextra -Wno-unused-parameter -Wno-comment @@ -56,7 +61,7 @@ install(FILES ${exportDir}/00_mod.in install(DIRECTORY lib/mod DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT pymod_run - FILES_MATCHING PATTERN "*.py") + FILES_MATCHING PATTERN "*.py" PATTERN "*.pyi") # mod diff --git a/libs/pymod/bin/mod.in b/libs/pymod/bin/mod.in index da20ecd..c880625 100755 --- a/libs/pymod/bin/mod.in +++ b/libs/pymod/bin/mod.in @@ -224,8 +224,6 @@ done # Create precommand (gdb/valgrind/...) precommand="" if [ $profile = "true" -o $memcheck = "true" ]; then - echo "Exporting environment for memcheck: PYTHONMALLOC=malloc" - export PYTHONMALLOC=malloc precommand="valgrind" fi if [ $profile = "true" ]; then diff --git a/libs/pymod/lib/mod/__init__.py b/libs/pymod/lib/mod/__init__.py index 2883c24..809d33f 100644 --- a/libs/pymod/lib/mod/__init__.py +++ b/libs/pymod/lib/mod/__init__.py @@ -4,14 +4,19 @@ import inspect import math import sys +from typing import ( + Any, Callable, cast, Generic, Iterable, List, Optional, Sequence, Tuple, + Type, TypeVar, Union +) _oldFlags = sys.getdlopenflags() sys.setdlopenflags(_oldFlags | ctypes.RTLD_GLOBAL) +from . import libpymod from .libpymod import * sys.setdlopenflags(_oldFlags) # from http://mail.python.org/pipermail/tutor/2003-November/026645.html -class Unbuffered(object): +class _Unbuffered: def __init__(self, stream): self.stream = stream def write(self, data): @@ -19,7 +24,7 @@ def write(self, data): self.stream.flush() def __getattr__(self, attr): return getattr(self.stream, attr) -sys.stdout = Unbuffered(sys.stdout) +sys.stdout = _Unbuffered(sys.stdout) # type: ignore def _NoNew__setattr__(self, name, value): if hasattr(self, "_frozen") and self._frozen: @@ -34,11 +39,11 @@ def _NoNew__setattr__(self, name, value): raise AttributeError(msg) -def _fixClass(name, c, indent): - if not name.startswith("Func_"): +def _fixClass(name, c, indent) -> None: + if not name.startswith("_Func_"): c.__setattr__ = _NoNew__setattr__ - if name.startswith("Func_") or name.startswith("Vec"): + if name.startswith("_Func_") or name.startswith("_Vec"): c.__hash__ = None elif name.endswith("Vertex"): assert c.__hash__ is not None and c.__hash__ != object.__hash__ @@ -48,7 +53,7 @@ def _fixClass(name, c, indent): elif c.__hash__ == object.__hash__: c.__hash__ = None - if not (name.startswith("Func_") or name.startswith("Vec")): + if not (name.startswith("_Func_") or name.startswith("_Vec")): if name.endswith("Vertex") or name.endswith("Edge"): assert c.__bool__ is not None @@ -56,14 +61,13 @@ def _fixClass(name, c, indent): if a[0] == "__class__": continue _fixClass(a[0], a[1], indent + 1) -classes = inspect.getmembers(sys.modules[__name__], inspect.isclass) +classes = inspect.getmembers(libpymod, inspect.isclass) for c in classes: - if c[1] == Unbuffered: continue _fixClass(c[0], c[1], 0) #---------------------------------------------------------- -def _deprecation(msg): +def _deprecation(msg) -> None: if config.common.ignoreDeprecation: print("WARNING: {} Use config.common.ignoreDeprecation = False to make this an exception.".format(msg)) else: @@ -74,17 +78,17 @@ def _deprecation(msg): #---------------------------------------------------------- class CWDPath: - def __init__(self, f): + def __init__(self, f) -> None: self.f = f -_filePrefixes = [] +_filePrefixes: List[str] = [] -def prefixFilename(name): +def prefixFilename(name: str) -> str: if isinstance(name, CWDPath): return name.f if len(name) == 0 or name[0] == '/': return name - prefixed = [] + prefixed: List[str] = [] for s in _filePrefixes: if len(s) != 0 and s[0] == '/': prefixed[:] = [s] @@ -93,10 +97,10 @@ def prefixFilename(name): prefixed.append(name) return ''.join(prefixed) -def pushFilePrefix(prefix): +def pushFilePrefix(prefix: str) -> None: _filePrefixes.append(prefix) -def popFilePrefix(): +def popFilePrefix() -> None: if len(_filePrefixes) == 0: raise LogicError("popFilePrefix failed; the stack is empty") _filePrefixes.pop() @@ -106,33 +110,31 @@ def popFilePrefix(): # Wrappers #---------------------------------------------------------- -def _wrap(C, l): - if type(l) is C: +def _wrap(C: Type["Vec[T]"], l: Union["Vec[T]", Iterable["T"]]) -> "Vec[T]": + if isinstance(l, C): return l lcpp = C() - lcpp.extend(a for a in l) + lcpp.extend(l) return lcpp -def _unwrap(lcpp): - l = [] - l.extend(a for a in lcpp) +def _unwrap(lcpp: Iterable["T"]) -> List["T"]: + l: List[T] = [] + l.extend(lcpp) return l -def _funcWrap(F, f, resultWrap=None, module=libpymod): - if isinstance(f, F): - res = f - elif hasattr(f, "__call__"): # wrap functor - class FuncWrapper(F): - def __init__(self, f): +def _funcWrap(F: Type["U"], f: Union["T", Callable], resultWrap: Optional[Type["Vec[T]"]] = None, module=libpymod) -> "U": + if hasattr(f, "__call__"): + class FuncWrapper(F): # type: ignore + def __init__(self, f) -> None: self.f = f F.__init__(self) - def clone(self): + def clone(self) -> "FuncWrapper": return module._sharedToStd(FuncWrapper(self.f)) - def __str__(self): + def __str__(self) -> str: lines, lnum = inspect.getsourcelines(self.f) source = ''.join(lines) filename = inspect.getfile(self.f) return "FuncWrapper(%s)\nCode from %s:%d >>>>>\n%s<<<<< Code from %s:%d" % (str(self.f), filename, lnum, source, filename, lnum) - def __call__(self, *args): + def __call__(self, *args) -> Union["T", "Vec[T]"]: try: if resultWrap is not None: return _wrap(resultWrap, self.f(*args)) @@ -145,60 +147,64 @@ def __call__(self, *args): res = FuncWrapper(f) else: # assume constant - class Constant(F): - def __init__(self, c): + class Constant(F): # type: ignore + def __init__(self, c) -> None: self.c = c F.__init__(self) - def clone(self): + def clone(self) -> "Constant": return module._sharedToStd(Constant(self.c)) - def __str__(self): + def __str__(self) -> str: return "Constant(" + str(self.c) + ")" - def __call__(self, *args): + def __call__(self, *args) -> "T": return self.c res = Constant(f) return module._sharedToStd(res) + ########################################################### # Chem ########################################################### -BondType.__str__ = libpymod._bondTypeToString +BondType.__str__ = libpymod._bondTypeToString # type: ignore + ########################################################### # Config ########################################################### -LabelType.__str__ = libpymod._LabelType__str__ -LabelRelation.__str__ = libpymod._LabelRelation__str__ -IsomorphismPolicy.__str__ = libpymod._IsomorphismPolicy__str__ -SmilesClassPolicy.__str__ = libpymod._SmilesClassPolicy__str__ +LabelType.__str__ = libpymod._LabelType__str__ # type: ignore +LabelRelation.__str__ = libpymod._LabelRelation__str__ # type: ignore +IsomorphismPolicy.__str__ = libpymod._IsomorphismPolicy__str__ # type: ignore +SmilesClassPolicy.__str__ = libpymod._SmilesClassPolicy__str__ # type: ignore config = getConfig() + ########################################################### # Derivation ########################################################### -Derivation.__repr__ = Derivation.__str__ +Derivation.__repr__ = Derivation.__str__ # type: ignore -def _Derivation__setattr__(self, name, value): +def _Derivation__setattr__(self, name, value) -> None: if name in ("left", "right"): - object.__setattr__(self, name, _wrap(VecGraph, value)) + object.__setattr__(self, name, _wrap(libpymod._VecGraph, value)) else: _NoNew__setattr__(self, name, value) -Derivation.__setattr__ = _Derivation__setattr__ +Derivation.__setattr__ = _Derivation__setattr__ # type: ignore -Derivations.__repr__ = Derivations.__str__ +Derivations.__repr__ = Derivations.__str__ # type: ignore -def _Derivations__setattr__(self, name, value): +def _Derivations__setattr__(self, name, value) -> None: if name in ("left", "right"): - object.__setattr__(self, name, _wrap(VecGraph, value)) + object.__setattr__(self, name, _wrap(libpymod._VecGraph, value)) elif name == "rules": - object.__setattr__(self, name, _wrap(VecRule, value)) + object.__setattr__(self, name, _wrap(libpymod._VecRule, value)) else: _NoNew__setattr__(self, name, value) -Derivations.__setattr__ = _Derivations__setattr__ +Derivations.__setattr__ = _Derivations__setattr__ # type: ignore + ########################################################### # DG @@ -228,55 +234,71 @@ def _DG_calc(dg, printInfo=True): return dg _DG_load_orig = DG.load -def _DG_load(graphDatabase, ruleDatabase, file, - graphPolicy=IsomorphismPolicy.Check, verbosity=2): - return _DG_load_orig(_wrap(VecGraph, graphDatabase), - _wrap(VecRule, ruleDatabase), - prefixFilename(file), - graphPolicy, verbosity) -DG.load = _DG_load +def _DG_load( + graphDatabase: List[Graph], ruleDatabase: List[Rule], file: str, + graphPolicy: IsomorphismPolicy = IsomorphismPolicy.Check, + verbosity: int = 2) -> DG: + return _DG_load_orig( + _wrap(libpymod._VecGraph, graphDatabase), + _wrap(libpymod._VecRule, ruleDatabase), + prefixFilename(file), graphPolicy, verbosity) +DG.load = _DG_load # type: ignore _DG__init__old = DG.__init__ def _DG__init__(self, *, - labelSettings=LabelSettings( - LabelType.String, - LabelRelation.Isomorphism), - graphDatabase=[], - graphPolicy=IsomorphismPolicy.Check): - return _DG__init__old(self, + labelSettings: LabelSettings = LabelSettings( + LabelType.String, + LabelRelation.Isomorphism), + graphDatabase: List[Graph] = [], + graphPolicy: IsomorphismPolicy = IsomorphismPolicy.Check) -> None: + return _DG__init__old(self, # type: ignore labelSettings, - _wrap(VecGraph, graphDatabase), + _wrap(libpymod._VecGraph, graphDatabase), graphPolicy) -DG.__init__ = _DG__init__ +DG.__init__ = _DG__init__ # type: ignore _DG_print_orig = DG.print -def _DG_print(self, printer=None, data=None): +def _DG_print(self, printer: Optional[DGPrinter] = None, data: Optional[DGPrintData] = None) -> Tuple[str, str]: if printer is None: printer = DGPrinter() if data is None: data = DGPrintData(self) - return _DG_print_orig(self, data, printer) -DG.print = _DG_print + return _DG_print_orig(self, printer, data) +DG.print = _DG_print # type: ignore _DG_findEdge_orig = DG.findEdge -def _DG_findEdge(self, srcsI, tarsI): - srcs = list(srcsI) - tars = list(tarsI) - if len(srcs) == 0: s = None - elif isinstance(srcs[0], Graph): s = VecGraph - else: s = VecDGVertex - if len(tars) == 0: t = None - elif isinstance(tars[0], Graph): t = VecGraph - else: t = VecDGVertex +def _DG_findEdge(self, + srcsI: Union[Sequence[Graph], Sequence[DGVertex]], + tarsI: Union[Sequence[Graph], Sequence[DGVertex]]) -> DGHyperEdge: + srcs = srcsI + tars = tarsI + + s: Union[None, Type[libpymod._VecGraph], Type[libpymod._VecDGVertex]] + t: Union[None, Type[libpymod._VecGraph], Type[libpymod._VecDGVertex]] + + if len(srcs) == 0: + s = None + elif isinstance(srcs[0], Graph): + s = libpymod._VecGraph + else: + s = libpymod._VecDGVertex + + if len(tars) == 0: + t = None + elif isinstance(tars[0], Graph): + t = libpymod._VecGraph + else: + t = libpymod._VecDGVertex + if s is None and t is None: - s = VecDGVertex - t = VecDGVertex + s = libpymod._VecDGVertex + t = libpymod._VecDGVertex elif s is None: s = t elif t is None: t = s - return _DG_findEdge_orig(self, _wrap(s, srcs), _wrap(t, tars)) -DG.findEdge = _DG_findEdge + return _DG_findEdge_orig(self, _wrap(s, srcs), _wrap(t, tars)) # type: ignore +DG.findEdge = _DG_findEdge # type: ignore -DG.__repr__ = DG.__str__ +DG.__repr__ = DG.__str__ # type: ignore def _DG__getattribute__(self, name): if name == "graphDatabase": @@ -285,53 +307,54 @@ def _DG__getattribute__(self, name): return _unwrap(self._products) else: return object.__getattribute__(self, name) -DG.__getattribute__ = _DG__getattribute__ +DG.__getattribute__ = _DG__getattribute__ # type: ignore -DG.__eq__ = lambda self, other: self.id == other.id -DG.__hash__ = lambda self: self.id +DG.__eq__ = lambda self, other: self.id == other.id # type: ignore +DG.__hash__ = lambda self: self.id # type: ignore -class DGBuildContextManager(object): - def __init__(self, dg): +class DGBuildContextManager: + dg: Optional[DG] + _builder: Optional[DGBuilder] + + def __init__(self, dg: DG) -> None: assert dg is not None self.dg = dg self._builder = _DG_build_orig(self.dg) - def __enter__(self): + def __enter__(self) -> "DGBuildContextManager": return self - def __exit__(self, exc_type, exc_val, exc_tb): + def __exit__(self, exc_type, exc_val, exc_tb) -> None: del self._builder self.dg = None self._builder = None - def _check(self): + def addDerivation(self, d: Derivations, + graphPolicy: IsomorphismPolicy = IsomorphismPolicy.Check) -> DGHyperEdge: assert self._builder - - def addDerivation(self, d, graphPolicy=IsomorphismPolicy.Check): - self._check() return self._builder.addDerivation(d, graphPolicy) - def execute(self, strategy, *, verbosity=2, ignoreRuleLabelTypes=False): - self._check() - return self._builder.execute(dgStrat(strategy), verbosity, ignoreRuleLabelTypes) + def execute(self, strategy, *, verbosity=2, ignoreRuleLabelTypes=False) -> DGExecuteResult: + assert self._builder + return self._builder.execute(dgStrat(strategy), verbosity, ignoreRuleLabelTypes) # type: ignore + + def apply(self, graphs, rule, onlyProper=True, verbosity=0, graphPolicy=IsomorphismPolicy.Check) -> List[DGHyperEdge]: + assert self._builder + return _unwrap(self._builder.apply(_wrap(libpymod._VecGraph, graphs), rule, onlyProper, verbosity, graphPolicy)) - def addAbstract(self, description): - self._check() + def addAbstract(self, description: str) -> None: + assert self._builder return self._builder.addAbstract(description) - - def apply(self, graphs, rule, verbosity=0, graphPolicy=IsomorphismPolicy.Check): - self._check() - return _unwrap(self._builder.apply(_wrap(VecGraph, graphs), rule, verbosity, graphPolicy)) - def load(self, ruleDatabase, file, verbosity=2): - self._check() + def load(self, ruleDatabase: List[Rule], file: str, verbosity: int = 2) -> None: + assert self._builder return self._builder.load( - _wrap(VecRule, ruleDatabase), + _wrap(libpymod._VecRule, ruleDatabase), prefixFilename(file), verbosity) _DG_build_orig = DG.build -DG.build = lambda self: DGBuildContextManager(self) +DG.build = lambda self: DGBuildContextManager(self) # type: ignore #---------------------------------------------------------- @@ -343,12 +366,12 @@ def _DGExecuteResult__getattribute__(self, name): return _unwrap(object.__getattribute__(self, name)) return object.__getattribute__(self, name) -DGExecuteResult.__getattribute__ = _DGExecuteResult__getattribute__ +DGExecuteResult.__getattribute__ = _DGExecuteResult__getattribute__ # type: ignore _DGExecuteResult_list_old = DGExecuteResult.list -def _DGExecuteResult_list(self, *, withUniverse=False): - return _DGExecuteResult_list_old(self, withUniverse) -DGExecuteResult.list = _DGExecuteResult_list +def _DGExecuteResult_list(self, *, withUniverse=False) -> None: + return _DGExecuteResult_list_old(self, withUniverse) # type: ignore +DGExecuteResult.list = _DGExecuteResult_list # type: ignore #---------------------------------------------------------- @@ -356,7 +379,7 @@ def _DGExecuteResult_list(self, *, withUniverse=False): #---------------------------------------------------------- _DGHyperEdge_print_orig = DGHyperEdge.print -DGHyperEdge.print = lambda self, *args, **kwargs: _unwrap(_DGHyperEdge_print_orig(self, *args, **kwargs)) +DGHyperEdge.print = lambda self, *args, **kwargs: _unwrap(_DGHyperEdge_print_orig(self, *args, **kwargs)) # type: ignore #---------------------------------------------------------- @@ -376,42 +399,42 @@ def callback(self, f, *args, **kwargs): return callback _DGPrinter_pushVertexVisible_orig = DGPrinter.pushVertexVisible -DGPrinter.pushVertexVisible = _makeGraphToVertexCallback( - _DGPrinter_pushVertexVisible_orig, "pushVertexVisible", Func_BoolDGVertex) +DGPrinter.pushVertexVisible = _makeGraphToVertexCallback( # type: ignore + _DGPrinter_pushVertexVisible_orig, "pushVertexVisible", libpymod._Func_BoolDGVertex) _DGPrinter_pushEdgeVisible_orig = DGPrinter.pushEdgeVisible -DGPrinter.pushEdgeVisible = \ - lambda self, f: _DGPrinter_pushEdgeVisible_orig(self, _funcWrap(Func_BoolDGHyperEdge, f)) +DGPrinter.pushEdgeVisible = ( # type: ignore + lambda self, f: _DGPrinter_pushEdgeVisible_orig(self, _funcWrap(libpymod._Func_BoolDGHyperEdge, f))) _DGPrinter_pushVertexLabel_orig = DGPrinter.pushVertexLabel -DGPrinter.pushVertexLabel = _makeGraphToVertexCallback( - _DGPrinter_pushVertexLabel_orig , "pushVertexLabel", Func_StringDGVertex) +DGPrinter.pushVertexLabel = _makeGraphToVertexCallback( # type: ignore + _DGPrinter_pushVertexLabel_orig , "pushVertexLabel", libpymod._Func_StringDGVertex) _DGPrinter_pushEdgeLabel_orig = DGPrinter.pushEdgeLabel -DGPrinter.pushEdgeLabel = \ - lambda self, f: _DGPrinter_pushEdgeLabel_orig(self, _funcWrap(Func_StringDGHyperEdge, f)) +DGPrinter.pushEdgeLabel = ( # type: ignore + lambda self, f: _DGPrinter_pushEdgeLabel_orig(self, _funcWrap(libpymod._Func_StringDGHyperEdge, f))) _DGPrinter_pushVertexColour_orig = DGPrinter.pushVertexColour _DGPrinter_pushVertexColour_inner = _makeGraphToVertexCallback( - _DGPrinter_pushVertexColour_orig, "pushVertexColour", Func_StringDGVertex) -DGPrinter.pushVertexColour = \ - lambda self, f, extendToEdges=True: _DGPrinter_pushVertexColour_inner(self, f, extendToEdges) + _DGPrinter_pushVertexColour_orig, "pushVertexColour", libpymod._Func_StringDGVertex) +DGPrinter.pushVertexColour = ( # type: ignore + lambda self, f, extendToEdges=True: _DGPrinter_pushVertexColour_inner(self, f, extendToEdges)) _DGPrinter_pushEdgeColour_orig = DGPrinter.pushEdgeColour -DGPrinter.pushEdgeColour = \ - lambda self, f: _DGPrinter_pushEdgeColour_orig(self, _funcWrap(Func_StringDGHyperEdge, f)) +DGPrinter.pushEdgeColour = ( # type: ignore + lambda self, f: _DGPrinter_pushEdgeColour_orig(self, _funcWrap(libpymod._Func_StringDGHyperEdge, f))) _DGPrinter_setRotationOverwrite_orig = DGPrinter.setRotationOverwrite -DGPrinter.setRotationOverwrite = \ - lambda self, f: _DGPrinter_setRotationOverwrite_orig(self, _funcWrap(Func_IntGraph, f)) +DGPrinter.setRotationOverwrite = ( # type: ignore + lambda self, f: _DGPrinter_setRotationOverwrite_orig(self, _funcWrap(libpymod._Func_IntGraph, f))) _DGPrinter_setMirrorOverwrite_orig = DGPrinter.setMirrorOverwrite -DGPrinter.setMirrorOverwrite = \ - lambda self, f: _DGPrinter_setMirrorOverwrite_orig(self, _funcWrap(Func_BoolGraph, f)) +DGPrinter.setMirrorOverwrite = ( # type: ignore + lambda self, f: _DGPrinter_setMirrorOverwrite_orig(self, _funcWrap(libpymod._Func_BoolGraph, f))) #---------------------------------------------------------- -# DGStrat +# Strategy #---------------------------------------------------------- def _DGStratGraphState__getattribute__(self, name): @@ -421,163 +444,48 @@ def _DGStratGraphState__getattribute__(self, name): return _unwrap(self._universe) else: return object.__getattribute__(self, name) -DGStratGraphState.__getattribute__ = _DGStratGraphState__getattribute__ +DGStrat.GraphState.__getattribute__ = _DGStratGraphState__getattribute__ # type: ignore _DGStrat_makeAddStatic_orig = DGStrat.makeAddStatic -def _DGStrat_makeAddStatic(onlyUniverse, graphs, graphPolicy): - return _DGStrat_makeAddStatic_orig(onlyUniverse, _wrap(VecGraph, graphs), graphPolicy) -DGStrat.makeAddStatic = _DGStrat_makeAddStatic +def _DGStrat_makeAddStatic(onlyUniverse, graphs, graphPolicy) -> DGStrat: + return _DGStrat_makeAddStatic_orig(onlyUniverse, _wrap(libpymod._VecGraph, graphs), graphPolicy) +DGStrat.makeAddStatic = _DGStrat_makeAddStatic # type: ignore _DGStrat_makeAddDynamic_orig = DGStrat.makeAddDynamic -def _DGStrat_makeAddDynamic(onlyUniverse, generator, graphPolicy): - return _DGStrat_makeAddDynamic_orig(onlyUniverse, _funcWrap(Func_VecGraph, generator, resultWrap=VecGraph), graphPolicy) -DGStrat.makeAddDynamic = _DGStrat_makeAddDynamic +def _DGStrat_makeAddDynamic(onlyUniverse, generator, graphPolicy) -> DGStrat: + return _DGStrat_makeAddDynamic_orig(onlyUniverse, _funcWrap(libpymod._Func_VecGraph, generator, resultWrap=libpymod._VecGraph), graphPolicy) +DGStrat.makeAddDynamic = _DGStrat_makeAddDynamic # type: ignore _DGStrat_makeSequence_orig = DGStrat.makeSequence -def _DGStrat_makeSequence(l): - return _DGStrat_makeSequence_orig(_wrap(VecDGStrat, l)) -DGStrat.makeSequence = _DGStrat_makeSequence +def _DGStrat_makeSequence(l) -> DGStrat: + return _DGStrat_makeSequence_orig(_wrap(libpymod._VecDGStrat, l)) +DGStrat.makeSequence = _DGStrat_makeSequence # type: ignore _DGStrat_makeParallel_orig = DGStrat.makeParallel -def _DGStrat_makeParallel(l): - return _DGStrat_makeParallel_orig(_wrap(VecDGStrat, l)) -DGStrat.makeParallel = _DGStrat_makeParallel +def _DGStrat_makeParallel(l) -> DGStrat: + return _DGStrat_makeParallel_orig(_wrap(libpymod._VecDGStrat, l)) +DGStrat.makeParallel = _DGStrat_makeParallel # type: ignore _DGStrat_makeFilter_orig = DGStrat.makeFilter -def _DGStrat_makeFilter(alsoUniverse, filterFunc): - return _DGStrat_makeFilter_orig(alsoUniverse, _funcWrap(Func_BoolGraphDGStratGraphStateBool, filterFunc)) -DGStrat.makeFilter = _DGStrat_makeFilter +def _DGStrat_makeFilter(alsoUniverse, filterFunc) -> DGStrat: + return _DGStrat_makeFilter_orig(alsoUniverse, _funcWrap(libpymod._Func_BoolGraphDGStratGraphStateBool, filterFunc)) +DGStrat.makeFilter = _DGStrat_makeFilter # type: ignore _DGStrat_makeExecute_orig = DGStrat.makeExecute -def _DGStrat_makeExecute(func): - return _DGStrat_makeExecute_orig(_funcWrap(Func_VoidDGStratGraphState, func)) -DGStrat.makeExecute = _DGStrat_makeExecute +def _DGStrat_makeExecute(func) -> DGStrat: + return _DGStrat_makeExecute_orig(_funcWrap(libpymod._Func_VoidDGStratGraphState, func)) +DGStrat.makeExecute = _DGStrat_makeExecute # type: ignore _DGStrat_makeLeftPredicate_orig = DGStrat.makeLeftPredicate -def _DGStrat_makeLeftPredicate(pred, strat): - return _DGStrat_makeLeftPredicate_orig(_funcWrap(Func_BoolDerivation, pred), strat) -DGStrat.makeLeftPredicate = _DGStrat_makeLeftPredicate +def _DGStrat_makeLeftPredicate(pred, strat) -> DGStrat: + return _DGStrat_makeLeftPredicate_orig(_funcWrap(libpymod._Func_BoolDerivation, pred), strat) +DGStrat.makeLeftPredicate = _DGStrat_makeLeftPredicate # type: ignore _DGStrat_makeRightPredicate_orig = DGStrat.makeRightPredicate -def _DGStrat_makeRightPredicate(pred, strat): - return _DGStrat_makeRightPredicate_orig(_funcWrap(Func_BoolDerivation, pred), strat) -DGStrat.makeRightPredicate = _DGStrat_makeRightPredicate - - -#---------------------------------------------------------- -# Graph -#---------------------------------------------------------- - -inputGraphs = [] - -_Graph_print_orig = Graph.print -def _Graph_print(self, first=None, second=None): - if first is None: - return _Graph_print_orig(self) - if second is None: - second = first - return _Graph_print_orig(self, first, second) -Graph.print = _Graph_print - -_Graph_aut = Graph.aut -Graph.aut = lambda self, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Graph_aut(self, labelSettings) +def _DGStrat_makeRightPredicate(pred, strat) -> DGStrat: + return _DGStrat_makeRightPredicate_orig(_funcWrap(libpymod._Func_BoolDerivation, pred), strat) +DGStrat.makeRightPredicate = _DGStrat_makeRightPredicate # type: ignore -_Graph_isomorphism = Graph.isomorphism -Graph.isomorphism = lambda self, g, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Graph_isomorphism(self, g, maxNumMatches, labelSettings) -_Graph_monomorphism = Graph.monomorphism -Graph.monomorphism = lambda self, g, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Graph_monomorphism(self, g, maxNumMatches, labelSettings) - -_Graph_getGMLString = Graph.getGMLString -Graph.getGMLString = lambda self, withCoords=False: _Graph_getGMLString(self, withCoords) -_Graph_printGML = Graph.printGML -Graph.printGML = lambda self, withCoords=False: _Graph_printGML(self, withCoords) - -def _graphLoad(a, name, add): - if name != None: - a.name = name - if add: - inputGraphs.append(a) - return a -def graphGMLString(d, name=None, add=True): - return _graphLoad(libpymod.graphGMLString(d), name, add) -def graphGML(f, name=None, add=True): - return _graphLoad(libpymod.graphGML(prefixFilename(f)), name, add) -def graphDFS(s, name=None, add=True): - return _graphLoad(libpymod.graphDFS(s), name, add) -def smiles(s, name=None, add=True, allowAbstract=False, classPolicy=SmilesClassPolicy.NoneOnDuplicate): - return _graphLoad(libpymod.smiles(s, allowAbstract, classPolicy), name, add) - -Graph.__repr__ = lambda self: str(self) + "(" + str(self.id) + ")" -Graph.__eq__ = lambda self, other: self.id == other.id -Graph.__lt__ = lambda self, other: self.id < other.id -Graph.__hash__ = lambda self: self.id - -def _Graph__setattr__(self, name, value): - if name == "image": - object.__setattr__(self, "image", _funcWrap(Func_String, value)) - else: - _NoNew__setattr__(self, name, value) -Graph.__setattr__ = _Graph__setattr__ - -#---------------------------------------------------------- -# RCEvaluator -#---------------------------------------------------------- - -def _RCEvaluator__getattribute__(self, name): - if name == "ruleDatabase": - return _unwrap(self._ruleDatabase) - elif name == "products": - return _unwrap(self._products) - else: - return object.__getattribute__(self, name) -RCEvaluator.__getattribute__ = _RCEvaluator__getattribute__ - -_RCEvaluator_eval = RCEvaluator.eval -RCEvaluator.eval = lambda self, e, *, verbosity=2: _unwrap(_RCEvaluator_eval(self, e, verbosity)) - -def rcEvaluator(rules, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)): - return libpymod.rcEvaluator(_wrap(VecRule, rules), labelSettings) - -#---------------------------------------------------------- -# Rule -#---------------------------------------------------------- - -inputRules = [] - -_Rule_print_orig = Rule.print -def _Rule_print(self, first=None, second=None): - if first is None: - return _Rule_print_orig(self) - if second is None: - second = first - return _Rule_print_orig(self, first, second) -Rule.print = _Rule_print - -_Rule_isomorphism = Rule.isomorphism -Rule.isomorphism = lambda self, r, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Rule_isomorphism(self, r, maxNumMatches, labelSettings) -_Rule_monomorphism = Rule.monomorphism -Rule.monomorphism = lambda self, r, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Rule_monomorphism(self, r, maxNumMatches, labelSettings) - -_Rule_getGMLString = Rule.getGMLString -Rule.getGMLString = lambda self, withCoords=False: _Rule_getGMLString(self, withCoords) -_Rule_printGML = Rule.printGML -Rule.printGML = lambda self, withCoords=False: _Rule_printGML(self, withCoords) - -def ruleGMLString(s, invert=False, add=True): - a = libpymod.ruleGMLString(s, invert) - if add: - inputRules.append(a) - return a -def ruleGML(f, invert=False, add=True): - a = libpymod.ruleGML(prefixFilename(f), invert) - if add: - inputRules.append(a) - return a - -Rule.__repr__ = lambda self: str(self) + "(" + str(self.id) + ")" -Rule.__eq__ = lambda self, other: self.id == other.id -Rule.__lt__ = lambda self, other: self.id < other.id -Rule.__hash__ = lambda self: self.id #---------------------------------------------------------- # DG Strategy Prettification @@ -687,10 +595,6 @@ def __call__(self, strat): # sequence #---------------------------------------------------------- -class _DGStrat_sequenceProxy(object): - def __init__(self, strats): - self.strats = strats - def _DGStrat_sequence__rshift__(a, b): strats = [] if isinstance(a, _DGStrat_sequenceProxy): @@ -702,17 +606,143 @@ def _DGStrat_sequence__rshift__(a, b): else: strats.append(dgStrat(b)) return _DGStrat_sequenceProxy(strats) -DGStrat.__rshift__ = _DGStrat_sequence__rshift__ -DGStrat.__rrshift__ = lambda self, other: _DGStrat_sequence__rshift__(other, self) -_DGStrat_sequenceProxy.__rshift__ = _DGStrat_sequence__rshift__ -Rule.__rshift__ = _DGStrat_sequence__rshift__ + + +class _DGStrat_sequenceProxy: + def __init__(self, strats): + self.strats = strats + + def __rshift__(self, other): + return _DGStrat_sequence__rshift__(self, other) + +DGStrat.__rshift__ = _DGStrat_sequence__rshift__ # type: ignore +DGStrat.__rrshift__ = lambda self, other: _DGStrat_sequence__rshift__(other, self) # type: ignore +Rule.__rshift__ = _DGStrat_sequence__rshift__ # type: ignore + + +########################################################### +# Graph +########################################################### + +inputGraphs = [] + +_Graph_print_orig = Graph.print +def _Graph_print(self, first=None, second=None) -> Tuple[str, str]: + if first is None: + return _Graph_print_orig(self) + if second is None: + second = first + return _Graph_print_orig(self, first, second) +Graph.print = _Graph_print # type: ignore + +_Graph_aut = Graph.aut +Graph.aut = lambda self, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Graph_aut(self, labelSettings) # type: ignore + +_Graph_isomorphism = Graph.isomorphism +Graph.isomorphism = lambda self, g, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Graph_isomorphism(self, g, maxNumMatches, labelSettings) # type: ignore +_Graph_monomorphism = Graph.monomorphism +Graph.monomorphism = lambda self, g, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Graph_monomorphism(self, g, maxNumMatches, labelSettings) # type: ignore + +_Graph_getGMLString = Graph.getGMLString +Graph.getGMLString = lambda self, withCoords=False: _Graph_getGMLString(self, withCoords) # type: ignore +_Graph_printGML = Graph.printGML +Graph.printGML = lambda self, withCoords=False: _Graph_printGML(self, withCoords) # type: ignore + +def _graphLoad(a, name, add): + if name != None: + a.name = name + if add: + inputGraphs.append(a) + return a +def graphGMLString(d, name=None, add=True): + return _graphLoad(libpymod.graphGMLString(d), name, add) +def graphGML(f, name=None, add=True): + return _graphLoad(libpymod.graphGML(prefixFilename(f)), name, add) +def graphDFS(s, name=None, add=True): + return _graphLoad(libpymod.graphDFS(s), name, add) +def smiles(s, name=None, add=True, allowAbstract=False, classPolicy=SmilesClassPolicy.NoneOnDuplicate): + return _graphLoad(libpymod.smiles(s, allowAbstract, classPolicy), name, add) + +Graph.__repr__ = lambda self: str(self) + "(" + str(self.id) + ")" # type: ignore +Graph.__eq__ = lambda self, other: self.id == other.id # type: ignore +Graph.__lt__ = lambda self, other: self.id < other.id # type: ignore +Graph.__hash__ = lambda self: self.id # type: ignore + +def _Graph__setattr__(self, name, value) -> None: + if name == "image": + object.__setattr__(self, "image", _funcWrap(libpymod._Func_String, value)) + else: + _NoNew__setattr__(self, name, value) +Graph.__setattr__ = _Graph__setattr__ # type: ignore + + +########################################################### +# Rule +########################################################### + +inputRules = [] + +_Rule_print_orig = Rule.print +def _Rule_print(self, first=None, second=None) -> Tuple[str, str]: + if first is None: + return _Rule_print_orig(self) + if second is None: + second = first + return _Rule_print_orig(self, first, second) +Rule.print = _Rule_print # type: ignore + +_Rule_isomorphism = Rule.isomorphism +Rule.isomorphism = lambda self, r, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Rule_isomorphism(self, r, maxNumMatches, labelSettings) # type: ignore +_Rule_monomorphism = Rule.monomorphism +Rule.monomorphism = lambda self, r, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism): _Rule_monomorphism(self, r, maxNumMatches, labelSettings) # type: ignore + +_Rule_getGMLString = Rule.getGMLString +Rule.getGMLString = lambda self, withCoords=False: _Rule_getGMLString(self, withCoords) # type: ignore +_Rule_printGML = Rule.printGML +Rule.printGML = lambda self, withCoords=False: _Rule_printGML(self, withCoords) # type: ignore + +def ruleGMLString(s, invert=False, add=True): + a = libpymod.ruleGMLString(s, invert) + if add: + inputRules.append(a) + return a +def ruleGML(f, invert=False, add=True): + a = libpymod.ruleGML(prefixFilename(f), invert) + if add: + inputRules.append(a) + return a + +Rule.__repr__ = lambda self: str(self) + "(" + str(self.id) + ")" # type: ignore +Rule.__eq__ = lambda self, other: self.id == other.id # type: ignore +Rule.__lt__ = lambda self, other: self.id < other.id # type: ignore +Rule.__hash__ = lambda self: self.id # type: ignore + + +#---------------------------------------------------------- +# Composition +#---------------------------------------------------------- + +def _RCEvaluator__getattribute__(self, name): + if name == "ruleDatabase": + return _unwrap(self._ruleDatabase) + elif name == "products": + return _unwrap(self._products) + else: + return object.__getattribute__(self, name) +RCEvaluator.__getattribute__ = _RCEvaluator__getattribute__ # type: ignore + +_RCEvaluator_eval = RCEvaluator.eval +RCEvaluator.eval = lambda self, exp, *, verbosity=2: _unwrap(_RCEvaluator_eval(self, exp, verbosity)) # type: ignore + +def rcEvaluator(rules, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)): + return libpymod.rcEvaluator(_wrap(libpymod._VecRule, rules), labelSettings) #---------------------------------------------------------- # RCExp prettification #---------------------------------------------------------- -def rcExp(e): +def rcExp(e) -> RCExpExp: if isinstance(e, RCExpExp) or isinstance(e, Rule) or isinstance(e, RCExpUnion): return e elif isinstance(e, RCExpBind) or isinstance(e, RCExpId) or isinstance(e, RCExpUnbind): @@ -720,174 +750,157 @@ def rcExp(e): elif isinstance(e, RCExpComposeCommon) or isinstance(e, RCExpComposeParallel) or isinstance(e, RCExpComposeSub) or isinstance(e, RCExpComposeSuper): return e elif isinstance(e, collections.Iterable): - return RCExpUnion(_wrap(VecRCExpExp, [rcExp(a) for a in e])) + return RCExpUnion(_wrap(libpymod._VecRCExpExp, [rcExp(a) for a in e])) else: raise TypeError("Can not convert type '" + str(type(e)) + "' to RCExpExp") -def _rcConvertGraph(g, cls, f): +def _rcConvertGraph(g, cls, f) -> RCExpExp: if isinstance(g, Graph): return cls(g) elif isinstance(g, collections.Iterable): l = [f(a) for a in g] return rcExp(l) else: - raise TypeError("Can not convert type '" + str(type(e)) + "' to " + str(cls)) -def rcBind(g): + raise TypeError("Can not convert type '" + str(type(g)) + "' to " + str(cls)) + + +def rcBind(g) -> RCExpExp: return _rcConvertGraph(g, RCExpBind, rcBind) -def rcId(g): + + +def rcId(g) -> RCExpExp: return _rcConvertGraph(g, RCExpId, rcId) -def rcUnbind(g): + + +def rcUnbind(g) -> RCExpExp: return _rcConvertGraph(g, RCExpUnbind, rcUnbind) -class _RCCommonOpFirstBound(object): - def __init__(self, discardNonchemical, maximum, connected, first): + +class _RCCommonOpFirstBound: + def __init__(self, discardNonchemical, maximum, connected, first) -> None: self.discardNonchemical = discardNonchemical self.maximum = maximum self.connected = connected self.first = first - def __mul__(self, second): + + def __mul__(self, second) -> RCExpExp: return RCExpComposeCommon(rcExp(self.first), rcExp(second), self.discardNonchemical, self.maximum, self.connected) -class _RCCommonOpArgsBound(object): - def __init__(self, discardNonchemical, maximum, connected): + + +class _RCCommonOpArgsBound: + def __init__(self, discardNonchemical, maximum, connected) -> None: self.discardNonchemical = discardNonchemical self.maximum = maximum self.connected = connected - def __rmul__(self, first): + + def __rmul__(self, first) -> _RCCommonOpFirstBound: return _RCCommonOpFirstBound(self.discardNonchemical, self.maximum, self.connected, first) -class _RCCommonOp(object): + + +class _RCCommonOp: def __call__(self, discardNonchemical=True, maximum=False, connected=True): return _RCCommonOpArgsBound(discardNonchemical, maximum, connected) - def __rmul__(self, first): + + def __rmul__(self, first) -> RCExpExp: return first * self() + + rcCommon = _RCCommonOp() -class _RCParallelOpFirstBound(object): - def __init__(self, discardNonchemical, first): + +class _RCParallelOpFirstBound: + def __init__(self, discardNonchemical, first) -> None: self.discardNonchemical = discardNonchemical self.first = first - def __mul__(self, second): + + def __mul__(self, second) -> RCExpExp: return RCExpComposeParallel(rcExp(self.first), rcExp(second), self.discardNonchemical) -class _RCParallelOpArgsBound(object): - def __init__(self, discardNonchemical): + + +class _RCParallelOpArgsBound: + def __init__(self, discardNonchemical) -> None: self.discardNonchemical = discardNonchemical - def __rmul__(self, first): + + def __rmul__(self, first) -> _RCParallelOpFirstBound: return _RCParallelOpFirstBound(self.discardNonchemical, first) -class _RCParallelOp(object): + + +class _RCParallelOp: def __call__(self, discardNonchemical=True): return _RCParallelOpArgsBound(discardNonchemical) - def __rmul__(self, first): + + def __rmul__(self, first) -> RCExpExp: return first * self() + + rcParallel = _RCParallelOp() -class _RCSubOpFirstBound(object): - def __init__(self, discardNonchemical, allowPartial, first): + +class _RCSubOpFirstBound: + def __init__(self, discardNonchemical, allowPartial, first) -> None: self.discardNonchemical = discardNonchemical self.allowPartial = allowPartial self.first = first - def __mul__(self, second): + + def __mul__(self, second) -> RCExpExp: return RCExpComposeSub(rcExp(self.first), rcExp(second), self.discardNonchemical, self.allowPartial) -class _RCSubOpArgsBound(object): - def __init__(self, discardNonchemical, allowPartial): + + +class _RCSubOpArgsBound: + def __init__(self, discardNonchemical, allowPartial) -> None: self.discardNonchemical = discardNonchemical self.allowPartial = allowPartial - def __rmul__(self, first): + + def __rmul__(self, first) -> _RCSubOpFirstBound: return _RCSubOpFirstBound(self.discardNonchemical, self.allowPartial, first) -class _RCSubOp(object): + + +class _RCSubOp: def __call__(self, discardNonchemical=True, allowPartial=True): return _RCSubOpArgsBound(discardNonchemical, allowPartial) - def __rmul__(self, first): + + def __rmul__(self, first) -> RCExpExp: return first * self() + + rcSub = _RCSubOp() -class _RCSuperOpFirstBound(object): - def __init__(self, discardNonchemical, allowPartial, enforceConstraints, first): + +class _RCSuperOpFirstBound: + def __init__(self, discardNonchemical, allowPartial, enforceConstraints, first) -> None: self.discardNonchemical = discardNonchemical self.allowPartial = allowPartial self.enforceConstraints = enforceConstraints self.first = first - def __mul__(self, second): + + def __mul__(self, second) -> RCExpExp: return RCExpComposeSuper(rcExp(self.first), rcExp(second), self.discardNonchemical, self.allowPartial, self.enforceConstraints) -class _RCSuperOpArgsBound(object): - def __init__(self, discardNonchemical, allowPartial, enforceConstraints): + + +class _RCSuperOpArgsBound: + def __init__(self, discardNonchemical, allowPartial, enforceConstraints) -> None: self.discardNonchemical = discardNonchemical self.allowPartial = allowPartial self.enforceConstraints = enforceConstraints - def __rmul__(self, first): + + def __rmul__(self, first) -> _RCSuperOpFirstBound: return _RCSuperOpFirstBound(self.discardNonchemical, self.allowPartial, self.enforceConstraints, first) -class _RCSuperOp(object): + + +class _RCSuperOp: def __call__(self, discardNonchemical=True, allowPartial=True, enforceConstraints=False): return _RCSuperOpArgsBound(discardNonchemical, allowPartial, enforceConstraints) - def __rmul__(self, first): + + def __rmul__(self, first) -> RCExpExp: return first * self() + + rcSuper = _RCSuperOp() -#---------------------------------------------------------- + +# ---------------------------------------------------------- # Util -#---------------------------------------------------------- +# ---------------------------------------------------------- def showDump(f): return libpymod.showDump(prefixFilename(f)) - -def boltzmannFactor(temperature, energy): - return math.exp(-energy / temperature) - -class Boltzmann(object): - def __init__(self, temperature): - self.temperature = temperature - self.col = None - def __call__(self, g, col, first): - if first: - self.col = col - self.sumFactors = sum(boltzmannFactor(self.temperature, a.energy) for a in col) - return boltzmannFactor(self.temperature, g.energy) / self.sumFactors - -class BoltzmannGroupIsomers(object): - def __init__(self, temperature): - self.temperature = temperature - self.col = None - def __call__(self, g, col, first): - class Data(dict): - def __missing__(self, key): - return 0 - class Histogram(object): - def __init__(self, g): - self.counts = {} - labels = ["C", "N", "H", "O", "c", "n", "O-"] - for l in labels: - self.counts[l] = g.vLabelCount(l) - if g.numVertices != sum(self.counts.values()): - print("Graph label histogram incomplete!") - print("Graph is", g) - g.print() - sys.exit(0) - self.counts = frozenset(self.counts.items()) - def __hash__(self): - return hash(self.counts) - def __eq__(self, other): - return self.counts == other.counts - if first: - self.col = col - self.groups = Data() - for a in col: - self.groups[Histogram(a)] += boltzmannFactor(self.temperature, a.energy) - return boltzmannFactor(self.temperature, g.energy) / self.groups[Histogram(g)] - - -#class BoltzmannGroupWeight(object): -# def __init__(self, temperature): -# self.temperature = temperature -# self.col = None -# def __call__(self, g, col, first): -# class Data(dict): -# def __missing__(self, key): -# assert(key == int(key)) -# return 0 -# if first: -# self.col = col -# self.sums = Data() -# for a in col: -# weight = int(a.weight) -# self.sums[weight] += boltzmannFactor(self.temperature, a.energy) -# weight = int(g.weight) -# return boltzmannFactor(self.temperature, g.energy) / self.sums[weight] - diff --git a/libs/pymod/lib/mod/latex.py b/libs/pymod/lib/mod/latex.py index 88cbf77..559857b 100644 --- a/libs/pymod/lib/mod/latex.py +++ b/libs/pymod/lib/mod/latex.py @@ -2,23 +2,29 @@ import os import sys +from typing import List + _texFile = None _figFolder = None -_graphs = [] -_rules = [] -_ls = mod.LabelSettings(mod.LabelType.String, mod.LabelRelation.Isomorphism, mod.LabelRelation.Isomorphism) +_graphs: List[mod.Graph] = [] +_rules: List[mod.Rule] = [] +_ls = mod.LabelSettings(mod.LabelType.String, mod.LabelRelation.Isomorphism, + mod.LabelRelation.Isomorphism) + def setTexFile(fName): global _texFile _texFile = open(fName, "w") mod.post("disableSummary") + def setFigFolder(fName): global _figFolder _figFolder = fName _checkSettings() mod.post("post \"mkdir -p '%s'\"" % _figFolder) + def _checkSettings(): if _texFile is None: print("Error: no tex file set") @@ -27,24 +33,27 @@ def _checkSettings(): print("Error: no figure folder set, or empty name") sys.exit(1) + def outputFile(f, inline=False): _checkSettings() assert f.endswith(".pdf") f = f[:-4] f += ".tex" if inline else ".pdf" mod.post("post \"cp '%s' '%s/'\"" % (f, _figFolder)) - res = _figFolder + "/" + os.path.basename(f) + res = _figFolder + "/" + os.path.basename(f) return res[:-4] + def texDefine(id, value): _checkSettings() _texFile.write(r"\expandafter\def\csname mod@figDef-%s\endcsname{%s}" % (str(id), str(value))) _texFile.write("\n") -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # Grpahs -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ def graph(id, g, p, inline): _checkSettings() @@ -54,23 +63,27 @@ def graph(id, g, p, inline): break else: _graphs.append(g) - f = g.print(p, p) + f = g.print(p, p) f = f[0] f = outputFile(f, inline) texDefine("graph-" + str(id), f) + def graphGML(id, data, printer, inline=False): graph(id, mod.graphGML(data), printer, inline) + def smiles(id, data, printer, inline=False): graph(id, mod.smiles(data.replace('##', '#')), printer, inline) + def graphDFS(id, data, printer, inline=False): graph(id, mod.graphDFS(data.replace('##', '#')), printer, inline) -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # Rules -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ def rule(id, r, p): _checkSettings() @@ -87,5 +100,6 @@ def rule(id, r, p): fR = outputFile(f + "_R.pdf") texDefine("rule-" + str(id), "{%s}{%s}{%s}" % (fL, fK, fR)) + def ruleGML(id, data, printer): rule(id, mod.ruleGML(data), printer) diff --git a/libs/pymod/lib/mod/libpymod.pyi b/libs/pymod/lib/mod/libpymod.pyi new file mode 100644 index 0000000..cd0ddc1 --- /dev/null +++ b/libs/pymod/lib/mod/libpymod.pyi @@ -0,0 +1,315 @@ +import enum +from typing import Callable, Generic, Iterable, List, Optional, overload, Tuple, TypeVar, Union + +T = TypeVar("T") +U = TypeVar("U") + + +#----------------------------------------------------------------------------- +# Meta +#----------------------------------------------------------------------------- + +# Collection +#----------------------------------------------------------------------------- + +class Vec(List[T]): ... + +class _VecDGHyperEdge(Vec[DGHyperEdge]): ... +class _VecDGVertex(Vec[DGVertex]): ... +class _VecDGStrat(Vec[DGStrat]): ... +class _VecGraph(Vec[Graph]): ... +class _VecRCExpExp(Vec[RCExpExp]): ... +class _VecRule(Vec[Rule]): ... + + +# Function +#----------------------------------------------------------------------------- + +class _Func_VecGraph: + def __call__(self) -> Vec[Graph]: ... +class _Func_String: + def __call__(self) -> str: ... + +class _Func_BoolDerivation: + def __call__(self, d: Derivation) -> bool: ... + +class _Func_BoolDGVertex: + def __call__(self, v: DGVertex) -> bool: ... +class _Func_StringDGVertex: + def __call__(self, v: DGVertex) -> str: ... + +class _Func_BoolDGHyperEdge: + def __call__(self, e: DGHyperEdge) -> bool: ... +class _Func_StringDGHyperEdge: + def __call__(self, e: DGHyperEdge) -> str: ... +class _Func_DoubleDGHyperEdge: + def __call__(self, e: DGHyperEdge) -> float: ... + +class _Func_BoolGraph: + def __call__(self, g: Graph) -> bool: ... +class _Func_IntGraph: + def __call__(self, g: Graph) -> int: ... + +class _Func_StringGraphDGBool: + def __call__(self, g: Graph, dg: DG, first: bool) -> str: ... + +class _Func_BoolGraphDGStratGraphStateBool: + def __call__(self, g: Graph, gs: DGStrat.GraphState, first: bool) -> bool: ... + +class _Func_VoidDGStratGraphState: + def __call__(self, gs: DGStrat.GraphState) -> None: ... + + +#----------------------------------------------------------------------------- +# Top-level non-meta +#----------------------------------------------------------------------------- + +# Chem +#----------------------------------------------------------------------------- + +class BondType(enum.Enum): ... +def _bondTypeToString(self) -> str: ... + + +# Config +#----------------------------------------------------------------------------- + +class LabelType(enum.Enum): + String: int +def _LabelType__str__(self) -> str: ... + +class LabelRelation(enum.Enum): + Isomorphism: int +def _LabelRelation__str__(self) -> str: ... + +class LabelSettings: + @overload + def __init__(self, lt: LabelType, lr: LabelRelation) -> None: ... + @overload + def __init__(self, lt: LabelType, lr: LabelRelation, slr: LabelRelation) -> None: ... + +class IsomorphismPolicy(enum.Enum): + Check: int +def _IsomorphismPolicy__str__(self) -> str: ... + +class SmilesClassPolicy(enum.Enum): ... +def _SmilesClassPolicy__str__(self) -> str: ... + + +def _getAvailableILPSolvers() -> List[str]: ... + + +class Config: + class Common: + def __init__(self) -> None: + self.ignoreDeprecation: bool = ... + + def __init__(self) -> None: + self.common = Config.Common() + +def getConfig() -> Config: ... + + +# Error +#----------------------------------------------------------------------------- + +class LogicError(Exception): ... + + +# Derivation +#----------------------------------------------------------------------------- + +class Derivation: ... +class Derivations: ... + + +# Misc +#----------------------------------------------------------------------------- + +def rngUniformReal() -> float: ... + + +#----------------------------------------------------------------------------- +# causality +#----------------------------------------------------------------------------- + +# Petri +#----------------------------------------------------------------------------- + +class PetriNet: + def __init__(self, dg: DG) -> None: ... + def syncSize(self) -> None: ... + + +class PetriNetMarking: + def __init__(self, net: PetriNet) -> None: ... + def syncSize(self) -> None: ... + def add(self, v: DGVertex, c: int) -> int: ... + def remove(self, v: DGVertex, c: int) -> int: ... + def __getitem__(self, v: DGVertex) -> int: ... + def getAllEnabled(self) -> List[DGHyperEdge]: ... + def getNonZeroPlaces(self) -> List[DGVertex]: ... + def getEmptyPostPlaces(self, e: DGHyperEdge) -> List[DGVertex]: ... + def fire(self, e: DGHyperEdge) -> None: ... + + +class PetriNetMarkingSet: + def addIfNotSubset(self, m: PetriNetMarking) -> bool: ... + + +# Stochsim +#----------------------------------------------------------------------------- + +class MassActionKinetics: + def __init__(self, dg: DG, rate: Callable[[DGHyperEdge], float]) -> None: ... + def draw(self, possibles: List[DGHyperEdge], m: PetriNetMarking) -> Tuple[DGHyperEdge, float]: ... + + +class EventTrace: + def __init__(self, initialState: PetriNetMarking) -> None: ... + def addEdge(self, time: float, e: DGHyperEdge) -> None: ... + def addTransfer(self, time: float, v: DGVertex, count: int) -> None: ... + + +#----------------------------------------------------------------------------- +# dg +#----------------------------------------------------------------------------- + +class DG: + def __init__(self, *, labelSettings: LabelSettings=..., graphDatabase=..., graphPolicy=...) -> None: ... + def findVertex(self, g: Graph) -> DGVertex: ... + @overload + def findEdge(self, sources: List[DGVertex], targets: List[DGVertex]) -> DGHyperEdge: ... + @overload + def findEdge(self, sourcesGraphs: List[Graph], targetGraphs: List[Graph]) -> DGHyperEdge: ... + def build(self) -> DGBuilder: ... + def print(self, printer: DGPrinter=..., data: Optional[DGPrintData]=...) -> Tuple[str, str]: ... + @staticmethod + def load(graphDatabase: List[Graph], ruleDatabase: List[Rule], file: str, graphPolicy: IsomorphismPolicy=..., verbosity: int=...) -> DG: ... + + +class DGBuilder: + def addDerivation(self, d: Derivations, graphPolicy: IsomorphismPolicy = ...) -> DGHyperEdge: ... + def execute(self, strategy: DGStrat, *, verbosity: int=..., ignoreRuleLabelTypes: bool=...) -> DGExecuteResult: ... + def apply(self, graphs: List[Graph], rule: Rule, onlyProper: bool = ..., verbosity: int = ..., graphPolicy: IsomorphismPolicy = ...) -> List[DGHyperEdge]: ... + def addAbstract(self, description: str) -> None: ... + def load(self, ruleDatabase: List[Rule], file: str, verbosity: int = ...) -> None: ... + + +class DGExecuteResult: + def list(self, *, withUniverse: bool=...) -> None: ... + + +class DGVertex: + graph: Graph + + +class DGHyperEdge: + def print(self, printer: GraphPrinter=..., nomatchColour: str=..., matchColour: str=...) -> List[Tuple[str, str]]: ... + + +class DGPrinter: + def pushVertexVisible(self, f: Union[Callable[[DGVertex], bool], bool]) -> None: ... + def pushEdgeVisible(self, f: Union[Callable[[DGHyperEdge], bool], bool]) -> None: ... + def pushVertexLabel(self, f: Union[Callable[[DGVertex], str], str]) -> None: ... + def pushEdgeLabel(self, f: Union[Callable[[DGHyperEdge], str], str]) -> None: ... + def pushVertexColour(self, f: Union[Callable[[DGVertex], str], str], extendToEdges: bool=...) -> None: ... + def pushEdgeColour(self, f: Union[Callable[[DGHyperEdge], str], str]) -> None: ... + def setRotationOverwrite(self, f: Union[Callable[[Graph], int], int]) -> None: ... + def setMirrorOverwrite(self, f: Union[Callable[[Graph], bool], bool]) -> None: ... + + +class DGPrintData: + def __init__(self, dg: DG) -> None: ... + + +class DGStrat: + class GraphState: ... + + def __rshift__(self, other): ... + def __rrshift__(self, other): ... + + @staticmethod + def makeAddStatic(onlyUniverse: bool, graphs: List[Graph], graphPolicy: IsomorphismPolicy) -> DGStrat: ... + @staticmethod + def makeAddDynamic(onlyUniverse: bool, graphsFunc: Callable[[], List[Graph]], graphPolicy: IsomorphismPolicy) -> DGStrat: ... + @staticmethod + def makeSequence(strats: List[DGStrat]) -> DGStrat: ... + @staticmethod + def makeParallel(strats: List[DGStrat]) -> DGStrat: ... + @staticmethod + def makeFilter(alsoUniverse: bool, p: Callable[[Graph, GraphState, bool], bool]) -> DGStrat: ... + @staticmethod + def makeExecute(func: Callable[[GraphState], None]) -> DGStrat: ... + @staticmethod + def makeLeftPredicate(p: Callable[[Derivation], bool], strat: DGStrat) -> DGStrat: ... + @staticmethod + def makeRightPredicate(p: Callable[[Derivation], bool], strat: DGStrat) -> DGStrat: ... + @staticmethod + def makeRevive(strat: DGStrat) -> DGStrat: ... + + +#----------------------------------------------------------------------------- +# graph +#----------------------------------------------------------------------------- + +class Graph: + def aut(self, labelSettings: LabelSettings=...) -> GraphAutGroup: ... + @overload + def print(self) -> Tuple[str, str]: ... + @overload + def print(self, first: GraphPrinter, second: Optional[GraphPrinter]=...) -> Tuple[str, str]: ... + def getGMLString(self, withCoords: bool=...) -> str: ... + def printGML(self, withCoords: bool=...) -> str: ... + def isomorphism(self, host: Graph, maxNumMatches: int=..., labelSettings: LabelSettings=...) -> int: ... + def monomorphism(self, host: Graph, maxNumMatches: int=..., labelSettings: LabelSettings=...) -> int: ... + + +class GraphAutGroup: ... + + +class GraphPrinter: ... + + + +#----------------------------------------------------------------------------- +# rule +#----------------------------------------------------------------------------- + +class RCEvaluator: + def eval(self, exp: RCExpExp, *, verbosity: int=...) -> List[Rule]: ... + + +class RCExpExp: ... + +class RCExpUnion(RCExpExp): + def __init__(self, es: Vec[RCExpExp]) -> None: ... +class RCExpId(RCExpExp): ... +class RCExpBind(RCExpExp): ... +class RCExpUnbind(RCExpExp): ... + +class RCExpComposeCommon(RCExpExp): + def __init__(self, first: RCExpExp, second: RCExpExp, discardNonchemical=bool, maximum=bool, connected=bool) -> None: ... + +class RCExpComposeParallel(RCExpExp): + def __init__(self, first: RCExpExp, second: RCExpExp, discardNonchemical=bool) -> None: ... + +class RCExpComposeSub(RCExpExp): + def __init__(self, first: RCExpExp, second: RCExpExp, discardNonchemical=bool, allowPartial=bool) -> None: ... + +class RCExpComposeSuper(RCExpExp): + def __init__(self, first: RCExpExp, second: RCExpExp, discardNonchemical=bool, allowPartial=bool, enforceConstraints=bool) -> None: ... + + +class Rule(RCExpExp): + @overload + def print(self) -> Tuple[str, str]: ... + @overload + def print(self, first: GraphPrinter, second: Optional[GraphPrinter]=...) -> Tuple[str, str]: ... + def getGMLString(self, withCoords: bool=...) -> str: ... + def printGML(self, withCoords: bool=...) -> str: ... + def isomorphism(self, host: Rule, maxNumMatches: int=..., labelSettings: LabelSettings=...) -> int: ... + def monomorphism(self, host: Rule, maxNumMatches: int=..., labelSettings: LabelSettings=...) -> int: ... + + + def __rshift__(self, other): ... diff --git a/libs/pymod/share/mod/python.supp b/libs/pymod/share/mod/python.supp index 8c52064..b9abc9b 100644 --- a/libs/pymod/share/mod/python.supp +++ b/libs/pymod/share/mod/python.supp @@ -15,27 +15,17 @@ # # See Misc/README.valgrind for more information. -# these first ones have been manually added and may not be correct -{ - # https://bugzilla.redhat.com/show_bug.cgi?id=1538073 - # https://sourceware.org/bugzilla/show_bug.cgi?id=23711 - - Memcheck:Cond - ... - fun:wcsrtombs -} - - -# end of manually added ones - - - # all tool names: Addrcheck,Memcheck,cachegrind,helgrind,massif { ADDRESS_IN_RANGE/Invalid read of size 4 Memcheck:Addr4 fun:address_in_range } +{ + ADDRESS_IN_RANGE/Invalid read of size 4, unknown inlined, v3.8 + Memcheck:Addr4 + src:obmalloc.c:1401 +} { ADDRESS_IN_RANGE/Invalid read of size 4 @@ -48,12 +38,22 @@ Memcheck:Value8 fun:address_in_range } +{ + ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64), unknown inlined, v3.8 + Memcheck:Value8 + src:obmalloc.c:1403 +} { ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value Memcheck:Cond fun:address_in_range } +{ + ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value, unknown inlined, v3.8 + Memcheck:Cond + src:obmalloc.c:1403 +} # # Leaks (including possible leaks) @@ -97,9 +97,10 @@ { Handle PyMalloc confusing valgrind (possibly leaked) Memcheck:Leak - fun:realloc + fun:malloc + ... fun:_PyObject_GC_Resize - fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING + #fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING } { @@ -114,8 +115,9 @@ Handle PyMalloc confusing valgrind (possibly leaked) Memcheck:Leak fun:malloc + ... fun:_PyObject_GC_NewVar - fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING + #fun:COMMENT_THIS_LINE_TO_DISABLE_LEAK_WARNING } # @@ -278,6 +280,14 @@ } +{ + Uninitialised byte(s) false alarm, see bpo-35561 + Memcheck:Param + epoll_ctl(event) + fun:epoll_ctl + fun:pyepoll_internal_ctl +} + { ZLIB problems, see test_gzip Memcheck:Cond diff --git a/libs/pymod/src/mod/py/Chem.cpp b/libs/pymod/src/mod/py/Chem.cpp index be83103..7b7fc1e 100644 --- a/libs/pymod/src/mod/py/Chem.cpp +++ b/libs/pymod/src/mod/py/Chem.cpp @@ -2,10 +2,9 @@ #include -#include +#include -namespace mod { -namespace Py { +namespace mod::Py { namespace { std::string bondTypeToString(mod::BondType b) { @@ -17,40 +16,40 @@ std::string bondTypeToString(mod::BondType b) { } // namespace void Chem_doExport() { - // rst: .. py:class:: AtomId + // rst: .. class:: AtomId // rst: // rst: Representation of the chemical element of an atom. // rst: py::class_("AtomId", py::no_init) - // rst: .. py:method:: __init__(self, id=AtomIds.Invalid) + // rst: .. method:: __init__(id=AtomIds.Invalid) // rst: // rst: Construct an atom ID from an integer. // rst: - // rst: :param int id: the atomic number to construct from, or :py:const:`AtomIds.Invalid` to explicitly signal an invalid atom. - // rst: Must be at most the same value as :py:const:`AtomIds.Max`. + // rst: :param int id: the atomic number to construct from, or :const:`AtomIds.Invalid` to explicitly signal an invalid atom. + // rst: Must be at most the same value as :const:`AtomIds.Max`. .def(py::init<>()) .def(py::init()) - // rst: .. py:attribute:: symbol + // rst: .. attribute:: symbol // rst: // rst: (Read-only) The symbol represented by the atom id. // rst: // rst: :type: str - // rst: :raises: :py:class:`LogicError` if the id is invalid. + // rst: :raises: :class:`LogicError` if the id is invalid. .add_property("symbol", &mod::AtomId::symbol) - // rst: .. py:method:: __int__(self) + // rst: .. method:: __int__() // rst: // rst: Implicit conversion to an integer type. .def(int_(py::self)) .def(str(py::self)) .def(py::self == py::self); - // rst: .. py:class:: Isotope + // rst: .. class:: Isotope // rst: // rst: Representation of the isotope of an atom. // rst: py::class_("Isotope", py::no_init) - // rst: .. py:method:: __init__(self) - // rst: __init__(self, i) + // rst: .. method:: __init__() + // rst: __init__(i) // rst: // rst: Construct a representation of an isotope. // rst: If an isotope number is given, that specific one is constructed, @@ -62,7 +61,7 @@ void Chem_doExport() { // rst: The number must be either -1 or at least 1. .def(py::init<>()) .def(py::init()) - // rst: .. py:method:: __int__(self) + // rst: .. method:: __int__() // rst: // rst: Implicit conversion to an integer type. .def(int_(py::self)) @@ -70,18 +69,18 @@ void Chem_doExport() { .def(py::self == py::self) .def(py::self == int()); - // rst: .. py:class:: Charge + // rst: .. class:: Charge // rst: // rst: Representation of the charge of an atom. // rst: py::class_("Charge", py::no_init) - // rst: .. py:method:: __init__(self, c=0) + // rst: .. method:: __init__(c=0) // rst: // rst: Construct a charge. // rst: // rst: :param int c: The charge to construct. Must be in the range :math:`[-9, 9]`. .def(py::init(py::args("c") = 0)) - // rst: .. py:method:: __int__(self) + // rst: .. method:: __int__() // rst: // rst: Implicit conversion to an integer type. .def(int_(py::self)) @@ -89,86 +88,87 @@ void Chem_doExport() { .def(py::self == py::self) .def(py::self == int()); - // rst: .. py:class:: AtomData + // rst: .. class:: AtomData // rst: // rst: Representation of basic data of an atom. // rst: py::class_("AtomData", py::no_init) - // rst: .. py:method:: __init__(self, atomId=AtomIds.Invalid, istotope=Isotope(), charge=Charge(), radical=False) + // rst: .. method:: __init__(atomId=AtomIds.Invalid, istotope=Isotope(), charge=Charge(), radical=False) // rst: // rst: Construct an atom data object. // rst: .def(py::init( (py::args("atomId") = AtomIds::Invalid, py::args("isotope") = Isotope(), py::args("charge") = Charge(), py::args("radical") = false))) - // rst: .. py:attribute:: atomId + // rst: .. attribute:: atomId // rst: // rst: (Read-only) The atom id. // rst: // rst: :type: AtomId .add_property("atomId", &mod::AtomData::getAtomId) - // rst: .. py:attribute:: isotope + // rst: .. attribute:: isotope // rst: // rst: (Read-only) The isotope. // rst: // rst: :type: Isotope .add_property("isotope", &mod::AtomData::getIsotope) - // rst: .. py:attribute:: charge + // rst: .. attribute:: charge // rst: // rst: (Read-only) The charge. // rst: // rst: :type: Charge .add_property("charge", &mod::AtomData::getCharge) - // rst: .. py::attribute:: radical + // rst: .. :attribute:: radical // rst: // rst: (Read-only) The radical. // rst: // rst: :type: bool .add_property("radical", &mod::AtomData::getRadical) - // rst: .. py::method:: __str__(self) + // rst: .. :method:: __str__() // rst: // rst: :returns: A string representation of the atom data adhering to the string encoding of atoms (see :ref:`mol-enc`). - // rst: :raises: :py::class:`LogicError` if the atom id is :py:const:`AtomIds.Invalid`. + // rst: :raises: ::class:`LogicError` if the atom id is :const:`AtomIds.Invalid`. .def(str(py::self)) - .def(py::self == py::self); + .def(py::self == py::self) + .def(py::self < py::self); - // rst: .. py:class:: BondType + // rst: .. class:: BondType // rst: // rst: Representation of a bond type. // rst: py::enum_("BondType") - // rst: .. py:attribute:: Invalid + // rst: .. attribute:: Invalid .value("Invalid", mod::BondType::Invalid) - // rst: .. py:attribute:: Single + // rst: .. attribute:: Single .value("Single", mod::BondType::Single) - // rst: .. py:attribute:: Aromatic + // rst: .. attribute:: Aromatic .value("Aromatic", mod::BondType::Aromatic) - // rst: .. py:attribute:: Double + // rst: .. attribute:: Double .value("Double", mod::BondType::Double) - // rst: .. py:attribute:: Triple + // rst: .. attribute:: Triple .value("Triple", mod::BondType::Triple) - // rst: .. py:method:: __str__(self) + // rst: .. method:: __str__() // rst: // rst: :returns: A string representation of the bond type adhering to the string encoding of bonds (see :ref:`mol-enc`). - // rst: :raises: :py:class:`LogicError` if the bond type is :py:const:`Invalid`. + // rst: :raises: :class:`LogicError` if the bond type is :const:`Invalid`. ; // TOOD: py::enum_ does not support overriding of methods, so we set __str__ on the Python side. py::def("_bondTypeToString", &bondTypeToString); - // rst: .. py:class:: AtomIds + // rst: .. class:: AtomIds // rst: // rst: This class contains constants for each chemical element, both as their abbreviations and their full names. // rst: Two additional constants are provided for convenience. // rst: - // rst: .. py:attribute:: Invalid + // rst: .. attribute:: Invalid // rst: // rst: Constant for the invalid atom id. // rst: // rst: :type: AtomId // rst: - // rst: .. py:attribute:: Max + // rst: .. attribute:: Max // rst: // rst: An atom id equal to the atom id with the maximum valid id. // rst: @@ -192,5 +192,4 @@ void Chem_doExport() { #undef MDO_CHEM_atomIdIter } -} // namespace Py -} // namespace mod \ No newline at end of file +} // namespace mod::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/Collections.cpp b/libs/pymod/src/mod/py/Collections.cpp index c553555..7c02f81 100644 --- a/libs/pymod/src/mod/py/Collections.cpp +++ b/libs/pymod/src/mod/py/Collections.cpp @@ -22,16 +22,14 @@ bool operator==(const Derivation &, const Derivation &) { std::exit(1); } -namespace rule { -namespace RCExp { +namespace rule::RCExp { bool operator==(const Expression &, const Expression &) { std::cerr << "RCExpExp does not support ==" << std::endl; std::exit(1); } -} // namespace RCExp -} // namespace rule +} // namespace rule::RCExp namespace Py { template @@ -49,7 +47,7 @@ bool listCompare(const std::vector &l, py::object r) { #define makeVector(Name, Type) \ using Name = std::vector; \ - py::class_(#Name) \ + py::class_("_" #Name) \ .def(py::vector_indexing_suite()) \ .def("__eq__", &listCompare) @@ -81,4 +79,4 @@ void Collections_doExport() { } } // namespace Py -} // namespace mod +} // namespace mod \ No newline at end of file diff --git a/libs/pymod/src/mod/py/Common.hpp b/libs/pymod/src/mod/py/Common.hpp index 6aeef3d..f5a0ada 100644 --- a/libs/pymod/src/mod/py/Common.hpp +++ b/libs/pymod/src/mod/py/Common.hpp @@ -8,8 +8,7 @@ #undef BOOST_BIND_GLOBAL_PLACEHOLDERS namespace py = boost::python; -namespace mod { -namespace Py { +namespace mod::Py { struct AttributeIsNotReadable { }; @@ -34,7 +33,6 @@ struct ToPythonOptionalValue { } }; -} // namespace Py -} // namespace mod +} // namespace mod::Py #endif /* MOD_PY_COMMON_H */ \ No newline at end of file diff --git a/libs/pymod/src/mod/py/Config.cpp b/libs/pymod/src/mod/py/Config.cpp index 17c8eca..184951c 100644 --- a/libs/pymod/src/mod/py/Config.cpp +++ b/libs/pymod/src/mod/py/Config.cpp @@ -2,8 +2,7 @@ #include -namespace mod { -namespace Py { +namespace mod::Py { namespace { std::string LabelType_str(LabelType lt) { @@ -25,59 +24,59 @@ std::string SmilesClassPolicy_str(SmilesClassPolicy p) { } // namespace void Config_doExport() { - // rst: .. py:class:: LabelType + // rst: .. class:: LabelType // rst: // rst: Selector for which type of label to use in algorithms. // rst: py::enum_("LabelType") - // rst: .. py:attribute:: String + // rst: .. attribute:: String // rst: // rst: Vertices and edges are considered to be labelled with // rst: character strings. If only first-order terms are present, // rst: then strings are generated as a serialisation of the term. .value("String", LabelType::String) // rst: - // rst: .. py:attribute:: Term + // rst: .. attribute:: Term // rst: // rst: Vertices and edges are considered to be labelled with // rst: first-order terms. If only strings are present, then first-order // rst: terms are generated by parsing the strings. This may result - // rst: in an :py:class:`TermParsingError` if a string can not be parsed. + // rst: in an :class:`TermParsingError` if a string can not be parsed. .value("Term", LabelType::Term); py::def("_LabelType__str__", &LabelType_str); - // rst: .. py:class:: LabelRelation + // rst: .. class:: LabelRelation // rst: // rst: Selector for which type of labelled morphism to use in an algorithm. // rst: For strings they are all defined to be equivalent to string equality. // rst: py::enum_("LabelRelation") - // rst: .. py:attribute:: Isomorphism + // rst: .. attribute:: Isomorphism // rst: // rst: Terms are considered isomorphic when their most general unifier // rst: is a renaming. .value("Isomorphism", LabelRelation::Isomorphism) - // rst: .. py:attribute:: Specialisation + // rst: .. attribute:: Specialisation // rst: // rst: A term :math:`t_2` is more special than, or isomorphic to, a term :math:`t_1` if there is a substitution // rst: which can be applied to :math: `t_1` to make the terms equal. // rst: This relation means that the right-hand side of a comparison is the more specialised term. .value("Specialisation", LabelRelation::Specialisation) - // rst: .. py:attribute:: Unification + // rst: .. attribute:: Unification // rst: // rst: Terms unify if a most general unifier (MGU) exists. The found MGU // rst: is used for substitution in some algorithms. .value("Unification", LabelRelation::Unification); py::def("_LabelRelation__str__", &LabelRelation_str); - // rst: .. py:class:: LabelSettings + // rst: .. class:: LabelSettings // rst: // rst: A group label settings commonly used together in algorithms. // rst: py::class_("LabelSettings", py::no_init) - // rst: .. py:method:: __init__(self, type, relation) - // rst: __init__(self, type, relation, stereoRelation) - // rst: __init__(self, type, relation, withStereo, stereoRelation) + // rst: .. method:: __init__(type, relation) + // rst: __init__(type, relation, stereoRelation) + // rst: __init__(type, relation, withStereo, stereoRelation) // rst: // rst: Construct label settings that only uses at least the vertex and edge labels. // rst: If ``stereoRelation`` is given but ``withStereo`` is not, then ``withStereo`` defaults to ``True``. @@ -87,42 +86,42 @@ void Config_doExport() { // rst: :param bool withStereo: A flag to specify if stereo information should be included. // rst: Defaults to ``False``, unless ``stereoRelation`` is gieven, then ``True``. // rst: :param LabelRelation stereoRelation: The relation that should hold in morphisms between stereo data. - // rst: Defaults to :py:class:`LabelRelation.Isomorphism`, but is only used when ``withStereo`` is ``True``. + // rst: Defaults to :class:`LabelRelation.Isomorphism`, but is only used when ``withStereo`` is ``True``. .def(py::init()) .def(py::init()) .def(py::init()) .def(py::self == py::self) .def(py::self != py::self) .def(str(py::self)) - // rst: .. py:attribute:: type + // rst: .. attribute:: type // rst: // rst: :type: LabelType .def_readwrite("type", &LabelSettings::type) - // rst: .. py:attribute:: relation + // rst: .. attribute:: relation // rst: // rst: :type: LabelRelation .def_readwrite("relation", &LabelSettings::relation) - // rst: .. py:attribute:: withStereo + // rst: .. attribute:: withStereo // rst: // rst: :type: bool .def_readwrite("withStereo", &LabelSettings::withStereo) - // rst: .. py:attribute:: stereoRelation + // rst: .. attribute:: stereoRelation // rst: // rst: :type: LabelRelation .def_readwrite("stereoRelation", &LabelSettings::stereoRelation); - // rst: .. py:class:: IsomorphismPolicy + // rst: .. class:: IsomorphismPolicy // rst: // rst: For some functions there is a choice of how to handle given arguments // rst: where two different objects may be isomorphic. Most notably the case is with graphs (:class:`Graph`). // rst: py::enum_("IsomorphismPolicy") - // rst: .. py:attribute:: Check + // rst: .. attribute:: Check // rst: // rst: Objects are checked for isomorphism as needed and exceptions are thrown when different objects are isomorphic. // rst: If in doubt, use this. .value("Check", IsomorphismPolicy::Check) - // rst: .. py:attribute:: TrustMe + // rst: .. attribute:: TrustMe // rst: // rst: No checks are performed and the function trusts the caller to have performed the equivalent isomorphism checks. // rst: Only use this when you are completely sure that no exceptions would have been thrown if using :attr:`Check`. @@ -132,28 +131,27 @@ void Config_doExport() { .value("TrustMe", IsomorphismPolicy::TrustMe); py::def("_IsomorphismPolicy__str__", &IsomorphismPolicy_str); - // rst: .. py:class:: SmilesClassPolicy + // rst: .. class:: SmilesClassPolicy // rst: // rst: When loading SMILES strings, the class labels can be recorded and mapped into the corresponding // rst: vertices of the loaded graph. This policy dictates what should happen when the same class label // rst: is written on multiple atoms. // rst: py::enum_("SmilesClassPolicy") - // rst: .. py:attribute:: AllOrNone + // rst: .. attribute:: AllOrNone // rst: // rst: If a class label is duplicated, then no labels are mapped to vertices. .value("NoneOnDuplicate", SmilesClassPolicy::NoneOnDuplicate) - // rst: .. py:attribute:: ThrowOnDuplicate + // rst: .. attribute:: ThrowOnDuplicate // rst: // rst: If a class label is duplicated, throw a :class:`InputError`. .value("ThrowOnDuplicate", SmilesClassPolicy::ThrowOnDuplicate) - // rst: .. py:attribute:: MapUnique + // rst: .. attribute:: MapUnique // rst: // rst: Map all class labels that are unique to vertices. .value("MapUnique", SmilesClassPolicy::MapUnique); py::def("_SmilesClassPolicy__str__", &SmilesClassPolicy_str); - #define NSIter(rNS, dataNS, tNS) \ BOOST_PP_SEQ_FOR_EACH_I(SettingIter, ~, \ BOOST_PP_TUPLE_ELEM(MOD_CONFIG_DATA_NS_SIZE(), 2, tNS)) @@ -171,8 +169,8 @@ void Config_doExport() { .value("SmilesCanonVF2", mod::Config::IsomorphismAlg::SmilesCanonVF2); #define NSIter(rNS, dataNS, tNS) \ - py::class_ \ - ("Config" MOD_toString(BOOST_PP_TUPLE_ELEM(MOD_CONFIG_DATA_NS_SIZE(), 0, tNS)), py::no_init) \ + py::class_ \ + (MOD_toString(BOOST_PP_TUPLE_ELEM(MOD_CONFIG_DATA_NS_SIZE(), 0, tNS)), py::no_init) \ BOOST_PP_SEQ_FOR_EACH_I(SettingIter, \ BOOST_PP_TUPLE_ELEM(MOD_CONFIG_DATA_NS_SIZE(), 0, tNS), \ BOOST_PP_TUPLE_ELEM(MOD_CONFIG_DATA_NS_SIZE(), 2, tNS)) \ @@ -221,15 +219,15 @@ void Config_doExport() { #undef NSIter #undef SettingIter -// rst: .. py:class:: Config +// rst: .. class:: Config // rst: // rst: This class contains a range of inner classes of config settings. See :doc:`the libMØD documentation`. -// rst: .. py:data:: config +// rst: .. data:: config // rst: -// rst: This variable is initialised to the return value of :py:func:`getConfig`, i.e., just use this instead of the method. +// rst: This variable is initialised to the return value of :func:`getConfig`, i.e., just use this instead of the method. // rst: -// rst: .. py:method:: getConfig() +// rst: .. method:: getConfig() // rst: // rst: :returns: the singleton :cpp:class:`Config` instance used by the library. py::def("getConfig", &getConfig, @@ -237,5 +235,4 @@ void Config_doExport() { ); } -} // namespace Py -} // namespace mod +} // namespace mod::Py diff --git a/libs/pymod/src/mod/py/Derivation.cpp b/libs/pymod/src/mod/py/Derivation.cpp index 4005f2c..4c5f654 100644 --- a/libs/pymod/src/mod/py/Derivation.cpp +++ b/libs/pymod/src/mod/py/Derivation.cpp @@ -3,11 +3,10 @@ #include #include -namespace mod { -namespace Py { +namespace mod::Py { void Derivation_doExport() { - // rst: .. py:class:: Derivation + // rst: .. class:: Derivation // rst: // rst: This class is a simple wrapper for passing data around. // rst: It contains two multisets of graphs :math:`G` and :math:`H`, @@ -15,30 +14,30 @@ void Derivation_doExport() { // rst: An object may thus implicitly store a set of direct derivations // rst: :math:`G\Rightarrow^p H`, though the validity of the data is not checked. // rst: - // rst: An object of this class is implicitly convertible to a :py:class:`Derivations` object. + // rst: An object of this class is implicitly convertible to a :class:`Derivations` object. // rst: py::class_("Derivation") .def(str(py::self)) - // rst: .. py:attribute:: left + // rst: .. attribute:: left // rst: // rst: Represents the multi-set of left graphs :math:`G`. // rst: // rst: :type: list[Graph] .def_readwrite("left", &mod::Derivation::left) - // rst: .. py:attribute:: rule + // rst: .. attribute:: rule // rst: // rst: Represents the transformation rule :math:`p`, or no rule at all. // rst: // rst: :type: Rule .def_readwrite("rule", &mod::Derivation::r) - // rst: .. py:attribute:: right + // rst: .. attribute:: right // rst: // rst: Represents the multi-set of right graphs :math:`H`. // rst: // rst: :type: list[Graph] .def_readwrite("right", &mod::Derivation::right); - // rst: .. py:class:: Derivations + // rst: .. class:: Derivations // rst: // rst: This class is a simple wrapper for passing data around. // rst: It contains two multisets of graphs :math:`G` and :math:`H`, @@ -50,19 +49,19 @@ void Derivation_doExport() { py::class_("Derivations") .def(py::init()) .def(str(py::self)) - // rst: .. py:attribute:: left + // rst: .. attribute:: left // rst: // rst: Represents the multi-set of left graphs :math:`G`. // rst: // rst: :type: list[Graph] .def_readwrite("left", &mod::Derivations::left) - // rst: .. py:attribute:: rules + // rst: .. attribute:: rules // rst: // rst: Represents a (possibly empty) set of transformation rules. // rst: // rst: :type: list[Rule] .def_readwrite("rules", &mod::Derivations::rules) - // rst: .. py:attribute:: right + // rst: .. attribute:: right // rst: // rst: Represents the multi-set of right graphs :math:`H`. // rst: @@ -72,5 +71,4 @@ void Derivation_doExport() { py::implicitly_convertible(); } -} // namespace Py -} // namespace mod \ No newline at end of file +} // namespace mod::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/Error.cpp b/libs/pymod/src/mod/py/Error.cpp index 8572065..d74726b 100644 --- a/libs/pymod/src/mod/py/Error.cpp +++ b/libs/pymod/src/mod/py/Error.cpp @@ -2,14 +2,13 @@ #include -#include +#include // see http://stackoverflow.com/questions/2261858/boostpython-export-custom-exception // and http://stackoverflow.com/questions/9620268/boost-python-custom-exception-class // and http://stackoverflow.com/questions/11448735/boostpython-export-custom-exception-and-inherit-from-pythons-exception -namespace mod { -namespace Py { +namespace mod::Py { namespace { PyObject *exportException(const std::string &name) { @@ -37,27 +36,26 @@ PyObject *exportException(const std::string &name) { } // namespace void Error_doExport() { - // rst: .. py:exception:: FatalError + // rst: .. exception:: FatalError // rst: // rst: See :cpp:class:`FatalError`. MOD_PY_ExportException(FatalError); - // rst: .. py:exception:: InputError + // rst: .. exception:: InputError // rst: // rst: See :cpp:class:`InputError`. MOD_PY_ExportException(InputError); - // rst: .. py:exception:: LogicError + // rst: .. exception:: LogicError // rst: // rst: See :cpp:class:`LogicError`. MOD_PY_ExportException(LogicError); - // rst: .. py:exception:: TermParsingError + // rst: .. exception:: TermParsingError // rst: // rst: See :cpp:class:`TermParsingError`. MOD_PY_ExportException(TermParsingError); - // rst: .. py:exception:: StereoDeductionError + // rst: .. exception:: StereoDeductionError // rst: // rst: See :cpp:class:`StereoDeductionError`. MOD_PY_ExportException(StereoDeductionError); } -} // namespace Py -} // namespace mod \ No newline at end of file +} // namespace mod::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/Function.cpp b/libs/pymod/src/mod/py/Function.cpp index 9e96c40..c02d20e 100644 --- a/libs/pymod/src/mod/py/Function.cpp +++ b/libs/pymod/src/mod/py/Function.cpp @@ -8,42 +8,41 @@ #include #include -namespace mod { -namespace Py { +namespace mod::Py { void Function_doExport() { // () -> X - exportFunc >()>("Func_VecGraph"); - exportFunc("Func_String"); + exportFunc >()>("_Func_VecGraph"); + exportFunc("_Func_String"); // Derivation -> X - exportFunc("Func_BoolDerivation"); - exportFunc("Func_StringDerivation"); + exportFunc("_Func_BoolDerivation"); + exportFunc("_Func_StringDerivation"); // DG::Vertex -> X - exportFunc("Func_BoolDGVertex"); - exportFunc("Func_StringDGVertex"); + exportFunc("_Func_BoolDGVertex"); + exportFunc("_Func_StringDGVertex"); // DG::HyperEdge -> X - exportFunc("Func_BoolDGHyperEdge"); - exportFunc("Func_StringDGHyperEdge"); - exportFunc("Func_DoubleDGHyperEdge"); + exportFunc("_Func_BoolDGHyperEdge"); + exportFunc("_Func_StringDGHyperEdge"); + exportFunc("_Func_DoubleDGHyperEdge"); // Graph -> X - exportFunc)>("Func_BoolGraph"); - exportFunc)>("Func_IntGraph"); - exportFunc)>("Func_StringGraph"); + exportFunc)>("_Func_BoolGraph"); + exportFunc)>("_Func_IntGraph"); + exportFunc)>("_Func_StringGraph"); // Graph x DG -> X - exportFunc, std::shared_ptr)>("Func_StringGraphDG"); + exportFunc, std::shared_ptr)>("_Func_StringGraphDG"); // Graph x DG x bool -> X - exportFunc, std::shared_ptr, bool)>("Func_StringGraphDGBool"); + exportFunc, std::shared_ptr, bool)>("_Func_StringGraphDGBool"); // Graph x Strategy::GraphState -> X - exportFunc, const dg::Strategy::GraphState &)>("Func_BoolGraphDGStratGraphState"); + exportFunc, const dg::Strategy::GraphState &)>( + "_Func_BoolGraphDGStratGraphState"); // Graph x Strategy::GraphState x bool -> X exportFunc, const dg::Strategy::GraphState &, bool)>( - "Func_BoolGraphDGStratGraphStateBool"); + "_Func_BoolGraphDGStratGraphStateBool"); // Graph x Graph x Strategy::GraphState -> X exportFunc, std::shared_ptr, const dg::Strategy::GraphState &)>( - "Func_BoolGraphGraphDGStratGraphState"); + "_Func_BoolGraphGraphDGStratGraphState"); // Strategy::GraphState -> X - exportFunc("Func_VoidDGStratGraphState"); + exportFunc("_Func_VoidDGStratGraphState"); } -} // namespace Py -} // namespace mod +} // namespace mod::Py diff --git a/libs/pymod/src/mod/py/Function.hpp b/libs/pymod/src/mod/py/Function.hpp index f94f263..d456682 100644 --- a/libs/pymod/src/mod/py/Function.hpp +++ b/libs/pymod/src/mod/py/Function.hpp @@ -11,14 +11,12 @@ #include -namespace mod { -namespace Py { +namespace mod::Py { namespace py = boost::python; namespace detail { template struct ArgWrap { - static T wrap(T t) { return t; } @@ -33,7 +31,6 @@ struct ArgWrap { template struct Returner { - static R doReturn(decltype((*static_cast (nullptr))()) r) { return r; } @@ -41,7 +38,6 @@ struct Returner { template<> struct Returner { - static void doReturn(decltype((*static_cast (nullptr))())) { } }; @@ -51,7 +47,6 @@ struct FunctionWrapper { template struct FunctionWrapper : mod::Function, py::wrapper > { - std::shared_ptr < mod::Function < R(Args...)> > clone() const { if(py::override f = this->get_override("clone")) { return f(); @@ -106,7 +101,6 @@ void exportFunc(const char *name) { py::def("_sharedToStd", &detail::sharedToStd); } -} // namespace Py -} // namespace mod +} // namespace mod::Py #endif /* MOD_PY_FUNCTION_H */ diff --git a/libs/pymod/src/mod/py/Misc.cpp b/libs/pymod/src/mod/py/Misc.cpp index b6ae379..8532f4e 100644 --- a/libs/pymod/src/mod/py/Misc.cpp +++ b/libs/pymod/src/mod/py/Misc.cpp @@ -5,29 +5,28 @@ #include -namespace mod { -namespace Py { +namespace mod::Py { // rst: // rst: .. function:: prefixFilename(name) // rst: // rst: Utility function for converting script-relative paths to current-working-directory-relative paths -// rst: (see also :py:func:`include`). +// rst: (see also :func:`include`). // rst: This function is used in all PyMØD functions that takes a filename as argument. -// rst: To circumvent this prefixing use the :py:class:`CWDPath` class. +// rst: To circumvent this prefixing use the :class:`CWDPath` class. // rst: -// rst: :returns: `name` prefixed with all strings pushed with :py:func:`pushFilePrefix` +// rst: :returns: `name` prefixed with all strings pushed with :func:`pushFilePrefix` // rst: and popped yet. // rst: :rtype: str // rst: // rst: .. function:: pushFilePrefix(s) // rst: -// rst: Push another prefix used in :py:func:`prefixFilename`. +// rst: Push another prefix used in :func:`prefixFilename`. // rst: The prefixes are concatenated in the order they are pushed. // rst: No directory delimiters are inserted, so they must explicitly be part of the pushed prefixes. // rst: If the argument starts with ``/``, then during concatenation all previously pushed prefixes are ignored. // rst: -// rst: :param str s: the string to push as a prefix to be concatenated in :py:func:`prefixFilename`. +// rst: :param str s: the string to push as a prefix to be concatenated in :func:`prefixFilename`. // rst: // rst: .. function:: popFilePrefix() // rst: @@ -35,25 +34,25 @@ namespace Py { // rst: // rst: .. class:: CWDPath // rst: -// rst: A dummy class to wrap a filename in to disable prefixing. +// rst: A dummy class to wrap a filename in to disable prefixing. // rst: -// rst: For example, if a graph GML file is to be loaded relative to the current file -// rst: (assuming :py:func:`include` is used for script inclusion), then it can be done with +// rst: For example, if a graph GML file is to be loaded relative to the current file +// rst: (assuming :func:`include` is used for script inclusion), then it can be done with // rst: -// rst: .. code-block:: python +// rst: .. code-block:: python // rst: -// rst: g = graphGML(f) +// rst: g = graphGML(f) // rst: -// rst: If the file is located relative to the current working directory -// rst: (i.e., where the :any:`mod` wrapper script were invoked from), then the graph loading should be done as +// rst: If the file is located relative to the current working directory +// rst: (i.e., where the :any:`mod` wrapper script were invoked from), then the graph loading should be done as // rst: -// rst: .. code-block:: python +// rst: .. code-block:: python // rst: -// rst: g = graphGML(CWDPath(f)) +// rst: g = graphGML(CWDPath(f)) // rst: -// rst: .. function:: __init__(self, f) +// rst: .. method:: __init__(f) // rst: -// rst: Wrap a filename. +// rst: Wrap a filename. // rst: namespace { @@ -88,20 +87,9 @@ void Misc_doExport() { // rst: :rtype: float py::def("rngUniformReal", &mod::rngUniformReal); - py::def("post", &mod::post); - py::def("postChapter", &mod::postChapter); - py::def("postSection", &mod::postSection); - - // rst: .. function:: makeUniqueFilePrefix() - // rst: - // rst: :returns: a unique file prefix from the ``out/`` folder. - // rst: :rtype: str - py::def("makeUniqueFilePrefix", &mod::makeUniqueFilePrefix); - py::def("showDump", &mod::showDump); py::def("printGeometryGraph", &mod::printGeometryGraph); } -} // namespace Py -} // namespace mod +} // namespace mod::Py diff --git a/libs/pymod/src/mod/py/Module.cpp b/libs/pymod/src/mod/py/Module.cpp index a4299e6..1f1d94d 100644 --- a/libs/pymod/src/mod/py/Module.cpp +++ b/libs/pymod/src/mod/py/Module.cpp @@ -18,8 +18,10 @@ ((Chem)) ((Collections)) ((Config)) ((Derivation)) \ ((dg, (Builder) (DG) (GraphInterface) (Printer) (Strategy))) \ ((Error)) ((Function)) \ - ((graph, (Automorphism) (Graph) (GraphInterface))) \ + ((graph, (Graph) (Union))) \ + ((graph, (Automorphism) (GraphInterface))) /* nested classes of Graph, so must be after */ \ ((rule, (RC) (Rule) (GraphInterface))) \ + ((post, (Post))) \ ((Misc)) ((Term)) namespace mod { diff --git a/libs/pymod/src/mod/py/Post.cpp b/libs/pymod/src/mod/py/Post.cpp new file mode 100644 index 0000000..2b5d562 --- /dev/null +++ b/libs/pymod/src/mod/py/Post.cpp @@ -0,0 +1,23 @@ +#include + +#include + +namespace mod::post::Py { + +void Post_doExport() { + py::def("post", &command); + py::def("postReset", &reset); + py::def("postFlush", &flush); + py::def("postDisable", &disable); + + py::def("postChapter", &summaryChapter); + py::def("postSection", &summarySection); + + // rst: .. function:: makeUniqueFilePrefix() + // rst: + // rst: :returns: a unique file prefix from the ``out/`` folder. + // rst: :rtype: str + py::def("makeUniqueFilePrefix", &makeUniqueFilePrefix); +} + +} // namespace mod::post::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/Term.cpp b/libs/pymod/src/mod/py/Term.cpp index 56ada59..d30fe3e 100644 --- a/libs/pymod/src/mod/py/Term.cpp +++ b/libs/pymod/src/mod/py/Term.cpp @@ -2,12 +2,10 @@ #include -namespace mod { -namespace Py { +namespace mod::Py { void Term_doExport() { py::def("mgu", &mod::Term::mgu); } -} // namespace Py -} // namespace mod \ No newline at end of file +} // namespace mod::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/dg/Builder.cpp b/libs/pymod/src/mod/py/dg/Builder.cpp index 70aa318..2940609 100644 --- a/libs/pymod/src/mod/py/dg/Builder.cpp +++ b/libs/pymod/src/mod/py/dg/Builder.cpp @@ -3,9 +3,7 @@ #include #include -namespace mod { -namespace dg { -namespace Py { +namespace mod::dg::Py { namespace { // see https://stackoverflow.com/questions/19062657/is-there-a-way-to-wrap-the-function-return-value-object-in-python-using-move-i @@ -21,12 +19,12 @@ Builder_execute(std::shared_ptr b, std::shared_ptr strategy, void Builder_doExport() { using AddDerivation = DG::HyperEdge (Builder::*)(const Derivations &, IsomorphismPolicy); using Apply = std::vector (Builder::*)(const std::vector > &, - std::shared_ptr, + std::shared_ptr, bool, int, IsomorphismPolicy); - // rst: .. py:class:: DGBuilder + // rst: .. class:: DGBuilder // rst: - // rst: An RAII-style object obtained from :py:meth:`DG.build`. - // rst: On destruction of an active builder object the owning :py:class:`DG` will be locked + // rst: An RAII-style object obtained from :meth:`DG.build`. + // rst: On destruction of an active builder object the owning :class:`DG` will be locked // rst: for further modifications. // rst: // rst: The object can be used as a context manager: @@ -41,7 +39,7 @@ void Builder_doExport() { // rst: Otherwise one can manually use ``del`` on the obtained builder to trigger the destruction. // rst: py::class_, boost::noncopyable>("DGBuilder", py::no_init) - // rst: .. py:method:: addDerivation(d, graphPolicy=IsomorphismPolicy.Check) + // rst: .. method:: addDerivation(d, graphPolicy=IsomorphismPolicy.Check) // rst: // rst: Adds a hyperedge corresponding to the given derivation to the associated :class:`DG`. // rst: If it already exists, only add the given rules to the edge. @@ -56,7 +54,7 @@ void Builder_doExport() { // rst: is different but isomorphic to another given graph object or to a graph object already // rst: in the internal graph database in the associated derivation graph. .def("addDerivation", static_cast(&Builder::addDerivation)) - // rst: .. py:method:: execute(strategy, *, verbosity=2, ignoreRuleLabelTypes=False) + // rst: .. method:: execute(strategy, *, verbosity=2, ignoreRuleLabelTypes=False) // rst: // rst: Execute the given strategy (:ref:`dgStrat`) and as a side-effect add // rst: vertices and hyperedges to the underlying derivation graph. @@ -84,12 +82,13 @@ void Builder_doExport() { // rst: and a rule in the given strategy has an associated :class:`LabelType` which is different from the one // rst: in the derivation graph. .def("execute", &Builder_execute) - // rst: .. py:method:: apply(graphs, r, verbosity=0, graphPolicy=IsomorphismPolicy.Check) + // rst: .. method:: apply(graphs, r, onlyProper=True, verbosity=0, graphPolicy=IsomorphismPolicy.Check) // rst: - // rst: Compute proper direct derivations. + // rst: Compute direct derivations. // rst: // rst: :param graphs: the graphs constituting the left-hand side of the computed direct derivations. // rst: :type graphs: list[Graph] + // rst: :param bool onlyProper: when ``True``, then all of ``graphs`` must be used in each direct derivation. // rst: :param Rule r: the rule to use for the direct derivations. // rst: :param int verbosity: the level of verbosity of printed information during calculation. // rst: See :cpp:func:`dg::Builder::apply` for explanations of the levels. @@ -105,7 +104,7 @@ void Builder_doExport() { // rst: is different but isomorphic to another given graph object or to a graph object already // rst: in the internal graph database in the associated derivation graph. .def("apply", static_cast(&Builder::apply)) - // rst: .. py:method:: addAbstract(description) + // rst: .. method:: addAbstract(description) // rst: // rst: Add vertices and hyperedges based on the given abstract description. // rst: The description must adhere to the grammar described at :ref:`dg_abstract-desc`. @@ -116,10 +115,10 @@ void Builder_doExport() { // rst: :param str description: the description to parse into abstract derivations. // rst: :raises: :class:`InputError` if the description could not be parsed. .def("addAbstract", &Builder::addAbstract) - // rst: .. py:method:: load(ruleDatabase, file, verbosity=2) + // rst: .. method:: load(ruleDatabase, file, verbosity=2) // rst: // rst: Load and add a derivation graph dump. - // rst: Use :py:func:`DG.load` to load a dump as a locked derivation graph. + // rst: Use :func:`DG.load` to load a dump as a locked derivation graph. // rst: // rst: The label settings of this DG and the ones retrieved from the dump file must match. // rst: Vertices with graphs and hyperedges with rules are then added from the dump. @@ -138,12 +137,12 @@ void Builder_doExport() { // rst: :raises: :class:`InputError` if the file can not be opened or its content is bad. .def("load", &Builder::load); - // rst: .. py:class:: DGExecuteResult + // rst: .. class:: DGExecuteResult // rst: // rst: The result from calling :func:`DGBuilder.execute`. // rst: py::class_, boost::noncopyable>("DGExecuteResult", py::no_init) - // rst: .. py:attribute:: subset + // rst: .. attribute:: subset // rst: universe // rst: // rst: (Read-only) Respectively the subset and the universe computed @@ -162,6 +161,4 @@ void Builder_doExport() { .def("list", &ExecuteResult::list); } -} // namespace Py -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/dg/DG.cpp b/libs/pymod/src/mod/py/dg/DG.cpp index f30b1ab..a32a8a8 100644 --- a/libs/pymod/src/mod/py/dg/DG.cpp +++ b/libs/pymod/src/mod/py/dg/DG.cpp @@ -8,9 +8,7 @@ #include #include -namespace mod { -namespace dg { -namespace Py { +namespace mod::dg::Py { namespace { DG::HyperEdge (DG::*findEdgeVertices)(const std::vector &, @@ -32,7 +30,7 @@ void DG_doExport() { const std::string &, IsomorphismPolicy, int); - // rst: .. py:class:: DG + // rst: .. class:: DG // rst: // rst: The derivation graph class. A derivation graph is a directed multi-hypergraph // rst: :math:`\mathcal{H} = (V, E)`. Each hyperedge :math:`e\in E` is thus an ordered pair @@ -42,7 +40,7 @@ void DG_doExport() { // rst: function. When the obtained builder is destructed the derivation graph becomes locked and can no longer be modified. // rst: py::class_, boost::noncopyable>("DG", py::no_init) - // rst: .. py:method:: __init__(*, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism), \ + // rst: .. method:: __init__(*, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism), \ // rst: graphDatabase=[], \ // rst: graphPolicy=IsomorphismPolicy.Check) // rst: @@ -60,57 +58,57 @@ void DG_doExport() { // rst: absolutely sure that the graphs are unique up to isomorphism. // rst: :raises: :class:`LogicError` if ``graphPolicy == IsomorphismPolicy.Check`` and two graphs // rst: in ``graphDatabase`` are different objects but represents isomorphic graphs. - // rst: :raises: :class:`LogicError` if there is a ``None``in ``graphDatabase``. + // rst: :raises: :class:`LogicError` if there is a ``None`` in ``graphDatabase``. .def("__init__", py::make_constructor(&DG::make)) - // rst: .. py:attribute:: id + // rst: .. attribute:: id // rst: // rst: The unique instance id among all :class:`DG` objects. // rst: // rst: :type: int .add_property("id", &DG::getId) .def(str(py::self)) - // rst: .. py:attribute:: labelSettings + // rst: .. attribute:: labelSettings // rst: // rst: (Read-only) The label settings for the derivation graph. // rst: // rst: :type: LabelSettings .add_property("labelSettings", &DG::getLabelSettings) //------------------------------------------------------------------ - // rst: .. py:attribute:: hasActiveBuilder + // rst: .. attribute:: hasActiveBuilder // rst: // rst: (Read-only) Whether :meth:`build` has been called and the returned :class:`DGBuilder` is still active. // rst: // rst: :type: bool .add_property("hasActiveBuilder", &DG::hasActiveBuilder) - // rst: .. py:attribute:: locked + // rst: .. attribute:: locked // rst: // rst: (Read-only) Whether the derivation graph is locked or not. // rst: // rst: :type: bool .add_property("locked", &DG::isLocked) //------------------------------------------------------------------ - // rst: .. py:attribute:: numVertices + // rst: .. attribute:: numVertices // rst: // rst: (Read-only) The number of vertices in the derivation graph. // rst: // rst: :type: int // rst: :raises: :class:`LogicError` if not `hasActiveBuilder` or `isLocked`. .add_property("numVertices", &DG::numVertices) - // rst: .. py:attribute:: vertices + // rst: .. attribute:: vertices // rst: // rst: (Read-only) An iterable of all vertices in the derivation graph. // rst: // rst: :type: DGVertexRange // rst: :raises: :class:`LogicError` if not `hasActiveBuilder` or `locked`. .add_property("vertices", &DG::vertices) - // rst: .. py:attribute:: numEdges + // rst: .. attribute:: numEdges // rst: // rst: (Read-only) The number of hyperedges in the derivation graph. // rst: // rst: :type: int // rst: :raises: :class:`LogicError` if not `hasActiveBuilder` or `locked`. .add_property("numEdges", &DG::numEdges) - // rst: .. py:attribute:: edges + // rst: .. attribute:: edges // rst: // rst: (Read-only) An iterable of all hyperedges in the derivation graph. // rst: @@ -118,7 +116,7 @@ void DG_doExport() { // rst: :raises: :class:`LogicError` if not `hasActiveBuilder` or `locked`. .add_property("edges", &DG::edges) //------------------------------------------------------------------ - // rst: .. py:method:: findVertex(g) + // rst: .. method:: findVertex(g) // rst: // rst: :param Graph g: the graph to find a vertex which has it associated. // rst: :returns: a vertex descriptor for which the given graph is associated, @@ -127,7 +125,7 @@ void DG_doExport() { // rst: :raises: :class:`LogicError` if not `hasActiveBuilder` or `locked`. // rst: :raises: :class:`LogicError` if ``g`` is ``None``. .def("findVertex", &DG::findVertex) - // rst: .. py:method:: findEdge(sources, targets) + // rst: .. method:: findEdge(sources, targets) // rst: findEdge(sourceGraphs, targetGraphs) // rst: // rst: :param sources: the list of source vertices the resulting hyperedge must have. @@ -147,7 +145,7 @@ void DG_doExport() { .def("findEdge", findEdgeVertices) .def("findEdge", findEdgeGraphs) //------------------------------------------------------------------ - // rst: .. py:method:: build() + // rst: .. method:: build() // rst: // rst: :returns: an RAII-style object which can be used to construct the derivation graph. // rst: It can be used as a context manager in a ``with``-statement (see the documentation of :class:`DGBuilder`). @@ -156,21 +154,21 @@ void DG_doExport() { // rst: :raises: :class:`LogicError` if the DG already has an active builder (see :attr:`hasActiveBuilder`). // rst: :raises: :class:`LogicError` if the DG is locked (see :attr:`locked`). .def("build", &DG_build) - // rst: .. py:attribute:: graphDatabase + // rst: .. attribute:: graphDatabase // rst: // rst: All graphs known to the derivation graph. // rst: // rst: :type: list[Graph] .add_property("_graphDatabase", py::make_function(&DG::getGraphDatabase, py::return_value_policy())) - // rst: .. py:attribute:: products + // rst: .. attribute:: products // rst: // rst: The subset of the vertex graphs which were discovered by the calculation. // rst: // rst: :type: list[Graph] .add_property("_products", py::make_function(&DG::getProducts, py::return_value_policy())) - // rst: .. py:method:: print(printer=DGPrinter(), data=None) + // rst: .. method:: print(printer=DGPrinter(), data=None) // rst: // rst: Print the derivation graph in style of a hypergraph. The appearance and structure // rst: of the visualisation can optionally be configured by giving a DG printer and/or data object. @@ -180,24 +178,24 @@ void DG_doExport() { // rst: :returns: the name of the PDF-file that will be compiled in post-processing and the name of the coordinate tex-file used. // rst: :rtype: tuple[str, str] .def("print", &DG::print) - // rst: .. py:method:: dump() + // rst: .. method:: dump() // rst: // rst: Export the derivation graph to an external file. The vertex graphs are exported as well. // rst: // rst: :returns: the filename of the exported derivation graph. // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` if the DG has not been calculated. + // rst: :raises: :class:`LogicError` if the DG has not been calculated. .def("dump", &DG::dump) - // rst: .. py:method:: listStats() + // rst: .. method:: listStats() // rst: // rst: Lists various statistics for the derivation graph. // rst: - // rst: :raises: :py:class:`LogicError` if the DG has not been calculated. + // rst: :raises: :class:`LogicError` if the DG has not been calculated. .def("listStats", &DG::listStats) - // rst: .. py:method:: load(graphDatabase, ruleDatabase, file, graphPolicy=IsomorphismPolicy.Check, verbosity=2) + // rst: .. method:: load(graphDatabase, ruleDatabase, file, graphPolicy=IsomorphismPolicy.Check, verbosity=2) // rst: // rst: Load a derivation graph dump as a locked object. - // rst: Use :py:func:`DGBuilder.load` to load a dump into a derivation graph under construction. + // rst: Use :func:`DGBuilder.load` to load a dump into a derivation graph under construction. // rst: // rst: This is done roughly by making a :class:`DG` with the given `graphDatabase` and `graphPolicy`. // rst: The label settings are retrieved from the dump file. @@ -227,7 +225,7 @@ void DG_doExport() { .def("load", static_cast(&DG::load)) .staticmethod("load"); - // rst: .. py:method:: diffDGs(dg1, dg2) + // rst: .. method:: diffDGs(dg1, dg2) // rst: // rst: Compare two derivation graphs and lists the difference. // rst: This is not a general isomorphism check; two vertices are equal if they have @@ -241,6 +239,4 @@ void DG_doExport() { py::def("diffDGs", &DG::diff); } -} // namespace Py -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/dg/GraphInterface.cpp b/libs/pymod/src/mod/py/dg/GraphInterface.cpp index aa98373..23d6c42 100644 --- a/libs/pymod/src/mod/py/dg/GraphInterface.cpp +++ b/libs/pymod/src/mod/py/dg/GraphInterface.cpp @@ -5,19 +5,17 @@ #include #include -#include +#include -namespace mod { -namespace dg { -namespace Py { +namespace mod::dg::Py { void GraphInterface_doExport() { - // rst: .. py:class:: DGVertex + // rst: .. class:: DGVertex // rst: // rst: A descriptor of either a vertex in a derivation graph, or a null vertex. // rst: py::class_("DGVertex", py::no_init) - // rst: .. py:function:: __init__(self) + // rst: .. method:: __init__() // rst: // rst: Constructs a null descriptor. .def(py::init<>()) @@ -26,59 +24,59 @@ void GraphInterface_doExport() { .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &DG::Vertex::hash) - // rst: .. py::method:: __bool__(self) + // rst: .. :method:: __bool__() // rst: // rst: :returns: ``not isNull()`` // rst: :rtype: bool .def("__bool__", &DG::Vertex::operator bool) - // rst: .. py:method:: isNull() + // rst: .. method:: isNull() // rst: // rst: :returns: whether this is a null descriptor or not. // rst: :rtype: bool .def("isNull", &DG::Vertex::isNull) - // rst: .. py:attribute:: id + // rst: .. attribute:: id // rst: // rst: (Read-only) The index of the vertex. It will be in the range :math:`[0, numVertices + numEdges[`. // rst: // rst: :type: int // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("id", &DG::Vertex::getId) - // rst: .. py:attribute:: dg + // rst: .. attribute:: dg // rst: // rst: (Read-only) The derivation graph the vertex belongs to. // rst: // rst: :type: DG // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("dg", &DG::Vertex::getDG) - // rst: .. py:attribute:: inDegree + // rst: .. attribute:: inDegree // rst: // rst: (Read-only) The in-degree of the vertex, including multiplicity of target multisets. // rst: // rst: :type: int // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("inDegree", &DG::Vertex::inDegree) - // rst: .. py:attribute:: inEdges + // rst: .. attribute:: inEdges // rst: // rst: (Read-only) A range of in-hyperedges for this vertex. // rst: // rst: :type: DGInEdgeRange // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("inEdges", &DG::Vertex::inEdges) - // rst: .. py:attribute:: outDegree + // rst: .. attribute:: outDegree // rst: // rst: (Read-only) The out-degree of the vertex, including multiplicity of source multisets. // rst: // rst: :type: int // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("outDegree", &DG::Vertex::outDegree) - // rst: .. py:attribute:: outEdges + // rst: .. attribute:: outEdges // rst: // rst: (Read-only) A range of out-hyperedges for this vertex. // rst: // rst: :type: DGOutEdgeRange // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("outEdges", &DG::Vertex::outEdges) - // rst: .. py:attribute:: graph + // rst: .. attribute:: graph // rst: // rst: (Read-only) The graph label of the vertex. // rst: @@ -86,12 +84,12 @@ void GraphInterface_doExport() { // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("graph", &DG::Vertex::getGraph); - // rst: .. py:class:: DGHyperEdge + // rst: .. class:: DGHyperEdge // rst: // rst: A descriptor of either a hyperedge in a derivation graph, or a null edge. // rst: py::class_("DGHyperEdge", py::no_init) - // rst: .. py:function:: __init__(self) + // rst: .. method:: __init__() // rst: // rst: Constructs a null descriptor. .def(py::init<>()) @@ -100,44 +98,44 @@ void GraphInterface_doExport() { .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &DG::HyperEdge::hash) - // rst: .. py::method:: __bool__(self) + // rst: .. :method:: __bool__() // rst: // rst: :returns: ``not isNull()`` // rst: :rtype: bool .def("__bool__", &DG::HyperEdge::operator bool) - // rst: .. py:method:: isNull() + // rst: .. method:: isNull() // rst: // rst: :returns: whether this is a null descriptor or not. // rst: :rtype: bool .def("isNull", &DG::HyperEdge::isNull) - // rst: .. py:attribute:: id + // rst: .. attribute:: id // rst: // rst: (Read-only) The index of the hyperedge. It will be in the range :math:`[0, numVertices + numEdges[`. // rst: // rst: :type: int // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("id", &DG::HyperEdge::getId) - // rst: .. py:attribute:: dg + // rst: .. attribute:: dg // rst: // rst: (Read-only) The derivation graph the edge belongs to. // rst: // rst: :type: DG // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("dg", &DG::HyperEdge::getDG) - // rst: .. py:attribute:: numSources + // rst: .. attribute:: numSources // rst: // rst: (Read-only) The number of sources of the hyperedge. // rst: // rst: :type: int .add_property("numSources", &DG::HyperEdge::numSources) - // rst: .. py:attribute:: sources + // rst: .. attribute:: sources // rst: // rst: (Read-only) The sources of the hyperedge. // rst: // rst: :type: DGSourceRange // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("sources", &DG::HyperEdge::sources) - // rst: .. py:attribute:: numTargets + // rst: .. attribute:: numTargets // rst: // rst: (Read-only) The number of targerts of the hyperedge. // rst: @@ -150,14 +148,14 @@ void GraphInterface_doExport() { // rst: :type: DGTargetRange // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("targets", &DG::HyperEdge::targets) - // rst: .. py:attribute:: rules + // rst: .. attribute:: rules // rst: // rst: (Read-only) The rules associated with the hyperedge. // rst: // rst: :type: DGRuleRange // rst: :raises: :class:`LogicError` if it is a null descriptor. .add_property("rules", &DG::HyperEdge::rules) - // rst: .. py:attribute:: inverse + // rst: .. attribute:: inverse // rst: // rst: (Read-only) A descriptor for the inverse hyperedge of this one, if it exists. // rst: Otherwise a null descriptor is returned. @@ -166,7 +164,7 @@ void GraphInterface_doExport() { // rst: :raises: :class:`LogicError` if it is a null descriptor. // rst: :raises: :class:`LogicError` if not ``dg.locked``. .add_property("inverse", &DG::HyperEdge::getInverse) - // rst: .. py:method:: print(printer=GraphPrinter(), nomatchColour="gray", matchColour="") + // rst: .. method:: print(printer=GraphPrinter(), nomatchColour="gray", matchColour="") // rst: // rst: Print the derivations represented by the hyperedge. // rst: All possible Double-Pushout diagrams are printed. @@ -202,6 +200,4 @@ void GraphInterface_doExport() { .def("__len__", &DG::RuleRange::size); } -} // namespace Py -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/dg/Printer.cpp b/libs/pymod/src/mod/py/dg/Printer.cpp index a457d6a..c06d3b8 100644 --- a/libs/pymod/src/mod/py/dg/Printer.cpp +++ b/libs/pymod/src/mod/py/dg/Printer.cpp @@ -6,9 +6,7 @@ #include #include -namespace mod { -namespace dg { -namespace Py { +namespace mod::dg::Py { namespace { void Printer_pushVertexVisible(Printer &printer, std::shared_ptr> f) { @@ -49,7 +47,7 @@ Printer_setMirrorOverwrite(Printer &printer, std::shared_ptr("DGPrintData", py::no_init) - // rst: .. py:method:: __init__(self, dg) + // rst: .. method:: __init__(dg) // rst: // rst: Construct a data object where all derivations have a single version, duplicate number 0, // rst: connected to version 0 of all heads and tails. @@ -74,11 +72,11 @@ void Printer_doExport() { // rst: :param DG dg: the derivation graph to hold data for. // rst: :raises: :class:`LogicError` if ``not dg.isLocked``. .def(py::init >()) - // rst: .. py:attribute:: dg + // rst: .. attribute:: dg // rst: // rst: (Read-only) The derivation graph the object holds data for. .add_property("dg", &PrintData::getDG) - // rst: .. py:method:: makeDuplicate(e, eDup) + // rst: .. method:: makeDuplicate(e, eDup) // rst: // rst: Create another version of the given hyperedge and give it the given duplicate number. // rst: It will connect to duplicate 0 of all head and tail vertices. @@ -89,7 +87,7 @@ void Printer_doExport() { // rst: :raises: :class:`LogicError` if ``e.dg != dg``. // rst: :raises: :class:`LogicError` if duplicate ``eDup`` already exists for ``e``. .def("makeDuplicate", &PrintData::makeDuplicate) - // rst: .. py:method:: removeDuplicate(e, eDup) + // rst: .. method:: removeDuplicate(e, eDup) // rst: // rst: Remove the version of the given hyperedge with the given duplicate number. // rst: @@ -99,7 +97,7 @@ void Printer_doExport() { // rst: :raises: :class:`LogicError` if ``e.dg != dg``. // rst: :raises: :class:`LogicError` if duplicate ``eDup`` does not exist for ``e``. .def("removeDuplicate", &PrintData::removeDuplicate) - // rst: .. py:method:: reconnectSource(e, eDup, v, vDupTar) + // rst: .. method:: reconnectSource(e, eDup, v, vDupTar) // rst: // rst: For the given hyperedge duplicate, reconnect the given source vertex to the given duplicate of that source. // rst: If the vertex is a source multiple times, then an arbitrary one of them is reconnected. @@ -115,7 +113,7 @@ void Printer_doExport() { // rst: :raises: :class:`LogicError` if ``v`` is not a source vertex of ``e``. // rst: :raises: :class:`LogicError` if duplicate ``eDup`` does not exist for ``e``. .def("reconnectSource", &PrintData::reconnectSource) - // rst: .. py:method:: reconnectTarget(e, eDup, v, vDupTar) + // rst: .. method:: reconnectTarget(e, eDup, v, vDupTar) // rst: // rst: For the given hyperedge duplicate, reconnect the given head to the given duplicate of that head. // rst: If the vertex is a head multiple times, then an arbitrary one of them is reconnected. @@ -136,13 +134,13 @@ void Printer_doExport() { void (*Printer_setGraphPrinter)(Printer &, const graph::Printer &) = [](Printer &p, const graph::Printer &gp) { p.getGraphPrinter() = gp; }; - // rst: .. py:class:: DGPrinter + // rst: .. class:: DGPrinter // rst: // rst: This class is used to configure how derivation graphs are visualised, // rst: how much is visualised and which extra properties are printed. // rst: py::class_("DGPrinter") - // rst: .. py:attribute:: graphPrinter + // rst: .. attribute:: graphPrinter // rst: // rst: Access the :class:`GraphPrinter` used when printing images of graphs. // rst: Note that assignment to the property copies the argument. @@ -151,20 +149,20 @@ void Printer_doExport() { .add_property("graphPrinter", py::make_function(Printer_getGraphPrinter, py::return_internal_reference<1>()), Printer_setGraphPrinter) - // rst: .. py:attribute:: withShortcutEdges + // rst: .. attribute:: withShortcutEdges // rst: // rst: Control whether or not hyperedges :math:`(T, H)` with :math:`|T| = |H| = 1` // rst: are printed as a simple arrow without the usual rectangle. // rst: // rst: :type: bool .add_property("withShortcutEdges", &Printer::getWithShortcutEdges, &Printer::setWithShortcutEdges) - // rst: .. py:attribute:: withGraphImages + // rst: .. attribute:: withGraphImages // rst: // rst: Control whether or not each vertex is printed with a image of its graph in it. // rst: // rst: :type: bool .add_property("withGraphImages", &Printer::getWithGraphImages, &Printer::setWithGraphImages) - // rst: .. py:attribute:: labelsAsLatexMath + // rst: .. attribute:: labelsAsLatexMath // rst: // rst: Control whether or not labels on vertices and hyperedges are put inline :math:`\LaTeX` math. // rst: Specifically, a label ``label`` is written as ``$\mathrm{label'}$``, with ``label'`` being @@ -172,7 +170,7 @@ void Printer_doExport() { // rst: // rst: :type: bool .add_property("labelsAsLatexMath", &Printer::getLabelsAsLatexMath, &Printer::setLabelsAsLatexMath) - // rst: .. py:method:: pushVertexVisible(f) + // rst: .. method:: pushVertexVisible(f) // rst: // rst: Add another function or constant controlling the visibility of vertices. // rst: All visibility functions must return ``true`` for a vertex to be visible. @@ -180,13 +178,13 @@ void Printer_doExport() { // rst: :param f: the function or constant to push for specifying vertex visibility. // rst: :type f: Callable[[DGVertex], bool] or bool .def("pushVertexVisible", &Printer_pushVertexVisible) - // rst: .. py:method:: popVertexVisible() + // rst: .. method:: popVertexVisible() // rst: // rst: Remove the last pushed vertex visibility function. // rst: // rst: :raises: :class:`LogicError` if no callback is left to pop. .def("popVertexVisible", &Printer::popVertexVisible) - // rst: .. py:method:: pushEdgeVisible(f) + // rst: .. method:: pushEdgeVisible(f) // rst: // rst: Add another function or constant controlling the visibility of hyperedges. // rst: All visibility functions must return ``true`` for a hyperedge to be visible. @@ -194,20 +192,20 @@ void Printer_doExport() { // rst: :param f: the function or constant to push for specifying hyperedge visibility. // rst: :type f: Callable[[DGHyperEdge], bool] or bool .def("pushEdgeVisible", &Printer_pushEdgeVisible) - // rst: .. py:method:: popEdgeVisible() + // rst: .. method:: popEdgeVisible() // rst: // rst: Remove the last pushed hyperedge visibility function. // rst: // rst: :raises: :class:`LogicError` if no callback is left to pop. .def("popEdgeVisible", &Printer::popEdgeVisible) - // rst: .. py:attribute:: withShortcutEdgesAfterVisibility + // rst: .. attribute:: withShortcutEdgesAfterVisibility // rst: // rst: Control whether or not hyperedges are depicted as simple arrows when all but 1 head and tail are hidden. // rst: // rst: :type: bool .add_property("withShortcutEdgesAfterVisibility", &Printer::getWithShortcutEdgesAfterVisibility, &Printer::setWithShortcutEdgesAfterVisibility) - // rst: .. py:attribute:: vertexLabelSep + // rst: .. attribute:: vertexLabelSep // rst: // rst: The string used as separator between each part of each vertex label. // rst: @@ -216,7 +214,7 @@ void Printer_doExport() { py::make_function(&Printer::getVertexLabelSep, py::return_value_policy()), &Printer::setVertexLabelSep) - // rst: .. py:attribute:: edgeLabelSep + // rst: .. attribute:: edgeLabelSep // rst: // rst: The string used as separator between each part of each edge label. // rst: @@ -225,7 +223,7 @@ void Printer_doExport() { py::make_function(&Printer::getEdgeLabelSep, py::return_value_policy()), &Printer::setEdgeLabelSep) - // rst: .. py:method:: pushVertexLabel(f) + // rst: .. method:: pushVertexLabel(f) // rst: // rst: Add another function or constant for vertex labelling. // rst: The result of this function is added to the end of each label. @@ -233,50 +231,50 @@ void Printer_doExport() { // rst: :param f: the function or constant to push for labelling vertices. // rst: :type f: Callable[[DGVertex], str] or str .def("pushVertexLabel", &Printer_pushVertexLabel) - // rst: .. py:method:: popVertexLabel() + // rst: .. method:: popVertexLabel() // rst: // rst: Remove the last pushed vertex labelling function. // rst: // rst: :raises: :class:`LogicError` if no callback is left to pop. .def("popVertexLabel", &Printer::popVertexLabel) - // rst: .. py:method:: pushEdgeLabel(f) + // rst: .. method:: pushEdgeLabel(f) // rst: // rst: Add another function or constant for edge labelling. The result of this function is appended to each label. // rst: // rst: :param f: the function or constant to push for labelling edges. // rst: :type f: Callable[[DGHyperEdge], str] or str .def("pushEdgeLabel", &Printer_pushEdgeLabel) - // rst: .. py:method:: popEdgeLabel() + // rst: .. method:: popEdgeLabel() // rst: // rst: Remove the last pushed edge labelling function. // rst: // rst: :raises: :class:`LogicError` if no callback is left to pop. .def("popEdgeLabel", &Printer::popEdgeLabel) - // rst: .. py:attribute:: withGraphName + // rst: .. attribute:: withGraphName // rst: // rst: Control whether or not graph names are appended to the vertex labels (see also :meth:`DGPrinter.pushVertexLabel`). // rst: // rst: :type: bool .add_property("withGraphName", &Printer::getWithGraphName, &Printer::setWithGraphName) - // rst: .. py:attribute:: withRuleName + // rst: .. attribute:: withRuleName // rst: // rst: Control whether or not rule names are appended to the edge labels (see also :meth:`DGPrinter.pushEdgeLabel`). // rst: // rst: :type: bool .add_property("withRuleName", &Printer::getWithRuleName, &Printer::setWithRuleName) - // rst: .. py:attribute:: withRuleId + // rst: .. attribute:: withRuleId // rst: // rst: Control whether or not rule IDs are appended to the edge labels (see also :meth:`DGPrinter.pushEdgeLabel`). // rst: // rst: :type: bool .add_property("withRuleId", &Printer::getWithRuleId, &Printer::setWithRuleId) - // rst: .. py:attribute:: withInlineGraphs + // rst: .. attribute:: withInlineGraphs // rst: // rst: Control whether or not graph depictions should be precompiled, or be included inline in the DG figure. // rst: // rst: :type: bool .add_property("withInlineGraphs", &Printer::getWithInlineGraphs, &Printer::setWithInlineGraphs) - // rst: .. py:method:: pushVertexColour(f, extendToEdges=True) + // rst: .. method:: pushVertexColour(f, extendToEdges=True) // rst: // rst: Add another function or constant for colouring vertices. The final colour of a vertex is the result of the first colour function returning a non-empty string. // rst: The functions are evaluated in the order they are pushed and the resulting string is used directly as a colour in Tikz. @@ -288,13 +286,13 @@ void Printer_doExport() { // rst: :type f: Callable[[DGVertex], str] or str // rst: :param bool extendToEdges: whether or not some hyperedges are coloured as well (see above). .def("pushVertexColour", &Printer_pushVertexColour) - // rst: .. py:method:: popVertexColour() + // rst: .. method:: popVertexColour() // rst: // rst: Remove the last pushed vertex colouring function. // rst: // rst: :raises: :class:`LogicError` if no callback is left to pop. .def("popVertexColour", &Printer::popVertexColour) - // rst: .. py:method:: pushEdgeColour(f) + // rst: .. method:: pushEdgeColour(f) // rst: // rst: Add another function or constant for colouring hyperedges. The final colour of a hyperedge (and all of its head and tail connectors) is the result of the // rst: first colour function returning a non-empty string. @@ -302,29 +300,29 @@ void Printer_doExport() { // rst: :param f: the function or constant to push for colouring hyperedges. // rst: :type f: Callable[[DGHyperEdge], str] or str .def("pushEdgeColour", &Printer_pushEdgeColour) - // rst: .. py:method:: popEdgeColour() + // rst: .. method:: popEdgeColour() // rst: // rst: Remove the last pushed hyperedge colouring function. // rst: // rst: :raises: :class:`LogicError` if no callback is left to pop. .def("popEdgeColour", &Printer::popEdgeColour) - // rst: .. py:method:: setRotationOverwrite(f) + // rst: .. method:: setRotationOverwrite(f) // rst: - // rst: Overwrite the rotation set in the nested :py:class:`GraphPrinter`. The given function will be used + // rst: Overwrite the rotation set in the nested :class:`GraphPrinter`. The given function will be used // rst: to set the rotation of each printed graph. // rst: // rst: :param f: the constant or the function called on each graph to retrieve the rotation to render it with. // rst: :type f: Callable[[Graph], int] or int .def("setRotationOverwrite", &Printer_setRotationOverwrite) - // rst: .. py:method:: setMirrorOverwrite(f) + // rst: .. method:: setMirrorOverwrite(f) // rst: - // rst: Overwrite the mirror set in the nested :py:class:`GraphPrinter`. The given function will be used + // rst: Overwrite the mirror set in the nested :class:`GraphPrinter`. The given function will be used // rst: to set the mirror of each printed graph. // rst: // rst: :param f: the function called on each graph to retrieve the mirror to render it with. // rst: :type f: Callable[[Graph], bool] or bool .def("setMirrorOverwrite", &Printer_setMirrorOverwrite) - // rst: .. py:attribute:: graphvizPrefix + // rst: .. attribute:: graphvizPrefix // rst: // rst: The string that will be inserted into generated DOT files, // rst: just after the graph declaration. @@ -336,6 +334,4 @@ void Printer_doExport() { &Printer::setGraphvizPrefix); } -} // namespace Py -} // namespace dg -} // namespace mod +} // namespace mod::dg::Py diff --git a/libs/pymod/src/mod/py/dg/Strategies.cpp b/libs/pymod/src/mod/py/dg/Strategies.cpp index 771ec77..664f22d 100644 --- a/libs/pymod/src/mod/py/dg/Strategies.cpp +++ b/libs/pymod/src/mod/py/dg/Strategies.cpp @@ -8,7 +8,7 @@ // rst: Usually the embedded strategy language is easiest and sufficient for constructing strategies. // rst: // rst: The semantics of the individual strategies are described in :ref:`dgStrat`. -// rst: Note that a :py:class:`DGStrat` is a representation of a strategy and must be given to a derivation graph to be evaluated. +// rst: Note that a :class:`DGStrat` is a representation of a strategy and must be given to a derivation graph to be evaluated. // rst: // rst: .. _dg_edsl: // rst: @@ -43,7 +43,7 @@ // rst: .. function:: addSubset(g, *gs, graphPolicy=IsomorphismPolicy.Check) // rst: addUniverse(g, *gs, graphPolicy=IsomorphismPolicy.Check) // rst: -// rst: Depending on ``g`` it calls either :func:`DGStrat.makeAddStatic` or :py:func:`DGStrat.makeAddDynamic`. +// rst: Depending on ``g`` it calls either :func:`DGStrat.makeAddStatic` or :func:`DGStrat.makeAddDynamic`. // rst: // rst: :param g: graph(s) to add, or a callback to compute them. // rst: :type g: Graph or Iterable[Graph] or Callable[[], Iterable[Graph]] @@ -82,35 +82,12 @@ // rst: :returns: the result of :func:`DGStrat.makeRevive`. // rst: -namespace mod { -namespace dg { -namespace Py { +namespace mod::dg::Py { void Strategy_doExport() { // rst: The Basic API // rst: ################# // rst: - // rst: .. py:class:: DGStratGraphState - // rst: - // rst: This class represents a graph state with a subset :math:`S` and a universe :math:`U` fulfilling :math:`S\subseteq U`. - // rst: - py::class_("DGStratGraphState", py::no_init) - // rst: .. py:attribute:: subset - // rst: - // rst: The subset :math:`\mathcal{S}`. - // rst: - // rst: :type: list[Graph] - // rst: - .add_property("_subset", - py::make_function(&Strategy::GraphState::getSubset, py::return_internal_reference<1>())) - // rst: .. py:attribute:: universe - // rst: - // rst: The universe :math:`\mathcal{U}`. - // rst: - // rst: :type: list[Graph] - // rst: - .add_property("_universe", - py::make_function(&Strategy::GraphState::getUniverse, py::return_internal_reference<1>())); std::shared_ptr (*makeAdd_static)(bool, const std::vector> &, @@ -118,12 +95,11 @@ void Strategy_doExport() { std::shared_ptr (*makeAdd_dynamic)(bool, const std::shared_ptr>()>>, IsomorphismPolicy) = &Strategy::makeAdd; - - // rst: .. py:class:: DGStrat + // rst: .. class:: DGStrat // rst: - py::class_, boost::noncopyable>("DGStrat", py::no_init) + auto pyStrat = py::class_, boost::noncopyable>("DGStrat", py::no_init) .def(str(py::self)) - // rst: .. py:staticmethod:: makeAddStatic(onlyUniverse, graphs, graphPolicy) + // rst: .. staticmethod:: makeAddStatic(onlyUniverse, graphs, graphPolicy) // rst: // rst: :param bool onlyUniverse: if the strategy is :ref:`strat-addUniverse` or :ref:`strat-addSubset`. // rst: :param graphs: the graphs to be added by the strategy. @@ -133,7 +109,7 @@ void Strategy_doExport() { // rst: :rtype: DGStrat // rst: :raises: :class:`LogicError` if there is a ``None`` in ``graphs``. .def("makeAddStatic", makeAdd_static).staticmethod("makeAddStatic") - // rst: .. py:staticmethod:: makeAddDynamic(onlyUniverse, graphsFunc, graphPolicy) + // rst: .. staticmethod:: makeAddDynamic(onlyUniverse, graphsFunc, graphPolicy) // rst: // rst: :param bool onlyUniverse: if the strategy is :ref:`strat-addUniverse` or :ref:`strat-addSubset`. // rst: :param graphsFunc: a function returning the graphs to be added by the strategy. @@ -142,7 +118,7 @@ void Strategy_doExport() { // rst: :returns: an :ref:`strat-addUniverse` strategy if ``onlyUniverse`` is ``True``, otherwise an :ref:`strat-addSubset` strategy. // rst: :rtype: DGStrat .def("makeAddDynamic", makeAdd_dynamic).staticmethod("makeAddDynamic") - // rst: .. py:staticmethod:: makeSequence(strats) + // rst: .. staticmethod:: makeSequence(strats) // rst: // rst: :param strats: the strategies to evaluate in sequence. // rst: :type strats: list[DGStrat] @@ -151,7 +127,7 @@ void Strategy_doExport() { // rst: :raises: :class:`LogicError` if the given list of strategies is empty. // rst: :raises: :class:`LogicError` if there is a ``None`` in ``strats``. .def("makeSequence", &Strategy::makeSequence).staticmethod("makeSequence") - // rst: .. py:staticmethod:: makeParallel(strats) + // rst: .. staticmethod:: makeParallel(strats) // rst: // rst: :param strats: the sub-strategies to evaluate. // rst: :type strats: list[DGStrat] @@ -160,31 +136,31 @@ void Strategy_doExport() { // rst: :raises: :class:`LogicError` if `strats` is empty. // rst: :raises: :class:`LogicError` if there is a ``None`` in ``strats``. .def("makeParallel", &Strategy::makeParallel).staticmethod("makeParallel") - // rst: .. py:staticmethod:: makeFilter(alsoUniverse, p) + // rst: .. staticmethod:: makeFilter(alsoUniverse, p) // rst: // rst: :param bool alsoUniverse: if the strategy is :ref:`strat-filterUniverse` or :ref:`strat-filterSubset`. // rst: :param p: the filtering predicate being called for each graph in either the subset or the universe. // rst: The predicate is called with the graph and the graph state as arguments, and a bool stating whether or not // rst: the call is the first in the filtering process. - // rst: :type p: Callable[[Graph, DGStratGraphState, bool], bool] + // rst: :type p: Callable[[Graph, DGStrat.GraphState, bool], bool] // rst: :returns: a :ref:`strat-filterUniverse` strategy if ``onlyUniverse`` is ``True``, otherwise a :ref:`strat-filterSubset` strategy. // rst: :rtype: DGStrat .def("makeFilter", &Strategy::makeFilter).staticmethod("makeFilter") - // rst: .. py:staticmethod:: makeExecute(func) + // rst: .. staticmethod:: makeExecute(func) // rst: // rst: :param func: A function being executed when the strategy is evaluated. - // rst: :type func: Callable[[DGStratGraphState], None] + // rst: :type func: Callable[[DGStrat.GraphState], None] // rst: :returns: an :ref:`strat-execute` strategy. // rst: :rtype: DGStrat .def("makeExecute", &Strategy::makeExecute).staticmethod("makeExecute") - // rst: .. py:staticmethod:: makeRule(r) + // rst: .. staticmethod:: makeRule(r) // rst: // rst: :param Rule r: the rule to make into a strategy. // rst: :returns: a :ref:`strat-rule` strategy. // rst: :rtype: DGStrat // rst: :raises: :class:`LogicError` is ``r`` is ``None``. .def("makeRule", &Strategy::makeRule).staticmethod("makeRule") - // rst: .. py:staticmethod:: makeLeftPredicate(p, strat) + // rst: .. staticmethod:: makeLeftPredicate(p, strat) // rst: // rst: :param p: the predicate to be called on each candidate derivation. // rst: Even though the predicate is called with a :class:`Derivation` object, only the left side and the rule of the object is valid. @@ -194,7 +170,7 @@ void Strategy_doExport() { // rst: :rtype: DGStrat // rst: :raises: :class:`LogicError` if ``strat`` is ``None``. .def("makeLeftPredicate", &Strategy::makeLeftPredicate).staticmethod("makeLeftPredicate") - // rst: .. py:staticmethod:: makeRightPredicate(p, strat) + // rst: .. staticmethod:: makeRightPredicate(p, strat) // rst: // rst: :param p: the predicate to be called on each candidate derivation. // rst: :type p: Callable[[Derivation], bool] @@ -203,14 +179,14 @@ void Strategy_doExport() { // rst: :rtype: DGStrat // rst: :raises: :class:`LogicError` if ``strat`` is ``None``. .def("makeRightPredicate", &Strategy::makeRightPredicate).staticmethod("makeRightPredicate") - // rst: .. py:staticmethod:: makeRevive(strat) + // rst: .. staticmethod:: makeRevive(strat) // rst: // rst: :param DGStrat strat: the strategy to encapsulate. // rst: :returns: a :ref:`strat-revive` strategy. // rst: :rtype: DGStrat // rst: :raises: :class:`LogicError` if ``strat`` is ``None``. .def("makeRevive", &Strategy::makeRevive).staticmethod("makeRevive") - // rst: .. py:staticmethod:: makeRepeat(limit, strat) + // rst: .. staticmethod:: makeRepeat(limit, strat) // rst: // rst: :param int limit: the maximum number of iterations. // rst: :param DGStrat strat: the strategy to be repeated. @@ -219,8 +195,31 @@ void Strategy_doExport() { // rst: :raises: :class:`LogicError` if ``limit`` is not positive. // rst: :raises: :class:`LogicError` if ``strat`` is ``None``. .def("makeRepeat", &Strategy::makeRepeat).staticmethod("makeRepeat"); + + { + auto scope = py::scope(pyStrat); + // rst: .. class:: GraphState + // rst: + // rst: This class represents a graph state with a subset :math:`S` and a universe :math:`U` fulfilling :math:`S\subseteq U`. + // rst: + py::class_("GraphState", py::no_init) + // rst: .. attribute:: subset + // rst: + // rst: The subset :math:`\mathcal{S}`. + // rst: + // rst: :type: list[Graph] + // rst: + .add_property("_subset", + py::make_function(&Strategy::GraphState::getSubset, py::return_internal_reference<1>())) + // rst: .. attribute:: universe + // rst: + // rst: The universe :math:`\mathcal{U}`. + // rst: + // rst: :type: list[Graph] + // rst: + .add_property("_universe", + py::make_function(&Strategy::GraphState::getUniverse, py::return_internal_reference<1>())); + } } -} // namespace Py -} // namespace dg -} // namespace mod \ No newline at end of file +} // namespace mod::dg::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/graph/Automorphism.cpp b/libs/pymod/src/mod/py/graph/Automorphism.cpp index 55fe202..c72f4f3 100644 --- a/libs/pymod/src/mod/py/graph/Automorphism.cpp +++ b/libs/pymod/src/mod/py/graph/Automorphism.cpp @@ -3,49 +3,45 @@ #include #include -namespace mod { -namespace graph { -namespace Py { +namespace mod::graph::Py { void Automorphism_doExport() { - // rst: .. py:class:: GraphAut + py::object graphObj = py::scope().attr("Graph"); + py::scope graphScope = graphObj; + + // rst: .. class:: Graph.Aut // rst: // rst: An automorphism of a graph. // rst: - py::class_("GraphAut", py::no_init) - // rst: .. py:method:: __getitem__(v) + py::class_("Aut", py::no_init) + // rst: .. method:: __getitem__(v) // rst: - // rst: :param GraphVertex v: the vertex to permute. + // rst: :param Graph.Vertex v: the vertex to permute. // rst: :returns: the image of the given vertex under the permutation. - // rst: :rtype: GraphVertex + // rst: :rtype: Graph.Vertex .def("__getitem__", &Graph::Aut::operator[]) - .def(str(py::self)) - ; + .def(str(py::self)); - // rst: .. py:class:: GraphAutGroup + // rst: .. class:: Graph.AutGroup // rst: // rst: A class representing the automorphism group of a :class:`Graph`. // rst: - py::class_("GraphAutGroup", py::no_init) + py::class_("AutGroup", py::no_init) // rst: .. attribute:: gens // rst: // rst: (Read-only) A range of the generators for the group. // rst: - // rst: :type: GraphAutGroupGensRange + // rst: :type: AutGroupGensRange .add_property("gens", &Graph::AutGroup::gens) - .def(str(py::self)) - ; + .def(str(py::self)); - // rst: .. py:class:: GraphAutGroupGensRange + // rst: .. class:: Graph.AutGroupGensRange // rst: - // rst: A random-access range of :py:class:`GraphAut`. - py::class_("GraphAutGroupGensRange", py::no_init) + // rst: A random-access range of :class:`Graph.Aut`. + py::class_("Graph.AutGroupGensRange", py::no_init) .def("__iter__", py::iterator()) .def("__getitem__", &Graph::AutGroup::Gens::operator[]) - .def("__len__", &Graph::AutGroup::Gens::size) - ; + .def("__len__", &Graph::AutGroup::Gens::size); } -} // namespace Py -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/graph/Graph.cpp b/libs/pymod/src/mod/py/graph/Graph.cpp index 9e546dc..87d934b 100644 --- a/libs/pymod/src/mod/py/graph/Graph.cpp +++ b/libs/pymod/src/mod/py/graph/Graph.cpp @@ -7,9 +7,7 @@ #include -namespace mod { -namespace graph { -namespace Py { +namespace mod::graph::Py { void Graph_doExport() { std::pair(Graph::* @@ -17,15 +15,18 @@ void Graph_doExport() { std::pair(Graph::* printWithOptions)(const graph::Printer&, const graph::Printer&) const = &Graph::print; - // rst: .. py:class:: Graph + // rst: .. class:: Graph // rst: // rst: This class models an undirected graph with labels on vertices and edges, // rst: without loops and without parallel edges. // rst: Certain labels are regarded as models of chemical atoms and bonds. // rst: See :ref:`mol-enc` for more information on this. // rst: + // rst: The class implements the :class:`protocols.LabelledGraph`. + // rst: See :ref:`py-Graph/GraphInterface` for additional guarantees. + // rst: py::class_, boost::noncopyable>("Graph", py::no_init) - // rst: .. py:attribute:: id + // rst: .. attribute:: id // rst: // rst: (Read-only) A unique instance id among :class:`Graph` objects. // rst: @@ -33,39 +34,20 @@ void Graph_doExport() { .add_property("id", &Graph::getId) .def(str(py::self)) //------------------------------------------------------------------ - // rst: .. py:attribute:: numVertices - // rst: - // rst: (Read-only) The number of vertices in the graph. - // rst: - // rst: :type: int + // LabelledGraph .add_property("numVertices", &Graph::numVertices) - // rst: .. py:attribute:: vertices - // rst: - // rst: (Read-only) An iterable of all vertices in the graph. - // rst: - // rst: :type: GraphVertexRange .add_property("vertices", &Graph::vertices) - // rst: .. py:attribute:: numEdges - // rst: - // rst: (Read-only) The number of edges in the graph. - // rst: - // rst: :type: int .add_property("numEdges", &Graph::numEdges) - // rst: .. py:attribute:: edges - // rst: - // rst: (Read-only) An iterable of all edges in the graph. - // rst: - // rst: :type: GraphEdgeRange .add_property("edges", &Graph::edges) //------------------------------------------------------------------ - // rst: .. py:function:: aut(labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) + // rst: .. method:: aut(labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) // rst: // rst: :param LabelSettings labelSettings: the label settings to use. // rst: :returns: an object representing the automorphism group of the graph, with the given label settings. - // rst: :rtype: GraphAutGroup + // rst: :rtype: AutGroup .def("aut", &Graph::aut) //------------------------------------------------------------------ - // rst: .. py:method:: print() + // rst: .. method:: print() // rst: print(first, second=None) // rst: // rst: Print the graph, using either the default options or the options in ``first`` and ``second``. @@ -79,60 +61,60 @@ void Graph_doExport() { // rst: :rtype: tuple[str, str] .def("print", printWithoutOptions) .def("print", printWithOptions) - // rst: .. py:method:: printTermState + // rst: .. method:: printTermState // rst: // rst: Print the term state for the graph. .def("printTermState", &Graph::printTermState) - // rst: .. py:method:: getGMLString(withCoords=False) + // rst: .. method:: getGMLString(withCoords=False) // rst: // rst: :returns: the :ref:`GML ` representation of the graph, // rst: optionally with generated 2D coordinates. // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` when coordinates are requested, but + // rst: :raises: :class:`LogicError` when coordinates are requested, but // rst: none can be generated. .def("getGMLString", &Graph::getGMLString) - // rst: .. py:method:: printGML(withCoords=False) + // rst: .. method:: printGML(withCoords=False) // rst: // rst: Print the :ref:`GML ` representation of the graph, // rst: optionally with generated 2D coordinates. // rst: // rst: :returns: the filename of the printed GML file. // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` when coordinates are requested, but + // rst: :raises: :class:`LogicError` when coordinates are requested, but // rst: none can be generated. .def("printGML", &Graph::printGML) - // rst: .. py:attribute:: name + // rst: .. attribute:: name // rst: // rst: The name of the graph. The default name includes the unique instance id. // rst: // rst: :type: str .add_property("name", py::make_function(&Graph::getName, py::return_value_policy()), &Graph::setName) - // rst: .. py:attribute:: smiles + // rst: .. attribute:: smiles // rst: // rst: (Read-only) If the graph models a molecule, this is the canonical :ref:`SMILES string ` for it. // rst: // rst: :type: str - // rst: :raises: :py:class:`LogicError` if the graph is not a molecule. + // rst: :raises: :class:`LogicError` if the graph is not a molecule. .add_property("smiles", py::make_function(&Graph::getSmiles, py::return_value_policy())) - // rst: .. py:attribute:: smilesWithIds + // rst: .. attribute:: smilesWithIds // rst: // rst: (Read-only) If the graph models a molecule, this is the canonical :ref:`SMILES string ` for it, // rst: that includes the internal vertex id as a class label on each atom. // rst: // rst: :type: str - // rst: :raises: :py:class:`LogicError` if the graph is not a molecule. + // rst: :raises: :class:`LogicError` if the graph is not a molecule. .add_property("smilesWithIds", py::make_function(&Graph::getSmilesWithIds, py::return_value_policy())) - // rst: .. py:attribute:: graphDFS + // rst: .. attribute:: graphDFS // rst: // rst: (Read-only) This is a :ref:`GraphDFS ` of the graph. // rst: // rst: :type: str .add_property("graphDFS", py::make_function(&Graph::getGraphDFS, py::return_value_policy())) - // rst: .. py:attribute:: graphDFSWithIds + // rst: .. attribute:: graphDFSWithIds // rst: // rst: (Read-only) This is a :ref:`GraphDFS ` of the graph, where each vertices have an explicit id, // rst: corresponding to its internal vertex id. @@ -140,33 +122,33 @@ void Graph_doExport() { // rst: :type: str .add_property("graphDFSWithIds", py::make_function(&Graph::getGraphDFSWithIds, py::return_value_policy())) - // rst: .. py:attribute:: linearEncoding + // rst: .. attribute:: linearEncoding // rst: // rst: (Read-only) If the graph models a molecule this is the :ref:`SMILES string ` string, otherwise it is the :ref:`GraphDFS ` string. // rst: // rst: :type: str .add_property("linearEncoding", py::make_function(&Graph::getLinearEncoding, py::return_value_policy())) - // rst: .. py:attribute:: isMolecule + // rst: .. attribute:: isMolecule // rst: // rst: (Read-only) Whether or not the graph models a molecule. See :ref:`mol-enc`. // rst: // rst: :type: bool .add_property("isMolecule", &Graph::getIsMolecule) - // rst: .. py:attribute:: energy + // rst: .. attribute:: energy // rst: // rst: (Read-only) If the graph models a molecule, this is some energy value. - // rst: The energy is calculated using Open Babel, unless already calculated or cached by :py:meth:`Graph.cacheEnergy`. + // rst: The energy is calculated using Open Babel, unless already calculated or cached by :meth:`Graph.cacheEnergy`. // rst: // rst: :type: float .add_property("energy", &Graph::getEnergy) - // rst: .. py:method:: cacheEnergy(e) + // rst: .. method:: cacheEnergy(e) // rst: // rst: If the graph models a molecule, sets the energy to a given value. // rst: // rst: :param float e: the value for the energy to be set. .def("cacheEnergy", &Graph::cacheEnergy) - // rst: .. py:attribute:: exactMass + // rst: .. attribute:: exactMass // rst: // rst: (Read-only) The exact mass of the graph, if it is a molecule. // rst: It is the sum of the exact mass of each atom, with the mass of electrons subtracted corresponding to the integer charge. @@ -176,19 +158,19 @@ void Graph_doExport() { // rst: :type: float // rst: :raises: :class:`LogicError` if it is not a molecule, including if some isotope has not been tabulated. .add_property("exactMass", &Graph::getExactMass) - // rst: .. py:method:: vLabelCount(label) + // rst: .. method:: vLabelCount(label) // rst: // rst: :param str label: some label for querying. // rst: :returns: the number of vertices in the graph with the given label. // rst: :rtype: int .def("vLabelCount", &Graph::vLabelCount) - // rst: .. py:method:: eLabelCount(label) + // rst: .. method:: eLabelCount(label) // rst: // rst: :param str label: some label for querying. // rst: :returns: the number of edges in the graph with the given label. // rst: :rtype: int .def("eLabelCount", &Graph::eLabelCount) - // rst: .. py:method:: isomorphism(other, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) + // rst: .. method:: isomorphism(other, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) // rst: // rst: :param Graph other: the codomain :class:`Graph` for finding morphisms. // rst: :param int maxNumMatches: the maximum number of isomorphisms to search for. @@ -196,7 +178,7 @@ void Graph_doExport() { // rst: :returns: the number of isomorphisms from this graph to ``other``, but at most ``maxNumMatches``. // rst: :rtype: int .def("isomorphism", &Graph::isomorphism) - // rst: .. py:method:: monomorphism(other, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) + // rst: .. method:: monomorphism(other, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) // rst: // rst: :param Graph other: the codomain :class:`Graph` for finding morphisms. // rst: :param int maxNumMatches: the maximum number of monomorphisms to search for. @@ -204,12 +186,12 @@ void Graph_doExport() { // rst: :returns: the number of monomorphisms from this graph to ``other``, though at most ``maxNumMatches``. // rst: :rtype: int .def("monomorphism", &Graph::monomorphism) - // rst: .. py:method:: makePermutation() + // rst: .. method:: makePermutation() // rst: // rst: :returns: a graph isomorphic to this, but with the vertex indices randomly permuted. // rst: :rtype: Graph .def("makePermutation", &Graph::makePermutation) - // rst: .. py:attribute:: image + // rst: .. attribute:: image // rst: // rst: (Write-only) A custom depiction for the graph. The depiction file used will be the string // rst: returned by the given function, with ``.pdf`` appended. @@ -217,14 +199,14 @@ void Graph_doExport() { // rst: // rst: :type: Callable[[], str] .add_property("image", &mod::Py::noGet, &Graph::setImage) - // rst: .. py:attribute:: imageCommad + // rst: .. attribute:: imageCommad // rst: // rst: A command to be run in post-processing if a custom depiction is set. // rst: The command is only run once. // rst: // rst: :type: str .add_property("imageCommand", &Graph::getImageCommand, &Graph::setImageCommand) - // rst: .. py:method:: getVertexFromExternalId(id) + // rst: .. method:: getVertexFromExternalId(id) // rst: // rst: If the graph was not loaded from an external data format, then this function // rst: always return a null descriptor. @@ -236,34 +218,34 @@ void Graph_doExport() { // rst: :param int id: the external id to find the vertex descriptor for. // rst: :returns: the vertex descriptor for the given external id. // rst: The descriptor is null if the external id was not used. - // rst: :rtype: GraphVertex + // rst: :rtype: Vertex .def("getVertexFromExternalId", &Graph::getVertexFromExternalId) - // rst: .. py:attribute:: minExternalId + // rst: .. attribute:: minExternalId // rst: maxExternalId // rst: // rst: If the graph was not loaded from an external data format, then these attributes // rst: are always return 0. Otherwise, they are the minimum/maximum external id from which - // rst: non-null vertices can be obtained from :py:meth:`getVertexFromExternalId`. + // rst: non-null vertices can be obtained from :meth:`getVertexFromExternalId`. // rst: If no such minimum and maximum exists, then they are 0. // rst: // rst: :type: int .add_property("minExternalId", &Graph::getMinExternalId) .add_property("maxExternalId", &Graph::getMaxExternalId) - // rst: .. py:method:: instantiateStereo() + // rst: .. method:: instantiateStereo() // rst: // rst: Make sure that stereo data is instantiated. // rst: - // rst: :raises: :py:class:`StereoDeductionError` if the data was not instantiated and deduction failed. + // rst: :raises: :class:`StereoDeductionError` if the data was not instantiated and deduction failed. .def("instantiateStereo", &Graph::instantiateStereo); - // rst: .. py:data:: inputGraphs + // rst: .. data:: inputGraphs // rst: // rst: A list of graphs to which explicitly loaded graphs as default are appended. // rst: // rst: :type: list[Graph] // rst: - // rst: .. py:method:: graphGMLString(s, name=None, add=True) + // rst: .. method:: graphGMLString(s, name=None, add=True) // rst: // rst: Load a graph in :ref:`GML ` format from a given string. // rst: @@ -274,7 +256,7 @@ void Graph_doExport() { // rst: :rtype: Graph // rst: :raises: :class:`InputError` on bad input. py::def("graphGMLString", &Graph::graphGMLString); - // rst: .. py:method:: graphGML(f, name=None, add=True) + // rst: .. method:: graphGML(f, name=None, add=True) // rst: // rst: Load a graph in :ref:`GML ` format from a given file. // rst: @@ -285,7 +267,7 @@ void Graph_doExport() { // rst: :rtype: Graph // rst: :raises: :class:`InputError` on bad input. py::def("graphGML", &Graph::graphGML); - // rst: .. py:method:: graphDFS(s, name=None, add=True) + // rst: .. method:: graphDFS(s, name=None, add=True) // rst: // rst: Load a graph from a :ref:`GraphDFS ` string. // rst: @@ -296,7 +278,7 @@ void Graph_doExport() { // rst: :rtype: Graph // rst: :raises: :class:`InputError` on bad input. py::def("graphDFS", &Graph::graphDFS); - // rst: .. py:method:: smiles(s, name=None, add=True, allowAbstract=False, classPolicy=SmilesClassPolicy.NoneOnDuplicate) + // rst: .. method:: smiles(s, name=None, add=True, allowAbstract=False, classPolicy=SmilesClassPolicy.NoneOnDuplicate) // rst: // rst: Load a molecule from a :ref:`SMILES ` string. // rst: @@ -311,6 +293,4 @@ void Graph_doExport() { static_cast (*)(const std::string &, bool, SmilesClassPolicy)>(&Graph::smiles)); } -} // namespace Py -} // namespace graph -} // namespace mod +} // namespace mod::graph::Py diff --git a/libs/pymod/src/mod/py/graph/GraphInterface.cpp b/libs/pymod/src/mod/py/graph/GraphInterface.cpp index e4c13b6..aff52cf 100644 --- a/libs/pymod/src/mod/py/graph/GraphInterface.cpp +++ b/libs/pymod/src/mod/py/graph/GraphInterface.cpp @@ -4,186 +4,90 @@ #include #include -namespace mod { -namespace graph { -namespace Py { +namespace mod::graph::Py { void GraphInterface_doExport() { - std::string(Graph::Vertex::*printStereoWithoutOptions)() const = &Graph::Vertex::printStereo; - std::string(Graph::Vertex::*printStereoWithOptions)(const graph::Printer&) const = &Graph::Vertex::printStereo; + std::string(Graph::Vertex::* + printStereoWithoutOptions)() const = &Graph::Vertex::printStereo; + std::string(Graph::Vertex::* + printStereoWithOptions)(const graph::Printer&) const = &Graph::Vertex::printStereo; - // rst: .. py:class:: GraphVertex + py::object graphObj = py::scope().attr("Graph"); + py::scope graphScope = graphObj; + + // rst: The :class:`Graph` class implements the :class:`protocols.LabelledGraph` protocol, + // rst: and thus have the following nested types. + // rst: + // rst: .. class:: Graph.Vertex // rst: - // rst: A descriptor of either a vertex in a graph, or a null vertex. + // rst: Implements the :class:`protocols.LabelledGraph.Vertex` protocol. + // rst: Additionally, the :attr:`id ` is in the range :math:`[0, numVertices[`. // rst: - py::class_("GraphVertex", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Vertex", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &Graph::Vertex::hash) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Graph::Vertex::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Graph::Vertex::isNull) - // rst: .. py:attribute:: id - // rst: - // rst: (Read-only) The index of the vertex. It will be in the range :math:`[0, numVertices[`. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("id", &Graph::Vertex::getId) - // rst: .. py:attribute:: graph - // rst: - // rst: (Read-only) The graph the vertex belongs to. - // rst: - // rst: :type: Graph - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("graph", &Graph::Vertex::getGraph) - // rst: .. py:attribute:: degree - // rst: - // rst: (Read-only) The degree of the vertex. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("degree", &Graph::Vertex::getDegree) - // rst: .. py:attribute:: incidentEdges - // rst: - // rst: (Read-only) A range of incident edges to this vertex. - // rst: - // rst: :type: GraphIncidentEdgeRange - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("incidentEdges", &Graph::Vertex::incidentEdges) - // rst: .. py:attribute:: stringLabel - // rst: - // rst: (Read-only) The string label of the vertex. - // rst: - // rst: :type: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("stringLabel", py::make_function(&Graph::Vertex::getStringLabel, py::return_value_policy())) - // rst: .. py:attribute:: atomId - // rst: - // rst: (Read-only) The atom id of the vertex. - // rst: - // rst: :type: AtomId - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. + .add_property("stringLabel", py::make_function(&Graph::Vertex::getStringLabel, + py::return_value_policy())) .add_property("atomId", &Graph::Vertex::getAtomId) - // rst: .. py:attribute:: isotope - // rst: - // rst: (Read-only) The isotope of the vertex. - // rst: - // rst: :type: Isotope - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("isotope", &Graph::Vertex::getIsotope) - // rst: .. py:attribute:: charge - // rst: - // rst: (Read-only) The charge of the vertex. - // rst: - // rst: :type: Charge - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("charge", &Graph::Vertex::getCharge) - // rst: .. py:attribute:: radical - // rst: - // rst: (Read-only) The radical status of the vertex. - // rst: - // rst: :type: bool - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("radical", &Graph::Vertex::getRadical) - // rst: .. py:method:: printStereo() - // rst: printStereo(p) - // rst: - // rst: Print the stereo configuration for the vertex. - // rst: - // rst: :param GraphPrinter p: the printing options used for the depiction. - // rst: :returns: the name of the PDF-file that will be compiled in post-processing. - // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .def("printStereo", printStereoWithoutOptions) - .def("printStereo", printStereoWithOptions) - ; + .def("printStereo", printStereoWithOptions); - // rst: .. py:class:: GraphEdge + // rst: .. class:: Graph.Edge // rst: - // rst: A descriptor of either an edge in a graph, or a null edge. + // rst: Implements the :class:`protocols.LabelledGraph.Edge` protocol. // rst: - py::class_("GraphEdge", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Edge", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool - .def("__bool__", &Graph::Vertex::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool + .def("__bool__", &Graph::Edge::operator bool) .def("isNull", &Graph::Edge::isNull) - // rst: .. py:attribute:: graph - // rst: - // rst: (Read-only) The graph the edge belongs to. - // rst: - // rst: :type: Graph - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("graph", &Graph::Edge::getGraph) - // rst: .. py:attribute:: source - // rst: - // rst: (Read-only) The source vertex of the edge. - // rst: - // rst: :type: GraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("source", &Graph::Edge::source) - // rst: .. attribute:: target - // rst: - // rst: (Read-only) The target vertex of the edge. - // rst: - // rst: :type: GraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("target", &Graph::Edge::target) - // rst: .. py:attribute:: stringLabel - // rst: - // rst: (Read-only) The string label of the edge. - // rst: - // rst: :type: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("stringLabel", py::make_function(&Graph::Edge::getStringLabel, py::return_value_policy())) - // rst: .. py:attribute:: bondType - // rst: - // rst: (Read-only) The bond type of the edge. - // rst: - // rst: :type: BondType - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("bondType", &Graph::Edge::getBondType) - ; + .add_property("stringLabel", py::make_function(&Graph::Edge::getStringLabel, + py::return_value_policy())) + .add_property("bondType", &Graph::Edge::getBondType); - py::class_("GraphVertexRange", py::no_init) + // rst: .. class:: Graph.VertexRange + // rst: + // rst: Implements the :class:`protocols.Graph.VertexRange` protocol, + // rst: in addition to the following functionality. + // rst: + py::class_("VertexRange", py::no_init) .def("__iter__", py::iterator()) - .def("__getitem__", &Graph::VertexRange::operator[]) - ; - py::class_("GraphEdgeRange", py::no_init) - .def("__iter__", py::iterator()) - ; - py::class_("GraphIncidentEdgeRange", py::no_init) - .def("__iter__", py::iterator()) - ; + // rst: .. method:: __getitem__(i) + // rst: + // rst: :returns: the ``i``\ th vertex of the graph. + // rst: :rtype: Graph.Vertex + .def("__getitem__", &Graph::VertexRange::operator[]); + // rst: .. class:: Graph.EdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.EdgeRange` protocol. + // rst: + py::class_("EdgeRange", py::no_init) + .def("__iter__", py::iterator()); + // rst: .. class:: Graph.IncidentEdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.IncidentEdgeRange` protocol. + // rst: + py::class_("IncidentEdgeRange", py::no_init) + .def("__iter__", py::iterator()); } -} // namespace Py -} // namespace graph -} // namespace mod +} // namespace mod::graph::Py diff --git a/libs/pymod/src/mod/py/graph/Printer.cpp b/libs/pymod/src/mod/py/graph/Printer.cpp index d44aef5..4c54998 100644 --- a/libs/pymod/src/mod/py/graph/Printer.cpp +++ b/libs/pymod/src/mod/py/graph/Printer.cpp @@ -4,12 +4,10 @@ #include -namespace mod { -namespace graph { -namespace Py { +namespace mod::graph::Py { void Printer_doExport() { - // rst: .. py:class:: GraphPrinter + // rst: .. class:: GraphPrinter // rst: // rst: This class is used to configure how graphs are visualised. // rst: @@ -17,95 +15,95 @@ void Printer_doExport() { // rst: and the result may not accurately represent the underlying graph, // rst: and may make non-molecules look like molecules. // rst: - // rst: .. py:method:: __init__(self) + // rst: .. method:: __init__() // rst: // rst: The default constructor enables edges as bonds, raised charges, and raised isotopes. py::class_("GraphPrinter") .def(py::self == py::self) .def(py::self != py::self) - // rst: .. py:method:: setMolDefault() + // rst: .. method:: setMolDefault() // rst: // rst: Shortcut for enabling all but thickening and index printing. .def("setMolDefault", &Printer::setMolDefault) - // rst: .. py:method:: setReactionDefault() + // rst: .. method:: setReactionDefault() // rst: // rst: Shortcut for enabling all but thickening, index printing and simplification of carbon atoms. .def("setReactionDefault", &Printer::setReactionDefault) - // rst: .. py:method:: disableAll() + // rst: .. method:: disableAll() // rst: // rst: Disable all special printing features. .def("disableAll", &Printer::disableAll) - // rst: .. py:method:: enableAll() + // rst: .. method:: enableAll() // rst: // rst: Enable all special printing features, except typewriter font. .def("enableAll", &Printer::enableAll) - // rst: .. py:attribute:: edgesAsBonds + // rst: .. attribute:: edgesAsBonds // rst: // rst: Control whether edges with special labels are drawn as chemical bonds. // rst: // rst: :type: bool .add_property("edgesAsBonds", &Printer::getEdgesAsBonds, &Printer::setEdgesAsBonds) - // rst: .. py:attribute:: collapseHydrogens + // rst: .. attribute:: collapseHydrogens // rst: // rst: Control whether vertices representing hydrogen atoms are collapsed into their neighbours labels. // rst: // rst: :type: bool .add_property("collapseHydrogens", &Printer::getCollapseHydrogens, &Printer::setCollapseHydrogens) - // rst: .. py:attribute:: raiseCharges + // rst: .. attribute:: raiseCharges // rst: // rst: Control whether a vertex label suffix encoding a charge is written as a superscript to the rest of the label. // rst: // rst: :type: bool .add_property("raiseCharges", &Printer::getRaiseCharges, &Printer::setRaiseCharges) - // rst: .. py:attribute:: simpleCarbons + // rst: .. attribute:: simpleCarbons // rst: // rst: Control whether some vertices encoding carbon atoms are depicted without any label. // rst: // rst: :type: bool .add_property("simpleCarbons", &Printer::getSimpleCarbons, &Printer::setSimpleCarbons) - // rst: .. py:attribute:: thick + // rst: .. attribute:: thick // rst: // rst: Control whether all edges are drawn thicker than normal and all labels are written in bold. // rst: // rst: :type: bool .add_property("thick", &Printer::getThick, &Printer::setThick) - // rst: .. py:attribute:: withColour + // rst: .. attribute:: withColour // rst: // rst: Control whether colour is applied to certain elements of the graph which are molecule-like. // rst: // rst: :type: bool .add_property("withColour", &Printer::getWithColour, &Printer::setWithColour) - // rst: .. py:attribute:: withIndex + // rst: .. attribute:: withIndex // rst: // rst: Control whether the underlying indices of the vertices are printed. // rst: // rst: :type: bool .add_property("withIndex", &Printer::getWithIndex, &Printer::setWithIndex) - // rst: .. py:attribute:: withTexttt + // rst: .. attribute:: withTexttt // rst: // rst: Control whether the vertex and edge labels are written with typewriter font. // rst: // rst: :type: bool .add_property("withTexttt", &Printer::getWithTexttt, &Printer::setWithTexttt) - // rst: .. py:attribute:: withRawStereo + // rst: .. attribute:: withRawStereo // rst: // rst: Control whether the vertices and edges are annotated with the raw stereo properties. // rst: // rst: :type: bool .add_property("withRawStereo", &Printer::getWithRawStereo, &Printer::setWithRawStereo) - // rst: .. py:attribute:: withPrettyStereo + // rst: .. attribute:: withPrettyStereo // rst: // rst: Control whether the vertices and edges are annotated with stylized stereo properties. // rst: // rst: :type: bool .add_property("withPrettyStereo", &Printer::getWithPrettyStereo, &Printer::setWithPrettyStereo) - // rst: .. py:attribute:: rotation + // rst: .. attribute:: rotation // rst: // rst: Rotation of internally computed coordinates. // rst: // rst: :type: int .add_property("rotation", &Printer::getRotation, &Printer::setRotation) - // rst: .. py:attribute:: mirror + // rst: .. attribute:: mirror // rst: // rst: Mirror internally computed coordinates in the y-axis. // rst: @@ -114,6 +112,4 @@ void Printer_doExport() { ; } -} // namespace Py -} // namespace graph -} // namespace mod \ No newline at end of file +} // namespace mod::graph::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/graph/Union.cpp b/libs/pymod/src/mod/py/graph/Union.cpp new file mode 100644 index 0000000..1c8d99b --- /dev/null +++ b/libs/pymod/src/mod/py/graph/Union.cpp @@ -0,0 +1,203 @@ +#include + +#include +#include +#include +#include +#include + +#include + +#include + +namespace mod::graph::Py { +namespace { + +Union *make(const py::object &o) { + return new Union(std::vector>( + py::stl_input_iterator>(o), + py::stl_input_iterator>() + )); +} + +} // namespace + +void Union_doExport() { + // rst: .. class:: UnionGraph + // rst: + // rst: An adaptor for a multiset of :class:`Graph`\ s to present them + // rst: as their disjoint union. + // rst: + // rst: It functions as an iterable of the adapted graphs, + // rst: and it implements the :class:`protocols.LabelledGraph` protocol. + // rst: + py::scope UnionScope = py::class_("UnionGraph") + // rst: .. method:: __init__() + // rst: __init__(graphs) + // rst: + // rst: Construct a graph representing the disjoint union of ``graphs``. + // rst: Thus, if no graphs are given the empty graph is constructed. + // rst: + // rst: :param graphs: the list of graphs to adapt. + // rst: :type graphs: list[Graph] + .def("__init__", py::make_constructor(&make)) + .def(py::self == py::self) + .def(py::self != py::self) + // rst: .. method:: __str__() + // rst: + // rst: :rtype: str + .def(str(py::self)) + // rst: .. method:: __len__() + // rst: + // rst: :returns: the number of adapted graphs. + // rst: :rtype: int + .def("__len__", &Union::size) + // rst: .. method:: __iter__() + // rst: + // rst: :returns: the range of graphs adapted by this object. + .def("__iter__", py::iterator()) + // rst: .. method:: __getitem__(i) + // rst: + // rst: :returns: the ``i``\ th adapted graph. + // rst: :rtype: Graph + // rst: :raises: :class:`LogicError` if ``i`` is out of range. + .def("__getitem__", &Union::operator[]) + .add_property("numVertices", &Union::numVertices) + .add_property("vertices", &Union::vertices) + .add_property("numEdges", &Union::numEdges) + .add_property("edges", &Union::edges); + + + // rst: .. class:: Vertex + // rst: + // rst: Implements the :class:`protocols.LabelledGraph.Vertex` protocol. + // rst: Additionally, the :attr:`id ` is in the range :math:`[0, numVertices[`. + // rst: + // rst: A non-null vertex represents a specific :class:`Graph.Vertex`. + // rst: As the same :class:`Graph` can be part of a :class:`UnionGraph` multiple times, + // rst: a vertex also has a graph index to determine which instance of a :class:`Graph` + // rst: in the :class:`UnionGraph` the vertex refers to. + // rst: + std::string(Union::Vertex::* + printStereoWithoutOptions)() const = &Union::Vertex::printStereo; + std::string(Union::Vertex::* + printStereoWithOptions)(const graph::Printer&) const = &Union::Vertex::printStereo; + py::class_("Vertex", py::no_init) + .def(py::init<>()) + .def(str(py::self)) + .def(py::self == py::self) + .def(py::self != py::self) + .def(py::self < py::self) + .def("__hash__", &Union::Vertex::hash) + .def("__bool__", &Union::Vertex::operator bool) + .def("isNull", &Union::Vertex::isNull) + .add_property("id", &Union::Vertex::getId) + .add_property("graph", &Union::Vertex::getGraph) + .add_property("degree", &Union::Vertex::getDegree) + .add_property("incidentEdges", &Union::Vertex::incidentEdges) + .add_property("stringLabel", py::make_function(&Union::Vertex::getStringLabel, + py::return_value_policy())) + .add_property("atomId", &Union::Vertex::getAtomId) + .add_property("isotope", &Union::Vertex::getIsotope) + .add_property("charge", &Union::Vertex::getCharge) + .add_property("radical", &Union::Vertex::getRadical) + .def("printStereo", printStereoWithoutOptions) + .def("printStereo", printStereoWithOptions) + // rst: .. attribute:: graphIndex + // rst: + // rst: (Read-only) The index of the graph in the owning :class:`UnionGraph` this vertex + // rst: is from. The index is thus in the range :math:`[0, len(graph)[`. + // rst: + // rst: We can obtain the underlying :class:`Graph` this vertex, ``self``, + // rst: is from both directly via the :attr:`vertex` attribute as ``self.vertex.graph``, + // rst: or via the graph index as ``self.graph[self.graphIndex]``. + // rst: + // rst: :type: int + // rst: :raises: :class:`LogicError` if it is a null vertex. + .add_property("graphIndex", &Union::Vertex::getGraphIndex) + // rst: .. attribute:: vertex + // rst: + // rst: (Read-only) The underlying :class:`Graph.Vertex` this vertex represents. + // rst: + // rst: We can obtain the underlying :class:`Graph` this vertex, ``self``, + // rst: is from both directly via the :attr:`vertex` attribute as ``self.vertex.graph``, + // rst: or via the graph index as ``self.graph[self.graphIndex]``. + // rst: + // rst: :type: Graph.Vertex + // rst: :raises: :class:`LogicError` if it is a null vertex. + .add_property("vertex", &Union::Vertex::getVertex); + + // rst: .. class:: Edge + // rst: + // rst: Implements the :class:`protocols.LabelledGraph.Vertex` protocol. + // rst: + // rst: A non-null edge represents a specific :class:`Graph.Edge`. + // rst: As the same :class:`Graph` can be part of a :class:`UnionGraph` multiple times, + // rst: an edge also has a graph index to determine which instance of a :class:`Graph` + // rst: in the :class:`UnionGraph` the edge refers to. + // rst: + py::class_("Edge", py::no_init) + .def(py::init<>()) + .def(str(py::self)) + .def(py::self == py::self) + .def(py::self != py::self) + .def(py::self < py::self) + .def("__bool__", &Union::Edge::operator bool) + .def("isNull", &Union::Edge::isNull) + .add_property("graph", &Union::Edge::getGraph) + .add_property("source", &Union::Edge::source) + .add_property("target", &Union::Edge::target) + .add_property("stringLabel", py::make_function(&Union::Edge::getStringLabel, + py::return_value_policy())) + .add_property("bondType", &Union::Edge::getBondType) + // rst: .. attribute:: graphIndex + // rst: + // rst: (Read-only) The index of the graph in the owning :class:`UnionGraph` this edge + // rst: is from. The index is thus in the range :math:`[0, len(graph)[`. + // rst: + // rst: We can obtain the underlying :class:`Graph` this edge, ``self``, + // rst: is from both directly via the :attr:`edge` attribute as ``self.edge.graph``, + // rst: or via the graph index as ``self.graph[self.graphIndex]``. + // rst: + // rst: :type: int + // rst: :raises: :class:`LogicError` if it is a null edge. + .add_property("graphIndex", &Union::Edge::getGraphIndex) + // rst: .. attribute:: edge + // rst: + // rst: (Read-only) The underlying :class:`Graph.Edge` this edge represents. + // rst: + // rst: We can obtain the underlying :class:`Graph` this edge, ``self``, + // rst: is from both directly via the :attr:`edge` attribute as ``self.edge.graph``, + // rst: or via the graph index as ``self.graph[self.graphIndex]``. + // rst: + // rst: :type: Graph.Edge + // rst: :raises: :class:`LogicError` if it is a null edge. + .add_property("edge", &Union::Edge::getEdge); + + // rst: .. class:: VertexRange + // rst: + // rst: Implements the :class:`protocols.Graph.VertexRange` protocol, + // rst: in addition to the following functionality. + // rst: + py::class_("VertexRange", py::no_init) + .def("__iter__", py::iterator()) + // rst: .. method:: __getitem__(i) + // rst: + // rst: :returns: the ``i``\ th vertex of the graph. + // rst: :rtype: UnionGraph.Vertex + .def("__getitem__", &Union::VertexRange::operator[]); + // rst: .. class:: EdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.EdgeRange` protocol. + // rst: + py::class_("EdgeRange", py::no_init) + .def("__iter__", py::iterator()); + // rst: .. class:: IncidentEdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.IncidentEdgeRange` protocol. + // rst: + py::class_("IncidentEdgeRange", py::no_init) + .def("__iter__", py::iterator()); +} + +} // namespace mod::graph::Py diff --git a/libs/pymod/src/mod/py/rule/Composition.cpp b/libs/pymod/src/mod/py/rule/Composition.cpp index 2dd887a..37e1ca9 100644 --- a/libs/pymod/src/mod/py/rule/Composition.cpp +++ b/libs/pymod/src/mod/py/rule/Composition.cpp @@ -39,26 +39,24 @@ // rst: and the corresponding :ref:`C++ page`. // rst: -namespace mod { -namespace rule { -namespace Py { +namespace mod::rule::Py { namespace { -std::vector > getRuleDatabase(std::shared_ptr rc) { - return std::vector < std::shared_ptr >(begin(rc->getRuleDatabase()), end(rc->getRuleDatabase())); +std::vector> getRuleDatabase(std::shared_ptr rc) { + return std::vector>(begin(rc->getRuleDatabase()), end(rc->getRuleDatabase())); } -std::vector > getProducts(std::shared_ptr rc) { - return std::vector < std::shared_ptr >(begin(rc->getProducts()), end(rc->getProducts())); +std::vector> getProducts(std::shared_ptr rc) { + return std::vector>(begin(rc->getProducts()), end(rc->getProducts())); } -std::vector > eval(std::shared_ptr rc, const RCExp::Expression &e, int verbosity) { +std::vector> eval(std::shared_ptr rc, const RCExp::Expression &e, int verbosity) { auto result = rc->eval(e, verbosity); - return std::vector >(begin(result), end(result)); + return std::vector>(begin(result), end(result)); } -std::shared_ptr create(const std::vector > dVec, LabelSettings labelSettings) { - std::unordered_set > dUSet(begin(dVec), end(dVec)); +std::shared_ptr create(const std::vector> dVec, LabelSettings labelSettings) { + std::unordered_set> dUSet(begin(dVec), end(dVec)); return Composer::create(dUSet, labelSettings); } @@ -88,26 +86,28 @@ void RC_doExport() { // rst: // rst: :type: list[Rule] .add_property("_ruleDatabase", &getRuleDatabase) - // rst: .. attribute:: products - // rst: - // rst: (Read-only) The list of unique rules this evaluator has constructed. - // rst: - // rst: :type: list[Rule] + // rst: .. attribute:: products + // rst: + // rst: (Read-only) The list of unique rules this evaluator has constructed. + // rst: + // rst: :type: list[Rule] .add_property("_products", &getProducts) - // rst: .. method:: eval(exp, *, verbosity=0) - // rst: - // rst: Evaluates a rule composition expression. Any created rule is replaced by a rule in the database if they are isomorphic. - // rst: - // rst: :param RCExpExp exp: the expression to evaluate. - // rst: :param int verbosity: the level of information being printed about the evaluation. - // rst: See :cpp:func:`rule::Composer::eval` for details. - // rst: :returns: the resulting list of rules of the expression. + // rst: .. method:: eval(exp, *, verbosity=0) + // rst: + // rst: Evaluates a rule composition expression. + // rst: Any created rule is replaced by a rule in the database if they are isomorphic. + // rst: A rule may appear multiple times in the result if multiple overlaps resulted in the same composed rule. + // rst: + // rst: :param RCExpExp exp: the expression to evaluate. + // rst: :param int verbosity: the level of information being printed about the evaluation. + // rst: See :cpp:func:`rule::Composer::eval` for details. + // rst: :returns: the resulting list of rules of the expression. + // rst: :rtype: list[Rule] .def("eval", &eval) - // rst: .. method:: print() - // rst: - // rst: Print the graph representing all expressions evaluated so far. - .def("print", &Composer::print) - ; + // rst: .. method:: print() + // rst: + // rst: Print the graph representing all expressions evaluated so far. + .def("print", &Composer::print); // rst: .. method:: rcEvaluator(database, labelSettings) // rst: @@ -130,85 +130,76 @@ void RC_doExport() { // Nullary/unary //-------------------------------------------------------------------------- - // rst: .. py:class:: RCExpUnion + // rst: .. class:: RCExpUnion // rst: // rst: Return the union of the subexpressions. I.e., flatten the subresult lists into a single list. // rst: py::class_("RCExpUnion", py::no_init) - .def(py::init >()) - .def(str(py::self)) - ; - // rst: .. py:class:: RCExpBind + .def(py::init>()) + .def(str(py::self)); + // rst: .. class:: RCExpBind // rst: // rst: Return the singleton list with the rule :math:`(\emptyset, \emptyset, G)` for the given graph :math:`G`. // rst: py::class_("RCExpBind", py::no_init) - .def(py::init >()) - .def(str(py::self)) - ; - // rst: .. py:class:: RCExpId + .def(py::init>()) + .def(str(py::self)); + // rst: .. class:: RCExpId // rst: // rst: Return the singleton list with the rule :math:`(G, G, G)` for the given graph :math:`G`. // rst: py::class_("RCExpId", py::no_init) - .def(py::init >()) - .def(str(py::self)) - ; - // rst: .. py:class:: RCExpUnbind + .def(py::init>()) + .def(str(py::self)); + // rst: .. class:: RCExpUnbind // rst: // rst: Return the singleton list with the rule :math:`(G, \emptyset, \emptyset)` for the given graph :math:`G`. // rst: py::class_("RCExpUnbind", py::no_init) - .def(py::init >()) - .def(str(py::self)) - ; + .def(py::init>()) + .def(str(py::self)); // Expresssion //-------------------------------------------------------------------------- - // rst: .. py:class:: RCExpExp + // rst: .. class:: RCExpExp // rst: // rst: A generic rule composition expression. // rst: py::class_("RCExpExp", py::no_init) - .def(str(py::self)) - ; + .def(str(py::self)); // Binary //-------------------------------------------------------------------------- - // rst: .. py:class:: RCExpComposeCommon + // rst: .. class:: RCExpComposeCommon // rst: // rst: The base class for the composition of two rule :math:`(L_1, K_1, R_1)` and :math:`(L_2, K_2, R_2)`. // rst: py::class_("RCExpComposeCommon", py::no_init) - .def(py::init < RCExp::Expression, RCExp::Expression, bool, bool, bool>()) - .def(str(py::self)) - ; - // rst: .. py:class:: RCExpComposeParallel + .def(py::init()) + .def(str(py::self)); + // rst: .. class:: RCExpComposeParallel // rst: // rst: Compose the rules by all common subgraphs of :math:`R_1` and :math:`L_2`, // rst: possibly limited to connected subgraphs or to the subgraphs of maximum size. // rst: py::class_("RCExpComposeParallel", py::no_init) - .def(py::init < RCExp::Expression, RCExp::Expression, bool>()) - .def(str(py::self)) - ; - // rst: .. py:class:: RCExpComposeSub + .def(py::init()) + .def(str(py::self)); + // rst: .. class:: RCExpComposeSub // rst: // rst: Compose the rules by the empty graph, i.e., create a rule representing the parallel application of two input rules. // rst: py::class_("RCExpComposeSub", py::no_init) - .def(py::init < RCExp::Expression, RCExp::Expression, bool, bool>()) - .def(str(py::self)) - ; - // rst: .. py:class:: RCExpComposeSuper + .def(py::init()) + .def(str(py::self)); + // rst: .. class:: RCExpComposeSuper // rst: // rst: Compose the rules such that overlapping connected components of :math:`R_1` and :math:`L_2` have the :math:`L_2` component as a subgraph of :math:`R_1`. // rst: The overlap is `partial` if not every connected component of :math:`L_2` is participating in the common subgraph. // rst: py::class_("RCExpComposeSuper", py::no_init) - .def(py::init < RCExp::Expression, RCExp::Expression, bool, bool, bool>()) - .def(str(py::self)) - ; + .def(py::init()) + .def(str(py::self)); py::implicitly_convertible, RCExp::Expression>(); py::implicitly_convertible(); @@ -221,6 +212,4 @@ void RC_doExport() { py::implicitly_convertible(); } -} // namespace Py -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/rule/GraphInterface.cpp b/libs/pymod/src/mod/py/rule/GraphInterface.cpp index ed2b80d..0362c7b 100644 --- a/libs/pymod/src/mod/py/rule/GraphInterface.cpp +++ b/libs/pymod/src/mod/py/rule/GraphInterface.cpp @@ -1,13 +1,10 @@ #include #include -#include #include #include -namespace mod { -namespace rule { -namespace Py { +namespace mod::rule::Py { namespace { void exportLeft() { @@ -16,374 +13,227 @@ void exportLeft() { std::string(Rule::LeftGraph::Vertex::* printStereoWithOptions)(const graph::Printer&) const = &Rule::LeftGraph::Vertex::printStereo; - // rst: .. py:class:: RuleLeftGraph + py::object ruleObj = py::scope().attr("Rule"); + py::scope ruleScope = ruleObj; + + // rst: .. class:: Rule.LeftGraph // rst: // rst: A proxy object representing the left graph of the rule. + // rst: The class implements the :class:`protocols.LabelledGraph` protocol, // rst: - py::class_("RuleLeftGraph", py::no_init) - // rst: .. py:attribute:: rule - // rst: - // rst: (Read-only) The rule the graph belongs to. - // rst: - // rst: :type: Rule - .add_property("rule", &Rule::LeftGraph::getRule) - // rst: .. py:attribute:: numVertices - // rst: - // rst: (Read-only) The number of vertices in the graph. - // rst: - // rst: :type: int + py::scope graphObj = py::class_("LeftGraph", py::no_init) + .def(py::self == py::self) + .def(py::self != py::self) + .def(str(py::self)) .add_property("numVertices", &Rule::LeftGraph::numVertices) - // rst: .. py:attribute:: vertices - // rst: - // rst: (Read-only) An iterable of all vertices in the graph. - // rst: - // rst: :type: RuleLeftGraphVertexRange .add_property("vertices", &Rule::LeftGraph::vertices) - // rst: .. py:attribute:: numEdges - // rst: - // rst: (Read-only) The number of edges in the graph. - // rst: - // rst: :type: int .add_property("numEdges", &Rule::LeftGraph::numEdges) - // rst: .. py:attribute:: edges + .add_property("edges", &Rule::LeftGraph::edges) + // rst: .. attribute:: rule // rst: - // rst: (Read-only) An iterable of all edges in the graph. + // rst: (Read-only) The rule the graph belongs to. // rst: - // rst: :type: RuleLeftGraphEdgeRange - .add_property("edges", &Rule::LeftGraph::edges); + // rst: :type: Rule + .add_property("rule", &Rule::LeftGraph::getRule); - // rst: .. py:class:: RuleLeftGraphVertex + // rst: .. class:: Vertex // rst: - // rst: A descriptor of either a vertex in a left side, or a null vertex. + // rst: A descriptor of either a vertex in a left side, or a null vertex. + // rst: Implements the :class:`protocols.LabelledGraph.Vertex` protocol. + // rst: Additionally, the :attr:`id ` is in the range :math:`[0, numCoreVertices[`. // rst: - py::class_("RuleLeftGraphVertex", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Vertex", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &Rule::LeftGraph::Vertex::hash) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::LeftGraph::Vertex::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::LeftGraph::Vertex::isNull) - // rst: .. py:attribute:: id - // rst: - // rst: (Read-only) The index of the vertex. It will be in the range :math:`[0, numCoreVertices[`. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("id", &Rule::LeftGraph::Vertex::getId) - // rst: .. py:attribute:: rule - // rst: - // rst: (Read-only) The rule the vertex belongs to. - // rst: - // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("rule", &Rule::LeftGraph::Vertex::getRule) - // rst: .. py:attribute:: core - // rst: - // rst: (Read-only) The descriptor for this vertex in the core graph. - // rst: - // rst: :type: RuleVertex - .add_property("core", &Rule::LeftGraph::Vertex::getCore) - // rst: .. py:attribute:: degree - // rst: - // rst: (Read-only) The degree of the vertex. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. + .add_property("graph", &Rule::LeftGraph::Vertex::getGraph) .add_property("degree", &Rule::LeftGraph::Vertex::getDegree) - // rst: .. py:attribute:: incidentEdges - // rst: - // rst: (Read-only) A range of incident edges to this vertex. - // rst: - // rst: :type: RuleLeftGraphIncidentEdgeRange - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("incidentEdges", &Rule::LeftGraph::Vertex::incidentEdges) - // rst: .. py:attribute:: stringLabel - // rst: - // rst: (Read-only) The string label of the vertex. - // rst: - // rst: :type: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("stringLabel", py::make_function(&Rule::LeftGraph::Vertex::getStringLabel, py::return_value_policy())) - // rst: .. py:attribute:: atomId - // rst: - // rst: (Read-only) The atom id of the vertex. - // rst: - // rst: :type: AtomId - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("atomId", &Rule::LeftGraph::Vertex::getAtomId) - // rst: .. py:attribute:: isotope - // rst: - // rst: (Read-only) The isotope of the vertex. - // rst: - // rst: :type: Isotope - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("isotope", &Rule::LeftGraph::Vertex::getIsotope) - // rst: .. py:attribute:: charge - // rst: - // rst: (Read-only) The charge of the vertex. - // rst: - // rst: :type: Charge - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("charge", &Rule::LeftGraph::Vertex::getCharge) - // rst: .. py:attribute:: radical + .add_property("radical", &Rule::LeftGraph::Vertex::getRadical) + .def("printStereo", printStereoWithoutOptions) + .def("printStereo", printStereoWithOptions) + // rst: .. attribute:: core // rst: - // rst: (Read-only) The radical status of the vertex. + // rst: (Read-only) The descriptor for this vertex in the core graph. // rst: - // rst: :type: bool - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("radical", &Rule::LeftGraph::Vertex::getRadical) - // rst: .. py:method:: printStereo() - // rst: printStereo(p) + // rst: :type: Rule.Vertex + .add_property("core", &Rule::LeftGraph::Vertex::getCore) + // rst: .. attribute:: rule // rst: - // rst: Print the stereo configuration for the vertex. + // rst: (Read-only) The rule the vertex belongs to. // rst: - // rst: :param GraphPrinter p: the printing options used for the depiction. - // rst: :returns: the name of the PDF-file that will be compiled in post-processing. - // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .def("printStereo", printStereoWithoutOptions) - .def("printStereo", printStereoWithOptions); + // rst: :type: Rule + // rst: :raises: :class:`LogicError` if it is a null descriptor. + .add_property("rule", &Rule::LeftGraph::Vertex::getRule); - // rst: .. py:class:: RuleLeftGraphEdge + // rst: .. class:: Edge // rst: - // rst: A descriptor of either an edge in a left side, or a null edge. + // rst: A descriptor of either an edge in a left side, or a null edge. + // rst: Implements the :class:`protocols.LabelledGraph.Edge` protocol. // rst: - py::class_("RuleLeftGraphEdge", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Edge", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::LeftGraph::Edge::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::LeftGraph::Edge::isNull) - // rst: .. py:attribute:: graph - // rst: - // rst: (Read-only) The rule the edge belongs to. - // rst: - // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("rule", &Rule::LeftGraph::Edge::getRule) - // rst: .. py:attribute:: core - // rst: - // rst: (Read-only) The descriptor for this edge in the core graph. - // rst: - // rst: :type: RuleEdge - .add_property("core", &Rule::LeftGraph::Edge::getCore) - // rst: .. py:attribute:: source - // rst: - // rst: (Read-only) The source vertex of the edge. - // rst: - // rst: :type: RuleLeftGraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. + .add_property("graph", &Rule::LeftGraph::Edge::getGraph) .add_property("source", &Rule::LeftGraph::Edge::source) - // rst: .. attribute:: target - // rst: - // rst: (Read-only) The target vertex of the edge. - // rst: - // rst: :type: RuleLeftGraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("target", &Rule::LeftGraph::Edge::target) - // rst: .. py:attribute:: stringLabel - // rst: - // rst: (Read-only) The string label of the edge. - // rst: - // rst: :type: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("stringLabel", py::make_function(&Rule::LeftGraph::Edge::getStringLabel, py::return_value_policy())) - // rst: .. py:attribute:: bondType + .add_property("bondType", &Rule::LeftGraph::Edge::getBondType) + // rst: .. attribute:: core + // rst: + // rst: (Read-only) The descriptor for this edge in the core graph. + // rst: + // rst: :type: Rule.Edge + .add_property("core", &Rule::LeftGraph::Edge::getCore) + // rst: .. attribute:: rule // rst: - // rst: (Read-only) The bond type of the edge. + // rst: (Read-only) The rule the edge belongs to. // rst: - // rst: :type: BondType - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("bondType", &Rule::LeftGraph::Edge::getBondType); + // rst: :type: Rule + // rst: :raises: :class:`LogicError` if it is a null descriptor. + .add_property("rule", &Rule::LeftGraph::Edge::getRule); - py::class_("RuleLeftGraphVertexRange", py::no_init) + // rst: .. class:: VertexRange + // rst: + // rst: Implements the :class:`protocols.Graph.VertexRange` protocol. + // rst: + py::class_("VertexRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleLeftGraphEdgeRange", py::no_init) + // rst: .. class:: EdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.EdgeRange` protocol. + // rst: + py::class_("EdgeRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleLeftGraphIncidentEdgeRange", py::no_init) + // rst: .. class:: IncidentEdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.IncidentEdgeRange` protocol. + // rst: + py::class_("IncidentEdgeRange", py::no_init) .def("__iter__", py::iterator()); } void exportContext() { - // rst: .. py:class:: RuleContextGraph + py::object ruleObj = py::scope().attr("Rule"); + py::scope ruleScope = ruleObj; + + // rst: .. class:: Rule.ContextGraph // rst: // rst: A proxy object representing the context graph of the rule. + // rst: The class implements the :class:`protocols.Graph` protocol, // rst: - py::class_("RuleContextGraph", py::no_init) - // rst: .. py:attribute:: rule - // rst: - // rst: (Read-only) The rule the graph belongs to. - // rst: - // rst: :type: Rule - .add_property("rule", &Rule::ContextGraph::getRule) - // rst: .. py:attribute:: numVertices - // rst: - // rst: (Read-only) The number of vertices in the graph. - // rst: - // rst: :type: int + py::scope graphObj = py::class_("ContextGraph", py::no_init) + .def(py::self == py::self) + .def(py::self != py::self) + .def(str(py::self)) .add_property("numVertices", &Rule::ContextGraph::numVertices) - // rst: .. py:attribute:: vertices - // rst: - // rst: (Read-only) An iterable of all vertices in the graph. - // rst: - // rst: :type: RuleContextGraphVertexRange .add_property("vertices", &Rule::ContextGraph::vertices) - // rst: .. py:attribute:: numEdges - // rst: - // rst: (Read-only) The number of edges in the graph. - // rst: - // rst: :type: int .add_property("numEdges", &Rule::ContextGraph::numEdges) - // rst: .. py:attribute:: edges + .add_property("edges", &Rule::ContextGraph::edges) + // rst: .. attribute:: rule // rst: - // rst: (Read-only) An iterable of all edges in the graph. + // rst: (Read-only) The rule the graph belongs to. // rst: - // rst: :type: RuleContextGraphEdgeRange - .add_property("edges", &Rule::ContextGraph::edges); + // rst: :type: Rule + .add_property("rule", &Rule::ContextGraph::getRule); - // rst: .. py:class:: RuleContextGraphVertex + // rst: .. class:: Vertex // rst: - // rst: A descriptor of either a vertex in a context, or a null vertex. + // rst: A descriptor of either a vertex in a context, or a null vertex. + // rst: Implements the :class:`protocols.Graph.Vertex` protocol. + // rst: Additionally, the :attr:`id ` is in the range :math:`[0, numCoreVertices[`. // rst: - py::class_("RuleContextGraphVertex", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Vertex", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &Rule::ContextGraph::Vertex::hash) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::ContextGraph::Vertex::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::ContextGraph::Vertex::isNull) - // rst: .. py:attribute:: id - // rst: - // rst: (Read-only) The index of the vertex. It will be in the range :math:`[0, numCoreVertices[`. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("id", &Rule::ContextGraph::Vertex::getId) - // rst: .. py:attribute:: rule - // rst: - // rst: (Read-only) The rule the vertex belongs to. - // rst: - // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("rule", &Rule::ContextGraph::Vertex::getRule) - // rst: .. py:attribute:: core + .add_property("graph", &Rule::ContextGraph::Vertex::getGraph) + .add_property("degree", &Rule::ContextGraph::Vertex::getDegree) + .add_property("incidentEdges", &Rule::ContextGraph::Vertex::incidentEdges) + // rst: .. attribute:: core // rst: - // rst: (Read-only) The descriptor for this vertex in the core graph. + // rst: (Read-only) The descriptor for this vertex in the core graph. // rst: - // rst: :type: RuleVertex + // rst: :type: Rule.Vertex .add_property("core", &Rule::ContextGraph::Vertex::getCore) - // rst: .. py:attribute:: degree - // rst: - // rst: (Read-only) The degree of the vertex. + // rst: .. attribute:: rule // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("degree", &Rule::ContextGraph::Vertex::getDegree) - // rst: .. py:attribute:: incidentEdges - // rst: - // rst: (Read-only) A range of incident edges to this vertex. + // rst: (Read-only) The rule the vertex belongs to. // rst: - // rst: :type: RuleContextGraphIncidentEdgeRange - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("incidentEdges", &Rule::ContextGraph::Vertex::incidentEdges); + // rst: :type: Rule + // rst: :raises: :class:`LogicError` if it is a null descriptor. + .add_property("rule", &Rule::ContextGraph::Vertex::getRule); - // rst: .. py:class:: RuleContextGraphEdge + // rst: .. class:: Edge // rst: - // rst: A descriptor of either an edge in a context, or a null edge. + // rst: A descriptor of either an edge in a context, or a null edge. + // rst: Implements the :class:`protocols.LabelledGraph.Edge` protocol. // rst: - py::class_("RuleContextGraphEdge", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Edge", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::ContextGraph::Edge::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::ContextGraph::Edge::isNull) - // rst: .. py:attribute:: graph - // rst: - // rst: (Read-only) The rule the edge belongs to. - // rst: - // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("rule", &Rule::ContextGraph::Edge::getRule) - // rst: .. py:attribute:: core + .add_property("graph", &Rule::ContextGraph::Edge::getGraph) + .add_property("source", &Rule::ContextGraph::Edge::source) + .add_property("target", &Rule::ContextGraph::Edge::target) + // rst: .. attribute:: core // rst: - // rst: (Read-only) The descriptor for this edge in the core graph. + // rst: (Read-only) The descriptor for this edge in the core graph. // rst: - // rst: :type: RuleEdge + // rst: :type: Rule.Edge .add_property("core", &Rule::ContextGraph::Edge::getCore) - // rst: .. py:attribute:: source - // rst: - // rst: (Read-only) The source vertex of the edge. + // rst: .. attribute:: graph // rst: - // rst: :type: RuleContextGraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("source", &Rule::ContextGraph::Edge::source) - // rst: .. attribute:: target - // rst: - // rst: (Read-only) The target vertex of the edge. + // rst: (Read-only) The rule the edge belongs to. // rst: - // rst: :type: RuleContextGraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("target", &Rule::ContextGraph::Edge::target); + // rst: :type: Rule + // rst: :raises: :class:`LogicError` if it is a null descriptor. + .add_property("rule", &Rule::ContextGraph::Edge::getRule); - py::class_("RuleContextGraphVertexRange", py::no_init) + // rst: .. class:: VertexRange + // rst: + // rst: Implements the :class:`protocols.Graph.VertexRange` protocol. + // rst: + py::class_("VertexRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleContextGraphEdgeRange", py::no_init) + // rst: .. class:: EdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.EdgeRange` protocol. + // rst: + py::class_("EdgeRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleContextGraphIncidentEdgeRange", py::no_init) + // rst: .. class:: IncidentEdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.IncidentEdgeRange` protocol. + // rst: + py::class_("IncidentEdgeRange", py::no_init) .def("__iter__", py::iterator()); } @@ -393,373 +243,255 @@ void exportRight() { std::string(Rule::RightGraph::Vertex::* printStereoWithOptions)(const graph::Printer&) const = &Rule::RightGraph::Vertex::printStereo; - // rst: .. py:class:: RuleRightGraph + py::object ruleObj = py::scope().attr("Rule"); + py::scope ruleScope = ruleObj; + + // rst: .. class:: Rule.RightGraph // rst: // rst: A proxy object representing the right graph of the rule. + // rst: The class implements the :class:`protocols.LabelledGraph` protocol, // rst: - py::class_("RuleRightGraph", py::no_init) - // rst: .. py:attribute:: rule - // rst: - // rst: (Read-only) The rule the graph belongs to. - // rst: - // rst: :type: Rule - .add_property("rule", &Rule::RightGraph::getRule) - // rst: .. py:attribute:: numVertices - // rst: - // rst: (Read-only) The number of vertices in the graph. - // rst: - // rst: :type: int + py::scope graphObj = py::class_("RightGraph", py::no_init) + .def(py::self == py::self) + .def(py::self != py::self) + .def(str(py::self)) .add_property("numVertices", &Rule::RightGraph::numVertices) - // rst: .. py:attribute:: vertices - // rst: - // rst: (Read-only) An iterable of all vertices in the graph. - // rst: - // rst: :type: RuleRightGraphVertexRange .add_property("vertices", &Rule::RightGraph::vertices) - // rst: .. py:attribute:: numEdges - // rst: - // rst: (Read-only) The number of edges in the graph. - // rst: - // rst: :type: int .add_property("numEdges", &Rule::RightGraph::numEdges) - // rst: .. py:attribute:: edges + .add_property("edges", &Rule::RightGraph::edges) + // rst: .. attribute:: rule // rst: - // rst: (Read-only) An iterable of all edges in the graph. + // rst: (Read-only) The rule the graph belongs to. // rst: - // rst: :type: RuleRightGraphEdgeRange - .add_property("edges", &Rule::RightGraph::edges); + // rst: :type: Rule + .add_property("rule", &Rule::RightGraph::getRule); - // rst: .. py:class:: RuleRightGraphVertex + // rst: .. class:: Vertex // rst: - // rst: A descriptor of either a vertex in a right side, or a null vertex. + // rst: A descriptor of either a vertex in a right side, or a null vertex. + // rst: Implements the :class:`protocols.LabelledGraph.Vertex` protocol. + // rst: Additionally, the :attr:`id ` is in the range :math:`[0, numCoreVertices[`. // rst: - py::class_("RuleRightGraphVertex", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Vertex", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &Rule::RightGraph::Vertex::hash) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::RightGraph::Vertex::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::RightGraph::Vertex::isNull) - // rst: .. py:attribute:: id - // rst: - // rst: (Read-only) The index of the vertex. It will be in the range :math:`[0, numCoreVertices[`. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("id", &Rule::RightGraph::Vertex::getId) - // rst: .. py:attribute:: rule - // rst: - // rst: (Read-only) The rule the vertex belongs to. - // rst: - // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("rule", &Rule::RightGraph::Vertex::getRule) - // rst: .. py:attribute:: core - // rst: - // rst: (Read-only) The descriptor for this vertex in the core graph. - // rst: - // rst: :type: RuleVertex - .add_property("core", &Rule::RightGraph::Vertex::getCore) - // rst: .. py:attribute:: degree - // rst: - // rst: (Read-only) The degree of the vertex. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. + .add_property("graph", &Rule::RightGraph::Vertex::getGraph) .add_property("degree", &Rule::RightGraph::Vertex::getDegree) - // rst: .. py:attribute:: incidentEdges - // rst: - // rst: (Read-only) A range of incident edges to this vertex. - // rst: - // rst: :type: RuleRightGraphIncidentEdgeRange - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("incidentEdges", &Rule::RightGraph::Vertex::incidentEdges) - // rst: .. py:attribute:: stringLabel - // rst: - // rst: (Read-only) The string label of the vertex. - // rst: - // rst: :type: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("stringLabel", py::make_function(&Rule::RightGraph::Vertex::getStringLabel, py::return_value_policy())) - // rst: .. py:attribute:: atomId - // rst: - // rst: (Read-only) The atom id of the vertex. - // rst: - // rst: :type: AtomId - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("atomId", &Rule::RightGraph::Vertex::getAtomId) - // rst: .. py:attribute:: isotope - // rst: - // rst: (Read-only) The isotope of the vertex. - // rst: - // rst: :type: Isotope - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("isotope", &Rule::RightGraph::Vertex::getIsotope) - // rst: .. py:attribute:: charge - // rst: - // rst: (Read-only) The charge of the vertex. - // rst: - // rst: :type: Charge - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("charge", &Rule::RightGraph::Vertex::getCharge) - // rst: .. py:attribute:: radical + .add_property("radical", &Rule::RightGraph::Vertex::getRadical) + .def("printStereo", printStereoWithoutOptions) + .def("printStereo", printStereoWithOptions) + // rst: .. attribute:: core // rst: - // rst: (Read-only) The radical status of the vertex. + // rst: (Read-only) The descriptor for this vertex in the core graph. // rst: - // rst: :type: bool - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("radical", &Rule::RightGraph::Vertex::getRadical) - // rst: .. py:method:: printStereo() - // rst: printStereo(p) + // rst: :type: Rule.Vertex + .add_property("core", &Rule::RightGraph::Vertex::getCore) + // rst: .. attribute:: rule // rst: - // rst: Print the stereo configuration for the vertex. + // rst: (Read-only) The rule the vertex belongs to. // rst: - // rst: :param GraphPrinter p: the printing options used for the depiction. - // rst: :returns: the name of the PDF-file that will be compiled in post-processing. - // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .def("printStereo", printStereoWithoutOptions) - .def("printStereo", printStereoWithOptions); + // rst: :type: Rule + // rst: :raises: :class:`LogicError` if it is a null descriptor. + .add_property("rule", &Rule::RightGraph::Vertex::getRule); - // rst: .. py:class:: RuleRightGraphEdge + // rst: .. class:: Edge // rst: - // rst: A descriptor of either an edge in a right side, or a null edge. + // rst: A descriptor of either an edge in a right side, or a null edge. + // rst: Implements the :class:`protocols.LabelledGraph.Edge` protocol. // rst: - py::class_("RuleRightGraphEdge", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Edge", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::RightGraph::Edge::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::RightGraph::Edge::isNull) - // rst: .. py:attribute:: graph - // rst: - // rst: (Read-only) The rule the edge belongs to. - // rst: - // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("rule", &Rule::RightGraph::Edge::getRule) - // rst: .. py:attribute:: core - // rst: - // rst: (Read-only) The descriptor for this edge in the core graph. - // rst: - // rst: :type: RuleEdge - .add_property("core", &Rule::RightGraph::Edge::getCore) - // rst: .. py:attribute:: source - // rst: - // rst: (Read-only) The source vertex of the edge. - // rst: - // rst: :type: RuleRightGraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. + .add_property("graph", &Rule::RightGraph::Edge::getGraph) .add_property("source", &Rule::RightGraph::Edge::source) - // rst: .. attribute:: target - // rst: - // rst: (Read-only) The target vertex of the edge. - // rst: - // rst: :type: RuleRightGraphVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("target", &Rule::RightGraph::Edge::target) - // rst: .. py:attribute:: stringLabel - // rst: - // rst: (Read-only) The string label of the edge. - // rst: - // rst: :type: str - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("stringLabel", py::make_function(&Rule::RightGraph::Edge::getStringLabel, py::return_value_policy())) - // rst: .. py:attribute:: bondType + .add_property("bondType", &Rule::RightGraph::Edge::getBondType) + // rst: .. attribute:: core // rst: - // rst: (Read-only) The bond type of the edge. + // rst: (Read-only) The descriptor for this edge in the core graph. // rst: - // rst: :type: BondType - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("bondType", &Rule::RightGraph::Edge::getBondType); + // rst: :type: Rule.Edge + .add_property("core", &Rule::RightGraph::Edge::getCore) + // rst: .. attribute:: rule + // rst: + // rst: (Read-only) The rule the edge belongs to. + // rst: + // rst: :type: Rule + // rst: :raises: :class:`LogicError` if it is a null descriptor. + .add_property("rule", &Rule::RightGraph::Edge::getRule); - py::class_("RuleRightGraphVertexRange", py::no_init) + // rst: .. class:: VertexRange + // rst: + // rst: Implements the :class:`protocols.Graph.VertexRange` protocol. + // rst: + py::class_("VertexRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleRightGraphEdgeRange", py::no_init) + // rst: .. class:: EdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.EdgeRange` protocol. + // rst: + py::class_("EdgeRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleRightGraphIncidentEdgeRange", py::no_init) + // rst: .. class:: IncidentEdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.IncidentEdgeRange` protocol. + // rst: + py::class_("IncidentEdgeRange", py::no_init) .def("__iter__", py::iterator()); } void exportCore() { - // rst: .. py:class:: RuleVertex + py::object ruleObj = py::scope().attr("Rule"); + py::scope ruleScope = ruleObj; + + // rst: .. class:: Rule.Vertex // rst: - // rst: A descriptor of either a vertex in a rule, or a null vertex. + // rst: Implements the :class:`protocols.Graph.Vertex` protocol. + // rst: Additionally, the :attr:`id ` is in the range :math:`[0, numVertices[`. // rst: - py::class_("RuleVertex", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Vertex", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) .def("__hash__", &Rule::Vertex::hash) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::Vertex::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::Vertex::isNull) - // rst: .. py:attribute:: id - // rst: - // rst: (Read-only) The index of the vertex. It will be in the range :math:`[0, numVertices[`. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("id", &Rule::Vertex::getId) - // rst: .. py:attribute:: rule + .add_property("graph", &Rule::Vertex::getGraph) + .add_property("degree", &Rule::Vertex::getDegree) + .add_property("incidentEdges", &Rule::Vertex::incidentEdges) + // rst: .. attribute:: rule // rst: - // rst: (Read-only) The rule the vertex belongs to. + // rst: An alias for :attr:`protocols.Graph.Vertex.graph`. // rst: // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("rule", &Rule::Vertex::getRule) - // rst: .. py:attribute:: left + // rst: .. attribute:: left // rst: // rst: (Read-only) A null descriptor if this vertex is not in the left graph, // rst: otherwise the descriptor of this vertex in the left graph. + // rst: + // rst: :type: LeftGraph.Vertex .add_property("left", &Rule::Vertex::getLeft) - // rst: .. py:attribute:: context + // rst: .. attribute:: context // rst: // rst: (Read-only) A null descriptor if this vertex is not in the context graph, // rst: otherwise the descriptor of this vertex in the context graph. + // rst: + // rst: :type: ContextGraph.Vertex .add_property("context", &Rule::Vertex::getContext) - // rst: .. py:attribute:: right + // rst: .. attribute:: right // rst: // rst: (Read-only) A null descriptor if this vertex is not in the right graph, // rst: otherwise the descriptor of this vertex in the right graph. - .add_property("right", &Rule::Vertex::getRight) - // rst: .. py:attribute:: degree - // rst: - // rst: (Read-only) The degree of the vertex. - // rst: - // rst: :type: int - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("degree", &Rule::Vertex::getDegree) - // rst: .. py:attribute:: incidentEdges - // rst: - // rst: (Read-only) A range of incident edges to this vertex. // rst: - // rst: :type: RuleIncidentEdgeRange - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("incidentEdges", &Rule::Vertex::incidentEdges) - // rst: .. py:method:: get2DX(withHydrogens=True) + // rst: :type: RightGraph.Vertex + .add_property("right", &Rule::Vertex::getRight) + // rst: .. method:: get2DX(withHydrogens=True) // rst: // rst: :returns: the x-coordinate in a 2D depiction of the rule. - // rst: Different sets of coordinates exists for rendering with and wihout certain hydrogens. + // rst: Different sets of coordinates exists for rendering with and without certain hydrogens. // rst: :rtype: float - // rst: :raises: :py:class:`LogicError` if it is a null descriptor, or + // rst: :raises: :class:`LogicError` if it is a null descriptor, or // rst: if ``withHydrogens`` is ``True`` and the vertex is a "clean" hydrogen. .def("get2DX", &Rule::Vertex::get2DX, py::arg("withHydrogens") = true) - // rst: .. py:method:: get2DY(withHydrogens=True) + // rst: .. method:: get2DY(withHydrogens=True) // rst: // rst: :returns: the y-coordinate in a 2D depiction of the rule. - // rst: Different sets of coordinates exists for rendering with and wihout certain hydrogens. + // rst: Different sets of coordinates exists for rendering with and without certain hydrogens. // rst: :rtype: float - // rst: :raises: :py:class:`LogicError` if it is a null descriptor, or + // rst: :raises: :class:`LogicError` if it is a null descriptor, or // rst: if ``withHydrogens`` is ``True`` and the vertex is a "clean" hydrogen. .def("get2DY", &Rule::Vertex::get2DY, py::arg("withHydrogens") = true); - // rst: .. py:class:: RuleEdge + // rst: .. class:: Rule.Edge // rst: - // rst: A descriptor of either an edge in a rule, or a null edge. + // rst: Implements the :class:`protocols.Graph.Edge` protocol. // rst: - py::class_("RuleEdge", py::no_init) - // rst: .. py:function:: __init__(self) - // rst: - // rst: Constructs a null descriptor. + py::class_("Edge", py::no_init) .def(py::init<>()) .def(str(py::self)) .def(py::self == py::self) .def(py::self != py::self) .def(py::self < py::self) - // rst: .. py::method:: __bool__(self) - // rst: - // rst: :returns: ``not isNull()`` - // rst: :rtype: bool .def("__bool__", &Rule::Edge::operator bool) - // rst: .. py:method:: isNull() - // rst: - // rst: :returns: whether this is a null descriptor or not. - // rst: :rtype: bool .def("isNull", &Rule::Edge::isNull) - // rst: .. py:attribute:: rule + .add_property("graph", &Rule::Edge::getGraph) + .add_property("source", &Rule::Edge::source) + .add_property("target", &Rule::Edge::target) + // rst: .. attribute:: rule // rst: - // rst: (Read-only) The rule the edge belongs to. + // rst: An alias for :attr:`protocols.Graph.Edge.graph`. // rst: // rst: :type: Rule - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. .add_property("rule", &Rule::Edge::getRule) - // rst: .. py:attribute:: left + // rst: .. attribute:: left // rst: // rst: (Read-only) A null descriptor if this edge is not in the left graph, // rst: otherwise the descriptor of this edge in the left graph. + // rst: + // rst: :type: LeftGraph.Edge .add_property("left", &Rule::Edge::getLeft) - // rst: .. py:attribute:: context + // rst: .. attribute:: context // rst: // rst: (Read-only) A null descriptor if this edge is not in the context graph, // rst: otherwise the descriptor of this edge in the context graph. + // rst: + // rst: :type: ContextGraph.Edge .add_property("context", &Rule::Edge::getContext) - // rst: .. py:attribute:: right + // rst: .. attribute:: right // rst: // rst: (Read-only) A null descriptor if this edge is not in the right graph, // rst: otherwise the descriptor of this edge in the right graph. - .add_property("right", &Rule::Edge::getRight) - // rst: .. py:attribute:: source // rst: - // rst: (Read-only) The source vertex of the edge. - // rst: - // rst: :type: RuleVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("source", &Rule::Edge::source) - // rst: .. attribute:: target - // rst: - // rst: (Read-only) The target vertex of the edge. - // rst: - // rst: :type: RuleVertex - // rst: :raises: :py:class:`LogicError` if it is a null descriptor. - .add_property("target", &Rule::Edge::target); + // rst: :type: RightGraph.Edge + .add_property("right", &Rule::Edge::getRight); - py::class_("RuleVertexRange", py::no_init) + // rst: .. class:: Rule.VertexRange + // rst: + // rst: Implements the :class:`protocols.Graph.VertexRange` protocol, + // rst: in addition to the following functionality. + // rst: + py::class_("VertexRange", py::no_init) .def("__iter__", py::iterator()) + // rst: .. method:: __getitem__(i) + // rst: + // rst: :returns: the ``i``\ th vertex of the graph. + // rst: :rtype: Rule.Vertex .def("__getitem__", &Rule::VertexRange::operator[]); - py::class_("RuleEdgeRange", py::no_init) + // rst: .. class:: Rule.EdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.EdgeRange` protocol. + // rst: + py::class_("EdgeRange", py::no_init) .def("__iter__", py::iterator()); - py::class_("RuleIncidentEdgeRange", py::no_init) + // rst: .. class:: Rule.IncidentEdgeRange + // rst: + // rst: Implements the :class:`protocols.Graph.IncidentEdgeRange` protocol. + // rst: + py::class_("IncidentEdgeRange", py::no_init) .def("__iter__", py::iterator()); } @@ -772,6 +504,4 @@ void GraphInterface_doExport() { exportCore(); } -} // namespace Py -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule::Py \ No newline at end of file diff --git a/libs/pymod/src/mod/py/rule/Rule.cpp b/libs/pymod/src/mod/py/rule/Rule.cpp index 66056e1..6211b7e 100644 --- a/libs/pymod/src/mod/py/rule/Rule.cpp +++ b/libs/pymod/src/mod/py/rule/Rule.cpp @@ -4,9 +4,7 @@ #include #include -namespace mod { -namespace rule { -namespace Py { +namespace mod::rule::Py { namespace { py::object getLabelType(std::shared_ptr r) { @@ -22,12 +20,22 @@ void Rule_doExport() { std::pair(Rule::* printWithOptions)(const graph::Printer&, const graph::Printer&) const = &Rule::print; - // rst: .. py:class:: Rule + // rst: .. class:: Rule // rst: - // rst: Model of a transformation rule in the Double Pushout formalism. + // rst: Model of a transformation rule in the Double Pushout formalism, + // rst: as the span :math:`L \leftarrow K \rightarrow R`. + // rst: The three graphs are referred to as respectively + // rst: the "left", "context", and "right" graphs of the rule. + // rst: + // rst: The class implements the :class:`protocols.Graph` protocol, + // rst: which gives access to a graph view of the rule which has the left, context, and right graphs + // rst: combined into a single graph, called the core graph. + // rst: In addition to the combined graph view that this claas offers, + // rst: there are also three graph views representing the :attr:`left`, :attr:`context` + // rst: See :ref:`py-Rule/GraphInterface` for details of how to use these four graph interfaces. // rst: py::class_, boost::noncopyable>("Rule", py::no_init) - // rst: .. py:attribute:: id + // rst: .. attribute:: id // rst: // rst: (Read-only) The unique instance id among all :class:`Rule` instances. // rst: @@ -35,56 +43,37 @@ void Rule_doExport() { .add_property("id", &Rule::getId) .def(str(py::self)) //------------------------------------------------------------------ - // rst: .. py:attribute:: numVertices - // rst: - // rst: (Read-only) The number of vertices in the rule. - // rst: - // rst: :type: int + // Graph .add_property("numVertices", &Rule::numVertices) - // rst: .. py:attribute:: vertices - // rst: - // rst: (Read-only) An iterable of all vertices in the rule. - // rst: - // rst: :type: RuleVertexRange .add_property("vertices", &Rule::vertices) - // rst: .. py:attribute:: numEdges - // rst: - // rst: (Read-only) The number of edges in the rule. - // rst: - // rst: :type: int .add_property("numEdges", &Rule::numEdges) - // rst: .. py:attribute:: edges - // rst: - // rst: (Read-only) An iterable of all edges in the rule. - // rst: - // rst: :type: RuleEdgeRange .add_property("edges", &Rule::edges) - // rst: .. py:attribute:: left + // rst: .. attribute:: left // rst: // rst: (Read-only) A proxy object representing the left graph of the rule. // rst: - // rst: :type: RuleLeftGraph + // rst: :type: LeftGraph .add_property("left", &Rule::getLeft) - // rst: .. py:attribute:: context + // rst: .. attribute:: context // rst: // rst: (Read-only) A proxy object representing the context graph of the rule. // rst: - // rst: :type: RuleContextGraph + // rst: :type: ContextGraph .add_property("context", &Rule::getContext) - // rst: .. py:attribute:: right + // rst: .. attribute:: right // rst: // rst: (Read-only) A proxy object representing the right graph of the rule. // rst: - // rst: :type: RuleRightGraph + // rst: :type: RightGraph .add_property("right", &Rule::getRight) //------------------------------------------------------------------ - // rst: .. py:method:: makeInverse() + // rst: .. method:: makeInverse() // rst: // rst: :returns: a rule representing the inversion of this rule. // rst: :rtype: Rule // rst: :raises: :class:`LogicError` if inversion is not possible (due to matching constraints). .def("makeInverse", &Rule::makeInverse) - // rst: .. py:method:: print() + // rst: .. method:: print() // rst: print(first, second=None) // rst: // rst: Print the rule, using either the default options or the options in ``first`` and ``second``. @@ -100,54 +89,54 @@ void Rule_doExport() { // rst: :rtype: tuple[str, str] .def("print", printWithoutOptions) .def("print", printWithOptions) - // rst: .. py:method:: printTermState + // rst: .. method:: printTermState // rst: // rst: Print the term state for the rule. .def("printTermState", &Rule::printTermState) - // rst: .. py:method:: getGMLString(withCoords=False) + // rst: .. method:: getGMLString(withCoords=False) // rst: // rst: :returns: the :ref:`GML ` representation of the rule, // rst: optionally with generated 2D coordinates. // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` when coordinates are requested, but + // rst: :raises: :class:`LogicError` when coordinates are requested, but // rst: none can be generated. .def("getGMLString", &Rule::getGMLString) - // rst: .. py:method:: printGML(withCoords=False) + // rst: .. method:: printGML(withCoords=False) // rst: // rst: Print the rule in :ref:`GML ` format, // rst: optionally with generated 2D coordinates. // rst: // rst: :returns: the filename of the printed GML file. // rst: :rtype: str - // rst: :raises: :py:class:`LogicError` when coordinates are requested, but + // rst: :raises: :class:`LogicError` when coordinates are requested, but // rst: none can be generated. .def("printGML", &Rule::printGML) - // rst: .. py:attribute:: name + // rst: .. attribute:: name // rst: // rst: The name of the rule. The default name includes the unique instance id. // rst: // rst: :type: str .add_property("name", py::make_function(&Rule::getName, py::return_value_policy()), &Rule::setName) - // rst: .. py:attribute:: labelType + // rst: .. attribute:: labelType // rst: // rst: (Read-only) The intended label type for this rule, or None if no specific label type is intended. // rst: // rst: :type: LabelType .add_property("labelType", &getLabelType) - // rst: .. py:attribute:: numLeftComponents + // rst: .. attribute:: numLeftComponents // rst: // rst: (Read-only) The number of connected components of the left graph. // rst: // rst: :type: :cpp:type:`std::size_t` .add_property("numLeftComponents", &Rule::getNumLeftComponents) - // rst: .. py:attribute:: numRightComponents + // rst: .. attribute:: numRightComponents // rst: // rst: (Read-only) The number of connected components of the right graph. // rst: // rst: :type: :cpp:type:`std::size_t` .add_property("numRightComponents", &Rule::getNumRightComponents) - // rst: .. py:method:: isomorphism(other, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) + // rst: .. method:: isomorphism(other, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) // rst: // rst: :param Rule other: the other :class:`Rule` for comparison. // rst: :param int maxNumMatches: the maximum number of isomorphisms to search for. @@ -155,7 +144,7 @@ void Rule_doExport() { // rst: :returns: the number of isomorphisms found between ``other`` and this rule, but at most ``maxNumMatches``. // rst: :rtype: int .def("isomorphism", &Rule::isomorphism) - // rst: .. py:method:: monomorphism(host, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) + // rst: .. method:: monomorphism(host, maxNumMatches=1, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) // rst: // rst: :param Rule host: the host :class:`Rule` to check for subgraphs. // rst: :param int maxNumMatches: the maximum number of morphisms to search for. @@ -163,7 +152,7 @@ void Rule_doExport() { // rst: :returns: the number of monomorphisms from this rule to subgraphs of ``host``, though at most ``maxNumMatches``. // rst: :rtype: int .def("monomorphism", &Rule::monomorphism) - // rst: .. py:method:: isomorphicLeftRight(other, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) + // rst: .. method:: isomorphicLeftRight(other, labelSettings=LabelSettings(LabelType.String, LabelRelation.Isomorphism)) // rst: // rst: :param Rule other: the other :class:`Rule` for comparison. // rst: :param LabelSettings labelSettings: the label settings to use during the search. @@ -171,7 +160,7 @@ void Rule_doExport() { // rst: :rtype: bool .def("isomorphicLeftRight", &Rule::isomorphicLeftRight, (py::arg("labelSettings") = LabelSettings(LabelType::String, LabelRelation::Isomorphism))) - // rst: .. py:method:: getVertexFromExternalId(id) + // rst: .. method:: getVertexFromExternalId(id) // rst: // rst: If the rule was not loaded from an external data format, then this function // rst: always return a null descriptor. @@ -181,28 +170,28 @@ void Rule_doExport() { // rst: :param int id: the external id to find the vertex descriptor for. // rst: :returns: the vertex descriptor for the given external id. // rst: The descriptor is null if the external id was not used. - // rst: :rtype: RuleVertex + // rst: :rtype: Vertex .def("getVertexFromExternalId", &Rule::getVertexFromExternalId) - // rst: .. py:attribute:: minExternalId + // rst: .. attribute:: minExternalId // rst: maxExternalId // rst: // rst: If the rule was not loaded from an external data format, then these attributes // rst: are always return 0. Otherwise, they are the minimum/maximum external id from which - // rst: non-null vertices can be obtained from :py:meth:`getVertexFromExternalId`. + // rst: non-null vertices can be obtained from :meth:`getVertexFromExternalId`. // rst: If no such minimum and maximum exists, then they are 0. // rst: // rst: :type: int .add_property("minExternalId", &Rule::getMinExternalId) .add_property("maxExternalId", &Rule::getMaxExternalId); - // rst: .. py:data:: inputRules + // rst: .. data:: inputRules // rst: // rst: A list of rules to which explicitly loaded rules as default are appended. // rst: // rst: :type: list[Rule] // rst: - // rst: .. py:method:: ruleGMLString(s, invert=False, add=True) + // rst: .. method:: ruleGMLString(s, invert=False, add=True) // rst: // rst: Load a rule from a :ref:`GML ` string, and maybe store it in a global list. // rst: The name of the rule is the one specified in the GML string, though when ``invert=True`` @@ -219,9 +208,9 @@ void Rule_doExport() { // rst: :returns: the rule in the GML string, possibly inverted. // rst: :rtype: Rule py::def("ruleGMLString", &Rule::ruleGMLString); - // rst: .. py:method:: ruleGML(f, invert=False, add=True) + // rst: .. method:: ruleGML(f, invert=False, add=True) // rst: - // rst: Read ``file`` and pass the contents to :py:func:`ruleGMLString`. + // rst: Read ``file`` and pass the contents to :func:`ruleGMLString`. // rst: // rst: :param str f: name of the GML file to be loaded. // rst: :param bool invert: whether or not to invert the loaded rule. @@ -231,6 +220,4 @@ void Rule_doExport() { py::def("ruleGML", &Rule::ruleGML); } -} // namespace Py -} // namespace rule -} // namespace mod \ No newline at end of file +} // namespace mod::rule::Py \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 8ac6eef..9ca9306 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -r requirements_nodoc.txt -sphinx>=3.2 +sphinx>=3.4 diff --git a/requirements_dev.txt b/requirements_dev.txt new file mode 100644 index 0000000..463a0ee --- /dev/null +++ b/requirements_dev.txt @@ -0,0 +1,3 @@ +-r requirements.txt +mypy +flake8 diff --git a/requirements_nodoc.txt b/requirements_nodoc.txt index 947aece..27092a3 100644 --- a/requirements_nodoc.txt +++ b/requirements_nodoc.txt @@ -1,4 +1,5 @@ bindep ipython -networkx -parse +networkx # epim +parse # epim +typing_extensions # remove when Python 3.7 can be assumed diff --git a/scripts/checkJsonVisibility.sh b/scripts/checkJsonVisibility.sh new file mode 100755 index 0000000..ea0584b --- /dev/null +++ b/scripts/checkJsonVisibility.sh @@ -0,0 +1,15 @@ +#!/bin/bash +root=$(git rev-parse --show-toplevel) +cd $root/libs +grep -Rn '#include.*nlohman' &> /dev/null +if [ $? -ne 0 ]; then + echo "grep failed:" + grep -Rn '#include.*nlohman' +fi +grep -Rn '#include.*nlohmann' | grep -v "^libmod/src/mod/lib/IO/JsonUtils.hpp" &> /dev/null +if [ $? -eq 0 ]; then + echo "nlohmann json(_schema) may only be included via ibmod/src/mod/lib/IO/JsonUtils.hpp" + echo "Found these other instances:" + grep -Rn '#include.*nlohmann' | grep -v "^libmod/src/mod/lib/IO/JsonUtils.hpp" + exit 1 +fi diff --git a/scripts/flake8.sh b/scripts/flake8.sh new file mode 100755 index 0000000..8e2e007 --- /dev/null +++ b/scripts/flake8.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Create an "installation" of the Python parts by symlinking them into +# build/checkPython/mod, and then run the Python tools. +root=$(git rev-parse --show-toplevel) +res=$? +if [ $res -ne 0 ]; then + exit $res +fi +cd $root +mkdir -p build/checkPython/mod +rm build/checkPython/mod/* +for f in $(ls libs/pymod/lib/mod); do + ln -s -T ../../../libs/pymod/lib/mod/$f build/checkPython/mod/$f +done +ln -s -T ../../../libs/epim/lib/mod/epim build/checkPython/mod/epim + +flake8 \ + --ignore W191,W503,E124,E127,E128 \ + --exclude "*/mod/__init__.py" \ + build/checkPython/mod diff --git a/jla_build.sh b/scripts/jla_build.sh similarity index 90% rename from jla_build.sh rename to scripts/jla_build.sh index 2f64256..123b7d0 100755 --- a/jla_build.sh +++ b/scripts/jla_build.sh @@ -1,6 +1,7 @@ #!/bin/bash export AS_RLIMIT=300000000 -root_PWD=$(pwd) +root=$(git rev-parse --show-toplevel) +cd $root numThreads=2 prefix="../stage" type="OptDebug" @@ -37,7 +38,7 @@ args+=" -DBUILD_TESTING=on" args+=" -DCMAKE_PREFIX_PATH=$HOME/programs" args+=" -DBOOST_ROOT=$HOME/programs" args+=" -DCMAKE_MODULE_LINKER_FLAGS='-flto=$numThreads'" -args+=" -DCMAKE_SHARED_LINKER_FLAGS='-flto=$numThreads'" +args+=" -DCMAKE_SHARED_LINKER_FLAGS='-flto=$numThreads'" args+=" -DCMAKE_INSTALL_PREFIX=$prefix $@" ./bootstrap.sh \ diff --git a/scripts/makeConda.sh b/scripts/makeConda.sh new file mode 100755 index 0000000..27eb1cc --- /dev/null +++ b/scripts/makeConda.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -e +root=$(git rev-parse --show-toplevel) +cd $root + +version=$(cat VERSION | tr -d '\n') +iBuild=mod-conda:$version +iExtract=mod-conda-extract-$version + +#cd build && rm mod-*.tar.gz && make dist && cd .. +docker build -t $iBuild -f conda/build.Dockerfile --build-arg version=$version . +docker create --name $iExtract $iBuild +rm -rf ./conda/conda-bld +docker cp $iExtract:/opt/conda-bld ./conda/conda-bld +docker rm $iExtract diff --git a/scripts/makeDepGraph.sh b/scripts/makeDepGraph.sh new file mode 100755 index 0000000..8324869 --- /dev/null +++ b/scripts/makeDepGraph.sh @@ -0,0 +1,9 @@ +#!/bin/bash +root=$(git rev-parse --show-toplevel) +res=$? +if [ $res -ne 0 ]; then + exit $res +fi +cd $root +python3 scripts/printDepGraph.py > depGraph.dot +dot -Tpdf -o depGraph.pdf depGraph.dot diff --git a/scripts/makeDocker.sh b/scripts/makeDocker.sh new file mode 100755 index 0000000..7482482 --- /dev/null +++ b/scripts/makeDocker.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +root=$(git rev-parse --show-toplevel) +cd $root +version=$(cat VERSION | tr -d '\n') +imageName="jakobandersen/mod:$version" +#cd build && rm mod-*.tar.gz && make dist && cd .. +docker build -t $imageName -f docker/Ubuntu.Dockerfile . +docker tag $imageName jakobandersen/mod:latest +echo "The docker image is $imageName" +echo "The image has been tagged with jakobandersen/mod:latest" diff --git a/scripts/mypy.sh b/scripts/mypy.sh new file mode 100755 index 0000000..24adf3c --- /dev/null +++ b/scripts/mypy.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Create an "installation" of the Python parts by symlinking them into +# build/checkPython/mod, and then run the Python tools. +root=$(git rev-parse --show-toplevel) +res=$? +if [ $res -ne 0 ]; then + exit $res +fi +cd $root +mkdir -p build/checkPython/mod +rm build/checkPython/mod/* +for f in $(ls libs/pymod/lib/mod); do + ln -s -T ../../../libs/pymod/lib/mod/$f build/checkPython/mod/$f +done +ln -s -T ../../../libs/epim/lib/mod/epim build/checkPython/mod/epim + +mypy \ + --warn-redundant-casts \ + --warn-unused-ignores \ + build/checkPython/mod diff --git a/scripts/printDepGraph.py b/scripts/printDepGraph.py new file mode 100644 index 0000000..9365596 --- /dev/null +++ b/scripts/printDepGraph.py @@ -0,0 +1,112 @@ +import os +import sys + +def clusterComponentFromFilename(f): + cs = f.split("/") + if "." in cs[-1]: + cs.pop() + assert cs[0] == 'mod' + if len(cs) == 1: + return 'interface', cs[0] + cs = cs[1:] + if len(cs) == 1: + if cs[0] == 'lib': + return 'lib', 'lib' + if cs[0] == 'internal': + return 'internal', 'internal' + return 'interface', cs[0] + if cs[1] == 'internal': + return 'internal', cs[0] + return cs[0], cs[1] + +mods = set() +deps = {} + +try: + os.chdir("libs/libmod/src") +except FileNotFoundError as e: + print(e) + print("Run from the root of the repository.") + sys.exit(1) +for root, dirs, files in os.walk("mod"): + mod = clusterComponentFromFilename(root) + mods.add(mod) + if mod not in deps: + deps[mod] = {} + for file_ in files: + fName = os.path.join(root, file_) + with open(fName) as f: + for line in f: + if not line.startswith("#include ") + line = line[first:last] + depMod = clusterComponentFromFilename(line) + mods.add(depMod) + if depMod not in deps[mod]: + deps[mod][depMod] = 0 + deps[mod][depMod] += 1 + +utilMods = ( + ('interface', 'mod'), + ('lib', 'lib'), + ('lib', 'Chem'), + ('lib', 'IO'), +) +clusterColour = { + 'interface': 'green', + 'internal': 'orange', + 'lib': 'blue', +} + +def printNode(mod): + print('\t"{}/{}" [ label="{}" ];'.format(mod[0], mod[1], mod[1])) +def ignoreEdge(mod, depMod): + if mod in utilMods: + return 'util' + if depMod in utilMods: + return 'util' + return 'dep' +def printEdge(mod, depMod, count, indent=False): + if depMod == mod: + return + options = "" + ignore = ignoreEdge(mod, depMod) + if ignore == 'util': + options += " constraint=false color=gray style=solid" + return + if ignore == 'deprecated': + options += " constraint=false color=gray style=dashed" + print('{}"{}/{}" -> "{}/{}" [ label="{}"{} ];'.format( + "\t" if indent else "", + mod[0], mod[1], depMod[0], depMod[1], count, options)) +def makeCluster(cluster): + print("subgraph cluster_{} {{\n\tcolor={};".format( + cluster, clusterColour[cluster])) + print("\tlabel = \"{}\";".format(cluster)) + for mod in mods: + if mod[0] == cluster: + printNode(mod) + for mod, data in deps.items(): + if mod[0] != cluster: + continue + for depMod, count in data.items(): + if depMod[0] != cluster: + continue + printEdge(mod, depMod, count, True) + print("}") + +print('''digraph g { +rankdir="LR" +node [ shape=box ]; +''') +makeCluster("lib") +makeCluster("interface" ) +makeCluster("internal") +for mod, data in deps.items(): + for depMod, count in data.items(): + if mod[0] == depMod[0]: + continue + printEdge(mod, depMod, count) +print("}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d934126..92c8894 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,11 @@ if(NOT TARGET tests) add_custom_target(tests) endif() -set(sanFlags -g -fsanitize=undefined -fsanitize=address -fsanitize=leak) +if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xAppleClang") + set(sanFlags -g -fsanitize=undefined -fsanitize=address) +else() + set(sanFlags -g -fsanitize=undefined -fsanitize=address -fsanitize=leak) +endif() foreach(fileName ${mod_TEST_CPP_FILES}) string(REPLACE "/" "__" testName "${fileName}") set(workDir ${CMAKE_CURRENT_BINARY_DIR}/workDir/${testName}) @@ -28,20 +32,9 @@ foreach(fileName ${mod_TEST_CPP_FILES}) endforeach() if(BUILD_PY_MOD) - function(make_py_test testName extraEnv) - set(workDir ${CMAKE_CURRENT_BINARY_DIR}/workDir/${testName}) - file(MAKE_DIRECTORY ${workDir}) - add_test(NAME ${testName} - COMMAND ${CMAKE_INSTALL_FULL_BINDIR}/mod -f ${CMAKE_CURRENT_LIST_DIR}/${fileName}.py - WORKING_DIRECTORY ${workDir}) - set_tests_properties(${testName} PROPERTIES - ENVIRONMENT "MOD_NUM_POST_THREADS=1${extraEnv}") - add_coverage_case(${testName}) - endfunction() - foreach(fileName ${mod_TEST_PY_FILES}) string(REPLACE "/" "__" testName "${fileName}") - make_py_test(${testName} "") + make_py_test(${fileName} ${testName} "") endforeach() endif() diff --git a/test/cpp/Chem.cpp b/test/cpp/Chem.cpp new file mode 100644 index 0000000..e79d9a3 --- /dev/null +++ b/test/cpp/Chem.cpp @@ -0,0 +1,24 @@ +#include + +#include + +#include + +using namespace mod; + +template +void check() { + BOOST_CONCEPT_ASSERT((boost::DefaultConstructible)); + BOOST_CONCEPT_ASSERT((boost::CopyConstructible)); + BOOST_CONCEPT_ASSERT((boost::Assignable)); + BOOST_CONCEPT_ASSERT((boost::EqualityComparable)); + BOOST_CONCEPT_ASSERT((boost::LessThanComparable)); +} + +int main() { + check(); + check(); + check(); + check(); + check(); +} \ No newline at end of file diff --git a/test/cpp/Function.cpp b/test/cpp/Function.cpp new file mode 100644 index 0000000..a7c1fa4 --- /dev/null +++ b/test/cpp/Function.cpp @@ -0,0 +1,8 @@ +#include + +int main() { + std::function f = []() { + }; + auto a = mod::fromStdFunction(f); + auto b = mod::fromStdFunction("test", f); +} \ No newline at end of file diff --git a/test/cpp/graph/graphInterface.cpp b/test/cpp/graph/graphInterface.cpp new file mode 100644 index 0000000..a95ea33 --- /dev/null +++ b/test/cpp/graph/graphInterface.cpp @@ -0,0 +1,9 @@ + +#include +#include + +#include + +int main() { + BOOST_CONCEPT_ASSERT((mod::concepts::LabelledGraph)); +} \ No newline at end of file diff --git a/test/cpp/graph/union.cpp b/test/cpp/graph/union.cpp new file mode 100644 index 0000000..e62a265 --- /dev/null +++ b/test/cpp/graph/union.cpp @@ -0,0 +1,9 @@ + +#include +#include + +#include + +int main() { + BOOST_CONCEPT_ASSERT((mod::concepts::LabelledGraph)); +} \ No newline at end of file diff --git a/test/cpp/rule/graphInterface.cpp b/test/cpp/rule/graphInterface.cpp new file mode 100644 index 0000000..a9fc1b2 --- /dev/null +++ b/test/cpp/rule/graphInterface.cpp @@ -0,0 +1,12 @@ + +#include +#include + +#include + +int main() { + BOOST_CONCEPT_ASSERT((mod::concepts::Graph)); + BOOST_CONCEPT_ASSERT((mod::concepts::LabelledGraph)); + BOOST_CONCEPT_ASSERT((mod::concepts::Graph)); + BOOST_CONCEPT_ASSERT((mod::concepts::LabelledGraph)); +} \ No newline at end of file diff --git a/test/py/chem.py b/test/py/chem.py index 9f2e508..e50669d 100644 --- a/test/py/chem.py +++ b/test/py/chem.py @@ -32,6 +32,9 @@ assert v.charge == a.charge assert v.radical == a.radical +assert AtomData() < AtomData(AtomId(1)) +assert AtomData(AtomId(1)) > AtomData() + print("BondType\n----------") for a in [BondType.Invalid, BondType.Single, BondType.Aromatic, BondType.Double, BondType.Triple]: print(repr(a)) diff --git a/test/py/dg/030_build_apply.py b/test/py/dg/030_build_apply.py index 6968d46..4cabe45 100644 --- a/test/py/dg/030_build_apply.py +++ b/test/py/dg/030_build_apply.py @@ -22,6 +22,8 @@ dg = DG(graphDatabase=[a, b, c]) with dg.build() as builder: + print("Apply") + print("=" * 60) res = builder.apply([a], r) assert len(res) == 3 for e in res: @@ -31,6 +33,8 @@ ts = [next(iter(e.targets)).graph for e in res] assert ts == [b, c, b] + print("Assume confluecnce") + print("=" * 60) config.dg.applyAssumeConfluence = True res = builder.apply([a], r) config.dg.applyAssumeConfluence = False @@ -42,10 +46,14 @@ ts = [next(iter(e.targets)).graph for e in res] assert ts == [b] + print("Limit 0") + print("=" * 60) config.dg.applyLimit = 0 res = builder.apply([a], r) assert len(res) == 0 + print("Limit 1") + print("=" * 60) config.dg.applyLimit = 1 res = builder.apply([a], r) assert len(res) == 1 @@ -56,6 +64,8 @@ ts = [next(iter(e.targets)).graph for e in res] assert ts == [b] + print("Limit 2") + print("=" * 60) config.dg.applyLimit = 2 res = builder.apply([a], r) assert len(res) == 2 @@ -66,6 +76,8 @@ ts = [next(iter(e.targets)).graph for e in res] assert ts == [b, c] + print("Limit 3") + print("=" * 60) config.dg.applyLimit = 3 res = builder.apply([a], r) assert len(res) == 3 @@ -76,6 +88,8 @@ ts = [next(iter(e.targets)).graph for e in res] assert ts == [b, c, b] + print("Limit 4") + print("=" * 60) config.dg.applyLimit = 4 res = builder.apply([a], r) assert len(res) == 3 @@ -86,7 +100,102 @@ ts = [next(iter(e.targets)).graph for e in res] assert ts == [b, c, b] + config.dg.applyLimit = -1 + for verbosity in (2, 10, 20): print("Verbosity:", verbosity) print("#" * 80) builder.apply([a], r, verbosity=verbosity) + + +print("Multiple components, different") +print("=" * 60) + +gO = smiles('[O]', "gO") +gC = smiles('[C]', "gC") +gOC = smiles('[O][C]', "gOC") + +r = ruleGMLString("""rule [ + ruleID "Connect O C" + context [ + node [ id 0 label "O" ] + node [ id 1 label "C" ] + ] + right [ + edge [ source 0 target 1 label "-" ] + ] +]""") + +dg = DG(graphDatabase=[gO, gC, gOC]) +with dg.build() as builder: + res = builder.apply([gO, gC], r, verbosity=4) + assert len(res) == 1 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([gO, gC]) + assert e.numTargets == 1 + ts = [next(iter(e.targets)).graph for e in res] + assert ts == [gOC] + + res = builder.apply([gO, gC, gC], r, verbosity=4) + assert len(res) == 0 + + +print("Multiple components, same") +print("=" * 60) + +gO = smiles('[O]', "gO") +gOO = smiles('[O][O]', "gOO") + +r = ruleGMLString("""rule [ + ruleID "Connect O O" + context [ + node [ id 0 label "O" ] + node [ id 1 label "O" ] + ] + right [ + edge [ source 0 target 1 label "-" ] + ] +]""") + +dg = DG(graphDatabase=[gO, gOO]) +with dg.build() as builder: + res = builder.apply([gO, gO], r, verbosity=4) + assert len(res) == 1 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([gO, gO]) + assert e.numTargets == 1 + ts = [next(iter(e.targets)).graph for e in res] + assert ts == [gOO] + + res = builder.apply([gO], r, verbosity=4) + assert len(res) == 0 + + +print("Split to isomorphic") +print("=" * 60) + +r = ruleGMLString("""rule [ + ruleID "Split to isomorphms" + left [ + edge [ source 1 target 2 label "-" ] + ] + context [ + node [ id 1 label "Q" ] + node [ id 2 label "Q" ] + ] +]""") +g1 = graphDFS("[Q][Q]", "QQ") +g2 = graphDFS("[Q]", "Q") + +dg = DG(graphDatabase=[g1, g2]) +with dg.build() as builder: + res = builder.apply([g1], r, verbosity=4) + assert len(res) == 2 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([g1]) + assert e.numTargets == 2 + ts = [v.graph for v in e.targets] + assert ts == [g2, g2] diff --git a/test/py/dg/035_build_apply_nonProper.py b/test/py/dg/035_build_apply_nonProper.py new file mode 100644 index 0000000..b8a4818 --- /dev/null +++ b/test/py/dg/035_build_apply_nonProper.py @@ -0,0 +1,138 @@ +include("xx0_helpers.py") + +a = smiles("[C][C][C]", name="ga") +b = smiles("[O][C][C]") +c = smiles("[C][O][C]") +aa = smiles("[C][C][C]", name="gaa") + +r = ruleGMLString("""rule [ + left [ + node [ id 0 label "C" ] + ] + right [ + node [ id 0 label "O" ] + ] +]""") + +DG().build().apply([], r, onlyProper=False) +fail(lambda: DG().build().apply([None], r, onlyProper=False), "One of the graphs is a null pointer.") +fail(lambda: DG().build().apply([], None, onlyProper=False), "The rule is a null pointer.") +fail(lambda: DG(graphDatabase=[a]).build().apply([aa], r, onlyProper=False), "Isomorphic graphs. Candidate graph 'gaa' is isomorphic to 'ga' in the graph database.") +fail(lambda: DG(graphDatabase=[]).build().apply([a, aa], r, onlyProper=False), "Isomorphic graphs. Candidate graph 'gaa' is isomorphic to 'ga' in the graph database.") + +dg = DG(graphDatabase=[a, b, c]) +with dg.build() as builder: + print("Apply") + print("=" * 60) + res = builder.apply([a], r, onlyProper=False) + assert len(res) == 3 + for e in res: + assert list(e.rules) == [r] + assert list(v.graph for v in e.sources) == [a] + assert e.numTargets == 1 + ts = [next(iter(e.targets)).graph for e in res] + assert ts == [b, c, b] + + for verbosity in (2, 10, 20): + print("Verbosity:", verbosity) + print("#" * 80) + builder.apply([a], r, verbosity=verbosity, onlyProper=False) + + +print("Multiple components, different") +print("=" * 60) + +gO = smiles('[O]', "gO") +gC = smiles('[C]', "gC") +gOC = smiles('[O][C]', "gOC") + +r = ruleGMLString("""rule [ + ruleID "Connect O C" + context [ + node [ id 0 label "O" ] + node [ id 1 label "C" ] + ] + right [ + edge [ source 0 target 1 label "-" ] + ] +]""") + +dg = DG(graphDatabase=[gO, gC, gOC]) +with dg.build() as builder: + res = builder.apply([gO, gC], r, verbosity=4, onlyProper=False) + assert len(res) == 1 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([gO, gC]) + assert e.numTargets == 1 + ts = [next(iter(e.targets)).graph for e in res] + assert ts == [gOC] + + res = builder.apply([gO, gC, gC], r, verbosity=4, onlyProper=False) + assert len(res) == 2 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([gO, gC]) + assert e.numTargets == 1 + ts = [next(iter(e.targets)).graph] + assert ts == [gOC] + + +print("Multiple components, same") +print("=" * 60) + +gO = smiles('[O]', "gO") +gOO = smiles('[O][O]', "gOO") + +r = ruleGMLString("""rule [ + ruleID "Connect O O" + context [ + node [ id 0 label "O" ] + node [ id 1 label "O" ] + ] + right [ + edge [ source 0 target 1 label "-" ] + ] +]""") + +dg = DG(graphDatabase=[gO, gOO]) +with dg.build() as builder: + res = builder.apply([gO, gO], r, verbosity=4, onlyProper=False) + assert len(res) == 1 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([gO, gO]) + assert e.numTargets == 1 + ts = [next(iter(e.targets)).graph] + assert ts == [gOO] + + res = builder.apply([gO], r, verbosity=4, onlyProper=False) + assert len(res) == 0 + + +print("Split to isomorphic") +print("=" * 60) + +r = ruleGMLString("""rule [ + ruleID "Split to isomorphms" + left [ + edge [ source 1 target 2 label "-" ] + ] + context [ + node [ id 1 label "Q" ] + node [ id 2 label "Q" ] + ] +]""") +g1 = graphDFS("[Q][Q]", "QQ") +g2 = graphDFS("[Q]", "Q") + +dg = DG(graphDatabase=[g1, g2]) +with dg.build() as builder: + res = builder.apply([g1], r, verbosity=4, onlyProper=False) + assert len(res) == 2 + for e in res: + assert list(e.rules) == [r] + assert set(v.graph for v in e.sources) == set([g1]) + assert e.numTargets == 2 + ts = [v.graph for v in e.targets] + assert ts == [g2, g2] diff --git a/test/py/dg/101_build_execute_add.py b/test/py/dg/101_build_execute_add.py index e584cce..d26c238 100644 --- a/test/py/dg/101_build_execute_add.py +++ b/test/py/dg/101_build_execute_add.py @@ -58,7 +58,8 @@ exeStrat(addUniverse(lambda: [g1a, g1b], graphPolicy=IsomorphismPolicy.TrustMe)) - - - - +# test verbose print +inputGraphs[:] = [] +for i in range(42): + smiles("C"*(i + 1)) +exeStrat(addSubset(inputGraphs) >> addUniverse(inputGraphs) >> addSubset(lambda: inputGraphs) >> addUniverse(lambda: inputGraphs), verbosity=10) diff --git a/test/py/dg/121_build_execute_rule.py b/test/py/dg/121_build_execute_rule.py new file mode 100644 index 0000000..0dc02f6 --- /dev/null +++ b/test/py/dg/121_build_execute_rule.py @@ -0,0 +1,41 @@ +include("1xx_execute_helpers.py") + +gO = smiles('[O]', "gO") +gC = smiles('[C]', "gC") +gN = smiles('[N]', "gN") +gOC = smiles('[O][C]', "gOC") + +rConvertOC = ruleGMLString("""rule [ + ruleID "Convert O -> C" + left [ node [ id 0 label "O" ] ] + right [ node [ id 0 label "C" ] ] +]""") + +rConnectOC = ruleGMLString("""rule [ + ruleID "Connect O C" + context [ + node [ id 0 label "O" ] + node [ id 1 label "C" ] + ] + right [ + edge [ source 0 target 1 label "-" ] + ] +]""") + +print("Subset, not universe") +print("="*80) +exeStrat(addSubset(gO) >> rConvertOC, [gC], [gO, gC], + graphDatabase=inputGraphs, verbosity=10) +exeStrat(addUniverse(gO) >> rConvertOC, [], [gO], + graphDatabase=inputGraphs, verbosity=10) + +print("Multiple, subset") +print("="*80) +exeStrat(addSubset(gO, gC) >> rConnectOC, [gOC], [gO, gC, gOC], + graphDatabase=inputGraphs, verbosity=10) + +print("Multiple, 1 subset, 1 universe") +print("="*80) +exeStrat(addSubset(gO) >> addUniverse(gC) >> rConnectOC, [gOC], [gO, gC, gOC], + graphDatabase=inputGraphs, verbosity=10) + diff --git a/test/py/dg/121_build_execute_rule_splitToIsomorphic.py b/test/py/dg/129_build_execute_rule_splitToIsomorphic.py similarity index 93% rename from test/py/dg/121_build_execute_rule_splitToIsomorphic.py rename to test/py/dg/129_build_execute_rule_splitToIsomorphic.py index c6873cd..1687e9c 100644 --- a/test/py/dg/121_build_execute_rule_splitToIsomorphic.py +++ b/test/py/dg/129_build_execute_rule_splitToIsomorphic.py @@ -12,4 +12,4 @@ ]""") g1 = graphDFS("[Q][Q]", "QQ") g2 = graphDFS("[Q]", "Q") -exeStrat(addSubset(g1) >> rSplit, [g2], [g1, g2], graphDatabase=[g1, g2]) +exeStrat(addSubset(g1) >> rSplit, [g2], [g1, g2], graphDatabase=[g1, g2], verbosity=10) diff --git a/test/py/graph/graphInterface.py b/test/py/graph/graphInterface.py new file mode 100644 index 0000000..d53482a --- /dev/null +++ b/test/py/graph/graphInterface.py @@ -0,0 +1,6 @@ +include("../xxx_graphInterface.py") + +g = graphDFS("CN1C=NC2=C1C(=O)N(C(=O)N2C)C{blah}[blah]:[blah]") + +checkLabelledGraph(g, string="'{}'".format(g.name), + vertexString="GraphVertex", edgeString="GraphEdge") diff --git a/test/py/graph/union.py b/test/py/graph/union.py new file mode 100644 index 0000000..90c4230 --- /dev/null +++ b/test/py/graph/union.py @@ -0,0 +1,79 @@ +include("../xxx_helpers.py") +include("../xxx_graphInterface.py") + +O = smiles("O") + +def check(ug, gs): + s = "UnionGraph{%s}" % ', '.join(a.name for a in gs) + checkLabelledGraph(ug, string=s, vertexString="UnionGraphVertex", + edgeString="UnionGraphEdge") + + assert str(ug) == s + assert len(ug) == len(gs) + assert list(ug) == gs + for i in range(len(ug)): + assert ug[i] == gs[i] + assert ug == UnionGraph(gs) + assert ug != UnionGraph(gs + [O]) + + + def compVertex(vCand, vReal): + assert len(list(vCand.incidentEdges)) == vReal.degree + assert vCand.degree == vReal.degree + assert vCand.stringLabel == vReal.stringLabel + assert vCand.atomId == vReal.atomId + assert vCand.isotope == vReal.isotope + assert vCand.charge == vReal.charge + assert vCand.radical == vReal.radical + + assert vCand.vertex == vReal + assert vCand.graph[vCand.graphIndex] == vReal.graph + + def compEdge(eCand, eReal): + compVertex(eCand.source, eReal.source) + compVertex(eCand.target, eReal.target) + assert eCand.stringLabel == eReal.stringLabel + assert eCand.bondType == eReal.bondType + + assert eCand.edge == eReal + + # vertices + n = sum(a.numVertices for a in ug) + assert ug.numVertices == n + vs = [] + for g in gs: + vs.extend(g.vertices) + assert len(vs) == n + vsIdx = list(ug.vertices[i] for i in range(ug.numVertices)) + assert list(ug.vertices) == vsIdx + for i in range(n): + assert ug.vertices[i].id == i + assert len(list(ug.vertices)) == n + i = 0 + for vCand, vReal in zip(ug.vertices, vs): + assert vCand.id == i + assert vCand + assert not vCand.isNull() + assert vCand.graph == ug + i += 1 + compVertex(vCand, vReal) + for eOutCand, eOutReal in zip(vCand.incidentEdges, vReal.incidentEdges): + compEdge(eOutCand, eOutReal) + + # edges + m = sum(a.numEdges for a in ug) + assert ug.numEdges == m + es = [] + for g in gs: + es.extend(g.edges) + assert len(es) == m + assert len(list(ug.edges)) == m + for eCand, eReal in zip(ug.edges, es): + assert eCand + assert not eCand.isNull() + compEdge(eCand, eReal) + + +check(UnionGraph(), []) +check(UnionGraph([O]), [O]) +check(UnionGraph([O, O]), [O, O]) diff --git a/test/py/graph/unionPrint.py b/test/py/graph/unionPrint.py new file mode 100644 index 0000000..5cd939f --- /dev/null +++ b/test/py/graph/unionPrint.py @@ -0,0 +1,6 @@ +O = smiles("O") +g = UnionGraph([O, O]) +for v in g.vertices: + if v.atomId != AtomIds.O: + continue + v.printStereo() diff --git a/test/py/rc/test.py b/test/py/rc/test.py index 01ec769..9a9fb4e 100644 --- a/test/py/rc/test.py +++ b/test/py/rc/test.py @@ -13,7 +13,7 @@ def check(exp, checks, resSize=1): global checkNum print("Check", checkNum, exp) checkNum += 1 - res = rc.eval(exp) + res = list(set(rc.eval(exp))) def redo(): rc.eval(exp, verbosity=20) if len(rc.products) != 0: diff --git a/test/py/rule/ruleInterface.py b/test/py/rule/ruleInterface.py index 6b504b0..f0bc0bb 100644 --- a/test/py/rule/ruleInterface.py +++ b/test/py/rule/ruleInterface.py @@ -1,3 +1,5 @@ +include("../xxx_graphInterface.py") + a = ruleGMLString("""rule [ left [ node [ id 0 label "C+." ] @@ -14,6 +16,22 @@ ] ]""") + +checkGraph(a, string="'{}'".format(a.name), + vertexString="RuleVertex", edgeString="RuleEdge") +checkLabelledGraph(a.left, string="RuleLeftGraph('{}')".format(a.name), + vertexString="RuleLeftGraphVertex", edgeString="RuleLeftGraphEdge", + graphNameInElements=str(a), vIdFull=False) +checkGraph(a.context, string="RuleContextGraph('{}')".format(a.name), + vertexString="RuleContextGraphVertex", edgeString="RuleContextGraphEdge", + graphNameInElements=str(a), vIdFull=False) +checkLabelledGraph(a.right, string="RuleRightGraph('{}')".format(a.name), + vertexString="RuleRightGraphVertex", edgeString="RuleRightGraphEdge", + graphNameInElements=str(a), vIdFull=False) + + + + print("Core\n" + "="*80) print("numVertices:", a.numVertices) for v in a.vertices: diff --git a/test/py/vector.py b/test/py/vector.py index 447ba53..73c0aee 100644 --- a/test/py/vector.py +++ b/test/py/vector.py @@ -1,9 +1,9 @@ a = smiles("O") -assert VecGraph() == VecGraph() -assert VecGraph() == [] -assert [] == VecGraph() -l = VecGraph() +assert libpymod._VecGraph() == libpymod._VecGraph() +assert libpymod._VecGraph() == [] +assert [] == libpymod._VecGraph() +l = libpymod._VecGraph() l.append(a) assert l == [a] assert [a] == l diff --git a/test/py/xxx_graphInterface.py b/test/py/xxx_graphInterface.py new file mode 100644 index 0000000..d135dcc --- /dev/null +++ b/test/py/xxx_graphInterface.py @@ -0,0 +1,115 @@ +include("xxx_helpers.py") +postDisable() + +def checkGraph(g, *, string: str, vertexString: str, edgeString: str, + graphNameInElements: str = None, + vIdFull: bool = True): + Vertex = g.Vertex + Edge = g.Edge + VertexRange = g.VertexRange + EdgeRange = g.EdgeRange + IncidentEdgeRange = g.IncidentEdgeRange + assert str(g) == string + assert g.numVertices == len(list(g.vertices)) + assert g.numEdges == len(list(g.edges)) + assert type(g.vertices) == g.VertexRange + assert type(g.edges) == g.EdgeRange + + vNull = Vertex() + assert str(vNull) == vertexString + "(null)" + assert type(vNull.__hash__()) == int + assert not vNull + assert vNull.isNull() + fail(lambda: vNull.id, "Can not get id on a null vertex.") + fail(lambda: vNull.graph, "Can not get graph on a null vertex.") + fail(lambda: vNull.degree, "Can not get degree on a null vertex.") + fail(lambda: vNull.incidentEdges, "Can not get incident edges on a null vertex.") + + graphNameInElements = graphNameInElements if graphNameInElements else str(g) + i = 0 + for v in g.vertices: + assert type(v) == Vertex + assert str(v) == "{}({}, {})".format(vertexString, graphNameInElements, + v.id) + assert not (vNull == v) + assert vNull != v + assert vNull < v + assert v > vNull + assert hash(v) == v.id + assert v + assert not v.isNull() + assert type(v.id) == int + if vIdFull: + assert v.id == i + assert v.graph == g + assert v.degree == len(list(v.incidentEdges)) + assert type(v.incidentEdges) == g.IncidentEdgeRange + for e in v.incidentEdges: + assert type(e.source) == Vertex + assert type(e.target) == Vertex + assert e.source == v + assert e.target != v + i += 1 + + for v1 in g.vertices: + for v2 in g.vertices: + assert (v1 == v2) == (v1.id == v2.id) + assert (v1 < v2) == (v1.id < v2.id) + assert (v1 > v2) == (v1.id > v2.id) + + eNull = Edge() + assert str(eNull) == edgeString + "(null)" + assert not eNull + assert eNull.isNull() + + for e in g.edges: + assert type(e) == Edge + assert str(e) == "{}({}, {}, {})".format(edgeString, + graphNameInElements, e.source.id, e.target.id) + assert not (eNull == e) + assert eNull != e + assert eNull < e + assert e > eNull + assert e.graph == g + assert type(e.source) == Vertex + assert type(e.target) == Vertex + + for e1 in g.edges: + for e2 in g.edges: + assert (e1 == e2) == ((e1.source.id, e1.target.id) == (e2.source.id, e2.target.id)) + assert (e1 < e2) == ((e1.source.id, e1.target.id) < (e2.source.id, e2.target.id)) + assert (e1 > e2) == ((e1.source.id, e1.target.id) > (e2.source.id, e2.target.id)) + + +def checkLabelledGraph(g, *, string: str, vertexString: str, edgeString: str, + graphNameInElements: str = None, + vIdFull: bool = True): + checkGraph(g, string=string, vertexString=vertexString, + edgeString=edgeString, graphNameInElements=graphNameInElements, + vIdFull=vIdFull) + + vNull = g.Vertex() + fail(lambda: vNull.stringLabel, "Can not get string label on a null vertex.") + fail(lambda: vNull.atomId, "Can not get atom id on a null vertex.") + fail(lambda: vNull.isotope, "Can not get isotope on a null vertex.") + fail(lambda: vNull.charge, "Can not get charge on a null vertex.") + fail(lambda: vNull.radical, "Can not get radical status on a null vertex.") + fail(lambda: vNull.printStereo(), "Can not print stereo on a null vertex.") + fail(lambda: vNull.printStereo(GraphPrinter()), "Can not print stereo on a null vertex.") + + for v in g.vertices: + assert type(v.stringLabel) == str + assert type(v.atomId) == AtomId + assert type(v.isotope) == Isotope + assert type(v.charge) == Charge + assert type(v.radical) == bool + v.printStereo() + v.printStereo(GraphPrinter()) + + eNull = g.Edge() + fail(lambda: eNull.stringLabel, "Can not get string label on a null edge.") + fail(lambda: eNull.bondType, "Can not get bond type on a null edge.") + + for e in g.edges: + assert type(e.stringLabel) == str + assert type(e.bondType) == BondType