Integrate Instant-Meshes

1. Drop windows 32bit support
Add windows 64bit support.

2. Remove Script(quickjs) support
The current integrated quickjs is a very old version which doesn’t support windows 64bit system. In the future, (TODO)WebAssembly should be integrate as plugin system.

3. Integrate Instant-Meshes
Instant-Meshes take less than 1 second on all three platforms.

4. Remove QuadriFlow
Current implementation of QuadriFlow is too slow (take about 5 seconds on the example model) to do realtime remeshing.
master
Jeremy Hu 2020-01-04 19:59:10 +09:30
parent ee53e3ed4f
commit 2d05583937
7002 changed files with 1834975 additions and 218042 deletions

View File

@ -36,7 +36,7 @@ install:
# (Linux) First install a maybe old version CGAL to resolve dependencies
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libcgal-dev; fi
# (Linux) Build from source
# (Linux) Build CGAL from source
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://github.com/CGAL/cgal/releases/download/releases/CGAL-4.13/CGAL-4.13.zip; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then unzip CGAL-4.13.zip; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cd CGAL-4.13; fi
@ -47,6 +47,14 @@ install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo make install; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then cd ../../; fi
# Build Instant-Meshes from source
- cd thirdparty/instant-meshes
- mkdir build
- cd build
- cmake ../
- make -j 4
- cd ../../../
# (Mac) Install Qt5
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then HOMEBREW_VERBOSE_USING_DOTS=1 brew reinstall --verbose qt; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/qt/bin:$(brew --prefix)/bin:$PATH"; fi
@ -55,9 +63,6 @@ install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install qt59base qt59tools --force-yes; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then source /opt/qt59/bin/qt59-env.sh; fi
# (Mac) Install OpenMP
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then HOMEBREW_VERBOSE_USING_DOTS=1 brew reinstall --verbose libomp; fi
script:
# Build Dust3D

View File

@ -1231,3 +1231,44 @@ https://www.reddit.com/r/gamedev/comments/5iuf3h/i_am_writting_a_3d_monster_mode
QuadriFlow: A Scalable and Robust Method for Quadrangulation
http://stanford.edu/~jingweih/papers/quadriflow/
</pre>
<h1>instant-meshes</h1>
<pre>
Copyright (c) 2015 Wenzel Jakob, Daniele Panozzo, Marco Tarini,
and Olga Sorkine-Hornung. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You are under no obligation whatsoever to provide any bug fixes, patches, or
upgrades to the features, functionality or performance of the source code
("Enhancements") to anyone; however, if you choose to make your Enhancements
available either publicly, or directly to the authors of this software, without
imposing a separate written license agreement for such Enhancements, then you
hereby grant the following license: a non-exclusive, royalty-free perpetual
license to install, use, modify, prepare derivative works, incorporate into
other computer software, distribute, and sublicense such enhancements or
derivative works thereof, in binary and source code form.
</pre>

View File

@ -2,33 +2,33 @@ os: Visual Studio 2017
environment:
matrix:
- platform: x86
target: i686-pc-windows-msvc
qtdir: C:\Qt\5.13.2\msvc2017
sysdirname: system32
cache:
CGAL-4.13-Setup.exe -> appveyor.yml
- platform: x64
target: x86_64-pc-windows-msvc
qtdir: C:\Qt\5.13.2\msvc2017_64
sysdirname: SysWOW64
install:
- if "%PLATFORM%" == "x86"
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
- if not exist CGAL-4.13-Setup.exe
appveyor DownloadFile https://github.com/CGAL/cgal/releases/download/releases/CGAL-4.13/CGAL-4.13-Setup.exe -FileName CGAL-4.13-Setup.exe
- CGAL-4.13-Setup.exe /S /D=%APPVEYOR_BUILD_FOLDER%\CGAL-4.13
- cd CGAL-4.13
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
- cd thirdparty/cgal/CGAL-4.13
- mkdir build
- cd build
- if "%PLATFORM%" == "x86"
cmake -G "Visual Studio 15 2017" ../ -DBOOST_INCLUDEDIR=C:\Libraries\boost_1_66_0
- cmake -G "Visual Studio 15 2017" -A %PLATFORM% ../ -DBOOST_INCLUDEDIR=C:\Libraries\boost_1_66_0
- msbuild /p:Configuration=Release ALL_BUILD.vcxproj
- cd %APPVEYOR_BUILD_FOLDER%
- cd thirdparty/instant-meshes
- mkdir build
- cd build
- cmake -G "Visual Studio 15 2017" -A %PLATFORM% ../
- msbuild /p:Configuration=RelWithDebInfo ALL_BUILD.vcxproj
- cd %APPVEYOR_BUILD_FOLDER%
build: false
test_script:
- set PATH=%PATH%;%QTDIR%\bin
- qmake "BOOST_INCLUDEDIR=C:\Libraries\boost_1_66_0" "CGAL_DIR=%APPVEYOR_BUILD_FOLDER%\CGAL-4.13"
- qmake "BOOST_INCLUDEDIR=C:\Libraries\boost_1_66_0" "CGAL_DIR=%APPVEYOR_BUILD_FOLDER%\thirdparty\cgal\CGAL-4.13"
- nmake -f Makefile.Release
after_test:
@ -36,7 +36,6 @@ after_test:
# Check Qt plugins by following https://wiki.qt.io/Deploy_an_Application_on_Windows
- set /p VCRedistVersion=<"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\Microsoft.VCRedistVersion.default.txt"
- set VCREDIST_CRT_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\%VCRedistVersion%\%PLATFORM%\Microsoft.VC141.CRT
- set VCREDIST_OPENMP_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Redist\MSVC\%VCRedistVersion%\%PLATFORM%\Microsoft.VC141.OPENMP
- set TAG=%APPVEYOR_REPO_TAG_NAME%
- if "%TAG%" == ""
@ -44,11 +43,17 @@ after_test:
- if "%TAG%" == "unstable"
7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\release\dust3d.pdb
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\release\dust3d.exe
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\CGAL-4.13\build\bin\Release\CGAL-vc140-mt-4.13.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\CGAL-4.13\auxiliary\gmp\lib\libgmp-10.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\CGAL-4.13\auxiliary\gmp\lib\libmpfr-4.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip C:\OpenSSL-v111-Win32\bin\libcrypto-1_1.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip C:\OpenSSL-v111-Win32\bin\libssl-1_1.dll
- if "%TAG%" == "unstable"
7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\instant-meshes\build\RelWithDebInfo\instant-meshes.pdb
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\instant-meshes\build\RelWithDebInfo\instant-meshes.dll
- if "%TAG%" == "unstable"
7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\instant-meshes\build\ext_build\tbb\RelWithDebInfo\tbb.pdb
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\instant-meshes\build\ext_build\tbb\RelWithDebInfo\tbb.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\cgal\CGAL-4.13\build\bin\Release\CGAL-vc140-mt-4.13.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\cgal\CGAL-4.13\auxiliary\gmp\lib\libgmp-10.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\thirdparty\cgal\CGAL-4.13\auxiliary\gmp\lib\libmpfr-4.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip C:\OpenSSL-v111-Win64\bin\libcrypto-1_1-x64.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip C:\OpenSSL-v111-Win64\bin\libssl-1_1-x64.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %QTDIR%\bin\Qt5Widgets.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %QTDIR%\bin\Qt5Gui.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip %QTDIR%\bin\Qt5Core.dll
@ -56,7 +61,6 @@ after_test:
- 7z a dust3d-%TAG%-%PLATFORM%.zip %QTDIR%\bin\opengl32sw.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip "%VCREDIST_CRT_DIR%\msvcp140.dll"
- 7z a dust3d-%TAG%-%PLATFORM%.zip "%VCREDIST_CRT_DIR%\vcruntime140.dll"
- 7z a dust3d-%TAG%-%PLATFORM%.zip "%VCREDIST_OPENMP_DIR%\vcomp140.dll"
- mkdir platforms
- copy %QTDIR%\plugins\platforms\qwindows.dll %APPVEYOR_BUILD_FOLDER%\platforms\qwindows.dll
- 7z a dust3d-%TAG%-%PLATFORM%.zip -r %APPVEYOR_BUILD_FOLDER%\platforms\

View File

@ -125,6 +125,7 @@ unix:!macx {
win32 {
QMAKE_CXXFLAGS += /O2
QMAKE_CXXFLAGS += /bigobj
}
include(thirdparty/QtAwesome/QtAwesome/QtAwesome.pri)
@ -394,21 +395,6 @@ HEADERS += src/preferences.h
HEADERS += src/shadervertex.h
SOURCES += src/scripteditwidget.cpp
HEADERS += src/scripteditwidget.h
SOURCES += src/scriptvariableswidget.cpp
HEADERS += src/scriptvariableswidget.h
SOURCES += src/scriptwidget.cpp
HEADERS += src/scriptwidget.h
SOURCES += src/scriptrunner.cpp
HEADERS += src/scriptrunner.h
SOURCES += src/variablesxml.cpp
HEADERS += src/variablesxml.h
SOURCES += src/updateschecker.cpp
HEADERS += src/updateschecker.h
@ -497,83 +483,28 @@ SOURCES += src/main.cpp
HEADERS += src/version.h
INCLUDEPATH += thirdparty/QuadriFlow/src
INCLUDEPATH += thirdparty/QuadriFlow/3rd/pcg32
INCLUDEPATH += thirdparty/QuadriFlow/3rd/pss
INCLUDEPATH += thirdparty/QuadriFlow/3rd/lemon-1.3.1
macx: {
!exists(/usr/local/opt/libomp) {
error("Please install OpenMP: brew install libomp")
INCLUDEPATH += thirdparty/instant-meshes
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/src
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/ext/tbb/include
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/ext/dset
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/ext/pss
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/ext/pcg32
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/ext/rply
INCLUDEPATH += thirdparty/instant-meshes/instant-meshes-dust3d/ext/half
unix {
SOURCES += thirdparty/instant-meshes/instant-meshes-api.cpp
LIBS += -Lthirdparty/instant-meshes/build -linstant-meshes
LIBS += -Lthirdparty/instant-meshes/build/ext_build/tbb -ltbb_static
unix:!macx {
LIBS += -ldl
}
DEFINES += WITH_OMP
QMAKE_CXXFLAGS += -Xpreprocessor -fopenmp
INCLUDEPATH += /usr/local/opt/libomp/include
LIBS += -L/usr/local/opt/libomp/lib -lomp
}
win32 {
QMAKE_CXXFLAGS += /openmp
DEFINES += WITH_OMP
DEFINES += _USE_MATH_DEFINES
LIBS += -Lthirdparty/instant-meshes/build/RelWithDebInfo -linstant-meshes
LIBS += -Lthirdparty/instant-meshes/build/ext_build/tbb/RelWithDebInfo -ltbb
}
unix:!macx {
QMAKE_CXXFLAGS += -fopenmp
DEFINES += WITH_OMP
LIBS += -lgomp
}
win32 {
# Fix error LNK2001: unresolved external symbol "struct lemon::Invalid const lemon::INVALID" (?INVALID@lemon@@3UInvalid@1@B)
DEFINES += LEMON_ONLY_TEMPLATES
}
SOURCES += thirdparty/QuadriFlow/src/adjacent-matrix.cpp
HEADERS += thirdparty/QuadriFlow/src/adjacent-matrix.hpp
HEADERS += thirdparty/QuadriFlow/src/compare-key.hpp
HEADERS += thirdparty/QuadriFlow/src/config.hpp
SOURCES += thirdparty/QuadriFlow/src/dedge.cpp
HEADERS += thirdparty/QuadriFlow/src/dedge.hpp
HEADERS += thirdparty/QuadriFlow/src/disajoint-tree.hpp
HEADERS += thirdparty/QuadriFlow/src/dset.hpp
HEADERS += thirdparty/QuadriFlow/src/field-math.hpp
HEADERS += thirdparty/QuadriFlow/src/flow.hpp
SOURCES += thirdparty/QuadriFlow/src/hierarchy.cpp
HEADERS += thirdparty/QuadriFlow/src/hierarchy.hpp
SOURCES += thirdparty/QuadriFlow/src/loader.cpp
HEADERS += thirdparty/QuadriFlow/src/loader.hpp
SOURCES += thirdparty/QuadriFlow/src/localsat.cpp
HEADERS += thirdparty/QuadriFlow/src/localsat.hpp
SOURCES += thirdparty/QuadriFlow/src/merge-vertex.cpp
HEADERS += thirdparty/QuadriFlow/src/merge-vertex.hpp
SOURCES += thirdparty/QuadriFlow/src/optimizer.cpp
HEADERS += thirdparty/QuadriFlow/src/optimizer.hpp
SOURCES += thirdparty/QuadriFlow/src/parametrizer.cpp
SOURCES += thirdparty/QuadriFlow/src/parametrizer-flip.cpp
SOURCES += thirdparty/QuadriFlow/src/parametrizer-int.cpp
SOURCES += thirdparty/QuadriFlow/src/parametrizer-mesh.cpp
SOURCES += thirdparty/QuadriFlow/src/parametrizer-scale.cpp
SOURCES += thirdparty/QuadriFlow/src/parametrizer-sing.cpp
HEADERS += thirdparty/QuadriFlow/src/parametrizer.hpp
HEADERS += thirdparty/QuadriFlow/src/serialize.hpp
SOURCES += thirdparty/QuadriFlow/src/subdivide.cpp
HEADERS += thirdparty/QuadriFlow/src/subdivide.hpp
INCLUDEPATH += thirdparty/bullet3/src
SOURCES += thirdparty/bullet3/src/LinearMath/btAlignedAllocator.cpp
@ -785,22 +716,6 @@ HEADERS += thirdparty/bullet3/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2
SOURCES += thirdparty/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.cpp
HEADERS += thirdparty/bullet3/src/BulletCollision/CollisionShapes/btBoxShape.h
INCLUDEPATH += thirdparty/quickjs/quickjs-2019-07-09-dust3d
DEFINES += "CONFIG_VERSION=\"\\\"2019-07-09\\\"\""
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/quickjs.c
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/quickjs.h
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/cutils.c
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/cutils.h
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libunicode.c
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libunicode.h
SOURCES += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libregexp.c
HEADERS += thirdparty/quickjs/quickjs-2019-07-09-dust3d/libregexp.h
INCLUDEPATH += thirdparty/crc64
SOURCES += thirdparty/crc64/crc64.c

View File

@ -318,10 +318,6 @@ Tips:
<source>Clear Cut Face</source>
<translation></translation>
</message>
<message>
<source>Script</source>
<translation></translation>
</message>
<message>
<source>Check for Updates...</source>
<translation>...</translation>

View File

@ -14,7 +14,6 @@
<file>resources/model-meerkat.ds3</file>
<file>resources/model-mosquito.ds3</file>
<file>resources/model-seagull.ds3</file>
<file>resources/model-procedural-tree.ds3</file>
<file>resources/triangle.png</file>
<file>resources/quad.png</file>
<file>resources/pentagon.png</file>
@ -26,7 +25,6 @@
<file>shaders/default.frag</file>
<file>shaders/default.core.vert</file>
<file>shaders/default.core.frag</file>
<file>thirdparty/three.js/dust3d.three.js</file>
<file>languages/dust3d_zh_CN.qm</file>
<file>ACKNOWLEDGEMENTS.html</file>
<file>AUTHORS</file>

View File

@ -1,881 +0,0 @@
DUST3D 1.0 xml 0000000257
<?xml version="1.0" encoding="UTF-8"?>
<ds3>
<model name="model.xml" offset="0" size="117317"/>
<script name="model.js" offset="117317" size="8514"/>
<variable name="variables.xml" offset="125831" size="1793"/>
</ds3>
<?xml version="1.0" encoding="UTF-8"?>
<canvas originX="0.506767" originY="0.615943" originZ="1.08543" rigType="None">
<nodes>
<node id="{001eb845-4bed-4de5-9803-ba8ca7faafaf}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0" x="0.624675" y="0.232533" z="1.08441"/>
<node id="{021bd224-eaac-49a1-a91f-0f2406f26f8a}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.00829716" x="0.529162" y="0.319461" z="0.834381"/>
<node id="{02b8c92c-3aad-43b4-b2d6-eb0659a8a206}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0094301" x="0.58636" y="0.281492" z="0.751192"/>
<node id="{0390d0a1-814a-4705-999e-5932354f0244}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.00841411" x="0.518194" y="0.26891" z="1.02987"/>
<node id="{0402a0e9-9712-4d9c-b022-ea25f2ed64d0}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0" x="0.508304" y="0.322731" z="0.792632"/>
<node id="{0434ac30-312c-4b70-984e-5a0971e9eb75}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.00817509" x="0.50548" y="0.256846" z="1.00709"/>
<node id="{052c2ec6-ad61-40af-b659-14a23612734d}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0" x="0.593867" y="0.274461" z="0.741533"/>
<node id="{05438075-6182-4f45-80c2-35625897b718}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.00541154" x="0.497586" y="0.140403" z="1.00711"/>
<node id="{0582fcb5-78cf-4f27-bd85-0ccd279e8713}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.0112927" x="0.50664" y="0.338481" z="0.812135"/>
<node id="{05c483ea-2649-48b1-80f9-f23a57335a5f}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.00121829" x="0.540098" y="0.379707" z="0.858939"/>
<node id="{067095a4-8e69-40d7-bc00-9c0a7f4e1e3c}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.0036703" x="0.518194" y="0.26891" z="1.02987"/>
<node id="{06f82254-ab2d-44f4-bc96-3814316535a9}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.00804375" x="0.540098" y="0.379707" z="0.858939"/>
<node id="{0711915a-a413-42b5-8022-35668c45d39b}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0192266" x="0.52941" y="0.945103" z="1.02527"/>
<node id="{071305c7-8044-4c28-8ccc-4f74cffb61cc}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0205617" x="0.526812" y="1.00058" z="1.01213"/>
<node id="{096379fc-4ca1-4c6d-b242-e353a20ffc88}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.0114691" x="0.61185" y="0.235283" z="1.07547"/>
<node id="{09f3f5fa-46f1-476c-aa35-3df95debd16f}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.00705143" x="0.733929" y="0.0905315" z="1.08278"/>
<node id="{0a8e8fb2-9858-49d2-8686-6ed728dccbc2}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00743484" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{0b4f4946-8ff1-4efe-bdfe-0b611af6a655}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.00854656" x="0.763122" y="0.056545" z="1.12847"/>
<node id="{0b58ba98-f204-40ee-be03-f62292b2d250}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0" x="0.431781" y="0.219264" z="0.994834"/>
<node id="{0bd7865d-7f8d-46cb-a1ba-4ed601bf62fe}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.0117866" x="0.747991" y="0.0634021" z="1.10862"/>
<node id="{0c131c2e-c763-4239-aae8-c71e219bb2ff}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0120206" x="0.517528" y="0.197616" z="1.01863"/>
<node id="{0c3ed74f-ee80-41a9-8568-1487fe0cfd7c}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.0165943" x="0.52147" y="0.327551" z="0.829132"/>
<node id="{0e5d29f3-fb8f-4d5c-b156-e4a3e028d97d}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.0136131" x="0.462094" y="0.0440756" z="0.990634"/>
<node id="{0f14d7ef-6d9e-42aa-afea-17e850abd25d}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.00665101" x="0.436937" y="0.226714" z="0.995019"/>
<node id="{0f798576-2812-4db6-b605-9ef70f713c8b}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.0181634" x="0.478383" y="0.0799667" z="0.997972"/>
<node id="{10582ab2-cd50-47a0-bb86-9272f251af03}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0" x="0.511773" y="0.247377" z="1.00342"/>
<node id="{105d5ada-f06b-474f-82a7-34fbfa628526}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0" x="0.490709" y="0.279837" z="1.03157"/>
<node id="{10d61f38-3849-4852-9dd1-2be2ad90d468}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0" x="0.794786" y="0.0436219" z="1.08823"/>
<node id="{117ef567-17a0-425e-9fcb-ae1610e91539}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0113278" x="0.435208" y="-0.122352" z="0.947148"/>
<node id="{1207414b-6386-42f4-b3b4-e774497e4fa9}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0" x="0.741845" y="0.083804" z="1.08452"/>
<node id="{14a0dfc1-38c0-4544-b5d4-65bdbe60b622}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.0151557" x="0.514648" y="0.144772" z="1.01763"/>
<node id="{14a9c743-142c-43a6-8962-5dbf6514c38a}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.00908169" x="0.481651" y="0.106262" z="0.991808"/>
<node id="{15283e25-d483-44c6-b530-113073ae54d0}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.00829716" x="0.506086" y="0.343731" z="0.818635"/>
<node id="{15d886b0-181e-4e8d-84c4-21da599037c1}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.00684339" x="0.690864" y="0.148628" z="1.10365"/>
<node id="{164fc21c-131b-42a2-a47b-3b2d930222c6}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.00625545" x="0.499048" y="0.16079" z="1.02006"/>
<node id="{172dd203-fbf9-4d7f-aafe-b751b7f943de}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.000446346" x="0.492055" y="0.304378" z="0.779797"/>
<node id="{173d8166-2d8d-4792-9187-d1f0dccb3713}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.0172223" x="0.507138" y="0.138639" z="1.03023"/>
<node id="{17408e0e-5237-45ce-8f5c-de1034fcf23c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00241779" x="0.639106" y="0.195709" z="1.06841"/>
<node id="{17722f68-bf1b-49d6-a22a-44a5fd7cd1f4}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0" x="0.633481" y="0.217282" z="1.08241"/>
<node id="{18a7f970-0d2e-4d47-a307-32c94a9105a3}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00147754" x="0.549438" y="0.337811" z="0.818152"/>
<node id="{1957320f-7dec-4069-a2b2-502d9a18442e}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.0125109" x="0.497234" y="0.142519" z="1.01624"/>
<node id="{199423e1-60c0-4b3c-b65a-3ab127cadf99}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00211381" x="0.459929" y="0.0522857" z="0.985105"/>
<node id="{1ad678c9-b640-43d5-af1c-92ddfc540416}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0138378" x="0.514346" y="0.194111" z="1.00654"/>
<node id="{1b515278-0117-48fe-a1fe-e772057573d9}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00127211" x="0.453427" y="-0.0558037" z="0.967476"/>
<node id="{1c85074d-db26-4962-9694-26df45d957c6}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00167325" x="0.465511" y="-0.00179739" z="0.96585"/>
<node id="{1d21ff2c-ba5f-4997-98db-a1ed63d01db3}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00246233" x="0.481651" y="0.106262" z="0.991808"/>
<node id="{1f0d5b25-4f21-4fd6-9142-0d56a594dd2c}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.00937295" x="0.520745" y="0.486083" z="0.929637"/>
<node id="{2015db8c-2d22-40d9-8605-073117da143a}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.0190246" x="0.530833" y="0.31094" z="1.03841"/>
<node id="{21a051be-53a6-442c-8c87-e5572e6ff05e}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0" x="0.523872" y="0.173925" z="0.975074"/>
<node id="{221a1797-ed67-4cfd-9cd8-34823e651ed3}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.000920665" x="0.506086" y="0.343731" z="0.818635"/>
<node id="{24b1db2c-8e14-4670-a523-bd31ab7758aa}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0" x="0.475115" y="0.0536713" z="1.00414"/>
<node id="{2501c90c-247d-42a1-b2fb-411d88b95e3a}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0188602" x="0.578853" y="0.288523" z="0.760851"/>
<node id="{27430d2c-0651-4361-a581-d304fcd67e22}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.0151221" x="0.574997" y="0.329256" z="0.826992"/>
<node id="{28381152-78fe-4c2d-8c3c-c776138efa17}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0113278" x="0.438589" y="-0.115943" z="0.942864"/>
<node id="{29686a15-7ddb-4717-a196-0412164025ef}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0055478" x="0.621696" y="0.233828" z="1.06758"/>
<node id="{2acf141a-f327-4469-bde3-ea54de99f8d6}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0" x="0.49542" y="0.124248" z="1.01241"/>
<node id="{2b2d6ee4-f105-491c-b098-4de0613fd37c}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.00652467" x="0.541733" y="0.286743" z="0.791092"/>
<node id="{2cc27239-bf74-49d5-b82d-0998c0103d6d}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0146973" x="0.517154" y="0.661798" z="1.02082"/>
<node id="{2ebd2648-14b0-4a21-b97b-7b34f021991b}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.0112927" x="0.507195" y="0.333231" z="0.805634"/>
<node id="{308ce17b-2a9a-4e10-b3f6-aaed5190c957}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.0116368" x="0.551163" y="0.337131" z="0.830778"/>
<node id="{31a4515c-5fd8-4e34-923e-750b726395f2}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.00985783" x="0.452406" y="0.249066" z="0.995575"/>
<node id="{32cc74f0-3f2c-450d-845d-9baabb852655}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0060103" x="0.520059" y="0.18953" z="1.0216"/>
<node id="{33cae706-74fd-423d-a240-a32c23657dcf}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.0187459" x="0.520931" y="0.493208" z="0.941731"/>
<node id="{3424cf20-48a1-4e64-be63-5890321cdbcd}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.00623232" x="0.505899" y="0.186592" z="1.01412"/>
<node id="{353010d5-28a2-4ce3-a465-12289cbadb21}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.0152136" x="0.570093" y="0.29639" z="0.772941"/>
<node id="{3547bb94-25b4-4740-a5e9-15046267f0f9}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.0124646" x="0.508088" y="0.195657" z="1.01365"/>
<node id="{35bf1780-fe7c-46dd-a93e-99896e097cf2}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.00908169" x="0.476749" y="0.066819" z="1.00105"/>
<node id="{36e6565b-5c7c-4203-9757-b7afa6731c57}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.0114691" x="0.605438" y="0.236659" z="1.071"/>
<node id="{379bec20-9be3-4a64-b259-d3ed4e84ebbc}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.00684339" x="0.675597" y="0.153363" z="1.08021"/>
<node id="{3932e31f-34f7-47da-8a0d-032bec47e53c}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.00804375" x="0.568858" y="0.358377" z="0.853901"/>
<node id="{39e3219e-a74d-4dd0-bedd-eb4fa010f34a}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0" x="0.530247" y="0.128753" z="1.01521"/>
<node id="{3b94ce3c-27ef-41af-87d1-4227ca2045f1}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.00625545" x="0.496327" y="0.133384" z="1.01432"/>
<node id="{3cce2c34-9aab-46dc-bbd3-3a73327a8875}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.440492" y="0.329685" z="0.713406"/>
<node id="{4029708e-b1f7-4f53-832e-d0983bfcd651}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.0167333" x="0.499882" y="0.295433" z="0.775861"/>
<node id="{404cdbf7-ef7b-4529-b04b-d775162d0edb}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.0147381" x="0.616253" y="0.227658" z="1.07447"/>
<node id="{408119ac-6fc0-40f5-b60c-99b7cc9517ae}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00288021" x="0.599025" y="0.238034" z="1.06653"/>
<node id="{40b1d9b4-f4ee-4c7d-8172-a9e0fc4d5654}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0111563" x="0.524322" y="0.493489" z="1.03635"/>
<node id="{427a3b1a-021e-4685-b78b-6080d8585450}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0" x="0.534364" y="0.281462" z="0.794733"/>
<node id="{442d48bd-1797-45dc-8e4f-d121fb89237c}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.0124646" x="0.510277" y="0.204723" z="1.01318"/>
<node id="{44dfeb44-b697-4c87-b313-325d3826cc63}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00955646" x="0.52" y="0.437582" z="1.01435"/>
<node id="{44e13dd8-a3d2-4d4f-af81-372da15218d2}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.00699227" x="0.755476" y="0.0488206" z="1.07007"/>
<node id="{4684632b-e51c-414e-aa21-df1ee91ea834}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.0175657" x="0.484479" y="0.285846" z="0.796773"/>
<node id="{48417392-2b8f-49a5-a628-ab7fc4c944d4}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.00564634" x="0.506086" y="0.343731" z="0.818635"/>
<node id="{491add8b-4be8-4171-b647-24334b050892}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.00547236" x="0.474945" y="0.0887811" z="0.976214"/>
<node id="{4b7f18aa-704e-4f55-9f69-16b0f38237ce}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0" x="0.428445" y="-0.135171" z="0.955714"/>
<node id="{4c81714b-6ac4-45d8-b4f0-c98539911521}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.0159439" x="0.402189" y="0.341997" z="0.713406"/>
<node id="{4d0f2620-8a2a-496f-ad0a-4d8002493035}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0060103" x="0.512466" y="0.213789" z="1.01271"/>
<node id="{5064c6c5-783a-44e5-8e70-49c8c9cc2416}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.0107256" x="0.528141" y="0.30701" z="1.0341"/>
<node id="{511c7a39-b0e7-4502-8bd3-730ae05506f0}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.00861113" x="0.511183" y="0.127563" z="1.03531"/>
<node id="{516a356a-f5a0-4c65-9f17-8d186eeccaa2}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.0172223" x="0.503093" y="0.149714" z="1.02514"/>
<node id="{516d36d9-b1db-4de8-8503-7ea829120487}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0" x="0.537046" y="0.325127" z="0.849158"/>
<node id="{528a1707-5b77-4963-a34e-db9dba558205}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.0187459" x="0.521116" y="0.500333" z="0.953824"/>
<node id="{52cc908a-1fa5-415d-9d64-51bb469706d7}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00089087" x="0.755719" y="0.068247" z="1.0946"/>
<node id="{5399b1af-6473-4df5-96cc-13e6e28784c1}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.0125641" x="0.516931" y="0.31407" z="1.03225"/>
<node id="{53f27881-5a75-4c22-b2cf-7b2d05ee1d8e}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0" x="0.505946" y="0.310252" z="1.07969"/>
<node id="{55340a9c-d66d-4d5d-a189-6d658d599e53}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0" x="0.572779" y="0.393653" z="0.869869"/>
<node id="{55b5bb5d-d614-4cd3-b331-8819186ed572}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0127438" x="0.50217" y="0.607202" z="1.02431"/>
<node id="{567a286a-bf1d-4291-b979-ba69733646f5}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.0152136" x="0.576346" y="0.290194" z="0.765713"/>
<node id="{567bcfd4-255f-478d-a9fe-362f2f832ff6}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0" x="0.629253" y="0.232427" z="1.06793"/>
<node id="{58321009-70bf-48ba-bbe7-f5afcd9e56f3}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.00581841" x="0.541752" y="0.329128" z="0.843031"/>
<node id="{58bd7c83-b479-4e17-b4df-754316eef264}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.000961544" x="0.44197" y="-0.109533" z="0.938581"/>
<node id="{593f1c87-b152-41e0-98b6-07acf061f646}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.00536282" x="0.531694" y="0.299966" z="1.03276"/>
<node id="{59fe931d-cbf2-47e6-b35e-0edcf8ad6830}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0.00861113" x="0.499048" y="0.16079" z="1.02006"/>
<node id="{5a7cf847-a78d-4877-9d4f-94cd9bb9eca8}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0" x="0.578445" y="0.351266" z="0.852222"/>
<node id="{5df7e38f-b9da-4c41-800c-56b5d25952b6}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.00736903" x="0.624867" y="0.22247" z="1.07844"/>
<node id="{5e465c5c-fdc5-4c81-95dc-4729f981df5c}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.00660156" x="0.437669" y="0.226572" z="0.991136"/>
<node id="{5eb9bd01-2f33-4a6d-bb01-4a8a6cc7469c}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.0160875" x="0.559272" y="0.365487" z="0.85558"/>
<node id="{61ba80ab-f761-4889-a07e-7b2b7ff91e5c}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0094301" x="0.563839" y="0.302585" z="0.780169"/>
<node id="{6394e5cc-a367-4664-a9af-753d41b82ba6}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.0157834" x="0.775252" y="0.0559345" z="1.09142"/>
<node id="{644464d2-775c-42ec-8544-206fe7d11fe7}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.00885373" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{651c39df-7b14-4fd3-beb3-592efcb25842}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0202136" x="0.471153" y="0.0252876" z="0.992578"/>
<node id="{66c32673-0a5b-4c93-8dd8-26ea2e206aa9}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.018684" x="0.508007" y="0.30584" z="1.01773"/>
<node id="{68be0242-2557-4881-b306-25936e0ac472}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00374236" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{6a16e994-9730-49a8-81f7-d9bcaf0d3614}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0" x="0.56023" y="0.280472" z="1.04329"/>
<node id="{6b2ab6a9-c11c-4c88-b4f9-b66df3f09e4f}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.0117866" x="0.751855" y="0.0658246" z="1.10161"/>
<node id="{6b586d8c-e5a3-4405-b346-0d07c1fc587b}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.0146164" x="0.561272" y="0.296321" z="0.771565"/>
<node id="{6c9d6544-ff34-4259-8d31-72393a4d7629}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.0108231" x="0.498074" y="0.147199" z="1.01143"/>
<node id="{6cbb96e6-231d-4ac1-b9ec-75b258b16a1e}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0" x="0.504622" y="0.292991" z="1.01866"/>
<node id="{6d108c14-4e3d-4273-8cee-084390309386}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0" x="0.55357" y="0.277529" z="0.745752"/>
<node id="{6d6619eb-70e2-48e4-b8a6-0ff52d14584b}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.00757784" x="0.499048" y="0.16079" z="1.02006"/>
<node id="{6dea3dfc-6305-4221-81f8-d59379db1f8c}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00562501" x="0.521301" y="0.507458" z="0.965918"/>
<node id="{6e591cdf-09bd-478c-a604-ac7d19acf528}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.00836663" x="0.515537" y="0.277544" z="0.767988"/>
<node id="{6ef80ba2-4d3c-4a6e-a901-e5ddc913a272}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" radius="0.0160875" x="0.549685" y="0.372597" z="0.85726"/>
<node id="{6fd6b2c1-ab1f-4904-ac30-2f800bbfc95a}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00439503" x="0.51987" y="0.465217" z="0.933138"/>
<node id="{7057282d-6ae5-4d7e-b10e-85ae69c7f72a}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.00699227" x="0.755719" y="0.068247" z="1.0946"/>
<node id="{70da7060-9223-4ac9-b6ca-ea16eeb20d45}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0101068" x="0.459929" y="0.0522857" z="0.985105"/>
<node id="{7153e3f6-ba74-4b9a-9a48-1f6b454b3678}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.0168282" x="0.518851" y="0.256622" z="1.02709"/>
<node id="{71b98c98-8654-42d8-b58a-22688b722630}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.0130493" x="0.549102" y="0.292024" z="0.787451"/>
<node id="{7285fcb8-4779-4e60-a474-4641c0943463}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.016105" x="0.533222" y="0.721447" z="1.02103"/>
<node id="{7293a322-fbad-4c7b-a059-606020ff09bf}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" radius="0.00564634" x="0.507749" y="0.327981" z="0.799133"/>
<node id="{734ab0d5-d4d8-485a-b521-ebd36a3a8720}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0" x="0.516227" y="0.174434" z="1.00037"/>
<node id="{7351a5f6-983d-4fdf-83c9-be734363f2ca}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.0173385" x="0.544025" y="0.414478" z="0.884335"/>
<node id="{73951d38-c2aa-4577-927b-7e9429d1f0db}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.0132031" x="0.442581" y="0.23407" z="0.992616"/>
<node id="{73b1a616-30a5-44a9-a246-76ff142d228b}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0" x="0.52259" y="0.181444" z="1.02456"/>
<node id="{743d083e-3e96-4eb7-9c5f-0f0cee310915}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.0132031" x="0.447494" y="0.241568" z="0.994095"/>
<node id="{74620eab-e43b-44e3-be3a-68f3838cda88}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.0166743" x="0.51349" y="0.315674" z="1.05824"/>
<node id="{751fee8a-4d20-44bf-b68f-24b908abf032}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00140585" x="0.710183" y="0.110714" z="1.07757"/>
<node id="{75239010-9a3d-434c-a036-a8a59a0fe3d6}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.0125641" x="0.512828" y="0.307044" z="1.02772"/>
<node id="{75d10124-3ee1-47f1-8e95-b397c0f35fe9}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.00652467" x="0.563839" y="0.302585" z="0.780169"/>
<node id="{76a160cd-60d5-4010-bd9a-6032c97f67b8}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.00789172" x="0.755719" y="0.068247" z="1.0946"/>
<node id="{78b55011-5b1b-4c44-9240-71968c7ad7f8}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0" x="0.695953" y="0.147049" z="1.11147"/>
<node id="{78daab6a-4bd3-44b5-b9a8-785d8e08bb78}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0069189" x="0.515287" y="0.184273" z="1.00346"/>
<node id="{796b1ebe-9414-4ec1-b58b-f3cdf6006d6e}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.0175657" x="0.488267" y="0.295112" z="0.788285"/>
<node id="{7a7cf872-03e0-4655-92e7-0af10466cc83}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.473324" y="0.317373" z="0.713406"/>
<node id="{7b04a282-03d9-4a06-bec2-b48417956ce9}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.0124613" x="0.49815" y="0.536441" z="1.01508"/>
<node id="{7b4bad9a-3192-479a-bc39-3d486444fe72}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.0124613" x="0.50195" y="0.541687" z="1.00836"/>
<node id="{7c5da7e3-9eab-47f1-9736-c53bcf1e8efa}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.00589328" x="0.744128" y="0.0609797" z="1.11563"/>
<node id="{7dfc521a-3f80-4e32-93c9-85fe7b84dd93}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0" x="0.482376" y="-0.00171058" z="1.00005"/>
<node id="{7e3c29a3-b4f3-466d-a888-a05b5e1704e6}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.00833715" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{7e6244ae-8921-4012-9dfd-badac7408adb}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.0033768" x="0.53444" y="0.421419" z="0.889157"/>
<node id="{7e852b72-9d70-4dfd-9bfc-f857d3dbbb16}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.00623065" x="0.50575" y="0.546933" z="1.00164"/>
<node id="{7f3333db-755a-4a86-a2d7-2126da8f6a49}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0" x="0.47453" y="0.202963" z="0.972421"/>
<node id="{80e3c868-985f-4c6d-a57d-34e359987138}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.00665101" x="0.452406" y="0.249066" z="0.995575"/>
<node id="{80faa256-324d-4c76-b4e6-491956155230}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.0109447" x="0.479416" y="0.100435" z="0.98661"/>
<node id="{818b69e5-7a8b-41dd-970a-90348c5b766c}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.00866923" x="0.563195" y="0.400594" z="0.874691"/>
<node id="{833ad6bd-3219-4093-9689-2f7cbe8ac8fc}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.00934199" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{8471ffad-53be-4a68-ab72-97d32d7308fc}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0138378" x="0.513406" y="0.20395" z="1.00963"/>
<node id="{84db1f93-1858-4a96-be7f-7a383a1430df}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.0173385" x="0.55361" y="0.407536" z="0.879513"/>
<node id="{84e6a0cf-c4e1-478c-8fed-a5cc25d9be5f}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.00573453" x="0.618263" y="0.233908" z="1.07994"/>
<node id="{8540d159-7f70-44d7-86d2-471873be9bdb}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00407143" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{85cd375b-8df3-4653-855e-2a7bb3f623fe}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.00756106" x="0.555869" y="0.341132" z="0.824651"/>
<node id="{85fceff6-5c5b-4882-9f92-e45d6c5613fe}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0" x="0.535248" y="0.292922" z="1.03142"/>
<node id="{8626c044-fef3-47d2-a38f-944010bdef05}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.00581841" x="0.555869" y="0.341132" z="0.824651"/>
<node id="{869cd102-81cd-4c15-b377-955b61d44d30}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0.0165943" x="0.513778" y="0.335641" z="0.823884"/>
<node id="{86a40600-8eac-4094-81a0-a1d698c94d2d}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.00760679" x="0.563839" y="0.302585" z="0.780169"/>
<node id="{86e86e5e-2ee3-46e3-ae87-6f88b27d3855}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" radius="0.0069189" x="0.512466" y="0.213789" z="1.01271"/>
<node id="{878d0098-c6f5-4a98-8e1e-d469396b6b4d}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0110956" x="0.606582" y="0.236632" z="1.06688"/>
<node id="{881104c8-1859-4bd6-8bc1-fe2f5e807e98}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0.00623065" x="0.494351" y="0.531195" z="1.0218"/>
<node id="{8b37e76a-099c-4b5d-af5c-26c1fe4f55ab}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0" x="0.76559" y="0.0526443" z="1.13977"/>
<node id="{8ba09bc4-ac19-42ad-8b41-31683e1dc872}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0" x="0.494981" y="0.290583" z="0.998667"/>
<node id="{8dc941af-cffe-4f7b-aa0a-b0db5a0e5e1d}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.314637" y="0.336525" z="0.713406"/>
<node id="{8e43cbd3-2aa9-4265-95b8-92056c4c4737}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.00536282" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{8f367bd2-114c-4d04-96c5-bbb53a16d8ba}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" radius="0.0120206" x="0.514997" y="0.205702" z="1.01567"/>
<node id="{90999c8b-a2c9-459f-847e-0fde4493fbff}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.00757784" x="0.522448" y="0.136762" z="1.01642"/>
<node id="{927f0b23-db5a-49e7-8d0f-bcc811f7752e}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.0151221" x="0.565433" y="0.335194" z="0.825821"/>
<node id="{9362b987-f419-4f31-bfaf-9539700ad242}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.0168282" x="0.519508" y="0.244335" z="1.0243"/>
<node id="{94362d37-639a-40ff-b191-5c0a6e19f664}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.0197157" x="0.457937" y="0.23754" z="0.989787"/>
<node id="{9530cb12-6d41-4bd3-8175-1ba24943e21b}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.000272999" x="0.569785" y="0.264018" z="0.742748"/>
<node id="{95ad6172-babb-45c4-a96d-4d734ba6a25e}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.00943412" x="0.52102" y="0.183891" z="0.984483"/>
<node id="{973af58c-b3f5-4346-b614-413eb42ca621}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.00736903" x="0.599025" y="0.238034" z="1.06653"/>
<node id="{979a9d6c-f734-4f25-a0fc-04310bd4646b}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00903996" x="0.513921" y="0.377636" z="1.03506"/>
<node id="{9a7851b9-a7e8-4666-a13e-5cb7a8cc09c4}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" radius="0.0188602" x="0.571346" y="0.295554" z="0.77051"/>
<node id="{9bf0c1e8-8582-442c-90a4-5037d7219b21}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.000953281" x="0.555869" y="0.341132" z="0.824651"/>
<node id="{9c766968-443b-4e52-88ce-f1f20d377b5c}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.00836663" x="0.492055" y="0.304378" z="0.779797"/>
<node id="{9c857bb2-10b3-45e0-8271-3272e88a8bd7}" partId="{acdc210c-e671-486e-9611-b9244c016807}" radius="0" x="0.490551" y="0.525949" z="1.02853"/>
<node id="{9d65e303-67cf-4bbb-ab6a-09120b410c7b}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0194515" x="0.519038" y="0.887627" z="1.02668"/>
<node id="{9db4d842-ce14-4854-a532-d10650139dfc}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.0170931" x="0.758187" y="0.0643464" z="1.10589"/>
<node id="{9e8b06ca-12a6-4927-bd46-4d3f479230ae}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.00943412" x="0.512466" y="0.213789" z="1.01271"/>
<node id="{a08ef2a3-d98f-44ab-9765-c725baf366dc}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0182872" x="0.515107" y="0.833052" z="1.01116"/>
<node id="{a0a9a94a-672a-45e8-a0bb-31be9300b41f}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00391173" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{a1101b66-19df-47af-9d58-822ff9eb26b9}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.0170931" x="0.760655" y="0.0604457" z="1.11718"/>
<node id="{a242b2bf-afe5-4672-aa61-e97e99e68a4c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00193612" x="0.675597" y="0.153363" z="1.08021"/>
<node id="{a370ab3d-5136-42d7-9aa9-ac3bed89d137}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0.00841411" x="0.520166" y="0.232048" z="1.02152"/>
<node id="{a3e0771b-c680-4c0c-8fcf-acd03fab6785}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00268242" x="0.452406" y="0.249066" z="0.995575"/>
<node id="{a3e169ff-fc5f-4dcd-b7c5-0a14fa29b73e}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.00730822" x="0.556137" y="0.283793" z="0.754356"/>
<node id="{a6209995-831e-4084-afeb-32704ca086bf}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.0141029" x="0.726014" y="0.097259" z="1.08104"/>
<node id="{a7137baa-7fe5-4d1c-b9f2-11b8bf6be38a}" partId="{b5812967-d429-4214-a11c-f04918089461}" radius="0.00854656" x="0.755719" y="0.068247" z="1.0946"/>
<node id="{a88191b2-a7cd-4b7a-be30-d5d97c3a0b48}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.0166743" x="0.517262" y="0.318385" z="1.04751"/>
<node id="{a9746f2b-b2ba-40a7-a405-d34b982c683f}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.0024147" x="0.540098" y="0.379707" z="0.858939"/>
<node id="{aa1e35db-d9de-48a1-9b6a-e18a54ac4435}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.013302" x="0.44725" y="0.241616" z="0.99539"/>
<node id="{aac479ee-6f32-4c7a-b2e6-5e2c1df8c251}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" radius="0.00682936" x="0.50575" y="0.546933" z="1.00164"/>
<node id="{adbd9948-2566-46d3-8603-0d4ecf4c9fa4}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.00878287" x="0.492055" y="0.304378" z="0.779797"/>
<node id="{adda25df-58c1-4e63-ba09-c05ec91ac643}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00123233" x="0.385379" y="0.176643" z="0.939178"/>
<node id="{aefc096e-5901-425f-a831-6a0ddbd50399}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.0157834" x="0.765485" y="0.0620907" z="1.09301"/>
<node id="{b1a5e801-c4b0-4478-aad0-41c40133502e}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0" x="0.497099" y="0.133608" z="1.0028"/>
<node id="{b1d0b918-225b-4399-a8d8-e90b84b5f5be}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" radius="0.0107256" x="0.524587" y="0.314053" z="1.03544"/>
<node id="{b256069f-8463-4f7d-b6e0-30af0bbf2898}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.0136868" x="0.685775" y="0.150206" z="1.09584"/>
<node id="{b31ca9d5-5b56-4c42-bebf-4d2d6aef739f}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.00136076" x="0.524949" y="0.382805" z="0.856618"/>
<node id="{b4b3a668-fd69-4887-ba98-abe5dae57101}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" radius="0.00866923" x="0.53444" y="0.421419" z="0.889157"/>
<node id="{b71171d7-1d32-46f7-8fca-fcc3a7a5a46e}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0101068" x="0.476764" y="0.0117885" z="0.996314"/>
<node id="{ba04e35f-5b85-46bf-84f6-f4b253125471}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0" x="0.588853" y="0.277802" z="0.751257"/>
<node id="{ba05b4f6-6652-449b-ad37-d4b09bda988b}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" radius="0.0136868" x="0.680686" y="0.151785" z="1.08803"/>
<node id="{ba2664a7-be02-420f-b744-931e66efefe0}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" radius="0.0147381" x="0.607639" y="0.232846" z="1.0705"/>
<node id="{baa52d8a-ed0e-4138-bc8b-6a72054cfe95}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.0146164" x="0.558704" y="0.290057" z="0.76296"/>
<node id="{bbab93bd-50a6-47f4-b608-00091b262e97}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.0188682" x="0.515317" y="0.203823" z="1.0033"/>
<node id="{bbdd82a9-286b-4c1c-b007-745c306e4f14}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0" x="0.594126" y="0.31738" z="0.829333"/>
<node id="{bd244a0f-1d5e-4307-85b7-f764e6c1304b}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" radius="0.00760679" x="0.5826" y="0.283998" z="0.758485"/>
<node id="{c1052900-009d-4ab3-9734-684f91bdab25}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0.00589328" x="0.755719" y="0.068247" z="1.0946"/>
<node id="{c1a57de4-5129-46f3-ace2-c662a6c079b8}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" radius="0.00756106" x="0.584562" y="0.323318" z="0.828163"/>
<node id="{c319f392-3b4d-4f01-a0f8-50ef45168844}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0" x="0.476903" y="0.267313" z="0.813748"/>
<node id="{c42a3e99-b6aa-4c26-8579-44228dd34b4b}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.00680655" x="0.466423" y="0.0276555" z="1.00169"/>
<node id="{c5cfd17f-ec0b-433b-b36b-f126b540b6a6}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00304648" x="0.512466" y="0.213789" z="1.01271"/>
<node id="{c62e9181-4388-4e00-a10a-8a61eb93c4ae}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0055478" x="0.599025" y="0.238034" z="1.06653"/>
<node id="{c78986e6-a263-42cf-b5f1-8b9fdc6f74a8}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" radius="0.0116368" x="0.546458" y="0.33313" z="0.836904"/>
<node id="{c7bd203d-7b04-47a9-a394-d7d1f18555c4}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.0109447" x="0.47718" y="0.0946081" z="0.981412"/>
<node id="{c8d861a6-491b-42d4-8e07-73e5df7c019b}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00318423" x="0.486602" y="0.285251" z="1.0181"/>
<node id="{c9174f26-59b1-4382-8214-bc4a91f1759e}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.00951228" x="0.550431" y="0.290628" z="1.04166"/>
<node id="{ccd8ef94-281b-4dfb-ab29-b50dfe17a770}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.0136131" x="0.464259" y="0.0358656" z="0.996163"/>
<node id="{ce3ca970-0d64-4ee1-92ef-8720f608f05f}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0056639" x="0.431826" y="-0.128762" z="0.951431"/>
<node id="{ce8a93e4-e574-4e93-82b1-fbd2ca77ef0f}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" radius="0" x="0.520823" y="0.219761" z="1.01874"/>
<node id="{cea888e7-491c-40e5-be50-e60137d4c8a4}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0.00547236" x="0.481651" y="0.106262" z="0.991808"/>
<node id="{cede8a6a-4e51-4c07-8581-0999b4705616}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.0177075" x="0.513452" y="0.310782" z="1.03548"/>
<node id="{cf6b2e2b-89ef-442c-87ca-74d86de7afdc}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" radius="0.00349248" x="0.572339" y="0.280627" z="1.0527"/>
<node id="{cf75b27e-3656-4130-8543-d07cbc98b9c9}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.377565" y="0.340629" z="0.713406"/>
<node id="{d043181f-393b-4e20-8ad5-bc2c04e61bfd}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" radius="0.00878287" x="0.480691" y="0.27658" z="0.80526"/>
<node id="{d1325b2e-e338-4239-9988-1d1dc6c44a6d}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" radius="0.00573453" x="0.599025" y="0.238034" z="1.06653"/>
<node id="{d2de90d6-ac0c-4bdd-b5e3-573960fad70c}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.00622413" x="0.53858" y="0.264806" z="1.03477"/>
<node id="{d2f4e68c-bc10-46d3-b82c-aadf00fa23e2}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" radius="0.00730822" x="0.563839" y="0.302585" z="0.780169"/>
<node id="{d36ed08a-2202-41de-9601-76d275344502}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0.0167333" x="0.507709" y="0.286489" z="0.771924"/>
<node id="{d5be35fe-16ec-40bd-b41b-d92171f18a01}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0" x="0.50371" y="0.177526" z="1.0146"/>
<node id="{d69b0b89-1efb-4918-baf5-d0cc0d5b972c}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0.00680655" x="0.459929" y="0.0522857" z="0.985105"/>
<node id="{d7bf67d3-f4df-45b3-8a40-2dabc5e41d32}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" radius="0" x="0.523364" y="0.268599" z="0.764051"/>
<node id="{d866de28-dae4-40ce-b547-81e4cf5c1bfc}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" radius="0" x="0.740264" y="0.0585572" z="1.12263"/>
<node id="{da2809c9-3b46-4621-a9da-abfa3839f9f5}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0" x="0.755395" y="0.0423452" z="1.0619"/>
<node id="{daa6e549-8d8c-4219-b312-84b523aa4f51}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0.00660156" x="0.452406" y="0.249066" z="0.995575"/>
<node id="{dc0aaf45-eb00-49b6-8e81-fa979245ac09}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0124874" x="0.50575" y="0.546933" z="1.00164"/>
<node id="{dedcce23-b5ab-4e30-a62a-29155b8d5e2a}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" radius="0.0056639" x="0.44197" y="-0.109533" z="0.938581"/>
<node id="{df693fdf-c112-4501-afcc-243afa0c4611}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.00934199" x="0.501494" y="0.298212" z="1.0082"/>
<node id="{dfd92d67-a666-4f9e-a606-217795b284cc}" partId="{092b0f10-67c1-4032-9c49-168067836057}" radius="0.00284921" x="0.499048" y="0.16079" z="1.02006"/>
<node id="{e04cf7e6-1351-49fc-acd7-67ea3641d678}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.00985783" x="0.468999" y="0.214489" z="0.97821"/>
<node id="{e08afd53-006d-4434-9905-0ef150d16cd9}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.00541154" x="0.499048" y="0.16079" z="1.02006"/>
<node id="{e2bae992-d1d2-4fdd-9a30-dba9c62f5322}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.00885373" x="0.49829" y="0.290152" z="1.03287"/>
<node id="{e2f0521a-2b2d-4c9b-b806-d6f4c2d078f4}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" radius="0.0188682" x="0.518169" y="0.193857" z="0.993893"/>
<node id="{e3592e6e-2c54-4f3c-8745-e35f79c472d2}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" radius="0.00174188" x="0.53444" y="0.421419" z="0.889157"/>
<node id="{e3a311f1-ab14-4e80-80dc-9f882721d9a8}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" radius="0.00196966" x="0.419713" y="0.213334" z="0.965049"/>
<node id="{e5a7a6e8-c4de-4ea6-a175-93b87b709bee}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" radius="0.0108231" x="0.498561" y="0.153995" z="1.01574"/>
<node id="{e5afd1fe-e4a7-4e2a-90cf-1cb2a55fe07e}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" radius="0" x="0.536854" y="0.311372" z="0.83963"/>
<node id="{e5cbc93e-98eb-45b3-9046-1d60f009b382}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" radius="0.00833715" x="0.509718" y="0.312963" z="1.06896"/>
<node id="{e785bb5a-3352-4545-a008-17d16d82c906}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" radius="0.0130493" x="0.55647" y="0.297305" z="0.78381"/>
<node id="{e79795d5-e758-4acb-8559-7f1033c9b02f}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" radius="0.005" x="0.343365" y="0.340629" z="0.713406"/>
<node id="{e7bc4edf-781b-4916-8abe-a304cda6ae75}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.0139845" x="0.755557" y="0.0552961" z="1.07825"/>
<node id="{e90118b2-e7ef-4ebc-ba06-784613255d46}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" radius="0.018684" x="0.51452" y="0.313468" z="1.02725"/>
<node id="{e94df7f8-d0ca-478e-aed1-25fa8d60b9fd}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" radius="0.0125109" x="0.498141" y="0.151655" z="1.01815"/>
<node id="{eb4fb92f-f8ea-49ef-b132-ae6b72fa6ea4}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" radius="0.0202136" x="0.465541" y="0.0387866" z="0.988842"/>
<node id="{eb6898b8-464b-4d10-9c56-9479d47438af}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" radius="0" x="0.47271" y="0.0829541" z="0.971016"/>
<node id="{ebe51975-e81f-45a6-aa7d-ca216cc56c8b}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.0163502" x="0.499188" y="0.266314" z="1.01076"/>
<node id="{ebe6c9ed-8cd5-4d44-acda-3846acf13ec1}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.00817509" x="0.486602" y="0.285251" z="1.0181"/>
<node id="{edb9977c-0dd1-4472-8534-dbeb127c9d16}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.00705143" x="0.710183" y="0.110714" z="1.07757"/>
<node id="{eddf44c5-0c61-446b-a724-4456c024978a}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" radius="0" x="0.432757" y="0.219074" z="0.989657"/>
<node id="{ee43d10c-d4f1-4315-a3c2-618c2ce40d6a}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0" x="0.52056" y="0.478958" z="0.917544"/>
<node id="{f06b2588-283a-4bcc-a9e5-00f5cb6c9c57}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" radius="0.0181634" x="0.480017" y="0.0931144" z="0.99489"/>
<node id="{f17183a2-5ecc-4b81-9399-5d3cfbb2eea2}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" radius="0" x="0.468588" y="0.0194454" z="1.00722"/>
<node id="{f1d52a81-d771-49f4-96f7-079e891415be}" partId="{62493532-0802-4e69-af81-89a1e382185d}" radius="0.0139845" x="0.755638" y="0.0617716" z="1.08642"/>
<node id="{f2778fa6-19d7-47dd-afc8-1e4f355c6475}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.00628206" x="0.508725" y="0.300017" z="1.02319"/>
<node id="{f419bd71-f788-4382-9479-6cc8b7e240c4}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.00951228" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{f5692d54-1eb7-4c3c-8e99-5323bd0046d4}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" radius="0.0190246" x="0.540632" y="0.300784" z="1.04004"/>
<node id="{f5c1ef85-7999-4224-845f-cfc4e07e2ef3}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0051308" x="0.53799" y="0.208533" z="1.01087"/>
<node id="{f6050cf2-105d-43b6-ade2-625e690e55f8}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" radius="0.0163502" x="0.492895" y="0.275783" z="1.01443"/>
<node id="{f650f5b5-094c-41d1-b3b2-ece8be532cc1}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" radius="0.0197157" x="0.463468" y="0.226014" z="0.983998"/>
<node id="{f738f338-39e1-495e-a94e-5e914d4d5317}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" radius="0" x="0.515228" y="0.116487" z="1.0404"/>
<node id="{f797fc7d-48c3-4a02-8215-11b2575f7982}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" radius="0.00623232" x="0.512466" y="0.213789" z="1.01271"/>
<node id="{f7984a7e-fd12-4428-8e71-9b9e913492fb}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" radius="0.013302" x="0.442093" y="0.234165" z="0.995204"/>
<node id="{f7c408de-4dc2-4201-8ab9-f02c04a19893}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" radius="0.0169183" x="0.509819" y="0.77672" z="1.03141"/>
<node id="{f7c9ef1b-11cc-4f1e-b217-322279b063b3}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" radius="0.00789172" x="0.785019" y="0.0497782" z="1.08983"/>
<node id="{f8e96450-96e9-4f56-b89c-3c74d76de271}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" radius="0.0141029" x="0.718098" y="0.103986" z="1.07931"/>
<node id="{fb5b878a-9ef0-4869-9dc9-4e8d6f623440}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" radius="0.0110956" x="0.614139" y="0.23523" z="1.06723"/>
<node id="{fcba37c4-7372-43df-9d2e-5404cc9a1b91}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" radius="0.00937295" x="0.521301" y="0.507458" z="0.965918"/>
<node id="{fd311c21-d781-4437-bfd3-414ae999f244}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" radius="0.0177075" x="0.505871" y="0.300467" z="1.03418"/>
<node id="{fd8dd98f-7c73-48e4-bdf0-904f2e2271e5}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" radius="0.000615901" x="0.563839" y="0.302585" z="0.780169"/>
<node id="{fda59363-53f2-4d4d-a6ad-dce8aee17257}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" radius="0.00628206" x="0.521034" y="0.321097" z="1.03678"/>
<node id="{fe831613-5b6a-43f2-a789-b7c0ce027d0a}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" radius="0.0151557" x="0.506848" y="0.152781" z="1.01884"/>
</nodes>
<edges>
<edge from="{6c9d6544-ff34-4259-8d31-72393a4d7629}" id="{0096dcff-d08a-41e2-9c15-cc57943d039f}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{05438075-6182-4f45-80c2-35625897b718}"/>
<edge from="{067095a4-8e69-40d7-bc00-9c0a7f4e1e3c}" id="{01176b68-f37c-4738-9f49-ba5b00869789}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{c5cfd17f-ec0b-433b-b36b-f126b540b6a6}"/>
<edge from="{86e86e5e-2ee3-46e3-ae87-6f88b27d3855}" id="{020cc0b2-ca8d-44ee-86aa-69b35311fdfa}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{8471ffad-53be-4a68-ab72-97d32d7308fc}"/>
<edge from="{e2f0521a-2b2d-4c9b-b806-d6f4c2d078f4}" id="{033ddc37-8b89-4f86-b344-0955e617f39e}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{95ad6172-babb-45c4-a96d-4d734ba6a25e}"/>
<edge from="{df693fdf-c112-4501-afcc-243afa0c4611}" id="{0359760c-8bbe-4290-88e6-ac58b26abc87}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{8ba09bc4-ac19-42ad-8b41-31683e1dc872}"/>
<edge from="{3932e31f-34f7-47da-8a0d-032bec47e53c}" id="{03e45417-242e-4896-b1f5-2e2c3354943e}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{5a7cf847-a78d-4877-9d4f-94cd9bb9eca8}"/>
<edge from="{78daab6a-4bd3-44b5-b9a8-785d8e08bb78}" id="{047b1783-1287-4175-91cd-771c9f57e81e}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{734ab0d5-d4d8-485a-b521-ebd36a3a8720}"/>
<edge from="{b31ca9d5-5b56-4c42-bebf-4d2d6aef739f}" id="{05675c45-4b4d-4ca1-9ef9-34dc12c16a9d}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" to="{221a1797-ed67-4cfd-9cd8-34823e651ed3}"/>
<edge from="{28381152-78fe-4c2d-8c3c-c776138efa17}" id="{059c952e-c740-42a3-b8b9-201b71f59f88}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{117ef567-17a0-425e-9fcb-ae1610e91539}"/>
<edge from="{a1101b66-19df-47af-9d58-822ff9eb26b9}" id="{08183a72-f98a-486c-a5fc-1fbdd8388ce4}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{0b4f4946-8ff1-4efe-bdfe-0b611af6a655}"/>
<edge from="{dedcce23-b5ab-4e30-a62a-29155b8d5e2a}" id="{09104af4-aaaa-476b-a2ca-14037f001996}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{28381152-78fe-4c2d-8c3c-c776138efa17}"/>
<edge from="{071305c7-8044-4c28-8ccc-4f74cffb61cc}" id="{096d65ab-e733-487d-9134-a295c3cad472}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{0711915a-a413-42b5-8022-35668c45d39b}"/>
<edge from="{55b5bb5d-d614-4cd3-b331-8819186ed572}" id="{0a23f811-2056-415d-83fa-d7c16be92cc2}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{dc0aaf45-eb00-49b6-8e81-fa979245ac09}"/>
<edge from="{4c81714b-6ac4-45d8-b4f0-c98539911521}" id="{0a325591-d1f0-490b-a602-57396ad4d84e}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{3cce2c34-9aab-46dc-bbd3-3a73327a8875}"/>
<edge from="{d1325b2e-e338-4239-9988-1d1dc6c44a6d}" id="{0b95966e-58f0-48f9-b474-8d6af804f41f}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{36e6565b-5c7c-4203-9757-b7afa6731c57}"/>
<edge from="{cf75b27e-3656-4130-8543-d07cbc98b9c9}" id="{0b9bf276-d38e-44bb-a0ed-47037621de51}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{4c81714b-6ac4-45d8-b4f0-c98539911521}"/>
<edge from="{1b515278-0117-48fe-a1fe-e772057573d9}" id="{0c223e7d-82d3-40d2-b5e9-47a11ac3f7d6}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{58bd7c83-b479-4e17-b4df-754316eef264}"/>
<edge from="{c78986e6-a263-42cf-b5f1-8b9fdc6f74a8}" id="{0d097ed2-6598-46f3-ac76-381fecf64297}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{58321009-70bf-48ba-bbe7-f5afcd9e56f3}"/>
<edge from="{9c766968-443b-4e52-88ce-f1f20d377b5c}" id="{0d263e4e-5038-4640-bbab-e9f346dde7fc}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{4029708e-b1f7-4f53-832e-d0983bfcd651}"/>
<edge from="{a242b2bf-afe5-4672-aa61-e97e99e68a4c}" id="{0e574fe6-7f52-4218-bdd0-4a2950e2a97f}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{751fee8a-4d20-44bf-b68f-24b908abf032}"/>
<edge from="{e94df7f8-d0ca-478e-aed1-25fa8d60b9fd}" id="{0fda6aea-37d5-4b90-9848-c5bcdb037f5e}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{1957320f-7dec-4069-a2b2-502d9a18442e}"/>
<edge from="{1c85074d-db26-4962-9694-26df45d957c6}" id="{0ff4697b-f1cf-4ba4-9980-21185fc9346b}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{1b515278-0117-48fe-a1fe-e772057573d9}"/>
<edge from="{e08afd53-006d-4434-9905-0ef150d16cd9}" id="{11530bb9-039f-4978-add5-ac73b953a642}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{e5a7a6e8-c4de-4ea6-a175-93b87b709bee}"/>
<edge from="{74620eab-e43b-44e3-be3a-68f3838cda88}" id="{13ed1669-4641-4c72-b633-c689cf72774b}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{e5cbc93e-98eb-45b3-9046-1d60f009b382}"/>
<edge from="{751fee8a-4d20-44bf-b68f-24b908abf032}" id="{143d5474-8a3d-4dcc-a628-d6a248c14426}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{52cc908a-1fa5-415d-9d64-51bb469706d7}"/>
<edge from="{ce3ca970-0d64-4ee1-92ef-8720f608f05f}" id="{15b5d349-7cae-47c2-84a9-c453a3b9525d}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{4b7f18aa-704e-4f55-9f69-16b0f38237ce}"/>
<edge from="{94362d37-639a-40ff-b191-5c0a6e19f664}" id="{164e77ed-3ed5-4eae-bb17-95fc1050d41c}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{f650f5b5-094c-41d1-b3b2-ece8be532cc1}"/>
<edge from="{979a9d6c-f734-4f25-a0fc-04310bd4646b}" id="{16adf7ad-d523-471c-bf19-7f7061996f65}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{0a8e8fb2-9858-49d2-8686-6ed728dccbc2}"/>
<edge from="{8540d159-7f70-44d7-86d2-471873be9bdb}" id="{17b22263-b406-4709-b49a-a678eff4c7ed}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{067095a4-8e69-40d7-bc00-9c0a7f4e1e3c}"/>
<edge from="{9db4d842-ce14-4854-a532-d10650139dfc}" id="{194e24c6-3018-4ae0-b9df-661cfdaeaf8a}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{a1101b66-19df-47af-9d58-822ff9eb26b9}"/>
<edge from="{aac479ee-6f32-4c7a-b2e6-5e2c1df8c251}" id="{1e0061ef-fe00-4405-9933-f6c47df15f7d}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{6dea3dfc-6305-4221-81f8-d59379db1f8c}"/>
<edge from="{e7bc4edf-781b-4916-8abe-a304cda6ae75}" id="{1e13cfd6-41dd-4eb3-a927-a5f4eadec2c4}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{44e13dd8-a3d2-4d4f-af81-372da15218d2}"/>
<edge from="{353010d5-28a2-4ce3-a465-12289cbadb21}" id="{1e500235-b08c-40a9-84ae-50884a9cebaa}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{567a286a-bf1d-4291-b979-ba69733646f5}"/>
<edge from="{7285fcb8-4779-4e60-a474-4641c0943463}" id="{1ec67251-fbda-4557-b1e7-571366b78c01}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{2cc27239-bf74-49d5-b82d-0998c0103d6d}"/>
<edge from="{cede8a6a-4e51-4c07-8581-0999b4705616}" id="{206685c9-6f62-42e1-a882-b8c77b81d8c1}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{fd311c21-d781-4437-bfd3-414ae999f244}"/>
<edge from="{7153e3f6-ba74-4b9a-9a48-1f6b454b3678}" id="{21503cae-2040-4dca-804b-6121ad0c87f4}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{9362b987-f419-4f31-bfaf-9539700ad242}"/>
<edge from="{199423e1-60c0-4b3c-b65a-3ab127cadf99}" id="{228c7b8d-ee59-401d-8ad9-ad209eed864a}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{1c85074d-db26-4962-9694-26df45d957c6}"/>
<edge from="{aa1e35db-d9de-48a1-9b6a-e18a54ac4435}" id="{23248007-e8ab-41b9-a06e-b7e2030b7737}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{f7984a7e-fd12-4428-8e71-9b9e913492fb}"/>
<edge from="{ba2664a7-be02-420f-b744-931e66efefe0}" id="{2334c6c9-8937-4ca3-8ba3-fadf7bf22add}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{404cdbf7-ef7b-4529-b04b-d775162d0edb}"/>
<edge from="{80e3c868-985f-4c6d-a57d-34e359987138}" id="{23d3917a-6afd-4d2e-9e7e-3d5192bad5bc}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{aa1e35db-d9de-48a1-9b6a-e18a54ac4435}"/>
<edge from="{f797fc7d-48c3-4a02-8215-11b2575f7982}" id="{25d4d757-7c7a-4e49-91c1-1c1331da8631}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{442d48bd-1797-45dc-8e4f-d121fb89237c}"/>
<edge from="{379bec20-9be3-4a64-b259-d3ed4e84ebbc}" id="{263c2d30-e148-4a3c-bc8d-a5288a19b0d2}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{ba05b4f6-6652-449b-ad37-d4b09bda988b}"/>
<edge from="{491add8b-4be8-4171-b647-24334b050892}" id="{26f34c35-7953-4d1d-9817-69bdcc8407ad}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{eb6898b8-464b-4d10-9c56-9479d47438af}"/>
<edge from="{a08ef2a3-d98f-44ab-9765-c725baf366dc}" id="{286131bc-5708-43b9-b354-24b62c64954c}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{f7c408de-4dc2-4201-8ab9-f02c04a19893}"/>
<edge from="{b1d0b918-225b-4399-a8d8-e90b84b5f5be}" id="{286e9d03-480a-4fbc-aeaf-db6df72b15dd}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{5064c6c5-783a-44e5-8e70-49c8c9cc2416}"/>
<edge from="{7b4bad9a-3192-479a-bc39-3d486444fe72}" id="{2920953c-c0ce-42ec-9ed4-6260647a45f0}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{7b04a282-03d9-4a06-bec2-b48417956ce9}"/>
<edge from="{f7c9ef1b-11cc-4f1e-b217-322279b063b3}" id="{2a4d76e0-cffe-40d0-a0d0-68880c787890}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{10d61f38-3849-4852-9dd1-2be2ad90d468}"/>
<edge from="{cf6b2e2b-89ef-442c-87ca-74d86de7afdc}" id="{2abfe96f-0c4b-41c3-8985-9525a5d0598c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{408119ac-6fc0-40f5-b60c-99b7cc9517ae}"/>
<edge from="{15283e25-d483-44c6-b530-113073ae54d0}" id="{2b9ff78a-67ef-4314-ae2e-6ff837fa5dfe}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{869cd102-81cd-4c15-b377-955b61d44d30}"/>
<edge from="{aefc096e-5901-425f-a831-6a0ddbd50399}" id="{2bd8eed2-1818-42ff-a5bc-5a69c04c9710}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{6394e5cc-a367-4664-a9af-753d41b82ba6}"/>
<edge from="{a0a9a94a-672a-45e8-a0bb-31be9300b41f}" id="{2fa4feb6-24c7-42a4-9747-d3b9a86047fc}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{cf6b2e2b-89ef-442c-87ca-74d86de7afdc}"/>
<edge from="{4684632b-e51c-414e-aa21-df1ee91ea834}" id="{30ee3f2e-eda0-4038-b30e-13f2635a5b24}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{d043181f-393b-4e20-8ad5-bc2c04e61bfd}"/>
<edge from="{796b1ebe-9414-4ec1-b58b-f3cdf6006d6e}" id="{32b0e144-7a1b-4ccf-9c59-05e1b504344b}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{4684632b-e51c-414e-aa21-df1ee91ea834}"/>
<edge from="{44e13dd8-a3d2-4d4f-af81-372da15218d2}" id="{3375cef7-ad82-44fc-b7a9-1eade3908a5d}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{da2809c9-3b46-4621-a9da-abfa3839f9f5}"/>
<edge from="{6fd6b2c1-ab1f-4904-ac30-2f800bbfc95a}" id="{338bc346-e040-404b-be5d-d986734f8055}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{7e6244ae-8921-4012-9dfd-badac7408adb}"/>
<edge from="{9d65e303-67cf-4bbb-ab6a-09120b410c7b}" id="{33b9ba1c-f491-4ac4-95f1-b5db2ba17afd}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{a08ef2a3-d98f-44ab-9765-c725baf366dc}"/>
<edge from="{e04cf7e6-1351-49fc-acd7-67ea3641d678}" id="{34179ba5-9481-4bb6-984a-390c87e013c9}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{7f3333db-755a-4a86-a2d7-2126da8f6a49}"/>
<edge from="{973af58c-b3f5-4346-b614-413eb42ca621}" id="{34c6b443-96c5-4c99-bfe5-8e78332609e4}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{ba2664a7-be02-420f-b744-931e66efefe0}"/>
<edge from="{6d6619eb-70e2-48e4-b8a6-0ff52d14584b}" id="{35e4a4db-5369-409e-977d-4c58ea33a724}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{fe831613-5b6a-43f2-a789-b7c0ce027d0a}"/>
<edge from="{927f0b23-db5a-49e7-8d0f-bcc811f7752e}" id="{365ffd29-e221-4516-9156-775ed09c8f04}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{27430d2c-0651-4361-a581-d304fcd67e22}"/>
<edge from="{84e6a0cf-c4e1-478c-8fed-a5cc25d9be5f}" id="{39385155-0aff-47ae-a9b5-f0d9a78424a8}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{001eb845-4bed-4de5-9803-ba8ca7faafaf}"/>
<edge from="{80faa256-324d-4c76-b4e6-491956155230}" id="{39b7e869-e586-4943-b6e5-76214e99d6b4}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{c7bd203d-7b04-47a9-a394-d7d1f18555c4}"/>
<edge from="{3547bb94-25b4-4740-a5e9-15046267f0f9}" id="{3a2dab82-5eb6-46db-b4b8-1afe92b105f7}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{3424cf20-48a1-4e64-be63-5890321cdbcd}"/>
<edge from="{05438075-6182-4f45-80c2-35625897b718}" id="{3b7d0700-ee48-4c52-8713-e89755f6ec41}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{b1a5e801-c4b0-4478-aad0-41c40133502e}"/>
<edge from="{2501c90c-247d-42a1-b2fb-411d88b95e3a}" id="{3cc889ef-5ff2-4655-abe0-fa4878665305}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{02b8c92c-3aad-43b4-b2d6-eb0659a8a206}"/>
<edge from="{833ad6bd-3219-4093-9689-2f7cbe8ac8fc}" id="{3cf1514d-d956-4da8-99b4-71606e8e63ef}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{e90118b2-e7ef-4ebc-ba06-784613255d46}"/>
<edge from="{15d886b0-181e-4e8d-84c4-21da599037c1}" id="{3eb0a7d3-a446-44b5-aab5-aaefb5d1c4ab}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{78b55011-5b1b-4c44-9240-71968c7ad7f8}"/>
<edge from="{8471ffad-53be-4a68-ab72-97d32d7308fc}" id="{3f4c2320-2fa7-4e68-877c-14b3f2e654d4}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{1ad678c9-b640-43d5-af1c-92ddfc540416}"/>
<edge from="{3cce2c34-9aab-46dc-bbd3-3a73327a8875}" id="{3ffc3ed2-4a9b-4b83-ab9f-52d4e3ba1384}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{7a7cf872-03e0-4655-92e7-0af10466cc83}"/>
<edge from="{8f367bd2-114c-4d04-96c5-bbb53a16d8ba}" id="{4180a4e0-22b4-474e-8fcf-cb78f8798906}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{0c131c2e-c763-4239-aae8-c71e219bb2ff}"/>
<edge from="{869cd102-81cd-4c15-b377-955b61d44d30}" id="{41fa76f3-3cbc-4858-a1c2-a2f037f4be88}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{0c3ed74f-ee80-41a9-8568-1487fe0cfd7c}"/>
<edge from="{b256069f-8463-4f7d-b6e0-30af0bbf2898}" id="{438257ce-1dbc-45c7-bf9f-360907a4b00e}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{15d886b0-181e-4e8d-84c4-21da599037c1}"/>
<edge from="{f5692d54-1eb7-4c3c-8e99-5323bd0046d4}" id="{45ba05df-2fcc-4a3b-86dd-13711499cf8d}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{c9174f26-59b1-4382-8214-bc4a91f1759e}"/>
<edge from="{651c39df-7b14-4fd3-beb3-592efcb25842}" id="{46be5837-af25-4f49-b837-c7b3fc309c37}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{b71171d7-1d32-46f7-8fca-fcc3a7a5a46e}"/>
<edge from="{e3592e6e-2c54-4f3c-8745-e35f79c472d2}" id="{47fa200b-6705-4cb5-bc1b-cb45fcc18270}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" to="{b31ca9d5-5b56-4c42-bebf-4d2d6aef739f}"/>
<edge from="{e3a311f1-ab14-4e80-80dc-9f882721d9a8}" id="{48a71f2a-4ad8-482d-b933-906b736c0cc6}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{adda25df-58c1-4e63-ba09-c05ec91ac643}"/>
<edge from="{14a9c743-142c-43a6-8962-5dbf6514c38a}" id="{49d839bf-7531-4776-b435-bc2a21782b46}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{f06b2588-283a-4bcc-a9e5-00f5cb6c9c57}"/>
<edge from="{e90118b2-e7ef-4ebc-ba06-784613255d46}" id="{4c297f88-7c9a-4e36-a0ff-d295a505eb02}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{66c32673-0a5b-4c93-8dd8-26ea2e206aa9}"/>
<edge from="{fda59363-53f2-4d4d-a6ad-dce8aee17257}" id="{4ec12ae8-59aa-4aea-8ae5-9adcc1c67b3f}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{5399b1af-6473-4df5-96cc-13e6e28784c1}"/>
<edge from="{e5cbc93e-98eb-45b3-9046-1d60f009b382}" id="{4ef7427a-44a6-4fbe-8a22-83b42145a363}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{53f27881-5a75-4c22-b2cf-7b2d05ee1d8e}"/>
<edge from="{73951d38-c2aa-4577-927b-7e9429d1f0db}" id="{539667f3-9c26-4d41-9730-4059d5a6c8fc}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{5e465c5c-fdc5-4c81-95dc-4729f981df5c}"/>
<edge from="{ccd8ef94-281b-4dfb-ab29-b50dfe17a770}" id="{5705b308-086e-4ea6-81cf-f78578bff77e}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{c42a3e99-b6aa-4c26-8579-44228dd34b4b}"/>
<edge from="{2cc27239-bf74-49d5-b82d-0998c0103d6d}" id="{576f4162-98f4-47f5-98a5-eba433e68ffa}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{55b5bb5d-d614-4cd3-b331-8819186ed572}"/>
<edge from="{7293a322-fbad-4c7b-a059-606020ff09bf}" id="{588e7c89-c53e-48e5-953e-4bd17eafe928}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{0402a0e9-9712-4d9c-b022-ea25f2ed64d0}"/>
<edge from="{bd244a0f-1d5e-4307-85b7-f764e6c1304b}" id="{58a164c5-d67e-4597-92aa-31bf56c6b16b}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{ba04e35f-5b85-46bf-84f6-f4b253125471}"/>
<edge from="{878d0098-c6f5-4a98-8e1e-d469396b6b4d}" id="{599287d2-a889-4443-a149-304f130c7e9e}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{fb5b878a-9ef0-4869-9dc9-4e8d6f623440}"/>
<edge from="{b71171d7-1d32-46f7-8fca-fcc3a7a5a46e}" id="{5b8dcc57-24a0-4e1d-92fb-630579900ff7}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{7dfc521a-3f80-4e32-93c9-85fe7b84dd93}"/>
<edge from="{71b98c98-8654-42d8-b58a-22688b722630}" id="{5bc071b7-b164-480a-82ca-729c0a445d3a}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{2b2d6ee4-f105-491c-b098-4de0613fd37c}"/>
<edge from="{70da7060-9223-4ac9-b6ca-ea16eeb20d45}" id="{5e30a9e5-db47-4b49-8c3f-601afaab621a}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{eb4fb92f-f8ea-49ef-b132-ae6b72fa6ea4}"/>
<edge from="{7c5da7e3-9eab-47f1-9736-c53bcf1e8efa}" id="{5faa9c7b-f509-4106-aeee-cbb81c2aa3a3}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{d866de28-dae4-40ce-b547-81e4cf5c1bfc}"/>
<edge from="{29686a15-7ddb-4717-a196-0412164025ef}" id="{60dcc41c-64d1-4c2b-ae3f-467026314d1e}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{567bcfd4-255f-478d-a9fe-362f2f832ff6}"/>
<edge from="{096379fc-4ca1-4c6d-b242-e353a20ffc88}" id="{61540c56-b89f-4001-b8a2-6dcc7315b687}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{84e6a0cf-c4e1-478c-8fed-a5cc25d9be5f}"/>
<edge from="{1ad678c9-b640-43d5-af1c-92ddfc540416}" id="{64323832-f151-4a98-9a2e-24041c1a43c3}" partId="{9279a14a-691a-436c-ae9e-efd74fa28300}" to="{78daab6a-4bd3-44b5-b9a8-785d8e08bb78}"/>
<edge from="{644464d2-775c-42ec-8544-206fe7d11fe7}" id="{69c93b35-b766-4ee8-a0ad-7eab683e6695}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{cede8a6a-4e51-4c07-8581-0999b4705616}"/>
<edge from="{308ce17b-2a9a-4e10-b3f6-aaed5190c957}" id="{6a9b4c34-ad0a-4deb-a02e-d72827a5da23}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{c78986e6-a263-42cf-b5f1-8b9fdc6f74a8}"/>
<edge from="{59fe931d-cbf2-47e6-b35e-0edcf8ad6830}" id="{6b38b65e-ab44-4303-a8c7-968005637564}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{516a356a-f5a0-4c65-9f17-8d186eeccaa2}"/>
<edge from="{a7137baa-7fe5-4d1c-b9f2-11b8bf6be38a}" id="{6b4abfec-cf01-42b3-8a19-f8761917760d}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{9db4d842-ce14-4854-a532-d10650139dfc}"/>
<edge from="{36e6565b-5c7c-4203-9757-b7afa6731c57}" id="{6da3668f-63de-4950-a7b4-5682d201c02f}" partId="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" to="{096379fc-4ca1-4c6d-b242-e353a20ffc88}"/>
<edge from="{221a1797-ed67-4cfd-9cd8-34823e651ed3}" id="{6e701462-7cf7-4666-90e8-f4b2ed413d33}" partId="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" to="{172dd203-fbf9-4d7f-aafe-b751b7f943de}"/>
<edge from="{5df7e38f-b9da-4c41-800c-56b5d25952b6}" id="{70368d24-9515-4d8f-9bb6-b143f4d3d8c8}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{17722f68-bf1b-49d6-a22a-44a5fd7cd1f4}"/>
<edge from="{fb5b878a-9ef0-4869-9dc9-4e8d6f623440}" id="{70970648-a7b5-4260-9623-61db470328df}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{29686a15-7ddb-4717-a196-0412164025ef}"/>
<edge from="{d36ed08a-2202-41de-9601-76d275344502}" id="{724ad440-1f0d-404c-b441-558e58fd6c93}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{6e591cdf-09bd-478c-a604-ac7d19acf528}"/>
<edge from="{8626c044-fef3-47d2-a38f-944010bdef05}" id="{74862140-774e-4429-838c-223ccff72d7e}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{308ce17b-2a9a-4e10-b3f6-aaed5190c957}"/>
<edge from="{7e6244ae-8921-4012-9dfd-badac7408adb}" id="{74c25298-da73-43bc-a7fe-40c75eed6b34}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{a9746f2b-b2ba-40a7-a405-d34b982c683f}"/>
<edge from="{7e3c29a3-b4f3-466d-a888-a05b5e1704e6}" id="{777c6a01-f0be-4cb6-a74f-cb950c3e8b5f}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{a88191b2-a7cd-4b7a-be30-d5d97c3a0b48}"/>
<edge from="{593f1c87-b152-41e0-98b6-07acf061f646}" id="{7799b90a-9c5e-4b32-a610-ec181002a01f}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{85fceff6-5c5b-4882-9f92-e45d6c5613fe}"/>
<edge from="{02b8c92c-3aad-43b4-b2d6-eb0659a8a206}" id="{7c86ab40-166d-4f83-af3f-63d90d17e638}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{052c2ec6-ad61-40af-b659-14a23612734d}"/>
<edge from="{1957320f-7dec-4069-a2b2-502d9a18442e}" id="{7dbfa944-373a-4c17-8ea1-f548966712ee}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{3b94ce3c-27ef-41af-87d1-4227ca2045f1}"/>
<edge from="{f8e96450-96e9-4f56-b89c-3c74d76de271}" id="{7e253ecf-5b0a-45b2-892c-71af785070c8}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{a6209995-831e-4084-afeb-32704ca086bf}"/>
<edge from="{4d0f2620-8a2a-496f-ad0a-4d8002493035}" id="{81331cbb-946a-4bfc-b4b6-37a13584570c}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{8f367bd2-114c-4d04-96c5-bbb53a16d8ba}"/>
<edge from="{ebe51975-e81f-45a6-aa7d-ca216cc56c8b}" id="{81430c8e-0e44-4045-8f2d-67c76fc7b496}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{0434ac30-312c-4b70-984e-5a0971e9eb75}"/>
<edge from="{17408e0e-5237-45ce-8f5c-de1034fcf23c}" id="{84411218-19f4-449c-815c-48c6c9eac63f}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{a242b2bf-afe5-4672-aa61-e97e99e68a4c}"/>
<edge from="{e785bb5a-3352-4545-a008-17d16d82c906}" id="{84ecd97a-3e83-4722-bdcd-ed3777f960fc}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{71b98c98-8654-42d8-b58a-22688b722630}"/>
<edge from="{c62e9181-4388-4e00-a10a-8a61eb93c4ae}" id="{87e83f14-914d-47a6-848a-7faac287e6ec}" partId="{80845e66-2299-48ca-8cbf-77b55a536c0c}" to="{878d0098-c6f5-4a98-8e1e-d469396b6b4d}"/>
<edge from="{a3e169ff-fc5f-4dcd-b7c5-0a14fa29b73e}" id="{87f83f97-ef97-4fad-a5ac-8dc0e87ec74a}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{6d108c14-4e3d-4273-8cee-084390309386}"/>
<edge from="{fcba37c4-7372-43df-9d2e-5404cc9a1b91}" id="{87fb7488-2d6c-44ab-ab6f-849defa74481}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{528a1707-5b77-4963-a34e-db9dba558205}"/>
<edge from="{0e5d29f3-fb8f-4d5c-b156-e4a3e028d97d}" id="{88268c31-32ea-4652-b405-6a18ed797fcc}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{ccd8ef94-281b-4dfb-ab29-b50dfe17a770}"/>
<edge from="{567a286a-bf1d-4291-b979-ba69733646f5}" id="{88ea2f4a-6869-4854-b25c-0b7e9068214e}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{bd244a0f-1d5e-4307-85b7-f764e6c1304b}"/>
<edge from="{a6209995-831e-4084-afeb-32704ca086bf}" id="{892c5570-841f-4c08-b2e2-dca141c94647}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{09f3f5fa-46f1-476c-aa35-3df95debd16f}"/>
<edge from="{0390d0a1-814a-4705-999e-5932354f0244}" id="{8b156381-67cb-4b5f-834b-cd3164b438c0}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{7153e3f6-ba74-4b9a-9a48-1f6b454b3678}"/>
<edge from="{06f82254-ab2d-44f4-bc96-3814316535a9}" id="{8f0ae77f-31d4-45aa-b9b2-67e4a2424a6c}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{6ef80ba2-4d3c-4a6e-a901-e5ddc913a272}"/>
<edge from="{ba05b4f6-6652-449b-ad37-d4b09bda988b}" id="{8facd603-513f-4464-baa8-9fbddf383931}" partId="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" to="{b256069f-8463-4f7d-b6e0-30af0bbf2898}"/>
<edge from="{9bf0c1e8-8582-442c-90a4-5037d7219b21}" id="{8fd42582-c37b-4ad6-b305-c53c448357d8}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" to="{fd8dd98f-7c73-48e4-bdf0-904f2e2271e5}"/>
<edge from="{bbab93bd-50a6-47f4-b608-00091b262e97}" id="{92be512b-2aab-4800-909a-372e1ea994bf}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{e2f0521a-2b2d-4c9b-b806-d6f4c2d078f4}"/>
<edge from="{1d21ff2c-ba5f-4997-98db-a1ed63d01db3}" id="{94f01483-83a8-499a-9204-e6d996cb7920}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{199423e1-60c0-4b3c-b65a-3ab127cadf99}"/>
<edge from="{117ef567-17a0-425e-9fcb-ae1610e91539}" id="{94fcf07d-3754-4aff-b22f-ac4f25db5310}" partId="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" to="{ce3ca970-0d64-4ee1-92ef-8720f608f05f}"/>
<edge from="{edb9977c-0dd1-4472-8534-dbeb127c9d16}" id="{951d69e2-6b90-4309-8ebb-625c64bf41ca}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{f8e96450-96e9-4f56-b89c-3c74d76de271}"/>
<edge from="{0582fcb5-78cf-4f27-bd85-0ccd279e8713}" id="{955971a0-2720-4c00-b3f7-f4a41ab9a1b7}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{2ebd2648-14b0-4a21-b97b-7b34f021991b}"/>
<edge from="{c1a57de4-5129-46f3-ace2-c662a6c079b8}" id="{95a75753-93fa-448d-b09e-aaaada89a7ab}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{bbdd82a9-286b-4c1c-b007-745c306e4f14}"/>
<edge from="{32cc74f0-3f2c-450d-845d-9baabb852655}" id="{987d4d6f-4043-47e3-a976-c629cc2062f1}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{73b1a616-30a5-44a9-a246-76ff142d228b}"/>
<edge from="{adbd9948-2566-46d3-8603-0d4ecf4c9fa4}" id="{9895d412-df9a-4104-8fce-f3d53239004b}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{796b1ebe-9414-4ec1-b58b-f3cdf6006d6e}"/>
<edge from="{44dfeb44-b697-4c87-b313-325d3826cc63}" id="{98d6c9f1-6c28-4435-a265-9a54df595469}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{979a9d6c-f734-4f25-a0fc-04310bd4646b}"/>
<edge from="{442d48bd-1797-45dc-8e4f-d121fb89237c}" id="{9989d0ed-422a-44f4-94f1-91f57780b3f8}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{3547bb94-25b4-4740-a5e9-15046267f0f9}"/>
<edge from="{0c3ed74f-ee80-41a9-8568-1487fe0cfd7c}" id="{9a9a11fe-79e1-4d05-9856-abb5b9d19da1}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{021bd224-eaac-49a1-a91f-0f2406f26f8a}"/>
<edge from="{58321009-70bf-48ba-bbe7-f5afcd9e56f3}" id="{9bdbe3b2-ed09-40a3-b026-2d073bdcadf0}" partId="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" to="{516d36d9-b1db-4de8-8503-7ea829120487}"/>
<edge from="{0bd7865d-7f8d-46cb-a1ba-4ed601bf62fe}" id="{9c70d61b-38d4-482b-9f5f-5876a612c8b8}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{7c5da7e3-9eab-47f1-9736-c53bcf1e8efa}"/>
<edge from="{3b94ce3c-27ef-41af-87d1-4227ca2045f1}" id="{9cd7f215-eedb-4a42-a5b1-eb4322f39973}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{2acf141a-f327-4469-bde3-ea54de99f8d6}"/>
<edge from="{c5cfd17f-ec0b-433b-b36b-f126b540b6a6}" id="{9d29af4f-1e74-4358-a054-f9bc0c4ce8aa}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{dfd92d67-a666-4f9e-a606-217795b284cc}"/>
<edge from="{6dea3dfc-6305-4221-81f8-d59379db1f8c}" id="{9d54a330-6f53-4548-9363-090295d98651}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{6fd6b2c1-ab1f-4904-ac30-2f800bbfc95a}"/>
<edge from="{fd311c21-d781-4437-bfd3-414ae999f244}" id="{9e035778-7556-47f9-b600-198c358f2c7d}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{e2bae992-d1d2-4fdd-9a30-dba9c62f5322}"/>
<edge from="{f06b2588-283a-4bcc-a9e5-00f5cb6c9c57}" id="{9e64da63-f984-4c9b-a5f9-fbcf357c6b5c}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{0f798576-2812-4db6-b605-9ef70f713c8b}"/>
<edge from="{0f798576-2812-4db6-b605-9ef70f713c8b}" id="{9ffe0695-a3f4-4b6c-951f-7af1d703912e}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{35bf1780-fe7c-46dd-a93e-99896e097cf2}"/>
<edge from="{f1d52a81-d771-49f4-96f7-079e891415be}" id="{a0515545-e378-4413-b6b3-a69f27ff7964}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{e7bc4edf-781b-4916-8abe-a304cda6ae75}"/>
<edge from="{c42a3e99-b6aa-4c26-8579-44228dd34b4b}" id="{a1d5fbbf-f1f8-4d5a-be27-51a976c01f7b}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{f17183a2-5ecc-4b81-9399-5d3cfbb2eea2}"/>
<edge from="{2b2d6ee4-f105-491c-b098-4de0613fd37c}" id="{a3ff149d-7d58-4018-aaf5-7549d6268a01}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{427a3b1a-021e-4685-b78b-6080d8585450}"/>
<edge from="{e2bae992-d1d2-4fdd-9a30-dba9c62f5322}" id="{a413f056-94b7-452f-bfca-3efb1edfba32}" partId="{3c4883ad-20db-4f7c-a728-e11bc72de231}" to="{105d5ada-f06b-474f-82a7-34fbfa628526}"/>
<edge from="{3424cf20-48a1-4e64-be63-5890321cdbcd}" id="{a511fc12-06db-4e7f-813b-27c18254de84}" partId="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" to="{d5be35fe-16ec-40bd-b41b-d92171f18a01}"/>
<edge from="{dfd92d67-a666-4f9e-a606-217795b284cc}" id="{a720b5ce-2b71-4922-81eb-9a9048241fce}" partId="{092b0f10-67c1-4032-9c49-168067836057}" to="{1d21ff2c-ba5f-4997-98db-a1ed63d01db3}"/>
<edge from="{0c131c2e-c763-4239-aae8-c71e219bb2ff}" id="{a99420af-71a5-47da-a1f1-280601594b96}" partId="{9b4be491-12d5-4eea-8ee9-87dff887b292}" to="{32cc74f0-3f2c-450d-845d-9baabb852655}"/>
<edge from="{95ad6172-babb-45c4-a96d-4d734ba6a25e}" id="{aa45882b-7149-41e8-9c8c-b2064f9dc5bd}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{21a051be-53a6-442c-8c87-e5572e6ff05e}"/>
<edge from="{9362b987-f419-4f31-bfaf-9539700ad242}" id="{aeff3443-032d-491f-b102-d07fedf66cd8}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{a370ab3d-5136-42d7-9aa9-ac3bed89d137}"/>
<edge from="{40b1d9b4-f4ee-4c7d-8172-a9e0fc4d5654}" id="{afc12d1a-ee5b-4598-939b-7209da2b2ab4}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{44dfeb44-b697-4c87-b313-325d3826cc63}"/>
<edge from="{68be0242-2557-4881-b306-25936e0ac472}" id="{afc5f18e-ff1d-43db-9df1-70059bab38c5}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{c8d861a6-491b-42d4-8e07-73e5df7c019b}"/>
<edge from="{84db1f93-1858-4a96-be7f-7a383a1430df}" id="{b02e4534-0081-493e-824b-ad04492ce590}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{818b69e5-7a8b-41dd-970a-90348c5b766c}"/>
<edge from="{404cdbf7-ef7b-4529-b04b-d775162d0edb}" id="{b0716ba4-19bc-476c-813b-8f536601ceeb}" partId="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" to="{5df7e38f-b9da-4c41-800c-56b5d25952b6}"/>
<edge from="{c9174f26-59b1-4382-8214-bc4a91f1759e}" id="{b160c3bc-fe1d-4040-a7c4-4a540ae64e82}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{6a16e994-9730-49a8-81f7-d9bcaf0d3614}"/>
<edge from="{e79795d5-e758-4acb-8559-7f1033c9b02f}" id="{b16bd2b9-e95e-4f0c-b35d-32cc673ce53e}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{cf75b27e-3656-4130-8543-d07cbc98b9c9}"/>
<edge from="{818b69e5-7a8b-41dd-970a-90348c5b766c}" id="{b188cd7d-7287-4846-8a1b-868f8594860c}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{55340a9c-d66d-4d5d-a189-6d658d599e53}"/>
<edge from="{2ebd2648-14b0-4a21-b97b-7b34f021991b}" id="{b19db57a-f8c1-4e2f-84da-1c1163ef3e66}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{7293a322-fbad-4c7b-a059-606020ff09bf}"/>
<edge from="{66c32673-0a5b-4c93-8dd8-26ea2e206aa9}" id="{b1b253d9-ff12-4246-ae53-2a3bbe6159f2}" partId="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" to="{df693fdf-c112-4501-afcc-243afa0c4611}"/>
<edge from="{f419bd71-f788-4382-9479-6cc8b7e240c4}" id="{b29f1338-5b75-40a5-aa9d-e980e1a0d4be}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{2015db8c-2d22-40d9-8605-073117da143a}"/>
<edge from="{b4b3a668-fd69-4887-ba98-abe5dae57101}" id="{b60e7df4-9557-452f-a82b-0bf1b7e10b65}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{7351a5f6-983d-4fdf-83c9-be734363f2ca}"/>
<edge from="{d69b0b89-1efb-4918-baf5-d0cc0d5b972c}" id="{b7637511-7819-4817-a2aa-684d31751971}" partId="{389a356e-22e6-4172-8c0d-1b835462d7b5}" to="{0e5d29f3-fb8f-4d5c-b156-e4a3e028d97d}"/>
<edge from="{6e591cdf-09bd-478c-a604-ac7d19acf528}" id="{b7b19a9f-5357-481b-8bde-6c132b0ef1ec}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{d7bf67d3-f4df-45b3-8a40-2dabc5e41d32}"/>
<edge from="{75d10124-3ee1-47f1-8e95-b397c0f35fe9}" id="{b7deba2c-d4f7-4ab7-a493-4167c2b47e82}" partId="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" to="{e785bb5a-3352-4545-a008-17d16d82c906}"/>
<edge from="{86a40600-8eac-4094-81a0-a1d698c94d2d}" id="{b7e1cf5e-679a-4a57-b03b-f4cf89e385d6}" partId="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" to="{353010d5-28a2-4ce3-a465-12289cbadb21}"/>
<edge from="{daa6e549-8d8c-4219-b312-84b523aa4f51}" id="{b8d4df7a-100d-46d5-a0b9-bdf28af8dee4}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{743d083e-3e96-4eb7-9c5f-0f0cee310915}"/>
<edge from="{d043181f-393b-4e20-8ad5-bc2c04e61bfd}" id="{b9358ec5-b955-46f8-9ebf-7eb1b6ec89e8}" partId="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" to="{c319f392-3b4d-4f01-a0f8-50ef45168844}"/>
<edge from="{5eb9bd01-2f33-4a6d-bb01-4a8a6cc7469c}" id="{b9a9fa2a-52d2-42d8-8da8-0a2921ed6330}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{3932e31f-34f7-47da-8a0d-032bec47e53c}"/>
<edge from="{516a356a-f5a0-4c65-9f17-8d186eeccaa2}" id="{ba8cc3fe-9fc3-48f5-be71-01f99c6b5adb}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{173d8166-2d8d-4792-9187-d1f0dccb3713}"/>
<edge from="{f6050cf2-105d-43b6-ade2-625e690e55f8}" id="{bb2739cf-bc85-45d7-85b8-b3bb86816606}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{ebe51975-e81f-45a6-aa7d-ca216cc56c8b}"/>
<edge from="{881104c8-1859-4bd6-8bc1-fe2f5e807e98}" id="{bd3f7038-40f5-47e0-9d2c-fb8c5796fbe4}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{9c857bb2-10b3-45e0-8271-3272e88a8bd7}"/>
<edge from="{164fc21c-131b-42a2-a47b-3b2d930222c6}" id="{bec2f05e-13b4-4fb2-b32e-cccfb9df0da8}" partId="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" to="{e94df7f8-d0ca-478e-aed1-25fa8d60b9fd}"/>
<edge from="{05c483ea-2649-48b1-80f9-f23a57335a5f}" id="{c0e943e1-7110-48a5-b6ea-58197091125f}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" to="{9bf0c1e8-8582-442c-90a4-5037d7219b21}"/>
<edge from="{33cae706-74fd-423d-a240-a32c23657dcf}" id="{c4e74e61-c23d-4c76-b405-8575a3416335}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{1f0d5b25-4f21-4fd6-9142-0d56a594dd2c}"/>
<edge from="{6b586d8c-e5a3-4405-b346-0d07c1fc587b}" id="{c4fa0184-c3c9-4636-9796-f867e7501b66}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{baa52d8a-ed0e-4138-bc8b-6a72054cfe95}"/>
<edge from="{f650f5b5-094c-41d1-b3b2-ece8be532cc1}" id="{c5351932-3680-4e36-aad4-77223c267265}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{e04cf7e6-1351-49fc-acd7-67ea3641d678}"/>
<edge from="{0f14d7ef-6d9e-42aa-afea-17e850abd25d}" id="{c536a2b7-d8b1-4f86-8502-d26360c07d9c}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{0b58ba98-f204-40ee-be03-f62292b2d250}"/>
<edge from="{9a7851b9-a7e8-4666-a13e-5cb7a8cc09c4}" id="{c591e524-3459-48ae-8f64-10a3813d8bd5}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{2501c90c-247d-42a1-b2fb-411d88b95e3a}"/>
<edge from="{2015db8c-2d22-40d9-8605-073117da143a}" id="{c7db3e9f-8600-4de1-a430-250d66b6ca60}" partId="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" to="{f5692d54-1eb7-4c3c-8e99-5323bd0046d4}"/>
<edge from="{31a4515c-5fd8-4e34-923e-750b726395f2}" id="{c852e5dd-7db7-413e-bb86-4ccccda5a010}" partId="{d049e679-f4f6-412e-963c-1019667439e8}" to="{94362d37-639a-40ff-b191-5c0a6e19f664}"/>
<edge from="{c8d861a6-491b-42d4-8e07-73e5df7c019b}" id="{c95cad57-e7b1-46b6-9c21-c3e8371533ff}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{a3e0771b-c680-4c0c-8fcf-acd03fab6785}"/>
<edge from="{173d8166-2d8d-4792-9187-d1f0dccb3713}" id="{c97dcd04-4d73-4291-9367-d50068436ad4}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{511c7a39-b0e7-4502-8bd3-730ae05506f0}"/>
<edge from="{f7c408de-4dc2-4201-8ab9-f02c04a19893}" id="{ca44b0a4-bccb-4b2b-b820-83568713cf31}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{7285fcb8-4779-4e60-a474-4641c0943463}"/>
<edge from="{cea888e7-491c-40e5-be50-e60137d4c8a4}" id="{ca857902-cc9f-46f4-bcc1-25f734a05a30}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{80faa256-324d-4c76-b4e6-491956155230}"/>
<edge from="{5e465c5c-fdc5-4c81-95dc-4729f981df5c}" id="{cf988d83-2aa7-4557-836f-950120aefdf6}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{eddf44c5-0c61-446b-a724-4456c024978a}"/>
<edge from="{75239010-9a3d-434c-a036-a8a59a0fe3d6}" id="{d294ab9c-f03e-4418-9b63-b38667d1547c}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{f2778fa6-19d7-47dd-afc8-1e4f355c6475}"/>
<edge from="{fe831613-5b6a-43f2-a789-b7c0ce027d0a}" id="{d2ff2167-9388-48dd-acf6-9a39d5365b0e}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{14a0dfc1-38c0-4544-b5d4-65bdbe60b622}"/>
<edge from="{c7bd203d-7b04-47a9-a394-d7d1f18555c4}" id="{d3533c27-bbec-46ec-b1be-e6d2b3f99483}" partId="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" to="{491add8b-4be8-4171-b647-24334b050892}"/>
<edge from="{27430d2c-0651-4361-a581-d304fcd67e22}" id="{d3bdcb26-c20f-41c2-8f83-e671878868d3}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{c1a57de4-5129-46f3-ace2-c662a6c079b8}"/>
<edge from="{6ef80ba2-4d3c-4a6e-a901-e5ddc913a272}" id="{d3dd8af5-0d64-4e0c-909f-1835e73869f2}" partId="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" to="{5eb9bd01-2f33-4a6d-bb01-4a8a6cc7469c}"/>
<edge from="{9e8b06ca-12a6-4927-bd46-4d3f479230ae}" id="{d71f8ba8-215b-4db7-a072-0aa70a39e0c6}" partId="{46304293-800c-4e01-8fc2-5135561ecc2d}" to="{bbab93bd-50a6-47f4-b608-00091b262e97}"/>
<edge from="{d2de90d6-ac0c-4bdd-b5e3-573960fad70c}" id="{d77a63b7-3f8d-41dd-8c7a-7d3457c15ac0}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{f5c1ef85-7999-4224-845f-cfc4e07e2ef3}"/>
<edge from="{48417392-2b8f-49a5-a628-ab7fc4c944d4}" id="{d8424bca-429b-4191-af90-d70007c0a43f}" partId="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" to="{0582fcb5-78cf-4f27-bd85-0ccd279e8713}"/>
<edge from="{f7984a7e-fd12-4428-8e71-9b9e913492fb}" id="{d889afdc-6b4e-4c4b-b6ac-948322eeee04}" partId="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" to="{0f14d7ef-6d9e-42aa-afea-17e850abd25d}"/>
<edge from="{85cd375b-8df3-4653-855e-2a7bb3f623fe}" id="{d96f650c-54d9-4dbe-8480-9d6a2575136f}" partId="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" to="{927f0b23-db5a-49e7-8d0f-bcc811f7752e}"/>
<edge from="{c1052900-009d-4ab3-9734-684f91bdab25}" id="{dae048e5-f932-41ab-96b4-f1076f841b11}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{6b2ab6a9-c11c-4c88-b4f9-b66df3f09e4f}"/>
<edge from="{eb4fb92f-f8ea-49ef-b132-ae6b72fa6ea4}" id="{dca95f1a-8dd4-4853-afd0-584b1dff30b7}" partId="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" to="{651c39df-7b14-4fd3-beb3-592efcb25842}"/>
<edge from="{7e852b72-9d70-4dfd-9bfc-f857d3dbbb16}" id="{dde69321-743f-4891-be2f-ee41ff885d65}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{7b4bad9a-3192-479a-bc39-3d486444fe72}"/>
<edge from="{14a0dfc1-38c0-4544-b5d4-65bdbe60b622}" id="{de3ae066-8d73-4237-8160-0bc1467455dc}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{90999c8b-a2c9-459f-847e-0fde4493fbff}"/>
<edge from="{511c7a39-b0e7-4502-8bd3-730ae05506f0}" id="{de62fbdf-534e-47d8-aa7b-3bcf18bb5be5}" partId="{f0f8818f-5795-4520-b544-ca04abca2521}" to="{f738f338-39e1-495e-a94e-5e914d4d5317}"/>
<edge from="{0434ac30-312c-4b70-984e-5a0971e9eb75}" id="{deec6450-02ce-4334-bcb4-85d645bf8123}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{10582ab2-cd50-47a0-bb86-9272f251af03}"/>
<edge from="{4029708e-b1f7-4f53-832e-d0983bfcd651}" id="{df189878-271e-4d33-b894-42a6030c9669}" partId="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" to="{d36ed08a-2202-41de-9601-76d275344502}"/>
<edge from="{a88191b2-a7cd-4b7a-be30-d5d97c3a0b48}" id="{dfeddf9e-4dd6-4c5a-8532-d6853a397e34}" partId="{524194d6-bde6-4708-b189-16535335dc5a}" to="{74620eab-e43b-44e3-be3a-68f3838cda88}"/>
<edge from="{f2778fa6-19d7-47dd-afc8-1e4f355c6475}" id="{e04fbabf-c764-45e0-8cab-67773b7c486d}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{6cbb96e6-231d-4ac1-b9ec-75b258b16a1e}"/>
<edge from="{408119ac-6fc0-40f5-b60c-99b7cc9517ae}" id="{e0796b97-0c3a-4b61-95cf-16bb0d8a626c}" partId="{13988a54-a274-49e0-aaf3-e5de769e18c1}" to="{17408e0e-5237-45ce-8f5c-de1034fcf23c}"/>
<edge from="{528a1707-5b77-4963-a34e-db9dba558205}" id="{e0d729c0-947d-4023-b868-b867cc109a77}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{33cae706-74fd-423d-a240-a32c23657dcf}"/>
<edge from="{61ba80ab-f761-4889-a07e-7b2b7ff91e5c}" id="{e0dfaeef-2435-49e2-a668-778a65525748}" partId="{36c17734-cbeb-4637-822c-71f680aa5a49}" to="{9a7851b9-a7e8-4666-a13e-5cb7a8cc09c4}"/>
<edge from="{d2f4e68c-bc10-46d3-b82c-aadf00fa23e2}" id="{e17b8625-9949-45ed-a25b-6856ea9c2aa4}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{6b586d8c-e5a3-4405-b346-0d07c1fc587b}"/>
<edge from="{e5a7a6e8-c4de-4ea6-a175-93b87b709bee}" id="{e1eaa489-de41-4b48-86cc-2b8fd2c4b854}" partId="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" to="{6c9d6544-ff34-4259-8d31-72393a4d7629}"/>
<edge from="{0b4f4946-8ff1-4efe-bdfe-0b611af6a655}" id="{e22500cd-ea80-475c-a2ca-f371cf78694c}" partId="{b5812967-d429-4214-a11c-f04918089461}" to="{8b37e76a-099c-4b5d-af5c-26c1fe4f55ab}"/>
<edge from="{8dc941af-cffe-4f7b-aa0a-b0db5a0e5e1d}" id="{e24483fd-0908-43e6-81ba-745940875182}" partId="{da7592eb-3353-4084-bff2-f31d92be4236}" to="{e79795d5-e758-4acb-8559-7f1033c9b02f}"/>
<edge from="{a9746f2b-b2ba-40a7-a405-d34b982c683f}" id="{e2f7b457-07f5-4cd3-a337-2e0443ef289d}" partId="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" to="{18a7f970-0d2e-4d47-a307-32c94a9105a3}"/>
<edge from="{7b04a282-03d9-4a06-bec2-b48417956ce9}" id="{e3b99e51-e9f3-4813-99a3-bce3b61180c2}" partId="{acdc210c-e671-486e-9611-b9244c016807}" to="{881104c8-1859-4bd6-8bc1-fe2f5e807e98}"/>
<edge from="{021bd224-eaac-49a1-a91f-0f2406f26f8a}" id="{e4d0eaf5-34e2-40d1-80d1-45206f32af10}" partId="{8f49f8aa-cb67-4955-9063-92e33042cb02}" to="{e5afd1fe-e4a7-4e2a-90cf-1cb2a55fe07e}"/>
<edge from="{09f3f5fa-46f1-476c-aa35-3df95debd16f}" id="{e6181a81-6104-43cc-8385-b5d071f5a8d0}" partId="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" to="{1207414b-6386-42f4-b3b4-e774497e4fa9}"/>
<edge from="{1f0d5b25-4f21-4fd6-9142-0d56a594dd2c}" id="{e76b9c52-1b59-443d-9387-c4b288bcb5e3}" partId="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" to="{ee43d10c-d4f1-4315-a3c2-618c2ce40d6a}"/>
<edge from="{76a160cd-60d5-4010-bd9a-6032c97f67b8}" id="{e8fc682c-43b3-48f3-bec6-36ea99b084ed}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{aefc096e-5901-425f-a831-6a0ddbd50399}"/>
<edge from="{7351a5f6-983d-4fdf-83c9-be734363f2ca}" id="{e93802a7-1cc5-4dcd-a866-8d4466c8bfe6}" partId="{deb52d1d-f439-4144-9284-6b990b239ae5}" to="{84db1f93-1858-4a96-be7f-7a383a1430df}"/>
<edge from="{ebe6c9ed-8cd5-4d44-acda-3846acf13ec1}" id="{ed7ce0f7-2dd3-454c-80a5-c363d70babd9}" partId="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" to="{f6050cf2-105d-43b6-ade2-625e690e55f8}"/>
<edge from="{8e43cbd3-2aa9-4265-95b8-92056c4c4737}" id="{effc5af7-3b9e-422f-9fa3-d9036143dfb9}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{b1d0b918-225b-4399-a8d8-e90b84b5f5be}"/>
<edge from="{7057282d-6ae5-4d7e-b10e-85ae69c7f72a}" id="{f09ef052-777c-4e4d-9726-623e7b5630f8}" partId="{62493532-0802-4e69-af81-89a1e382185d}" to="{f1d52a81-d771-49f4-96f7-079e891415be}"/>
<edge from="{dc0aaf45-eb00-49b6-8e81-fa979245ac09}" id="{f2843cac-a688-4cf4-a8bf-cac168d7f9f3}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{40b1d9b4-f4ee-4c7d-8172-a9e0fc4d5654}"/>
<edge from="{0711915a-a413-42b5-8022-35668c45d39b}" id="{f2c70830-462e-4577-87a0-53f44a9bec08}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{9d65e303-67cf-4bbb-ab6a-09120b410c7b}"/>
<edge from="{743d083e-3e96-4eb7-9c5f-0f0cee310915}" id="{f3678ad5-32fd-4ff2-a2cf-2d04e4633cca}" partId="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" to="{73951d38-c2aa-4577-927b-7e9429d1f0db}"/>
<edge from="{5399b1af-6473-4df5-96cc-13e6e28784c1}" id="{f389bf5a-f49b-42a8-91c3-691ef9b55456}" partId="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" to="{75239010-9a3d-434c-a036-a8a59a0fe3d6}"/>
<edge from="{baa52d8a-ed0e-4138-bc8b-6a72054cfe95}" id="{f3fefe97-5b55-4f5b-a3f8-8cc92361df88}" partId="{499562a3-978a-46b8-82ac-ad5a45c3288b}" to="{a3e169ff-fc5f-4dcd-b7c5-0a14fa29b73e}"/>
<edge from="{fd8dd98f-7c73-48e4-bdf0-904f2e2271e5}" id="{f4ef9157-7082-46aa-816b-3ab6932c871b}" partId="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" to="{9530cb12-6d41-4bd3-8175-1ba24943e21b}"/>
<edge from="{90999c8b-a2c9-459f-847e-0fde4493fbff}" id="{f6b257cd-db2e-4bb4-8c4e-35d87ab7f8f6}" partId="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" to="{39e3219e-a74d-4dd0-bedd-eb4fa010f34a}"/>
<edge from="{5064c6c5-783a-44e5-8e70-49c8c9cc2416}" id="{f7e36eab-500f-4a28-902b-5a245aef422b}" partId="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" to="{593f1c87-b152-41e0-98b6-07acf061f646}"/>
<edge from="{35bf1780-fe7c-46dd-a93e-99896e097cf2}" id="{fa61de23-5291-4464-81cb-802682d6a1c5}" partId="{700ce49d-5978-4ae1-847e-404fdc912625}" to="{24b1db2c-8e14-4670-a523-bd31ab7758aa}"/>
<edge from="{6394e5cc-a367-4664-a9af-753d41b82ba6}" id="{faf0fae4-1daa-49e5-985f-24940e3324e9}" partId="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" to="{f7c9ef1b-11cc-4f1e-b217-322279b063b3}"/>
<edge from="{0a8e8fb2-9858-49d2-8686-6ed728dccbc2}" id="{fbb032f0-d170-42cb-a5fc-0a57fd06a90f}" partId="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" to="{d2de90d6-ac0c-4bdd-b5e3-573960fad70c}"/>
<edge from="{6b2ab6a9-c11c-4c88-b4f9-b66df3f09e4f}" id="{fbd20729-2f29-49fa-beac-66b2a0f7a406}" partId="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" to="{0bd7865d-7f8d-46cb-a1ba-4ed601bf62fe}"/>
<edge from="{a3e0771b-c680-4c0c-8fcf-acd03fab6785}" id="{fc556933-a669-4975-9b1f-ebebc0b4b3de}" partId="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" to="{e3a311f1-ab14-4e80-80dc-9f882721d9a8}"/>
<edge from="{a370ab3d-5136-42d7-9aa9-ac3bed89d137}" id="{fe75bbf6-fe0e-455c-9af5-2af84da68e3b}" partId="{e47c18bd-1154-48f4-96d5-954787c54562}" to="{ce8a93e4-e574-4e93-82b1-fbd2ca77ef0f}"/>
</edges>
<parts>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{092b0f10-67c1-4032-9c49-168067836057}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{13988a54-a274-49e0-aaf3-e5de769e18c1}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{36c17734-cbeb-4637-822c-71f680aa5a49}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{389a356e-22e6-4172-8c0d-1b835462d7b5}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{3c4883ad-20db-4f7c-a728-e11bc72de231}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{46304293-800c-4e01-8fc2-5135561ecc2d}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{499562a3-978a-46b8-82ac-ad5a45c3288b}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{524194d6-bde6-4708-b189-16535335dc5a}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{62493532-0802-4e69-af81-89a1e382185d}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{700ce49d-5978-4ae1-847e-404fdc912625}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{80845e66-2299-48ca-8cbf-77b55a536c0c}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{8f49f8aa-cb67-4955-9063-92e33042cb02}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{9279a14a-691a-436c-ae9e-efd74fa28300}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{9b4be491-12d5-4eea-8ee9-87dff887b292}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{acdc210c-e671-486e-9611-b9244c016807}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{b5812967-d429-4214-a11c-f04918089461}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#939297" disabled="false" id="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{d049e679-f4f6-412e-963c-1019667439e8}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" disabled="false" id="{da7592eb-3353-4084-bff2-f31d92be4236}" locked="false" rounded="false" subdived="false" target="CutFace" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{deb52d1d-f439-4144-9284-6b990b239ae5}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{e47c18bd-1154-48f4-96d5-954787c54562}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{f0f8818f-5795-4520-b544-ca04abca2521}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
<part chamfered="false" color="#a4f98d" cutFace="{da7592eb-3353-4084-bff2-f31d92be4236}" disabled="false" id="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" locked="false" rounded="false" subdived="false" visible="true" xMirrored="false"/>
</parts>
<components>
<component combineMode="Normal" expanded="false" id="{501e951b-cea7-4dc1-9f7e-89c464c11bb3}" linkData="{da7592eb-3353-4084-bff2-f31d92be4236}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{c8ac259f-5de6-454e-90be-4bbd8269808c}" linkData="{6f0945eb-96e8-4a0b-8eea-55fa96a2561f}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{49e68887-892b-4525-8763-a574313a87f3}" linkData="{50b2e680-31ba-4d62-9c93-10c51edea1bf}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{46a52d46-1320-4d54-8716-656192fcce32}" linkData="{acdc210c-e671-486e-9611-b9244c016807}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{f3b5c2f0-7190-496e-a3b1-45221cd9cddd}" linkData="{6986bf40-3089-4db5-bcc4-533d7ed960e3}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{87e47914-242e-47e1-aa23-d8fc87401a1e}" linkData="{78887fc7-dcfb-4d38-9eac-f8beaa99dce3}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{44c5c761-8483-40cb-9b15-8d904e233115}" linkData="{deb52d1d-f439-4144-9284-6b990b239ae5}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{37232b01-fdc1-4f59-a1d9-4921f4dd82e7}" linkData="{8f49f8aa-cb67-4955-9063-92e33042cb02}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{3c2fcff5-1412-41d8-9615-f8bb0c97d5dd}" linkData="{504953c2-aef4-4f37-be54-8f23c1f3f0fc}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{6de4b520-3bb4-4391-a997-0d9b9a6bc446}" linkData="{2e4d7f86-270e-44c8-8e6c-27c9d1badd8d}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{ec80b776-20d0-4508-93d7-ba911d250fdf}" linkData="{1aaacb49-c100-4361-b227-422bc9c3a3b9}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{4d72e4e9-6432-4d1f-8b82-01a8949809e4}" linkData="{52d54b31-5e73-444b-8bae-2ebc51ff209e}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{3e67b71b-5e85-4401-8f46-c241c6381d8b}" linkData="{6be248ef-32e3-43b0-b4bc-9e9cc8fae38e}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{51764c7c-7118-47ca-a70e-08607cd54765}" linkData="{709b8a08-78b0-4a8d-9978-27eb2eda8b93}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{40708ab9-7391-4735-83af-dad392e26f04}" linkData="{57dbdd98-cd36-4a18-a1b9-a22884c6b343}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{e2866f4f-a2c5-45a4-a8f7-8d5dbf575700}" linkData="{36c17734-cbeb-4637-822c-71f680aa5a49}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{8aff815a-3592-4ea1-bee5-79b110a00686}" linkData="{c3e8e9c2-eb6f-4d7f-8f72-6d4cd3003c26}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{ddb43b75-a690-475c-acf9-7c6d7794e3e7}" linkData="{4c083326-6b05-4a2d-85ce-576dc7dd5c34}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{32815245-bcca-4d29-81b9-be222920f67b}" linkData="{499562a3-978a-46b8-82ac-ad5a45c3288b}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{ec533680-f287-4914-8b85-536312088cb8}" linkData="{c4c54ceb-2b1e-476c-8785-6fa69f041925}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{f043c3d8-4ede-4ecf-9a21-0afb9efcd520}" linkData="{3c4883ad-20db-4f7c-a728-e11bc72de231}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{658043b1-0b8f-4c9a-aca8-d1fd44997995}" linkData="{d8f9b36d-cec1-4026-a344-16edbbc0fc13}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{bcccd4d5-ae07-4ea2-9f33-8b8e8d8fdfd3}" linkData="{3a4bc54a-f2cc-40d9-82c3-4c1acd434048}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{ad417335-eeb9-45e8-acf1-10c89da5e4a0}" linkData="{5b7db920-6126-4e3a-a16d-2fa6c227a696}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{a3376bed-fd56-4d11-b0e6-e280bda88094}" linkData="{f1b78adc-6fdc-4414-bab8-8e98890a21ca}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{2e0fe333-6638-4e95-89d5-862055009502}" linkData="{d049e679-f4f6-412e-963c-1019667439e8}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{792df41a-a26a-4555-bebb-d8ff32d4804f}" linkData="{1cb0fafb-2cee-4fba-b0c6-ffbe586ba374}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{c4b28529-4d95-44dc-be3b-0ec6a67dfe9a}" linkData="{092b0f10-67c1-4032-9c49-168067836057}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{792a323a-8a14-4ee8-80e7-171cb263a6dd}" linkData="{534e034a-1fef-4d7d-82e4-12f7b8e82728}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{506c7834-d834-4af2-84cc-3566d0131327}" linkData="{e47c18bd-1154-48f4-96d5-954787c54562}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{eb8defd0-5d93-4676-95ec-5cda66da741e}" linkData="{46304293-800c-4e01-8fc2-5135561ecc2d}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{e8bd263c-3272-4e1a-9bbf-799ba60d1d1c}" linkData="{0564a8bf-85c6-4bd7-bad1-8cb70a2bacd9}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{a853e0f4-c525-40e3-b336-86570ad6af6d}" linkData="{9279a14a-691a-436c-ae9e-efd74fa28300}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{04bc8afe-1bb7-431d-a1c6-a9c255b67ae8}" linkData="{9b4be491-12d5-4eea-8ee9-87dff887b292}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{58545e99-3d7f-443f-8e60-0e96a69f5586}" linkData="{1aca42d2-f80a-4516-a8bf-0a066935d31c}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{6801e8c9-4494-48da-91cc-cf33b81811e4}" linkData="{a96bc03c-93f9-4cfd-abd4-e8d135fc8b49}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{d38da8c4-2f06-4c8c-8ec9-51aaa244697b}" linkData="{b78ff84d-5acd-4b46-a58b-564abba2c7e2}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{ad223702-121e-4855-9dc8-614d879292a1}" linkData="{f0f8818f-5795-4520-b544-ca04abca2521}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{0cf27234-4529-49b8-8729-4a515c190534}" linkData="{700ce49d-5978-4ae1-847e-404fdc912625}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{fa27ae40-b168-4860-bd1e-1dc356fade5d}" linkData="{8fa5ba18-7e7f-4713-bd40-6ac223f08d12}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{63785235-da1a-4da7-a896-1a91359ae978}" linkData="{ae6741e2-ad53-4265-8b9b-310b65badd1e}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{5b2932ca-f7ef-430f-9731-ffc91c0f3b75}" linkData="{389a356e-22e6-4172-8c0d-1b835462d7b5}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{240f4df6-3b56-4867-bc12-178171b1990f}" linkData="{9538c8a9-1e82-4d5a-8e0e-b7a0d701c5f9}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{1ab51bc8-5e0d-4f6c-b90e-1179f0dc8068}" linkData="{13988a54-a274-49e0-aaf3-e5de769e18c1}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{5c618c7f-32eb-4e6f-9dfb-59b9458597ca}" linkData="{5e45c98d-9283-4386-b0ae-e6a8f85f2dad}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{f9dbb17f-89e8-4fb4-bbe8-e336da9fd57d}" linkData="{524194d6-bde6-4708-b189-16535335dc5a}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{7f5cd199-2903-48c7-823c-8f5824fc6ead}" linkData="{1b950787-9a25-4f55-9d21-9d6d12eaff28}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{95f7cee9-c33c-48f1-9386-c16e6bcb78f9}" linkData="{87fbd826-5677-48f5-83d3-8091d48ef8d7}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{e52ce4f8-7c3f-4741-8310-a2e5b5afde0e}" linkData="{80845e66-2299-48ca-8cbf-77b55a536c0c}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{b4ba271a-3e7f-44fe-86d4-dcabf6bd95da}" linkData="{c4ac9d40-ad41-4b17-8098-04fc2dec48a2}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{279a974e-5bea-4bfe-a3a4-462aa30d9c65}" linkData="{1716cb6d-01ed-4522-9ea3-7470418c6b51}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{e7c16696-24ee-43bc-9258-88bada7af5d6}" linkData="{bb6e0337-94a1-4b8b-8894-9f40dc5577b5}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{79d7a2f5-bcb3-4fe2-86b0-c4145b0b40e9}" linkData="{62493532-0802-4e69-af81-89a1e382185d}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{40c08780-2e4b-4711-9912-7e2b88e3afd3}" linkData="{b5812967-d429-4214-a11c-f04918089461}" linkDataType="partId"/>
<component combineMode="Normal" expanded="false" id="{1c05b9c2-d958-42b1-ac29-a3c38de9e959}" linkData="{01f7a857-f594-42fc-8b5d-b3bdae4dacda}" linkDataType="partId"/>
</components>
<materials/>
<poses/>
<motions/>
</canvas>
var SUBDIVED = document.createCheckInput("Subdived", false);
var MAX_RADIUS_OFFSET = document.createFloatInput("Max Radius Offset", 0.10, -1.0, 1.0);
var MAX_ORIGIN_OFFSET = document.createFloatInput("Max Origin Offset", 0.47, -1.0, 1.0);
var TREE_HEIGHT = document.createFloatInput("Height", 0.85, 0.1, 1.0);
var TRUNK_RADIUS = document.createFloatInput("Trunk Radius", 0.02, 0.01, 0.2);
var TRUNK_SEGMENTS = document.createIntInput("Trunk Segments", 15, 2, 30);
var TRUNK_COLOR = document.createColorInput("Trunk Color", "#939297");
var BRANCH_MIN_ANGLE = document.createFloatInput("Branch Min Angle", 10.72, 8, 30);
var BRANCH_MAX_ANGLE = document.createFloatInput("Branch Max Angle", 58.81, 50, 75);
var MAX_BRANCHES_PER_GROWTH = document.createIntInput("Max Branches", 7, 1, 7);
var BRANCH_LENGTH_MIN_RATIO = document.createFloatInput("Branch Length Min Ratio", 0.24, 0.2, 0.9);
var BRANCH_LENGTH_MAX_RATIO = document.createFloatInput("Branch Length Max Ratio", 0.78, 0.2, 0.9);
var LEAF_MIN_LENGTH = document.createFloatInput("Leaf Min Length", 0.05, 0.005, 0.1);
var LEAF_MAX_LENGTH = document.createFloatInput("Leaf Max Length", 0.08, 0.005, 0.2);
var LEAF_SEGMENTS = document.createIntInput("Leaf Segments", 5, 3, 6);
var LEAF_COLOR = document.createColorInput("Leaf Color", "#58834b");
var X = new THREE.Vector3( 1, 0, 0 );
var Y = new THREE.Vector3( 0, 1, 0 );
function createNode(part, origin, radius)
{
var node = document.createNode(part);
document.setAttribute(node, "x", origin.getComponent(0));
document.setAttribute(node, "y", origin.getComponent(1));
document.setAttribute(node, "z", origin.getComponent(2));
document.setAttribute(node, "radius", radius);
return node;
}
THREE.Vector3.prototype.random = function (maxOffset)
{
for (var i = 0; i < 3; ++i)
this.setComponent(i, this.getComponent(i) + maxOffset * Math.random());
return this;
};
function randInRange(min, max)
{
if (min > max) {
var tmp = min;
min = max;
max = tmp;
}
return (min + (max - min) * Math.random());
}
function createLeafCutFace()
{
var component = document.createComponent();
var part = document.createPart(component);
document.setAttribute(part, "target", "CutFace");
var predefinesCutFace = [
{radius:"0.005", x:"0.314637", y:"0.336525", z:"0.713406"},
{radius:"0.005", x:"0.343365", y:"0.340629", z:"0.713406"},
{radius:"0.005", x:"0.377565", y:"0.340629", z:"0.713406"},
{radius:"0.0159439", x:"0.402189", y:"0.341997", z:"0.713406"},
{radius:"0.005", x:"0.440492", y:"0.329685", z:"0.713406"},
{radius:"0.005", x:"0.473324", y:"0.317373", z:"0.713406"},
];
var previousNode = undefined;
for (var i = 0; i < predefinesCutFace.length; ++i) {
var node = createNode(part,
new THREE.Vector3(parseFloat(predefinesCutFace[i]["x"]),
parseFloat(predefinesCutFace[i]["y"]),
parseFloat(predefinesCutFace[i]["z"])),
parseFloat(predefinesCutFace[i]["radius"]));
if (undefined != previousNode)
document.connect(previousNode, node);
previousNode = node;
}
return part;
}
function getRandChildDirection(parentDirection)
{
var rotationAxis = parentDirection.clone().cross(X);
var degree = randInRange(BRANCH_MIN_ANGLE, BRANCH_MAX_ANGLE);
var branchRotateQuaternion = new THREE.Quaternion();
branchRotateQuaternion.setFromAxisAngle(rotationAxis, degree * (Math.PI / 180));
var rotatedDirection = parentDirection.clone().applyQuaternion(branchRotateQuaternion);
var distributeQuaternion = new THREE.Quaternion();
distributeQuaternion.setFromAxisAngle(Y, 360 * Math.random() * (Math.PI / 180));
rotatedDirection = rotatedDirection.applyQuaternion(distributeQuaternion);
return rotatedDirection;
}
var CUTFACE_PART_ID = document.attribute(createLeafCutFace(), "id");
function createLeaf(leafRootPosition, parentDirection)
{
var direction = getRandChildDirection(parentDirection);
var component = document.createComponent();
var part = document.createPart(component);
document.setAttribute(part, "color", LEAF_COLOR);
document.setAttribute(part, "cutFace", CUTFACE_PART_ID);
var length = randInRange(LEAF_MIN_LENGTH, LEAF_MAX_LENGTH);
var segments = LEAF_SEGMENTS;
var maxRadius = length / 3;
var toPosition = leafRootPosition.clone().add(direction.clone().multiplyScalar(length));
var previousNode = undefined;
for (var i = 0; i < segments; ++i) {
var alpha = (i + 0.0) / segments;
var origin = leafRootPosition.clone().lerp(toPosition, alpha);
var radiusFactor = 1.0 - 2 * Math.abs(alpha - 0.3);
var radius = maxRadius * radiusFactor;
var node = createNode(part, origin, radius);
if (undefined != previousNode)
document.connect(previousNode, node);
previousNode = node;
}
}
function createBranch(branchRootPosition, radius, length, segments, parentDirection, maxRadius)
{
var rotatedDirection = getRandChildDirection(parentDirection);
var branchEndPosition = branchRootPosition.clone().add(rotatedDirection.multiplyScalar(length));
createTrunk(branchRootPosition, radius, branchEndPosition, segments, maxRadius);
}
function shouldGrowBranch(alpha, alreadyGrowedNum)
{
var factor = alpha * Math.random();
if (factor > 0.5 && factor < 0.8) {
if (alreadyGrowedNum > 0)
return true;
if (Math.random() > 0.5)
return true;
}
return false;
}
function shouldGrowLeaf(alreadyGrowedNum)
{
var factor = Math.random();
if (factor > 0.5) {
if (alreadyGrowedNum > 0)
return true;
if (Math.random() > 0.5)
return true;
}
return false;
}
function createTrunk(fromPosition, fromRadius, toPosition, segments, maxRadius)
{
var component = document.createComponent();
var part = document.createPart(component);
if (SUBDIVED)
document.setAttribute(part, "subdived", "true");
document.setAttribute(part, "color", TRUNK_COLOR);
var previousNode = undefined;
var toRadius = fromRadius * 0.2;
var direction = toPosition.clone().sub(fromPosition).normalize();
var length = fromPosition.distanceTo(toPosition);
for (var i = 0; i < segments; ++i) {
var alpha = (i + 0.0) / segments;
var origin = fromPosition.clone().lerp(toPosition, alpha);
var radius = fromRadius * (1.0 - alpha) + toRadius * alpha;
radius += radius * MAX_RADIUS_OFFSET * Math.random();
if (undefined != maxRadius && radius > maxRadius)
radius = maxRadius;
var oldY = origin.y;
origin.random(length * 0.1 * MAX_ORIGIN_OFFSET);
origin.setY(oldY + radius * 0.5 * Math.random());
if (undefined != maxRadius && i == 0)
origin = fromPosition;
var node = createNode(part, origin, radius);
if (undefined != previousNode)
document.connect(previousNode, node);
var maxBranches = MAX_BRANCHES_PER_GROWTH * Math.random();
var alreadyGrowedBranchNum = 0;
var alreadyGrowedLeafNum = 0;
for (var j = 0; j < maxBranches; ++j) {
if (shouldGrowBranch(alpha, alreadyGrowedBranchNum)) {
var branchLength = length * randInRange(BRANCH_LENGTH_MIN_RATIO, BRANCH_LENGTH_MAX_RATIO);
var branchRadius = radius * 0.5;
var branchSegments = segments * (branchLength / length);
if (branchSegments >= 3 && branchRadius > TRUNK_RADIUS / 20) {
createBranch(origin, branchRadius, branchLength, branchSegments, direction, radius);
++alreadyGrowedBranchNum;
}
}
if (undefined != maxRadius && shouldGrowLeaf(alreadyGrowedLeafNum)) {
createLeaf(origin, direction);
++alreadyGrowedLeafNum;
}
}
previousNode = node;
}
}
var treeRootPosition = new THREE.Vector3(0.5, 1.0, 1.0);
var treeTopPosition = treeRootPosition.clone();
treeTopPosition.add((new THREE.Vector3(0, -1, 0)).multiplyScalar(TREE_HEIGHT));
document.setAttribute(document.canvas, "originX", 0.506767);
document.setAttribute(document.canvas, "originY", 0.615943);
document.setAttribute(document.canvas, "originZ", 1.08543);
createTrunk(treeRootPosition, TRUNK_RADIUS, treeTopPosition, TRUNK_SEGMENTS);
<?xml version="1.0" encoding="UTF-8"?>
<variables>
<variable name="Branch Length Max Ratio" defaultValue="0.78" input="Float" maxValue="0.9" minValue="0.2" value="0.78"/>
<variable name="Branch Length Min Ratio" defaultValue="0.24" input="Float" maxValue="0.9" minValue="0.2" value="0.24"/>
<variable name="Branch Max Angle" defaultValue="58.81" input="Float" maxValue="75" minValue="50" value="58.81"/>
<variable name="Branch Min Angle" defaultValue="10.72" input="Float" maxValue="30" minValue="8" value="10.72"/>
<variable name="Height" defaultValue="0.85" input="Float" maxValue="1" minValue="0.1" value="0.85"/>
<variable name="Leaf Color" defaultValue="#58834b" input="Color" value="#a4f98d"/>
<variable name="Leaf Max Length" defaultValue="0.08" input="Float" maxValue="0.2" minValue="0.005" value="0.08"/>
<variable name="Leaf Min Length" defaultValue="0.05" input="Float" maxValue="0.1" minValue="0.005" value="0.04"/>
<variable name="Leaf Segments" defaultValue="5" input="Int" maxValue="6" minValue="3" value="5"/>
<variable name="Max Branches" defaultValue="7" input="Int" maxValue="7" minValue="1" value="7"/>
<variable name="Max Origin Offset" defaultValue="0.47" input="Float" maxValue="1" minValue="-1" value="0.47"/>
<variable name="Max Radius Offset" defaultValue="0.1" input="Float" maxValue="1" minValue="-1" value="0.1"/>
<variable name="Subdived" defaultValue="false" input="Check" value="false"/>
<variable name="Trunk Color" defaultValue="#939297" input="Color" value="#939297"/>
<variable name="Trunk Radius" defaultValue="0.02" input="Float" maxValue="0.2" minValue="0.01" value="0.02"/>
<variable name="Trunk Segments" defaultValue="15" input="Int" maxValue="30" minValue="2" value="15"/>
</variables>

View File

@ -16,7 +16,6 @@
#include "materialpreviewsgenerator.h"
#include "motionsgenerator.h"
#include "skeletonside.h"
#include "scriptrunner.h"
#include "mousepicker.h"
#include "imageforever.h"
#include "contourtopartconverter.h"
@ -69,8 +68,6 @@ Document::Document() :
m_motionsGenerator(nullptr),
m_meshGenerationId(0),
m_nextMeshGenerationId(1),
m_scriptRunner(nullptr),
m_isScriptResultObsolete(false),
m_mousePicker(nullptr),
m_isMouseTargetResultObsolete(false),
m_paintMode(PaintMode::None),
@ -1850,15 +1847,6 @@ void Document::silentReset()
removeRigResults();
}
void Document::silentResetScript()
{
m_script.clear();
m_mergedVariables.clear();
m_cachedVariables.clear();
m_scriptError.clear();
m_scriptConsoleLog.clear();
}
void Document::reset()
{
silentReset();
@ -1866,16 +1854,6 @@ void Document::reset()
emit skeletonChanged();
}
void Document::resetScript()
{
silentResetScript();
emit cleanupScript();
emit scriptChanged();
emit scriptErrorChanged();
emit scriptConsoleLogChanged();
emit mergedVaraiblesChanged();
}
void Document::fromSnapshot(const Snapshot &snapshot)
{
reset();
@ -3804,194 +3782,6 @@ void Document::copyNodes(std::set<QUuid> nodeIdSet) const
clipboard->setText(snapshotXml);
}
void Document::initScript(const QString &script)
{
m_script = script;
emit scriptModifiedFromExternal();
}
void Document::updateScript(const QString &script)
{
if (m_script == script)
return;
m_script = script;
emit scriptChanged();
}
void Document::updateVariable(const QString &name, const std::map<QString, QString> &value)
{
bool needRunScript = false;
auto variable = m_cachedVariables.find(name);
if (variable == m_cachedVariables.end()) {
m_cachedVariables[name] = value;
needRunScript = true;
} else if (variable->second != value) {
variable->second = value;
} else {
return;
}
m_mergedVariables[name] = value;
emit mergedVaraiblesChanged();
if (needRunScript)
runScript();
}
void Document::updateVariableValue(const QString &name, const QString &value)
{
auto variable = m_cachedVariables.find(name);
if (variable == m_cachedVariables.end()) {
qDebug() << "Update a nonexist variable:" << name << "value:" << value;
return;
}
auto &variableValue = variable->second["value"];
if (variableValue == value)
return;
variableValue = value;
m_mergedVariables[name] = variable->second;
runScript();
}
bool Document::updateDefaultVariables(const std::map<QString, std::map<QString, QString>> &defaultVariables)
{
bool updated = false;
for (const auto &it: defaultVariables) {
auto findMergedVariable = m_mergedVariables.find(it.first);
if (findMergedVariable != m_mergedVariables.end()) {
bool hasChangedAttribute = false;
for (const auto &attribute: it.second) {
if (attribute.first == "value")
continue;
const auto &findMatch = findMergedVariable->second.find(attribute.first);
if (findMatch != findMergedVariable->second.end()) {
if (findMatch->second == attribute.second)
continue;
}
hasChangedAttribute = true;
}
if (!hasChangedAttribute)
continue;
}
updated = true;
auto findCached = m_cachedVariables.find(it.first);
if (findCached != m_cachedVariables.end()) {
m_mergedVariables[it.first] = it.second;
m_mergedVariables[it.first]["value"] = valueOfKeyInMapOrEmpty(findCached->second, "value");
} else {
m_mergedVariables[it.first] = it.second;
m_cachedVariables[it.first] = it.second;
}
}
std::vector<QString> eraseList;
for (const auto &it: m_mergedVariables) {
if (defaultVariables.end() == defaultVariables.find(it.first)) {
eraseList.push_back(it.first);
updated = true;
}
}
for (const auto &it: eraseList) {
m_mergedVariables.erase(it);
}
if (updated) {
emit mergedVaraiblesChanged();
}
return updated;
}
void Document::runScript()
{
if (nullptr != m_scriptRunner) {
m_isScriptResultObsolete = true;
return;
}
m_isScriptResultObsolete = false;
qDebug() << "Script running..";
QThread *thread = new QThread;
m_scriptRunner = new ScriptRunner();
m_scriptRunner->moveToThread(thread);
m_scriptRunner->setScript(new QString(m_script));
m_scriptRunner->setVariables(new std::map<QString, std::map<QString, QString>>(
m_mergedVariables.empty() ? m_cachedVariables : m_mergedVariables
));
connect(thread, &QThread::started, m_scriptRunner, &ScriptRunner::process);
connect(m_scriptRunner, &ScriptRunner::finished, this, &Document::scriptResultReady);
connect(m_scriptRunner, &ScriptRunner::finished, thread, &QThread::quit);
connect(thread, &QThread::finished, thread, &QThread::deleteLater);
emit scriptRunning();
thread->start();
}
void Document::scriptResultReady()
{
Snapshot *snapshot = m_scriptRunner->takeResultSnapshot();
std::map<QString, std::map<QString, QString>> *defaultVariables = m_scriptRunner->takeDefaultVariables();
bool errorChanged = false;
bool consoleLogChanged = false;
bool mergedVariablesChanged = false;
const QString &scriptError = m_scriptRunner->scriptError();
if (m_scriptError != scriptError) {
m_scriptError = scriptError;
errorChanged = true;
}
const QString &consoleLog = m_scriptRunner->consoleLog();
if (m_scriptConsoleLog != consoleLog) {
m_scriptConsoleLog = consoleLog;
consoleLogChanged = true;
}
if (nullptr != snapshot) {
fromSnapshot(*snapshot);
delete snapshot;
saveSnapshot();
}
if (nullptr != defaultVariables) {
mergedVariablesChanged = updateDefaultVariables(*defaultVariables);
delete defaultVariables;
}
delete m_scriptRunner;
m_scriptRunner = nullptr;
if (errorChanged)
emit scriptErrorChanged();
if (consoleLogChanged)
emit scriptConsoleLogChanged();
qDebug() << "Script run done";
if (m_isScriptResultObsolete || mergedVariablesChanged) {
runScript();
}
}
const QString &Document::script() const
{
return m_script;
}
const std::map<QString, std::map<QString, QString>> &Document::variables() const
{
return m_mergedVariables;
}
const QString &Document::scriptError() const
{
return m_scriptError;
}
const QString &Document::scriptConsoleLog() const
{
return m_scriptConsoleLog;
}
void Document::startPaint(void)
{
}

View File

@ -32,7 +32,6 @@
class MaterialPreviewsGenerator;
class MotionsGenerator;
class ScriptRunner;
class MousePicker;
class HistoryItem
@ -441,7 +440,6 @@ signals:
void partGridStateChanged(QUuid partId);
void componentCombineModeChanged(QUuid componentId);
void cleanup();
void cleanupScript();
void originChanged();
void xlockStateChanged();
void ylockStateChanged();
@ -485,12 +483,6 @@ signals:
void postProcessing();
void textureGenerating();
void textureChanged();
void scriptChanged();
void scriptModifiedFromExternal();
void mergedVaraiblesChanged();
void scriptRunning();
void scriptErrorChanged();
void scriptConsoleLogChanged();
void mouseTargetChanged();
void mousePickRadiusChanged();
public: // need initialize
@ -560,10 +552,6 @@ public:
bool isMeshGenerating() const;
bool isPostProcessing() const;
bool isTextureGenerating() const;
const QString &script() const;
const std::map<QString, std::map<QString, QString>> &variables() const;
const QString &scriptError() const;
const QString &scriptConsoleLog() const;
const QVector3D &mouseTargetPosition() const;
float mousePickRadius() const;
public slots:
@ -670,10 +658,8 @@ public slots:
void batchChangeBegin();
void batchChangeEnd();
void reset();
void resetScript();
void clearHistories();
void silentReset();
void silentResetScript();
void breakEdge(QUuid edgeId);
void setXlockState(bool locked);
void setYlockState(bool locked);
@ -702,12 +688,6 @@ public slots:
void renameMaterial(QUuid materialId, QString name);
void applyPreferencePartColorChange();
void applyPreferenceFlatShadingChange();
void initScript(const QString &script);
void updateScript(const QString &script);
void runScript();
void scriptResultReady();
void updateVariable(const QString &name, const std::map<QString, QString> &value);
void updateVariableValue(const QString &name, const QString &value);
void startPaint(void);
void stopPaint(void);
void setMousePickMaskNodeIds(const std::set<QUuid> &nodeIds);
@ -764,8 +744,6 @@ private: // need initialize
quint64 m_nextMeshGenerationId;
std::map<QString, std::map<QString, QString>> m_cachedVariables;
std::map<QString, std::map<QString, QString>> m_mergedVariables;
ScriptRunner *m_scriptRunner;
bool m_isScriptResultObsolete;
MousePicker *m_mousePicker;
bool m_isMouseTargetResultObsolete;
PaintMode m_paintMode;
@ -780,9 +758,6 @@ private:
QVector3D m_mouseRayNear;
QVector3D m_mouseRayFar;
QVector3D m_mouseTargetPosition;
QString m_scriptError;
QString m_scriptConsoleLog;
QString m_script;
std::set<QUuid> m_mousePickMaskNodeIds;
std::set<QUuid> m_intermediatePaintImageIds;
};

View File

@ -39,8 +39,6 @@
#include "shortcuts.h"
#include "floatnumberwidget.h"
#include "cutfacelistwidget.h"
#include "scriptwidget.h"
#include "variablesxml.h"
#include "updatescheckwidget.h"
int DocumentWindow::m_modelRenderWidgetInitialX = 16;
@ -405,17 +403,10 @@ DocumentWindow::DocumentWindow() :
connect(motionManageWidget, &MotionManageWidget::unregisterDialog, this, &DocumentWindow::unregisterDialog);
addDockWidget(Qt::RightDockWidgetArea, motionDocker);
QDockWidget *scriptDocker = new QDockWidget(tr("Script"), this);
scriptDocker->setAllowedAreas(Qt::RightDockWidgetArea);
ScriptWidget *scriptWidget = new ScriptWidget(m_document, scriptDocker);
scriptDocker->setWidget(scriptWidget);
addDockWidget(Qt::RightDockWidgetArea, scriptDocker);
tabifyDockWidget(partTreeDocker, materialDocker);
tabifyDockWidget(materialDocker, rigDocker);
tabifyDockWidget(rigDocker, poseDocker);
tabifyDockWidget(poseDocker, motionDocker);
tabifyDockWidget(motionDocker, scriptDocker);
partTreeDocker->raise();
@ -454,8 +445,7 @@ DocumentWindow::DocumentWindow() :
"Giraffe",
"Meerkat",
"Mosquito",
"Seagull",
"Procedural Tree",
"Seagull"
};
for (const auto &model: exampleModels) {
QAction *openModelAction = new QAction(model, this);
@ -784,13 +774,6 @@ DocumentWindow::DocumentWindow() :
});
m_windowMenu->addAction(m_showMotionsAction);
m_showScriptAction = new QAction(tr("Script"), this);
connect(m_showScriptAction, &QAction::triggered, [=]() {
scriptDocker->show();
scriptDocker->raise();
});
m_windowMenu->addAction(m_showScriptAction);
QMenu *dialogsMenu = m_windowMenu->addMenu(tr("Dialogs"));
connect(dialogsMenu, &QMenu::aboutToShow, [=]() {
dialogsMenu->clear();
@ -1114,7 +1097,6 @@ DocumentWindow::DocumentWindow() :
connect(m_document, &Document::turnaroundChanged, this, &DocumentWindow::documentChanged);
connect(m_document, &Document::optionsChanged, this, &DocumentWindow::documentChanged);
connect(m_document, &Document::rigChanged, this, &DocumentWindow::documentChanged);
connect(m_document, &Document::scriptChanged, this, &DocumentWindow::documentChanged);
connect(m_modelRenderWidget, &ModelWidget::customContextMenuRequested, [=](const QPoint &pos) {
graphicsWidget->showContextMenu(graphicsWidget->mapFromGlobal(m_modelRenderWidget->mapToGlobal(pos)));
@ -1154,9 +1136,6 @@ DocumentWindow::DocumentWindow() :
m_document->generateMaterialPreviews();
});
connect(m_document, &Document::scriptChanged, m_document, &Document::runScript);
connect(m_document, &Document::scriptModifiedFromExternal, m_document, &Document::runScript);
initShortCuts(this, m_graphicsWidget);
connect(this, &DocumentWindow::initialized, m_document, &Document::uiReady);
@ -1257,7 +1236,6 @@ void DocumentWindow::newDocument()
return;
}
m_document->clearHistories();
m_document->resetScript();
m_document->reset();
m_document->saveSnapshot();
}
@ -1404,20 +1382,6 @@ void DocumentWindow::saveTo(const QString &saveAsFilename)
ds3Writer.add("canvas.png", "asset", &m_document->turnaroundPngByteArray);
}
if (!m_document->script().isEmpty()) {
auto script = m_document->script().toUtf8();
ds3Writer.add("model.js", "script", &script);
}
const auto &variables = m_document->variables();
if (!variables.empty()) {
QByteArray variablesXml;
QXmlStreamWriter variablesXmlStream(&variablesXml);
saveVariablesToXmlStream(variables, &variablesXmlStream);
if (variablesXml.size() > 0)
ds3Writer.add("variables.xml", "variable", &variablesXml);
}
std::set<QUuid> imageIds;
for (const auto &material: snapshot.materials) {
@ -1468,7 +1432,6 @@ void DocumentWindow::openPathAs(const QString &path, const QString &asName)
Ds3FileReader ds3Reader(path);
m_document->clearHistories();
m_document->resetScript();
m_document->reset();
m_document->saveSnapshot();
@ -1506,22 +1469,6 @@ void DocumentWindow::openPathAs(const QString &path, const QString &asName)
QImage image = QImage::fromData(data, "PNG");
m_document->updateTurnaround(image);
}
} else if (item.type == "script") {
if (item.name == "model.js") {
QByteArray script;
ds3Reader.loadItem(item.name, &script);
m_document->initScript(QString::fromUtf8(script.constData()));
}
} else if (item.type == "variable") {
if (item.name == "variables.xml") {
QByteArray data;
ds3Reader.loadItem(item.name, &data);
QXmlStreamReader stream(data);
std::map<QString, std::map<QString, QString>> variables;
loadVariablesFromXmlStream(&variables, stream);
for (const auto &it: variables)
m_document->updateVariable(it.first, it.second);
}
}
}
QApplication::restoreOverrideCursor();

View File

@ -177,7 +177,6 @@ private:
QAction *m_showRigAction;
QAction *m_showPosesAction;
QAction *m_showMotionsAction;
QAction *m_showScriptAction;
QMenu *m_helpMenu;
QAction *m_gotoHomepageAction;

View File

@ -15,20 +15,19 @@ MeshCombiner::Mesh::Mesh(const std::vector<QVector3D> &vertices, const std::vect
CgalMesh *cgalMesh = nullptr;
if (!faces.empty()) {
cgalMesh = buildCgalMesh<CgalKernel>(vertices, faces);
if (!disableSelfIntersects) {
if (!CGAL::is_valid_polygon_mesh(*cgalMesh)) {
qDebug() << "Mesh is not valid polygon";
delete cgalMesh;
cgalMesh = nullptr;
} else {
if (CGAL::Polygon_mesh_processing::triangulate_faces(*cgalMesh)) {
if (!disableSelfIntersects) {
if (CGAL::Polygon_mesh_processing::does_self_intersect(*cgalMesh)) {
m_isSelfIntersected = true;
qDebug() << "Mesh does_self_intersect";
delete cgalMesh;
cgalMesh = nullptr;
}
}
} else {
qDebug() << "Mesh triangulate failed";
delete cgalMesh;
@ -36,6 +35,7 @@ MeshCombiner::Mesh::Mesh(const std::vector<QVector3D> &vertices, const std::vect
}
}
}
}
m_privateData = cgalMesh;
validate();
}

View File

@ -23,7 +23,7 @@ public:
{
public:
Mesh() = default;
Mesh(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, bool disableSelfIntersects=true);
Mesh(const std::vector<QVector3D> &vertices, const std::vector<std::vector<size_t>> &faces, bool disableSelfIntersects=false);
Mesh(const Mesh &other);
~Mesh();
void fetch(std::vector<QVector3D> &vertices, std::vector<std::vector<size_t>> &faces) const;

View File

@ -716,7 +716,7 @@ MeshCombiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdString,
it += xMirrorStart;
partCache.faces.push_back(newFace);
}
MeshCombiner::Mesh *xMirroredMesh = new MeshCombiner::Mesh(xMirroredVertices, xMirroredFaces);
MeshCombiner::Mesh *xMirroredMesh = new MeshCombiner::Mesh(xMirroredVertices, xMirroredFaces, false);
MeshCombiner::Mesh *newMesh = combineTwoMeshes(*mesh,
*xMirroredMesh, MeshCombiner::Method::Union);
delete xMirroredMesh;
@ -1359,23 +1359,6 @@ void MeshGenerator::generate()
m_outcome->nodeVertices = componentCache.outcomeNodeVertices;
m_outcome->vertices = combinedVertices;
m_outcome->triangles = combinedFaces;
/*
if (remeshed) {
remesh(componentCache.outcomeNodes,
combinedVertices,
combinedFaces,
&m_outcome->vertices,
&m_outcome->triangleAndQuads,
&m_outcome->triangles,
&m_outcome->nodeVertices);
} else {
recoverQuads(combinedVertices, combinedFaces, componentCache.sharedQuadEdges, m_outcome->triangleAndQuads);
m_outcome->nodeVertices = componentCache.outcomeNodeVertices;
m_outcome->vertices = combinedVertices;
m_outcome->triangles = combinedFaces;
}
*/
}
// Recursively check uncombined components
@ -1486,10 +1469,12 @@ void MeshGenerator::remesh(const std::vector<OutcomeNode> &inputNodes,
outputTriangles->push_back(std::vector<size_t> {
it[0], it[1], it[2]
});
if (4 == it.size()) {
outputTriangles->push_back(std::vector<size_t> {
it[2], it[3], it[0]
});
}
}
const auto &remeshedVertexSources = remesher.getRemeshedVertexSources();
outputNodeVertices->clear();
outputNodeVertices->reserve(outputVertices->size());

View File

@ -1,38 +1,10 @@
#include <config.hpp>
#include <field-math.hpp>
#include <optimizer.hpp>
#include <parametrizer.hpp>
#include <instant-meshes-api.h>
#include <cmath>
#ifdef WITH_CUDA
#include <cuda_runtime.h>
#endif
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/border.h>
#include <boost/function_output_iterator.hpp>
#include <fstream>
#include <vector>
#include "remesher.h"
#include "booleanmesh.h"
typedef boost::graph_traits<CgalMesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<CgalMesh>::edge_descriptor edge_descriptor;
namespace PMP = CGAL::Polygon_mesh_processing;
struct halfedge2edge
Remesher::Remesher()
{
halfedge2edge(const CgalMesh& m, std::vector<edge_descriptor>& edges)
: m_mesh(m), m_edges(edges)
{}
void operator()(const halfedge_descriptor& h) const
{
m_edges.push_back(edge(h, m_mesh));
}
const CgalMesh& m_mesh;
std::vector<edge_descriptor>& m_edges;
};
using namespace qflow;
}
Remesher::~Remesher()
{
@ -60,108 +32,62 @@ const std::vector<std::pair<QUuid, QUuid>> &Remesher::getRemeshedVertexSources()
return m_remeshedVertexSources;
}
void Remesher::isotropicRemesh(float targetEdgeLength, unsigned int iterationNum)
{
CgalMesh *mesh = buildCgalMesh<CgalKernel>(m_vertices, m_triangles);
if (nullptr == mesh)
return;
std::vector<edge_descriptor> border;
PMP::border_halfedges(faces(*mesh),
*mesh,
boost::make_function_output_iterator(halfedge2edge(*mesh, border)));
PMP::split_long_edges(border, targetEdgeLength, *mesh);
PMP::isotropic_remeshing(faces(*mesh),
targetEdgeLength,
*mesh,
PMP::parameters::number_of_iterations(iterationNum)
.protect_constraints(true));
m_vertices.clear();
m_triangles.clear();
fetchFromCgalMesh<CgalKernel>(mesh, m_vertices, m_triangles);
delete mesh;
}
void Remesher::remesh()
{
Parametrizer field;
#ifdef WITH_CUDA
cudaFree(0);
#endif
isotropicRemesh();
field.V.resize(3, m_vertices.size());
field.F.resize(3, m_triangles.size());
for (decltype(m_vertices.size()) i = 0; i < m_vertices.size(); i++) {
std::vector<Dust3D_InstantMeshesVertex> inputVertices(m_vertices.size());
for (size_t i = 0; i < m_vertices.size(); ++i) {
const auto &vertex = m_vertices[i];
field.V.col(i) << (double)vertex.x(), (double)vertex.y(), (double)vertex.z();
inputVertices[i] = Dust3D_InstantMeshesVertex {
vertex.x(), vertex.y(), vertex.z()
};
}
for (decltype(m_triangles.size()) i = 0; i < m_triangles.size(); i++) {
const auto &face = m_triangles[i];
field.F.col(i) << (uint32_t)face[0], (uint32_t)face[1], (uint32_t)face[2];
std::vector<Dust3D_InstantMeshesTriangle> inputTriangles;
inputTriangles.reserve(m_triangles.size());
for (size_t i = 0; i < m_triangles.size(); ++i) {
const auto &triangle = m_triangles[i];
if (triangle.size() != 3)
continue;
inputTriangles.push_back(Dust3D_InstantMeshesTriangle {{
triangle[0],
triangle[1],
triangle[2]
}});
}
field.NormalizeMesh();
int faces = -1;
field.Initialize(faces);
if (field.flag_preserve_boundary) {
Hierarchy& hierarchy = field.hierarchy;
hierarchy.clearConstraints();
for (uint32_t i = 0; i < 3 * hierarchy.mF.cols(); ++i) {
if (hierarchy.mE2E[i] == -1) {
uint32_t i0 = hierarchy.mF(i % 3, i / 3);
uint32_t i1 = hierarchy.mF((i + 1) % 3, i / 3);
Vector3d p0 = hierarchy.mV[0].col(i0), p1 = hierarchy.mV[0].col(i1);
Vector3d edge = p1 - p0;
if (edge.squaredNorm() > 0) {
edge.normalize();
hierarchy.mCO[0].col(i0) = p0;
hierarchy.mCO[0].col(i1) = p1;
hierarchy.mCQ[0].col(i0) = hierarchy.mCQ[0].col(i1) = edge;
hierarchy.mCQw[0][i0] = hierarchy.mCQw[0][i1] = hierarchy.mCOw[0][i0] = hierarchy.mCOw[0][i1] =
1.0;
}
}
}
hierarchy.propagateConstraints();
}
Optimizer::optimize_orientations(field.hierarchy);
field.ComputeOrientationSingularities();
if (field.flag_adaptive_scale == 1) {
field.EstimateSlope();
}
Optimizer::optimize_scale(field.hierarchy, field.rho, field.flag_adaptive_scale);
field.flag_adaptive_scale = 1;
Optimizer::optimize_positions(field.hierarchy, field.flag_adaptive_scale);
field.ComputePositionSingularities();
field.ComputeIndexMap();
m_remeshedVertices.reserve(field.O_compact.size());
for (size_t i = 0; i < field.O_compact.size(); ++i) {
auto t = field.O_compact[i] * field.normalize_scale + field.normalize_offset;
m_remeshedVertices.push_back(QVector3D(t[0], t[1], t[2]));
}
m_remeshedFaces.reserve(field.F_compact.size());
for (size_t i = 0; i < field.F_compact.size(); ++i) {
const Dust3D_InstantMeshesVertex *resultVertices = nullptr;
size_t nResultVertices = 0;
const Dust3D_InstantMeshesTriangle *resultTriangles = nullptr;
size_t nResultTriangles = 0;
const Dust3D_InstantMeshesQuad *resultQuads = nullptr;
size_t nResultQuads = 0;
Dust3D_instantMeshesRemesh(inputVertices.data(), inputVertices.size(),
inputTriangles.data(), inputTriangles.size(),
(size_t)(inputVertices.size() * 1.0f),
&resultVertices,
&nResultVertices,
&resultTriangles,
&nResultTriangles,
&resultQuads,
&nResultQuads);
m_remeshedVertices.resize(nResultVertices);
memcpy(m_remeshedVertices.data(), resultVertices, sizeof(Dust3D_InstantMeshesVertex) * nResultVertices);
m_remeshedFaces.reserve(nResultTriangles + nResultQuads);
for (size_t i = 0; i < nResultTriangles; ++i) {
const auto &source = resultTriangles[i];
m_remeshedFaces.push_back(std::vector<size_t> {
(size_t)field.F_compact[i][0],
(size_t)field.F_compact[i][1],
(size_t)field.F_compact[i][2],
(size_t)field.F_compact[i][3]
source.indices[0],
source.indices[1],
source.indices[2]
});
}
for (size_t i = 0; i < nResultQuads; ++i) {
const auto &source = resultQuads[i];
m_remeshedFaces.push_back(std::vector<size_t> {
source.indices[0],
source.indices[1],
source.indices[2],
source.indices[3]
});
}
resolveSources();
}

View File

@ -9,6 +9,7 @@ class Remesher : public QObject
{
Q_OBJECT
public:
Remesher();
~Remesher();
void setMesh(const std::vector<QVector3D> &vertices,
const std::vector<std::vector<size_t>> &triangles);
@ -27,7 +28,6 @@ private:
std::vector<std::pair<QVector3D, float>> m_nodes;
std::vector<std::pair<QUuid, QUuid>> m_sourceIds;
void resolveSources();
void isotropicRemesh(float targetEdgeLength=0.02f, unsigned int iterationNum=3);
};
#endif

View File

@ -1,153 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
#include "theme.h"
#include "scripteditwidget.h"
ScriptEditWidget::ScriptEditWidget(QWidget *parent) : QPlainTextEdit(parent)
{
connect(this, &QPlainTextEdit::textChanged, this, [&]() {
emit scriptChanged(toPlainText());
});
m_lineNumberArea = new LineNumberArea(this);
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
updateLineNumberAreaWidth(0);
highlightCurrentLine();
}
int ScriptEditWidget::lineNumberAreaWidth()
{
int digits = 1;
int max = qMax(1, blockCount());
while (max >= 10) {
max /= 10;
++digits;
}
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
return space;
}
void ScriptEditWidget::updateLineNumberAreaWidth(int /* newBlockCount */)
{
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
}
void ScriptEditWidget::updateLineNumberArea(const QRect &rect, int dy)
{
if (dy)
m_lineNumberArea->scroll(0, dy);
else
m_lineNumberArea->update(0, rect.y(), m_lineNumberArea->width(), rect.height());
if (rect.contains(viewport()->rect()))
updateLineNumberAreaWidth(0);
}
void ScriptEditWidget::resizeEvent(QResizeEvent *e)
{
QPlainTextEdit::resizeEvent(e);
QRect cr = contentsRect();
m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}
void ScriptEditWidget::highlightCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(0x24, 0x24, 0x24).lighter(160);
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}
setExtraSelections(extraSelections);
}
void ScriptEditWidget::lineNumberAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(m_lineNumberArea);
painter.fillRect(event->rect(), QColor(0x24, 0x24, 0x24));
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + (int) blockBoundingRect(block).height();
while (block.isValid() && top <= event->rect().bottom()) {
if (block.isVisible() && bottom >= event->rect().top()) {
QString number = QString::number(blockNumber + 1);
painter.setPen(Theme::white);
painter.drawText(0, top, m_lineNumberArea->width(), fontMetrics().height(),
Qt::AlignRight, number);
}
block = block.next();
top = bottom;
bottom = top + (int) blockBoundingRect(block).height();
++blockNumber;
}
}

View File

@ -1,99 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef CODEEDITOR_H
#define CODEEDITOR_H
#include <QPlainTextEdit>
#include <QObject>
class QPaintEvent;
class QResizeEvent;
class QSize;
class QWidget;
class LineNumberArea;
class ScriptEditWidget : public QPlainTextEdit
{
Q_OBJECT
signals:
void scriptChanged(const QString &script);
public:
ScriptEditWidget(QWidget *parent=0);
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth();
protected:
void resizeEvent(QResizeEvent *event);
private slots:
void updateLineNumberAreaWidth(int newBlockCount);
void highlightCurrentLine();
void updateLineNumberArea(const QRect &, int);
private:
QWidget *m_lineNumberArea;
};
class LineNumberArea : public QWidget
{
public:
LineNumberArea(ScriptEditWidget *editor) : QWidget(editor) {
m_codeEditor = editor;
}
QSize sizeHint() const {
return QSize(m_codeEditor->lineNumberAreaWidth(), 0);
}
protected:
void paintEvent(QPaintEvent *event) {
m_codeEditor->lineNumberAreaPaintEvent(event);
}
private:
ScriptEditWidget *m_codeEditor;
};
#endif

View File

@ -1,884 +0,0 @@
#include <QDebug>
#include <QElapsedTimer>
#include <QUuid>
#include <QFile>
#include "scriptrunner.h"
#include "util.h"
JSClassID ScriptRunner::js_canvasClassId = 0;
JSClassID ScriptRunner::js_partClassId = 0;
JSClassID ScriptRunner::js_componentClassId = 0;
JSClassID ScriptRunner::js_nodeClassId = 0;
static JSValue js_print(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
int i;
const char *str;
for (i = 0; i < argc; i++) {
if (i != 0)
runner->consoleLog() += ' ';
str = JS_ToCString(context, argv[i]);
if (!str)
return JS_EXCEPTION;
runner->consoleLog() += str;
JS_FreeCString(context, str);
}
runner->consoleLog() += '\n';
return JS_UNDEFINED;
}
static ScriptRunner::DocumentElement *GetElementFromArg(JSValueConst arg)
{
ScriptRunner::DocumentElement *element = nullptr;
if (nullptr == element) {
ScriptRunner::DocumentNode *node = (ScriptRunner::DocumentNode *)JS_GetOpaque(arg,
ScriptRunner::js_nodeClassId);
if (nullptr != node) {
element = (ScriptRunner::DocumentElement *)node;
}
}
if (nullptr == element) {
ScriptRunner::DocumentPart *part = (ScriptRunner::DocumentPart *)JS_GetOpaque(arg,
ScriptRunner::js_partClassId);
if (nullptr != part) {
element = (ScriptRunner::DocumentElement *)part;
}
}
if (nullptr == element) {
ScriptRunner::DocumentComponent *component = (ScriptRunner::DocumentComponent *)JS_GetOpaque(arg,
ScriptRunner::js_componentClassId);
if (nullptr != component) {
element = (ScriptRunner::DocumentElement *)component;
}
}
if (nullptr == element) {
ScriptRunner::DocumentCanvas *canvas = (ScriptRunner::DocumentCanvas *)JS_GetOpaque(arg,
ScriptRunner::js_canvasClassId);
if (nullptr != canvas) {
element = (ScriptRunner::DocumentElement *)canvas;
}
}
return element;
}
static JSValue js_setAttribute(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 3) {
runner->consoleLog() += "Incomplete parameters, expect: element, attributeName, attributeValue\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentElement *element = GetElementFromArg(argv[0]);
if (nullptr == element) {
runner->consoleLog() += "Parameters error\r\n";
return JS_EXCEPTION;
}
const char *attributeName = nullptr;
const char *attributeValue = nullptr;
attributeName = JS_ToCString(context, argv[1]);
if (!attributeName)
goto fail;
attributeValue = JS_ToCString(context, argv[2]);
if (!attributeValue)
goto fail;
runner->setAttribute(element, attributeName, attributeValue);
JS_FreeCString(context, attributeName);
JS_FreeCString(context, attributeValue);
return JS_UNDEFINED;
fail:
JS_FreeCString(context, attributeName);
JS_FreeCString(context, attributeValue);
return JS_EXCEPTION;
}
static JSValue js_attribute(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 2) {
runner->consoleLog() += "Incomplete parameters, expect: element, attributeName\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentElement *element = GetElementFromArg(argv[0]);
if (nullptr == element) {
runner->consoleLog() += "Parameters error\r\n";
return JS_EXCEPTION;
}
QString attributeValue;
const char *attributeName = nullptr;
attributeName = JS_ToCString(context, argv[1]);
if (!attributeName)
goto fail;
attributeValue = runner->attribute(element, attributeName);
JS_FreeCString(context, attributeName);
return JS_NewString(context, attributeValue.toUtf8().constData());
fail:
JS_FreeCString(context, attributeName);
return JS_EXCEPTION;
}
static JSValue js_connect(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 2) {
runner->consoleLog() += "Incomplete parameters, expect: firstNode, secondNode\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentElement *firstElement = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
ScriptRunner::js_nodeClassId);
if (nullptr == firstElement ||
ScriptRunner::DocumentElementType::Node != firstElement->type) {
runner->consoleLog() += "First parameter must be node\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentElement *secondElement = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[1],
ScriptRunner::js_nodeClassId);
if (nullptr == secondElement ||
ScriptRunner::DocumentElementType::Node != secondElement->type) {
runner->consoleLog() += "Second parameter must be node\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentNode *firstNode = (ScriptRunner::DocumentNode *)firstElement;
ScriptRunner::DocumentNode *secondNode = (ScriptRunner::DocumentNode *)secondElement;
if (firstNode->part != secondNode->part) {
runner->consoleLog() += "Cannot connect nodes come from different parts\r\n";
return JS_EXCEPTION;
}
runner->connect(firstNode, secondNode);
return JS_UNDEFINED;
}
static JSValue js_createComponent(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
ScriptRunner::DocumentComponent *parentComponent = nullptr;
if (argc >= 1) {
ScriptRunner::DocumentElement *element = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
ScriptRunner::js_componentClassId);
if (nullptr == element ||
ScriptRunner::DocumentElementType::Component != element->type) {
runner->consoleLog() += "First parameter must be null or component\r\n";
return JS_EXCEPTION;
}
parentComponent = (ScriptRunner::DocumentComponent *)element;
}
JSValue component = JS_NewObjectClass(context, ScriptRunner::js_componentClassId);
JS_SetOpaque(component, runner->createComponent(parentComponent));
return component;
}
static JSValue js_createPart(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 1) {
runner->consoleLog() += "Incomplete parameters, expect: component\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentElement *element = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
ScriptRunner::js_componentClassId);
if (nullptr == element ||
ScriptRunner::DocumentElementType::Component != element->type) {
runner->consoleLog() += "First parameter must be component\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentComponent *component = (ScriptRunner::DocumentComponent *)element;
JSValue part = JS_NewObjectClass(context, ScriptRunner::js_partClassId);
JS_SetOpaque(part, runner->createPart(component));
return part;
}
static JSValue js_createNode(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 1) {
runner->consoleLog() += "Incomplete parameters, expect: part\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentElement *element = (ScriptRunner::DocumentElement *)JS_GetOpaque(argv[0],
ScriptRunner::js_partClassId);
if (nullptr == element ||
ScriptRunner::DocumentElementType::Part != element->type) {
runner->consoleLog() += "First parameter must be part\r\n";
return JS_EXCEPTION;
}
ScriptRunner::DocumentPart *part = (ScriptRunner::DocumentPart *)element;
JSValue node = JS_NewObjectClass(context, ScriptRunner::js_nodeClassId);
JS_SetOpaque(node, runner->createNode(part));
return node;
}
static JSValue js_createFloatInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 4) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, minValue, maxValue\r\n";
return JS_EXCEPTION;
}
double mergedValue = 0.0;
const char *name = nullptr;
double defaultValue = 0.0;
double minValue = 0.0;
double maxValue = 0.0;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
JS_ToFloat64(context, &defaultValue, argv[1]);
JS_ToFloat64(context, &minValue, argv[2]);
JS_ToFloat64(context, &maxValue, argv[3]);
mergedValue = runner->createFloatInput(name, defaultValue, minValue, maxValue);
JS_FreeCString(context, name);
return JS_NewFloat64(context, mergedValue);
fail:
JS_FreeCString(context, name);
return JS_EXCEPTION;
}
static JSValue js_createIntInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 4) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, minValue, maxValue\r\n";
return JS_EXCEPTION;
}
int64_t mergedValue = 0.0;
const char *name = nullptr;
int64_t defaultValue = 0;
int64_t minValue = 0;
int64_t maxValue = 0;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
JS_ToInt64(context, &defaultValue, argv[1]);
JS_ToInt64(context, &minValue, argv[2]);
JS_ToInt64(context, &maxValue, argv[3]);
mergedValue = runner->createIntInput(name, defaultValue, minValue, maxValue);
JS_FreeCString(context, name);
return JS_NewInt64(context, mergedValue);
fail:
JS_FreeCString(context, name);
return JS_EXCEPTION;
}
static JSValue js_createColorInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 2) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue\r\n";
return JS_EXCEPTION;
}
QColor mergeValue;
const char *name = nullptr;
const char *defaultValue = nullptr;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
defaultValue = JS_ToCString(context, argv[1]);
if (!defaultValue)
goto fail;
mergeValue = runner->createColorInput(name, defaultValue);
JS_FreeCString(context, name);
JS_FreeCString(context, defaultValue);
return JS_NewString(context, mergeValue.name().toUtf8().constData());
fail:
JS_FreeCString(context, name);
JS_FreeCString(context, defaultValue);
return JS_EXCEPTION;
}
static JSValue js_createCheckInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 2) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue\r\n";
return JS_EXCEPTION;
}
bool mergedValue = false;
const char *name = nullptr;
const char *value = nullptr;
bool defaultValue = false;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
value = JS_ToCString(context, argv[1]);
if (!value)
goto fail;
defaultValue = isTrueValueString(value);
mergedValue = runner->createCheckInput(name, defaultValue);
JS_FreeCString(context, name);
JS_FreeCString(context, value);
return JS_NewBool(context, mergedValue);
fail:
JS_FreeCString(context, name);
JS_FreeCString(context, value);
return JS_EXCEPTION;
}
static JSValue js_createSelectInput(JSContext *context, JSValueConst thisValue,
int argc, JSValueConst *argv)
{
ScriptRunner *runner = (ScriptRunner *)JS_GetContextOpaque(context);
if (argc < 3) {
runner->consoleLog() += "Incomplete parameters, expect: name, defaultValue, options\r\n";
return JS_EXCEPTION;
}
const char *name = nullptr;
int32_t defaultValue = 0;
int32_t mergedValue = 0;
JSValue *arrayItems = nullptr;
uint32_t arrayLength = 0;
QStringList options;
name = JS_ToCString(context, argv[0]);
if (!name)
goto fail;
JS_ToInt32(context, &defaultValue, argv[1]);
if (true != JS_IsArray(context, argv[2])) {
runner->consoleLog() += "Expect array as the third parameter\r\n";
goto fail;
}
if (!js_get_fast_array(context, argv[2], &arrayItems, &arrayLength)) {
runner->consoleLog() += "Read third parameter as array failed\r\n";
goto fail;
}
for (uint32_t i = 0; i < arrayLength; ++i) {
const char *optionValue = JS_ToCString(context, arrayItems[i]);
if (nullptr != optionValue) {
options.append(optionValue);
JS_FreeCString(context, optionValue);
} else {
options.append("");
}
}
mergedValue = runner->createSelectInput(name, defaultValue, options);
if (mergedValue < 0)
mergedValue = 0;
else if (mergedValue >= options.size())
mergedValue = options.size() - 1;
JS_FreeCString(context, name);
return JS_NewInt32(context, mergedValue);
fail:
JS_FreeCString(context, name);
return JS_EXCEPTION;
}
ScriptRunner::ScriptRunner()
{
}
ScriptRunner::~ScriptRunner()
{
delete m_resultSnapshot;
delete m_defaultVariables;
for (auto &it: m_parts)
delete it;
for (auto &it: m_components)
delete it;
for (auto &it: m_nodes)
delete it;
}
QString &ScriptRunner::consoleLog()
{
return m_consoleLog;
}
const QString &ScriptRunner::scriptError()
{
return m_scriptError;
}
ScriptRunner::DocumentPart *ScriptRunner::createPart(DocumentComponent *component)
{
ScriptRunner::DocumentPart *part = new ScriptRunner::DocumentPart;
part->component = component;
m_parts.push_back(part);
return part;
}
ScriptRunner::DocumentComponent *ScriptRunner::createComponent(DocumentComponent *parentComponent)
{
ScriptRunner::DocumentComponent *component = new ScriptRunner::DocumentComponent;
component->parentComponent = parentComponent;
m_components.push_back(component);
return component;
}
ScriptRunner::DocumentNode *ScriptRunner::createNode(DocumentPart *part)
{
ScriptRunner::DocumentNode *node = new ScriptRunner::DocumentNode;
node->part = part;
m_nodes.push_back(node);
return node;
}
bool ScriptRunner::setAttribute(DocumentElement *element, const QString &name, const QString &value)
{
element->attributes[name] = value;
// TODO: Validate attribute name and value
return true;
}
QString ScriptRunner::attribute(DocumentElement *element, const QString &name)
{
auto findAttribute = element->attributes.find(name);
if (findAttribute == element->attributes.end())
return QString();
return findAttribute->second;
}
void ScriptRunner::connect(DocumentNode *firstNode, DocumentNode *secondNode)
{
m_edges.push_back(std::make_pair(firstNode, secondNode));
}
static void js_componentFinalizer(JSRuntime *runtime, JSValue value)
{
ScriptRunner::DocumentComponent *component = (ScriptRunner::DocumentComponent *)JS_GetOpaque(value,
ScriptRunner::js_componentClassId);
if (component) {
component->deleted = true;
}
}
static JSClassDef js_componentClass = {
"Component",
js_componentFinalizer,
};
static void js_nodeFinalizer(JSRuntime *runtime, JSValue value)
{
ScriptRunner::DocumentNode *node = (ScriptRunner::DocumentNode *)JS_GetOpaque(value,
ScriptRunner::js_nodeClassId);
if (node) {
node->deleted = true;
}
}
static JSClassDef js_nodeClass = {
"Node",
js_nodeFinalizer,
};
static void js_partFinalizer(JSRuntime *runtime, JSValue value)
{
ScriptRunner::DocumentPart *part = (ScriptRunner::DocumentPart *)JS_GetOpaque(value,
ScriptRunner::js_partClassId);
if (part) {
part->deleted = true;
}
}
static JSClassDef js_partClass = {
"Part",
js_partFinalizer,
};
void ScriptRunner::run()
{
QElapsedTimer countTimeConsumed;
countTimeConsumed.start();
// Warning: Not thread safe, but we have only one script instance running, so it doesn't matter
js_canvasClassId = JS_NewClassID(&js_canvasClassId);
js_partClassId = JS_NewClassID(&js_partClassId);
js_componentClassId = JS_NewClassID(&js_componentClassId);
js_nodeClassId = JS_NewClassID(&js_nodeClassId);
m_defaultVariables = new std::map<QString, std::map<QString, QString>>;
JSRuntime *runtime = JS_NewRuntime();
JSContext *context = JS_NewContext(runtime);
JS_NewClass(runtime, js_partClassId, &js_partClass);
JS_NewClass(runtime, js_componentClassId, &js_componentClass);
JS_NewClass(runtime, js_nodeClassId, &js_nodeClass);
JS_SetContextOpaque(context, this);
if (nullptr != m_script &&
!m_script->trimmed().isEmpty()) {
auto buffer = m_script->toUtf8();
JSValue globalObject = JS_GetGlobalObject(context);
JSValue document = JS_NewObject(context);
JS_SetPropertyStr(context,
document, "createComponent",
JS_NewCFunction(context, js_createComponent, "createComponent", 1));
JS_SetPropertyStr(context,
document, "createPart",
JS_NewCFunction(context, js_createPart, "createPart", 1));
JS_SetPropertyStr(context,
document, "createNode",
JS_NewCFunction(context, js_createNode, "createNode", 1));
JS_SetPropertyStr(context,
document, "createFloatInput",
JS_NewCFunction(context, js_createFloatInput, "createFloatInput", 4));
JS_SetPropertyStr(context,
document, "createIntInput",
JS_NewCFunction(context, js_createIntInput, "createIntInput", 4));
JS_SetPropertyStr(context,
document, "createColorInput",
JS_NewCFunction(context, js_createColorInput, "createColorInput", 2));
JS_SetPropertyStr(context,
document, "createCheckInput",
JS_NewCFunction(context, js_createCheckInput, "createCheckInput", 2));
JS_SetPropertyStr(context,
document, "createSelectInput",
JS_NewCFunction(context, js_createSelectInput, "createSelectInput", 3));
JS_SetPropertyStr(context,
document, "connect",
JS_NewCFunction(context, js_connect, "connect", 2));
JS_SetPropertyStr(context,
document, "setAttribute",
JS_NewCFunction(context, js_setAttribute, "setAttribute", 3));
JS_SetPropertyStr(context,
document, "attribute",
JS_NewCFunction(context, js_attribute, "attribute", 2));
JSValue canvas = JS_NewObjectClass(context, ScriptRunner::js_canvasClassId);
JS_SetOpaque(canvas, &m_canvas);
JS_SetPropertyStr(context,
document, "canvas",
canvas);
JS_SetPropertyStr(context, globalObject, "document", document);
JSValue console = JS_NewObject(context);
JS_SetPropertyStr(context,
console, "log",
JS_NewCFunction(context, js_print, "log", 1));
JS_SetPropertyStr(context,
console, "warn",
JS_NewCFunction(context, js_print, "warn", 1));
JS_SetPropertyStr(context,
console, "error",
JS_NewCFunction(context, js_print, "error", 1));
JS_SetPropertyStr(context, globalObject, "console", console);
QFile file(":/thirdparty/three.js/dust3d.three.js");
if (file.open(QIODevice::ReadOnly)) {
QByteArray fileContent = file.readAll();
JSValue three = JS_NewObject(context);
JS_SetPropertyStr(context, globalObject, "THREE", three);
JSValue object = JS_Eval(context, (char *)fileContent.constData(), fileContent.size(), "<thirdparty/three.js/dust3d.three.js>",
JS_EVAL_TYPE_GLOBAL);
JS_FreeValue(context, object);
file.close();
}
JS_FreeValue(context, globalObject);
JSValue object = JS_Eval(context, buffer.constData(), buffer.size(), "<input>",
JS_EVAL_TYPE_GLOBAL);
if (JS_IsException(object)) {
JSValue exceptionValue = JS_GetException(context);
bool isError = JS_IsError(context, exceptionValue);
if (isError) {
m_scriptError += "Throw: ";
const char *exceptionError = JS_ToCString(context, exceptionValue);
m_scriptError += exceptionError;
m_scriptError += "\r\n";
JS_FreeCString(context, exceptionError);
JSValue value = JS_GetPropertyStr(context, exceptionValue, "stack");
if (!JS_IsUndefined(value)) {
const char *stack = JS_ToCString(context, value);
m_scriptError += stack;
m_scriptError += "\r\n";
JS_FreeCString(context, stack);
}
JS_FreeValue(context, value);
qDebug() << "QuickJS" << m_scriptError;
}
} else {
generateSnapshot();
const char *objectString = JS_ToCString(context, object);
qDebug() << "Result:" << objectString;
JS_FreeCString(context, objectString);
}
JS_FreeValue(context, object);
}
JS_FreeContext(context);
JS_FreeRuntime(runtime);
qDebug() << "The script run" << countTimeConsumed.elapsed() << "milliseconds";
}
void ScriptRunner::generateSnapshot()
{
m_resultSnapshot = new Snapshot;
std::map<void *, QString> pointerToIdMap;
std::map<void *, QStringList> componentChildrensMap;
QStringList rootChildren;
m_resultSnapshot->canvas = m_canvas.attributes;
for (const auto &it: m_components) {
QString idString = it->id;
pointerToIdMap[it] = idString;
auto &component = m_resultSnapshot->components[idString];
component = it->attributes;
component["id"] = idString;
componentChildrensMap[it->parentComponent].append(idString);
if (nullptr == it->parentComponent)
rootChildren.append(idString);
}
m_resultSnapshot->rootComponent["children"] = rootChildren.join(",");
for (const auto &it: m_components) {
const auto &idString = pointerToIdMap[it];
auto &component = m_resultSnapshot->components[idString];
auto &childrens = componentChildrensMap[it];
if (!childrens.empty())
component["children"] = childrens.join(",");
}
for (const auto &it: m_parts) {
auto findComponent = pointerToIdMap.find(it->component);
if (findComponent == pointerToIdMap.end()) {
m_scriptError += "Find component pointer failed, component maybe deleted\r\n";
continue;
}
QString idString = it->id;
pointerToIdMap[it] = idString;
auto &part = m_resultSnapshot->parts[idString];
part = it->attributes;
part.insert({"visible", "true"});
part["id"] = idString;
auto &component = m_resultSnapshot->components[findComponent->second];
component["linkData"] = idString;
component["linkDataType"] = "partId";
}
for (const auto &it: m_nodes) {
auto findPart = pointerToIdMap.find(it->part);
if (findPart == pointerToIdMap.end()) {
m_scriptError += "Find part pointer failed, part maybe deleted\r\n";
continue;
}
QString idString = it->id;
pointerToIdMap[it] = idString;
auto &node = m_resultSnapshot->nodes[idString];
node = it->attributes;
node["id"] = idString;
node["partId"] = findPart->second;
}
for (const auto &it: m_edges) {
if (it.first->part != it.second->part) {
m_scriptError += "Cannot connect nodes come from different parts\r\n";
continue;
}
auto findFirstNode = pointerToIdMap.find(it.first);
if (findFirstNode == pointerToIdMap.end()) {
m_scriptError += "Find first node pointer failed, node maybe deleted\r\n";
continue;
}
auto findSecondNode = pointerToIdMap.find(it.second);
if (findSecondNode == pointerToIdMap.end()) {
m_scriptError += "Find second node pointer failed, node maybe deleted\r\n";
continue;
}
auto findPart = pointerToIdMap.find(it.first->part);
if (findPart == pointerToIdMap.end()) {
m_scriptError += "Find part pointer failed, part maybe deleted\r\n";
continue;
}
QString idString = QUuid::createUuid().toString();
auto &edge = m_resultSnapshot->edges[idString];
edge["id"] = idString;
edge["from"] = findFirstNode->second;
edge["to"] = findSecondNode->second;
edge["partId"] = findPart->second;
}
for (const auto &it: m_resultSnapshot->nodes) {
qDebug() << "Generated node:" << it.second;
}
for (const auto &it: m_resultSnapshot->edges) {
qDebug() << "Generated edge:" << it.second;
}
for (const auto &it: m_resultSnapshot->parts) {
qDebug() << "Generated part:" << it.second;
}
for (const auto &it: m_resultSnapshot->components) {
qDebug() << "Generated component:" << it.second;
}
}
QString ScriptRunner::createInput(const QString &name, const std::map<QString, QString> &attributes)
{
if (nullptr != m_defaultVariables) {
if (m_defaultVariables->find(name) != m_defaultVariables->end()) {
m_scriptError += "Repeated variable name found: \"" + name + "\"\r\n";
}
(*m_defaultVariables)[name] = attributes;
}
if (nullptr != m_variables) {
auto findVariable = m_variables->find(name);
if (findVariable != m_variables->end()) {
auto findValue = findVariable->second.find("value");
if (findValue != findVariable->second.end())
return findValue->second;
}
}
auto findValue = attributes.find("value");
if (findValue != attributes.end())
return findValue->second;
return QString();
}
float ScriptRunner::createFloatInput(const QString &name, float defaultValue, float minValue, float maxValue)
{
std::map<QString, QString> attributes;
attributes["input"] = "Float";
attributes["value"] = QString::number(defaultValue);
attributes["defaultValue"] = attributes["value"];
attributes["minValue"] = QString::number(minValue);
attributes["maxValue"] = QString::number(maxValue);
auto inputValue = createInput(name, attributes);
return inputValue.toFloat();
}
int ScriptRunner::createIntInput(const QString &name, int defaultValue, int minValue, int maxValue)
{
std::map<QString, QString> attributes;
attributes["input"] = "Int";
attributes["value"] = QString::number(defaultValue);
attributes["defaultValue"] = attributes["value"];
attributes["minValue"] = QString::number(minValue);
attributes["maxValue"] = QString::number(maxValue);
auto inputValue = createInput(name, attributes);
return inputValue.toInt();
}
QColor ScriptRunner::createColorInput(const QString &name, const QColor &defaultValue)
{
std::map<QString, QString> attributes;
attributes["input"] = "Color";
attributes["value"] = defaultValue.name();
attributes["defaultValue"] = attributes["value"];
auto inputValue = createInput(name, attributes);
return QColor(inputValue);
}
bool ScriptRunner::createCheckInput(const QString &name, bool checked)
{
std::map<QString, QString> attributes;
attributes["input"] = "Check";
attributes["value"] = checked ? "true" : "false";
attributes["defaultValue"] = attributes["value"];
auto inputValue = createInput(name, attributes);
return isTrueValueString(inputValue);
}
int ScriptRunner::createSelectInput(const QString &name, int defaultSelectedIndex, const QStringList &options)
{
std::map<QString, QString> attributes;
attributes["input"] = "Select";
attributes["value"] = QString::number(defaultSelectedIndex);
attributes["defaultValue"] = attributes["value"];
attributes["length"] = QString::number(options.size());
for (int i = 0; i < options.size(); ++i) {
attributes["option" + QString::number(i)] = options[i];
}
auto inputValue = createInput(name, attributes);
int selectedIndex = inputValue.toInt();
if (selectedIndex >= options.size()) {
m_scriptError += QString("Selected index of select input \"%1\" is been reset to 0 because of out of range\r\n").arg(name);
selectedIndex = 0;
}
return selectedIndex;
}
void ScriptRunner::process()
{
run();
emit finished();
}
void ScriptRunner::setScript(QString *script)
{
m_script = script;
}
void ScriptRunner::setVariables(std::map<QString, std::map<QString, QString>> *variables)
{
m_variables = variables;
}
Snapshot *ScriptRunner::takeResultSnapshot()
{
Snapshot *snapshot = m_resultSnapshot;
m_resultSnapshot = nullptr;
return snapshot;
}
std::map<QString, std::map<QString, QString>> *ScriptRunner::takeDefaultVariables()
{
std::map<QString, std::map<QString, QString>> *defaultVariables = m_defaultVariables;
m_defaultVariables = nullptr;
return defaultVariables;
}
void ScriptRunner::mergeVaraibles(std::map<QString, std::map<QString, QString>> *target, const std::map<QString, std::map<QString, QString>> &source)
{
for (const auto &it: source) {
(*target)[it.first] = it.second;
}
}

View File

@ -1,114 +0,0 @@
#ifndef DUST3D_SCRIPT_RUNNER_H
#define DUST3D_SCRIPT_RUNNER_H
#include <QObject>
#include <QUuid>
#include <QColor>
#include <QStringList>
#include "snapshot.h"
extern "C" {
#include "quickjs.h"
}
class ScriptRunner : public QObject
{
Q_OBJECT
public:
enum class DocumentElementType
{
Unknown = 0,
Canvas,
Component,
Part,
Node
};
struct DocumentElement
{
QString id = QUuid::createUuid().toString();
DocumentElementType type = DocumentElementType::Unknown;
bool deleted = false;
std::map<QString, QString> attributes = {std::make_pair("id", id)};
};
struct DocumentComponent : DocumentElement
{
DocumentComponent()
{
type = DocumentElementType::Component;
}
DocumentComponent *parentComponent = nullptr;
};
struct DocumentPart : DocumentElement
{
DocumentPart()
{
type = DocumentElementType::Part;
}
DocumentComponent *component = nullptr;
};
struct DocumentNode : DocumentElement
{
DocumentNode()
{
type = DocumentElementType::Node;
}
DocumentPart *part = nullptr;
};
struct DocumentCanvas : DocumentElement
{
DocumentCanvas()
{
type = DocumentElementType::Canvas;
}
};
ScriptRunner();
~ScriptRunner();
void run();
void setScript(QString *script);
void setVariables(std::map<QString, std::map<QString, QString>> *variables);
Snapshot *takeResultSnapshot();
std::map<QString, std::map<QString, QString>> *takeDefaultVariables();
const QString &scriptError();
static void mergeVaraibles(std::map<QString, std::map<QString, QString>> *target, const std::map<QString, std::map<QString, QString>> &source);
DocumentPart *createPart(DocumentComponent *component);
DocumentComponent *createComponent(DocumentComponent *parentComponent);
DocumentNode *createNode(DocumentPart *part);
bool setAttribute(DocumentElement *element, const QString &name, const QString &value);
QString attribute(DocumentElement *element, const QString &name);
void connect(DocumentNode *firstNode, DocumentNode *secondNode);
QString &consoleLog();
QString createInput(const QString &name, const std::map<QString, QString> &attributes);
float createFloatInput(const QString &name, float defaultValue, float minValue, float maxValue);
int createIntInput(const QString &name, int defaultValue, int minValue, int maxValue);
QColor createColorInput(const QString &name, const QColor &defaultValue);
bool createCheckInput(const QString &name, bool checked);
int createSelectInput(const QString &name, int defaultSelectedIndex, const QStringList &options);
signals:
void finished();
public slots:
void process();
private:
QString *m_script = nullptr;
Snapshot *m_resultSnapshot = nullptr;
std::map<QString, std::map<QString, QString>> *m_defaultVariables = nullptr;
std::map<QString, std::map<QString, QString>> *m_variables = nullptr;
std::vector<DocumentPart *> m_parts;
std::vector<DocumentComponent *> m_components;
std::vector<DocumentNode *> m_nodes;
std::vector<std::pair<DocumentNode *, DocumentNode *>> m_edges;
QString m_scriptError;
QString m_consoleLog;
DocumentCanvas m_canvas;
void generateSnapshot();
public:
static JSClassID js_canvasClassId;
static JSClassID js_partClassId;
static JSClassID js_componentClassId;
static JSClassID js_nodeClassId;
};
#endif

View File

@ -1,194 +0,0 @@
#include <QDoubleSpinBox>
#include <QFormLayout>
#include <QDebug>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QColorDialog>
#include "scriptvariableswidget.h"
#include "util.h"
#include "theme.h"
#include "floatnumberwidget.h"
#include "intnumberwidget.h"
ScriptVariablesWidget::ScriptVariablesWidget(const Document *document,
QWidget *parent) :
QScrollArea(parent),
m_document(document)
{
connect(this, &ScriptVariablesWidget::updateVariableValue, m_document, &Document::updateVariableValue);
setWidgetResizable(true);
reload();
}
void ScriptVariablesWidget::reload()
{
QWidget *widget = new QWidget;
QFormLayout *formLayout = new QFormLayout;
for (const auto &variable: m_document->variables()) {
auto name = variable.first;
auto input = valueOfKeyInMapOrEmpty(variable.second, "input");
if ("Float" == input) {
auto minValue = valueOfKeyInMapOrEmpty(variable.second, "minValue").toFloat();
auto maxValue = valueOfKeyInMapOrEmpty(variable.second, "maxValue").toFloat();
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toFloat();
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toFloat();
FloatNumberWidget *floatWidget = new FloatNumberWidget;
floatWidget->setItemName(name);
floatWidget->setRange(minValue, maxValue);
floatWidget->setValue(value);
connect(floatWidget, &FloatNumberWidget::valueChanged, [=](float toValue) {
emit updateVariableValue(name, QString::number(toValue));
});
QPushButton *floatEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(floatEraser);
connect(floatEraser, &QPushButton::clicked, [=]() {
floatWidget->setValue(defaultValue);
});
QHBoxLayout *floatLayout = new QHBoxLayout;
floatLayout->addWidget(floatEraser);
floatLayout->addWidget(floatWidget);
formLayout->addRow(floatLayout);
} else if ("Int" == input) {
auto minValue = valueOfKeyInMapOrEmpty(variable.second, "minValue").toInt();
auto maxValue = valueOfKeyInMapOrEmpty(variable.second, "maxValue").toInt();
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toInt();
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toInt();
IntNumberWidget *intWidget = new IntNumberWidget;
intWidget->setItemName(name);
intWidget->setRange(minValue, maxValue);
intWidget->setValue(value);
connect(intWidget, &IntNumberWidget::valueChanged, [=](int toValue) {
emit updateVariableValue(name, QString::number(toValue));
});
QPushButton *intEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(intEraser);
connect(intEraser, &QPushButton::clicked, [=]() {
intWidget->setValue(defaultValue);
});
QHBoxLayout *intLayout = new QHBoxLayout;
intLayout->addWidget(intEraser);
intLayout->addWidget(intWidget);
formLayout->addRow(intLayout);
} else if ("Check" == input) {
auto value = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "value"));
auto defaultValue = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "defaultValue"));
QCheckBox *checkBox = new QCheckBox;
Theme::initCheckbox(checkBox);
checkBox->setText(name);
checkBox->setChecked(value);
connect(checkBox, &QCheckBox::stateChanged, [=](int) {
emit updateVariableValue(name, checkBox->isChecked() ? "true" : "false");
});
QPushButton *checkEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(checkEraser);
connect(checkEraser, &QPushButton::clicked, [=]() {
checkBox->setChecked(defaultValue);
});
QHBoxLayout *checkLayout = new QHBoxLayout;
checkLayout->addWidget(checkEraser);
checkLayout->addWidget(checkBox);
formLayout->addRow(checkLayout);
} else if ("Select" == input) {
auto value = valueOfKeyInMapOrEmpty(variable.second, "value").toInt();
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue").toInt();
auto length = valueOfKeyInMapOrEmpty(variable.second, "length").toInt();
QComboBox *selectBox = new QComboBox;
selectBox->setEditable(false);
selectBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
for (auto i = 0; i < length; ++i) {
selectBox->addItem(valueOfKeyInMapOrEmpty(variable.second, "option" + QString::number(i)));
}
selectBox->setCurrentIndex(value);
connect(selectBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index) {
emit updateVariableValue(name, QString::number(index));
});
QPushButton *selectEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(selectEraser);
connect(selectEraser, &QPushButton::clicked, [=]() {
selectBox->setCurrentIndex(defaultValue);
});
QLabel *selectLabel = new QLabel;
selectLabel->setText(name);
QHBoxLayout *selectLayout = new QHBoxLayout;
selectLayout->addWidget(selectEraser);
selectLayout->addWidget(selectBox);
selectLayout->addWidget(selectLabel);
formLayout->addRow(selectLayout);
} else if ("Color" == input) {
auto value = valueOfKeyInMapOrEmpty(variable.second, "value");
auto defaultValue = valueOfKeyInMapOrEmpty(variable.second, "defaultValue");
QPushButton *colorEraser = new QPushButton(QChar(fa::eraser));
Theme::initAwesomeToolButton(colorEraser);
QPushButton *pickButton = new QPushButton();
Theme::initAwesomeToolButtonWithoutFont(pickButton);
auto updatePickButtonColor = [=](const QColor &color) {
QPalette palette = pickButton->palette();
palette.setColor(QPalette::Window, color);
palette.setColor(QPalette::Button, color);
pickButton->setPalette(palette);
};
updatePickButtonColor(QColor(value));
connect(colorEraser, &QPushButton::clicked, [=]() {
updatePickButtonColor(defaultValue);
emit updateVariableValue(name, defaultValue);
});
connect(pickButton, &QPushButton::clicked, [=]() {
QColor color = QColorDialog::getColor(value, this);
if (color.isValid()) {
updatePickButtonColor(color.name());
emit updateVariableValue(name, color.name());
}
});
QLabel *selectLabel = new QLabel;
selectLabel->setText(name);
QHBoxLayout *colorLayout = new QHBoxLayout;
colorLayout->addWidget(colorEraser);
colorLayout->addWidget(pickButton);
colorLayout->addWidget(selectLabel);
colorLayout->addStretch();
formLayout->addRow(colorLayout);
}
}
widget->setLayout(formLayout);
setWidget(widget);
}
QSize ScriptVariablesWidget::sizeHint() const
{
return QSize(Theme::sidebarPreferredWidth, 0);
}

View File

@ -1,25 +0,0 @@
#ifndef DUST3D_SCRIPT_VARIABLES_WIDGET_H
#define DUST3D_SCRIPT_VARIABLES_WIDGET_H
#include <QWidget>
#include <QString>
#include <map>
#include <QScrollArea>
#include "document.h"
class ScriptVariablesWidget : public QScrollArea
{
Q_OBJECT
signals:
void updateVariableValue(const QString &name, const QString &value);
public:
ScriptVariablesWidget(const Document *document,
QWidget *parent=nullptr);
public slots:
void reload();
protected:
QSize sizeHint() const override;
private:
const Document *m_document = nullptr;
};
#endif

View File

@ -1,68 +0,0 @@
#include <QVBoxLayout>
#include <QSplitter>
#include "scriptwidget.h"
#include "scripteditwidget.h"
#include "theme.h"
ScriptWidget::ScriptWidget(const Document *document, QWidget *parent) :
QWidget(parent),
m_document(document)
{
m_consoleEdit = new QPlainTextEdit;
m_consoleEdit->setReadOnly(true);
m_consoleEdit->hide();
ScriptVariablesWidget *scriptVariablesWidget = new ScriptVariablesWidget(m_document);
scriptVariablesWidget->hide();
connect(m_document, &Document::mergedVaraiblesChanged, this, [=]() {
if (m_document->variables().empty())
scriptVariablesWidget->hide();
else
scriptVariablesWidget->show();
});
ScriptEditWidget *scriptEditWidget = new ScriptEditWidget;
connect(m_document, &Document::cleanupScript, scriptEditWidget, &ScriptEditWidget::clear);
connect(m_document, &Document::scriptModifiedFromExternal, this, [=]() {
scriptEditWidget->setPlainText(document->script());
});
connect(m_document, &Document::scriptErrorChanged, this, &ScriptWidget::updateScriptConsole);
connect(m_document, &Document::scriptConsoleLogChanged, this, &ScriptWidget::updateScriptConsole);
connect(scriptEditWidget, &ScriptEditWidget::scriptChanged, m_document, &Document::updateScript);
connect(m_document, &Document::mergedVaraiblesChanged, scriptVariablesWidget, &ScriptVariablesWidget::reload);
scriptEditWidget->setStyleSheet("color: white;");
m_consoleEdit->setStyleSheet("color: white;");
QSplitter *splitter = new QSplitter;
splitter->setOrientation(Qt::Vertical);
splitter->addWidget(scriptEditWidget);
splitter->addWidget(m_consoleEdit);
splitter->addWidget(scriptVariablesWidget);
splitter->setStretchFactor(2, 1);
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(splitter);
setLayout(mainLayout);
}
QSize ScriptWidget::sizeHint() const
{
return QSize(Theme::sidebarPreferredWidth, 0);
}
void ScriptWidget::updateScriptConsole()
{
const auto &scriptError = m_document->scriptError();
const auto &scriptConsoleLog = m_document->scriptConsoleLog();
if (scriptError.isEmpty() && scriptConsoleLog.isEmpty()) {
m_consoleEdit->hide();
} else {
m_consoleEdit->setPlainText(scriptError + scriptConsoleLog);
m_consoleEdit->show();
}
}

View File

@ -1,22 +0,0 @@
#ifndef SCRIPT_WIDGET_H
#define SCRIPT_WIDGET_H
#include <QWidget>
#include <QPlainTextEdit>
#include "document.h"
#include "scriptvariableswidget.h"
class ScriptWidget : public QWidget
{
Q_OBJECT
public:
ScriptWidget(const Document *document, QWidget *parent=nullptr);
public slots:
void updateScriptConsole();
protected:
QSize sizeHint() const override;
private:
const Document *m_document = nullptr;
QPlainTextEdit *m_consoleEdit = nullptr;
};
#endif

View File

@ -1,5 +1,3 @@
#include <CGAL/convex_hull_3.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <QVector3D>
#include <vector>
#include <map>
@ -10,224 +8,8 @@
#include "triangleislandsresolve.h"
#include "booleanmesh.h"
template <class InputIterator, class Kernel>
bool precheckForConvexHull(InputIterator first, InputIterator beyond)
{
typedef typename CGAL::internal::Convex_hull_3::Default_traits_for_Chull_3<typename Kernel::Point_3, typename CGAL::Surface_mesh<typename Kernel::Point_3>>::type Traits;
typedef typename Traits::Point_3 Point_3;
typedef std::list<Point_3> Point_3_list;
typedef typename Point_3_list::iterator P3_iterator;
Traits traits;
Point_3_list points(first, beyond);
if (!(points.size() > 3))
return false;
// at least 4 points
typename Traits::Collinear_3 collinear = traits.collinear_3_object();
typename Traits::Equal_3 equal = traits.equal_3_object();
P3_iterator point1_it = points.begin();
P3_iterator point2_it = points.begin();
point2_it++;
// find three that are not collinear
while (point2_it != points.end() && equal(*point1_it,*point2_it))
++point2_it;
if (!(point2_it != points.end()))
return false;
P3_iterator point3_it = point2_it;
++point3_it;
if (!(point3_it != points.end()))
return false;
while (point3_it != points.end() && collinear(*point1_it,*point2_it,*point3_it))
++point3_it;
if (!(point3_it != points.end()))
return false;
return true;
}
template <class Kernel>
typename CGAL::Surface_mesh<typename Kernel::Point_3> *buildConvexCgalMesh(const std::vector<QVector3D> &positions, const std::vector<std::vector<size_t>> &indices)
{
typename CGAL::Surface_mesh<typename Kernel::Point_3> *mesh = new typename CGAL::Surface_mesh<typename Kernel::Point_3>;
std::vector<typename Kernel::Point_3> points;
std::unordered_set<size_t> addedIndices;
for (const auto &face: indices) {
for (const auto &index: face) {
if (addedIndices.find(index) != addedIndices.end())
continue;
addedIndices.insert(index);
const auto &position = positions[index];
points.push_back(typename Kernel::Point_3(position.x(), position.y(), position.z()));
}
}
try {
if (precheckForConvexHull<typename std::vector<typename Kernel::Point_3>::iterator, Kernel>(points.begin(), points.end())) {
CGAL::convex_hull_3(points.begin(), points.end(), *mesh);
} else {
delete mesh;
return nullptr;
}
} catch (...) {
delete mesh;
return nullptr;
}
return mesh;
}
static CgalMesh *doIntersection(CgalMesh *firstCgalMesh, CgalMesh *secondCgalMesh)
{
if (nullptr == firstCgalMesh || nullptr == secondCgalMesh)
return nullptr;
CgalMesh *resultCgalMesh = new CgalMesh;
try {
if (!CGAL::Polygon_mesh_processing::corefine_and_compute_intersection(*firstCgalMesh, *secondCgalMesh, *resultCgalMesh)) {
delete resultCgalMesh;
resultCgalMesh = nullptr;
}
} catch (...) {
delete resultCgalMesh;
resultCgalMesh = nullptr;
}
return resultCgalMesh;
}
static CgalMesh *doUnion(CgalMesh *firstCgalMesh, CgalMesh *secondCgalMesh)
{
if (nullptr == firstCgalMesh || nullptr == secondCgalMesh)
return nullptr;
CgalMesh *resultCgalMesh = new CgalMesh;
try {
if (!CGAL::Polygon_mesh_processing::corefine_and_compute_union(*firstCgalMesh, *secondCgalMesh, *resultCgalMesh)) {
delete resultCgalMesh;
resultCgalMesh = nullptr;
}
} catch (...) {
delete resultCgalMesh;
resultCgalMesh = nullptr;
}
return resultCgalMesh;
}
static bool fetchCgalMeshCenter(CgalMesh *cgalMesh, QVector3D &center)
{
if (nullptr == cgalMesh)
return false;
std::vector<QVector3D> vertices;
std::vector<std::vector<size_t>> faces;
fetchFromCgalMesh<CgalKernel>(cgalMesh, vertices, faces);
if (vertices.empty() || faces.empty())
return false;
QVector3D sumOfPositions;
for (const auto &face: faces) {
QVector3D sumOfTrianglePositions;
for (const auto &vertex: face) {
sumOfTrianglePositions += vertices[vertex];
}
sumOfPositions += sumOfTrianglePositions / face.size();
}
center = sumOfPositions / faces.size();
return true;
}
static std::pair<size_t, size_t> findNearestTriangleEdge(const Outcome &outcome,
const std::vector<size_t> &group,
const QVector3D &point)
{
float minLength2 = std::numeric_limits<float>::max();
std::pair<size_t, size_t> choosenEdge = std::make_pair(0, 0);
for (const auto &triangleIndex: group) {
const auto &indices = outcome.triangles[triangleIndex];
for (size_t i = 0; i < indices.size(); ++i) {
size_t j = (i + 1) % indices.size();
QVector3D edgeMiddle = (outcome.vertices[indices[i]] + outcome.vertices[indices[j]]) / 2;
float length2 = (point - edgeMiddle).lengthSquared();
if (length2 < minLength2) {
minLength2 = length2;
choosenEdge = std::make_pair(indices[i], indices[j]);
}
}
}
return choosenEdge;
}
static bool mergeIntersectedConvexMeshesAndLinkTriangles(const Outcome &outcome,
std::map<QString, std::pair<CgalMesh *, std::vector<size_t>>> &convexMeshes,
std::vector<std::pair<std::pair<size_t, size_t>, std::pair<size_t, size_t>>> &links)
{
if (convexMeshes.size() <= 1)
return false;
auto head = *convexMeshes.begin();
for (const auto &it: convexMeshes) {
if (it.first == head.first)
continue;
CgalMesh *intersectionMesh = doIntersection(head.second.first, it.second.first);
QVector3D center;
bool fetchSuccess = fetchCgalMeshCenter(intersectionMesh, center);
delete intersectionMesh;
if (fetchSuccess) {
QString firstGroupName = head.first;
QString secondGroupName = it.first;
std::vector<size_t> firstGroupTriangleIndices = head.second.second;
std::vector<size_t> secondGroupTriangleIndices = it.second.second;
std::pair<size_t, size_t> firstGroupChoosenIndex = findNearestTriangleEdge(outcome, firstGroupTriangleIndices, center);
std::pair<size_t, size_t> secondGroupChoosenIndex = findNearestTriangleEdge(outcome, secondGroupTriangleIndices, center);
links.push_back(std::make_pair(firstGroupChoosenIndex, secondGroupChoosenIndex));
std::vector<size_t> triangleIndices(firstGroupTriangleIndices);
triangleIndices.insert(triangleIndices.end(), secondGroupTriangleIndices.begin(), secondGroupTriangleIndices.end());
CgalMesh *unionMesh = doUnion(head.second.first, it.second.first);
delete head.second.first;
delete it.second.first;
convexMeshes.erase(firstGroupName);
convexMeshes.erase(secondGroupName);
convexMeshes[firstGroupName + "+" + secondGroupName] = std::make_pair(
unionMesh,
triangleIndices);
return true;
}
}
return false;
}
void triangleIslandsLink(const Outcome &outcome,
std::vector<std::pair<std::pair<size_t, size_t>, std::pair<size_t, size_t>>> &links)
{
std::vector<size_t> group;
std::vector<std::vector<size_t>> islands;
size_t triangleCount = outcome.triangles.size();
for (size_t i = 0; i < triangleCount; ++i)
group.push_back(i);
triangleIslandsResolve(outcome, group, islands);
if (islands.size() <= 2)
return;
const std::vector<QVector3D> &positions = outcome.vertices;
std::map<QString, std::pair<CgalMesh *, std::vector<size_t>>> convexMeshes;
for (size_t islandIndex = 0; islandIndex < islands.size(); ++islandIndex) {
const auto &island = islands[islandIndex];
std::vector<std::vector<size_t>> indices;
for (const auto &triangleIndex: island) {
indices.push_back(outcome.triangles[triangleIndex]);
}
convexMeshes[QString::number(islandIndex)] = std::make_pair(
buildConvexCgalMesh<CgalKernel>(positions, indices),
island);
}
while (convexMeshes.size() >= 2) {
if (!mergeIntersectedConvexMeshesAndLinkTriangles(outcome,
convexMeshes, links))
break;
}
for (auto &it: convexMeshes) {
delete it.second.first;
}
// TODO:
}

View File

@ -1,64 +0,0 @@
#include <QDebug>
#include "variablesxml.h"
void saveVariablesToXmlStream(const std::map<QString, std::map<QString, QString>> &variables, QXmlStreamWriter *writer)
{
writer->setAutoFormatting(true);
writer->writeStartDocument();
writer->writeStartElement("variables");
for (const auto &it: variables) {
writer->writeStartElement("variable");
writer->writeAttribute("name", it.first);
for (const auto &subIt: it.second) {
if (subIt.first == "name")
continue;
writer->writeAttribute(subIt.first, subIt.second);
}
writer->writeEndElement();
}
writer->writeEndElement();
writer->writeEndDocument();
}
void loadVariablesFromXmlStream(std::map<QString, std::map<QString, QString>> *variables, QXmlStreamReader &reader)
{
std::vector<QString> elementNameStack;
while (!reader.atEnd()) {
reader.readNext();
if (!reader.isStartElement() && !reader.isEndElement()) {
if (!reader.name().toString().isEmpty())
qDebug() << "Skip xml element:" << reader.name().toString() << " tokenType:" << reader.tokenType();
continue;
}
QString baseName = reader.name().toString();
if (reader.isStartElement())
elementNameStack.push_back(baseName);
QStringList nameItems;
for (const auto &nameItem: elementNameStack) {
nameItems.append(nameItem);
}
QString fullName = nameItems.join(".");
if (reader.isEndElement())
elementNameStack.pop_back();
if (reader.isStartElement()) {
if (fullName == "variables.variable") {
QString variableName;
std::map<QString, QString> map;
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
auto attrNameString = attr.name().toString();
auto attrValueString = attr.value().toString();
if ("name" == attrNameString) {
variableName = attrValueString;
} else {
map[attrNameString] = attrValueString;
}
}
if (!variableName.isEmpty()) {
(*variables)[variableName] = map;
}
}
}
}
}

View File

@ -1,9 +0,0 @@
#ifndef DUST3D_VARIABLES_XML_H
#define DUST3D_VARIABLES_XML_H
#include <QXmlStreamWriter>
#include <map>
void saveVariablesToXmlStream(const std::map<QString, std::map<QString, QString>> &variables, QXmlStreamWriter *writer);
void loadVariablesFromXmlStream(std::map<QString, std::map<QString, QString>> *variables, QXmlStreamReader &reader);
#endif

View File

@ -1,5 +0,0 @@
Language: Cpp
BasedOnStyle: Google
IndentWidth: 4
Standard: Cpp11
ColumnLimit: 99

View File

@ -1,293 +0,0 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.o
*.or
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
data/
[Bb]uild/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
open-wbo
open-wbo_*
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

View File

@ -1,29 +0,0 @@
cmake_minimum_required(VERSION 3.1)
project(MapleCOMSPS_LRB)
find_package(ZLIB)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories(${ZLIB_INCLUDE_DIRS})
set(
minisat_SRC
core/Solver.cc
simp/Main.cc
simp/SimpSolver.cc
utils/Options.cc
utils/System.cc
)
add_executable(
minisat
${minisat_SRC}
)
target_link_libraries(
minisat
${ZLIB_LIBRARIES}
)

View File

@ -1,23 +0,0 @@
MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010 Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,24 +0,0 @@
================================================================================
DIRECTORY OVERVIEW:
mtl/ Mini Template Library
utils/ Generic helper code (I/O, Parsing, CPU-time, etc)
core/ A core version of the solver
simp/ An extended solver with simplification capabilities
README
LICENSE
================================================================================
BUILDING: (release version: without assertions, statically linked, etc)
export MROOT=<minisat-dir> (or setenv in cshell)
cd { core | simp }
gmake rs
cp minisat_static <install-dir>/minisat
================================================================================
EXAMPLES:
Run minisat with same heuristics as version 2.0:
> minisat <cnf-file> -no-luby -rinc=1.5 -phase-saving=0 -rnd-freq=0.02

View File

@ -1,89 +0,0 @@
/****************************************************************************************[Dimacs.h]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Dimacs_h
#define Minisat_Dimacs_h
#include <stdio.h>
#include "utils/ParseUtils.h"
#include "core/SolverTypes.h"
namespace Minisat {
//=================================================================================================
// DIMACS Parser:
template<class B, class Solver>
static void readClause(B& in, Solver& S, vec<Lit>& lits) {
int parsed_lit, var;
lits.clear();
for (;;){
parsed_lit = parseInt(in);
if (parsed_lit == 0) break;
var = abs(parsed_lit)-1;
while (var >= S.nVars()) S.newVar();
lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) );
}
}
template<class B, class Solver>
static void parse_DIMACS_main(B& in, Solver& S) {
vec<Lit> lits;
int vars = 0;
int clauses = 0;
int cnt = 0;
for (;;){
skipWhitespace(in);
if (*in == EOF) break;
else if (*in == 'p'){
if (eagerMatch(in, "p cnf")){
vars = parseInt(in);
clauses = parseInt(in);
// SATRACE'06 hack
// if (clauses > 4000000)
// S.eliminate(true);
}else{
printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
}
} else if (*in == 'c' || *in == 'p')
skipLine(in);
else{
cnt++;
readClause(in, S, lits);
S.addClause_(lits); }
}
if (vars != S.nVars())
fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of variables.\n");
if (cnt != clauses)
fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of clauses.\n");
}
// Inserts problem into solver.
//
template<class Solver>
static void parse_DIMACS(gzFile input_stream, Solver& S) {
StreamBuffer in(input_stream);
parse_DIMACS_main(in, S); }
//=================================================================================================
}
#endif

View File

@ -1,202 +0,0 @@
/*****************************************************************************************[Main.cc]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#include <errno.h>
#include <signal.h>
#include <zlib.h>
#include "utils/System.h"
#include "utils/ParseUtils.h"
#include "utils/Options.h"
#include "core/Dimacs.h"
#include "core/Solver.h"
using namespace Minisat;
//=================================================================================================
void printStats(Solver& solver)
{
double cpu_time = cpuTime();
// double mem_used = memUsedPeak();
// printf("c restarts : %"PRIu64"\n", solver.starts);
// printf("c conflicts : %-12"PRIu64" (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time);
// printf("c decisions : %-12"PRIu64" (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time);
// printf("c propagations : %-12"PRIu64" (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time);
// printf("c conflict literals : %-12"PRIu64" (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals);
// if (mem_used != 0) printf("c Memory used : %.2f MB\n", mem_used);
printf("c CPU time : %g s\n", cpu_time);
}
static Solver* solver;
// Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case
// for this feature of the Solver as it may take longer than an immediate call to '_exit()'.
static void SIGINT_interrupt(int signum) { solver->interrupt(); }
// Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls
// destructors and may cause deadlocks if a malloc/free function happens to be running (these
// functions are guarded by locks for multithreaded use).
static void SIGINT_exit(int signum) {
printf("\n"); printf("c *** INTERRUPTED ***\n");
if (solver->verbosity > 0){
printStats(*solver);
printf("\n"); printf("c *** INTERRUPTED ***\n"); }
_exit(1); }
//=================================================================================================
// Main:
int main(int argc, char** argv)
{
try {
setUsageHelp("USAGE: %s [options] <input-file> <result-output-file>\n\n where input may be either in plain or gzipped DIMACS.\n");
printf("c This is COMiniSatPS.\n");
#if defined(__linux__)
fpu_control_t oldcw, newcw;
_FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
printf("c WARNING: for repeatability, setting FPU to use double precision\n");
#endif
// Extra options:
//
IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2));
IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX));
IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX));
parseOptions(argc, argv, true);
Solver S;
double initial_time = cpuTime();
S.verbosity = verb;
solver = &S;
// Use signal handlers that forcibly quit until the solver will be able to respond to
// interrupts:
signal(SIGINT, SIGINT_exit);
signal(SIGXCPU,SIGINT_exit);
// Set limit on CPU-time:
if (cpu_lim != INT32_MAX){
rlimit rl;
getrlimit(RLIMIT_CPU, &rl);
if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){
rl.rlim_cur = cpu_lim;
if (setrlimit(RLIMIT_CPU, &rl) == -1)
printf("c WARNING! Could not set resource limit: CPU-time.\n");
} }
// Set limit on virtual memory:
if (mem_lim != INT32_MAX){
rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024;
rlimit rl;
getrlimit(RLIMIT_AS, &rl);
if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){
rl.rlim_cur = new_mem_lim;
if (setrlimit(RLIMIT_AS, &rl) == -1)
printf("c WARNING! Could not set resource limit: Virtual memory.\n");
} }
if (argc == 1)
printf("c Reading from standard input... Use '--help' for help.\n");
gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
if (in == NULL)
printf("c ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
if (S.verbosity > 0){
printf("c ============================[ Problem Statistics ]=============================\n");
printf("c | |\n"); }
parse_DIMACS(in, S);
gzclose(in);
FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL;
if (S.verbosity > 0){
printf("c | Number of variables: %12d |\n", S.nVars());
printf("c | Number of clauses: %12d |\n", S.nClauses()); }
double parsed_time = cpuTime();
if (S.verbosity > 0){
printf("c | Parse time: %12.2f s |\n", parsed_time - initial_time);
printf("c | |\n"); }
// Change to signal-handlers that will only notify the solver and allow it to terminate
// voluntarily:
signal(SIGINT, SIGINT_interrupt);
signal(SIGXCPU,SIGINT_interrupt);
if (!S.simplify()){
if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
if (S.verbosity > 0){
printf("c ===============================================================================\n");
printf("c Solved by unit propagation\n");
printStats(S);
printf("\n"); }
printf("s UNSATISFIABLE\n");
exit(20);
}
vec<Lit> dummy;
lbool ret = S.solveLimited(dummy);
if (S.verbosity > 0){
printStats(S);
printf("\n"); }
printf(ret == l_True ? "s SATISFIABLE\n" : ret == l_False ? "s UNSATISFIABLE\n" : "s UNKNOWN\n");
if (ret == l_True){
printf("v ");
for (int i = 0; i < S.nVars(); i++)
if (S.model[i] != l_Undef)
printf("%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
printf(" 0\n");
}
if (res != NULL){
if (ret == l_True){
fprintf(res, "SAT\n");
for (int i = 0; i < S.nVars(); i++)
if (S.model[i] != l_Undef)
fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
fprintf(res, " 0\n");
}else if (ret == l_False)
fprintf(res, "UNSAT\n");
else
fprintf(res, "INDET\n");
fclose(res);
}
#ifdef NDEBUG
exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver')
#else
return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
#endif
} catch (OutOfMemoryException&){
printf("c ===============================================================================\n");
printf("s UNKNOWN\n");
exit(0);
}
}

View File

@ -1,4 +0,0 @@
EXEC = minisat
DEPDIR = mtl utils
include $(MROOT)/mtl/template.mk

File diff suppressed because it is too large Load Diff

View File

@ -1,524 +0,0 @@
/****************************************************************************************[Solver.h]
MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Solver_h
#define Minisat_Solver_h
#define BIN_DRUP
#define GLUCOSE23
//#define INT_QUEUE_AVG
//#define LOOSE_PROP_STAT
#ifdef GLUCOSE23
#define INT_QUEUE_AVG
#define LOOSE_PROP_STAT
#endif
#include "mtl/Vec.h"
#include "mtl/Heap.h"
#include "mtl/Alg.h"
#include "utils/Options.h"
#include "core/SolverTypes.h"
// Don't change the actual numbers.
#define LOCAL 0
#define TIER2 2
#define CORE 3
namespace Minisat {
//=================================================================================================
// Solver -- the main class:
class Solver {
private:
template<typename T>
class MyQueue {
int max_sz, q_sz;
int ptr;
int64_t sum;
vec<T> q;
public:
MyQueue(int sz) : max_sz(sz), q_sz(0), ptr(0), sum(0) { assert(sz > 0); q.growTo(sz); }
inline bool full () const { return q_sz == max_sz; }
#ifdef INT_QUEUE_AVG
inline T avg () const { assert(full()); return sum / max_sz; }
#else
inline double avg () const { assert(full()); return sum / (double) max_sz; }
#endif
inline void clear() { sum = 0; q_sz = 0; ptr = 0; }
void push(T e) {
if (q_sz < max_sz) q_sz++;
else sum -= q[ptr];
sum += e;
q[ptr++] = e;
if (ptr == max_sz) ptr = 0;
}
};
public:
// Constructor/Destructor:
//
Solver();
virtual ~Solver();
// Problem specification:
//
Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode.
bool addClause (const vec<Lit>& ps); // Add a clause to the solver.
bool addEmptyClause(); // Add the empty clause, making the solver contradictory.
bool addClause (Lit p); // Add a unit clause to the solver.
bool addClause (Lit p, Lit q); // Add a binary clause to the solver.
bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver.
bool addClause_( vec<Lit>& ps); // Add a clause to the solver without making superflous internal copy. Will
// change the passed vector 'ps'.
// Solving:
//
bool simplify (bool do_stamping = false); // Removes already satisfied clauses.
bool solve (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions.
lbool solveLimited (const vec<Lit>& assumps); // Search for a model that respects a given set of assumptions (With resource constraints).
bool solve (); // Search without assumptions.
bool solve (Lit p); // Search for a model that respects a single assumption.
bool solve (Lit p, Lit q); // Search for a model that respects two assumptions.
bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions.
bool okay () const; // FALSE means solver is in a conflicting state
void toDimacs (FILE* f, const vec<Lit>& assumps); // Write CNF to file in DIMACS-format.
void toDimacs (const char *file, const vec<Lit>& assumps);
void toDimacs (FILE* f, Clause& c, vec<Var>& map, Var& max);
// Convenience versions of 'toDimacs()':
void toDimacs (const char* file);
void toDimacs (const char* file, Lit p);
void toDimacs (const char* file, Lit p, Lit q);
void toDimacs (const char* file, Lit p, Lit q, Lit r);
// Variable mode:
//
void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'.
void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic.
// Read state:
//
lbool value (Var x) const; // The current value of a variable.
lbool value (Lit p) const; // The current value of a literal.
lbool modelValue (Var x) const; // The value of a variable in the last model. The last call to solve must have been satisfiable.
lbool modelValue (Lit p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable.
int nAssigns () const; // The current number of assigned literals.
int nClauses () const; // The current number of original clauses.
int nLearnts () const; // The current number of learnt clauses.
int nVars () const; // The current number of variables.
int nFreeVars () const;
// Resource contraints:
//
void setConfBudget(int64_t x);
void setPropBudget(int64_t x);
void budgetOff();
void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver.
void clearInterrupt(); // Clear interrupt indicator flag.
// Memory managment:
//
virtual void garbageCollect();
void checkGarbage(double gf);
void checkGarbage();
// Extra results: (read-only member variable)
//
vec<lbool> model; // If problem is satisfiable, this vector contains the model (if any).
vec<Lit> conflict; // If problem is unsatisfiable (possibly under assumptions),
// this vector represent the final conflict clause expressed in the assumptions.
// Mode of operation:
//
FILE* drup_file;
int verbosity;
double step_size;
double step_size_dec;
double min_step_size;
int timer;
double var_decay;
double clause_decay;
double random_var_freq;
double random_seed;
bool VSIDS;
int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, 2=deep).
int phase_saving; // Controls the level of phase saving (0=none, 1=limited, 2=full).
bool rnd_pol; // Use random polarities for branching heuristics.
bool rnd_init_act; // Initialize variable activities with a small random value.
double garbage_frac; // The fraction of wasted memory allowed before a garbage collection is triggered.
int restart_first; // The initial restart limit. (default 100)
double restart_inc; // The factor with which the restart limit is multiplied in each restart. (default 1.5)
double learntsize_factor; // The intitial limit for learnt clauses is a factor of the original clauses. (default 1 / 3)
double learntsize_inc; // The limit for learnt clauses is multiplied with this factor each restart. (default 1.1)
int learntsize_adjust_start_confl;
double learntsize_adjust_inc;
// Statistics: (read-only member variable)
//
uint64_t solves, starts, decisions, rnd_decisions, propagations, conflicts, conflicts_VSIDS;
uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals;
vec<uint32_t> picked;
vec<uint32_t> conflicted;
vec<uint32_t> almost_conflicted;
protected:
// Helper structures:
//
struct VarData { CRef reason; int level; };
static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; }
struct Watcher {
CRef cref;
Lit blocker;
Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {}
bool operator==(const Watcher& w) const { return cref == w.cref; }
bool operator!=(const Watcher& w) const { return cref != w.cref; }
};
struct WatcherDeleted
{
const ClauseAllocator& ca;
WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {}
bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; }
};
struct VarOrderLt {
const vec<double>& activity;
bool operator () (Var x, Var y) const { return activity[x] > activity[y]; }
VarOrderLt(const vec<double>& act) : activity(act) { }
};
// Solver state:
//
bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used!
vec<CRef> clauses; // List of problem clauses.
vec<CRef> learnts_core, // List of learnt clauses.
learnts_tier2,
learnts_local;
double cla_inc; // Amount to bump next clause with.
vec<double> activity_CHB, // A heuristic measurement of the activity of a variable.
activity_VSIDS;
double var_inc; // Amount to bump next variable with.
OccLists<Lit, vec<Watcher>, WatcherDeleted>
watches_bin, // Watches for binary clauses only.
watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true).
vec<lbool> assigns; // The current assignments.
vec<char> polarity; // The preferred polarity of each variable.
vec<char> decision; // Declares if a variable is eligible for selection in the decision heuristic.
vec<Lit> trail; // Assignment stack; stores all assigments made in the order they were made.
vec<int> trail_lim; // Separator indices for different decision levels in 'trail'.
vec<VarData> vardata; // Stores reason and level for each variable.
int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat).
int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'.
int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'.
vec<Lit> assumptions; // Current set of assumptions provided to solve by the user.
Heap<VarOrderLt> order_heap_CHB, // A priority queue of variables ordered with respect to the variable activity.
order_heap_VSIDS;
double progress_estimate;// Set by 'search()'.
bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'.
int core_lbd_cut;
float global_lbd_sum;
MyQueue<int> lbd_queue; // For computing moving averages of recent LBD values.
uint64_t next_T2_reduce,
next_L_reduce;
ClauseAllocator ca;
// Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is
// used, exept 'seen' wich is used in several places.
//
vec<char> seen;
vec<Lit> analyze_stack;
vec<Lit> analyze_toclear;
vec<Lit> add_tmp;
vec<Lit> add_oc;
vec<uint64_t> seen2; // Mostly for efficient LBD computation. 'seen2[i]' will indicate if decision level or variable 'i' has been seen.
uint64_t counter; // Simple counter for marking purpose with 'seen2'.
double max_learnts;
double learntsize_adjust_confl;
int learntsize_adjust_cnt;
// Resource contraints:
//
int64_t conflict_budget; // -1 means no budget.
int64_t propagation_budget; // -1 means no budget.
bool asynch_interrupt;
// Main internal methods:
//
void insertVarOrder (Var x); // Insert a variable in the decision order priority queue.
Lit pickBranchLit (); // Return the next decision variable.
void newDecisionLevel (); // Begins a new decision level.
void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined.
bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise.
CRef propagate (); // Perform unit propagation. Returns possibly conflicting clause.
void cancelUntil (int level); // Backtrack until a certain level.
void analyze (CRef confl, vec<Lit>& out_learnt, int& out_btlevel, int& out_lbd); // (bt = backtrack)
void analyzeFinal (Lit p, vec<Lit>& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION?
bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()')
lbool search (int& nof_conflicts); // Search for a given number of conflicts.
lbool solve_ (); // Main solve method (assumptions given in 'assumptions').
void reduceDB (); // Reduce the set of learnt clauses.
void reduceDB_Tier2 ();
void removeSatisfied (vec<CRef>& cs); // Shrink 'cs' to contain only non-satisfied clauses.
void safeRemoveSatisfiedCompact(vec<CRef>& cs, unsigned valid_mark);
void rebuildOrderHeap ();
bool binResMinimize (vec<Lit>& out_learnt); // Further learnt clause minimization by binary resolution.
// Maintaining Variable/Clause activity:
//
void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead.
void varBumpActivity (Var v, double mult); // Increase a variable with the current 'bump' value.
void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead.
void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value.
// Operations on clauses:
//
void attachClause (CRef cr); // Attach a clause to watcher lists.
void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists.
void removeClause (CRef cr); // Detach and free a clause.
void removeClauseHack (CRef cr, Lit watched0, Lit watched1);
bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state.
bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state.
void relocAll (ClauseAllocator& to);
// Misc:
//
int decisionLevel () const; // Gives the current decisionlevel.
uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels.
CRef reason (Var x) const;
int level (Var x) const;
double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ...
bool withinBudget () const;
template<class V> int computeLBD(const V& c) {
int lbd = 0;
counter++;
for (int i = 0; i < c.size(); i++){
int l = level(var(c[i]));
if (l != 0 && seen2[l] != counter){
seen2[l] = counter;
lbd++; } }
return lbd;
}
#ifdef BIN_DRUP
static int buf_len;
static unsigned char drup_buf[];
static unsigned char* buf_ptr;
static inline void byteDRUP(Lit l){
unsigned int u = 2 * (var(l) + 1) + sign(l);
do{
*buf_ptr++ = u & 0x7f | 0x80; buf_len++;
u = u >> 7;
}while (u);
*(buf_ptr - 1) &= 0x7f; // End marker of this unsigned number.
}
template<class V>
static inline void binDRUP(unsigned char op, const V& c, FILE* drup_file){
assert(op == 'a' || op == 'd');
*buf_ptr++ = op; buf_len++;
for (int i = 0; i < c.size(); i++) byteDRUP(c[i]);
*buf_ptr++ = 0; buf_len++;
if (buf_len > 1048576) binDRUP_flush(drup_file);
}
static inline void binDRUP_strengthen(const Clause& c, Lit l, FILE* drup_file){
*buf_ptr++ = 'a'; buf_len++;
for (int i = 0; i < c.size(); i++)
if (c[i] != l) byteDRUP(c[i]);
*buf_ptr++ = 0; buf_len++;
if (buf_len > 1048576) binDRUP_flush(drup_file);
}
static inline void binDRUP_flush(FILE* drup_file){
fwrite(drup_buf, sizeof(unsigned char), buf_len, drup_file);
buf_ptr = drup_buf; buf_len = 0;
}
#endif
// Static helpers:
//
// Returns a random float 0 <= x < 1. Seed must never be 0.
static inline double drand(double& seed) {
seed *= 1389796;
int q = (int)(seed / 2147483647);
seed -= (double)q * 2147483647;
return seed / 2147483647; }
// Returns a random integer 0 <= x < size. Seed must never be 0.
static inline int irand(double& seed, int size) {
return (int)(drand(seed) * size); }
// For (advanced) stamping.
struct Frame {
enum TYPE { START = 0, ENTER = 1, RETURN = 2, CLOSE = 3 };
Lit curr, next;
unsigned type : 3;
unsigned learnt : 1;
Frame(TYPE t, Lit p, Lit q, unsigned l) : curr(p), next(q), type(t), learnt(l) {}
};
vec<int32_t> discovered;
vec<int32_t> finished;
vec<int32_t> observed;
vec<char> flag;
vec<Lit> root;
vec<Lit> parent;
vec<Frame> rec_stack;
vec<Lit> scc; // Strongly connected component.
bool stampAll(bool use_bin_learnts);
int stamp(Lit p, int stamp_time, bool use_bin_learnts);
inline bool implExistsByBin(Lit p, bool use_bin_learnts) const;
inline bool isRoot(Lit p, bool use_bin_learnts) const;
};
//=================================================================================================
// Implementation of inline methods:
inline CRef Solver::reason(Var x) const { return vardata[x].reason; }
inline int Solver::level (Var x) const { return vardata[x].level; }
inline void Solver::insertVarOrder(Var x) {
Heap<VarOrderLt>& order_heap = VSIDS ? order_heap_VSIDS : order_heap_CHB;
if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); }
inline void Solver::varDecayActivity() {
var_inc *= (1 / var_decay); }
inline void Solver::varBumpActivity(Var v, double mult) {
if ( (activity_VSIDS[v] += var_inc * mult) > 1e100 ) {
// Rescale:
for (int i = 0; i < nVars(); i++)
activity_VSIDS[i] *= 1e-100;
var_inc *= 1e-100; }
// Update order_heap with respect to new activity:
if (order_heap_VSIDS.inHeap(v)) order_heap_VSIDS.decrease(v); }
inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); }
inline void Solver::claBumpActivity (Clause& c) {
if ( (c.activity() += cla_inc) > 1e20 ) {
// Rescale:
for (int i = 0; i < learnts_local.size(); i++)
ca[learnts_local[i]].activity() *= 1e-20;
cla_inc *= 1e-20; } }
inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); }
inline void Solver::checkGarbage(double gf){
if (ca.wasted() > ca.size() * gf)
garbageCollect(); }
// NOTE: enqueue does not set the ok flag! (only public methods do)
inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); }
inline bool Solver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); }
inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); }
inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
inline bool Solver::locked (const Clause& c) const {
int i = c.size() != 2 ? 0 : (value(c[0]) == l_True ? 0 : 1);
return value(c[i]) == l_True && reason(var(c[i])) != CRef_Undef && ca.lea(reason(var(c[i]))) == &c;
}
inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); }
inline int Solver::decisionLevel () const { return trail_lim.size(); }
inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); }
inline lbool Solver::value (Var x) const { return assigns[x]; }
inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); }
inline lbool Solver::modelValue (Var x) const { return model[x]; }
inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); }
inline int Solver::nAssigns () const { return trail.size(); }
inline int Solver::nClauses () const { return clauses.size(); }
inline int Solver::nLearnts () const { return learnts_core.size() + learnts_tier2.size() + learnts_local.size(); }
inline int Solver::nVars () const { return vardata.size(); }
inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); }
inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; }
inline void Solver::setDecisionVar(Var v, bool b)
{
if ( b && !decision[v]) dec_vars++;
else if (!b && decision[v]) dec_vars--;
decision[v] = b;
if (b && !order_heap_CHB.inHeap(v)){
order_heap_CHB.insert(v);
order_heap_VSIDS.insert(v); }
}
inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; }
inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; }
inline void Solver::interrupt(){ asynch_interrupt = true; }
inline void Solver::clearInterrupt(){ asynch_interrupt = false; }
inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; }
inline bool Solver::withinBudget() const {
return !asynch_interrupt &&
(conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) &&
(propagation_budget < 0 || propagations < (uint64_t)propagation_budget); }
// FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a
// pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or
// all calls to solve must return an 'lbool'. I'm not yet sure which I prefer.
inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; }
inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; }
inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; }
inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; }
inline bool Solver::solve (const vec<Lit>& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; }
inline lbool Solver::solveLimited (const vec<Lit>& assumps){ assumps.copyTo(assumptions); return solve_(); }
inline bool Solver::okay () const { return ok; }
inline void Solver::toDimacs (const char* file){ vec<Lit> as; toDimacs(file, as); }
inline void Solver::toDimacs (const char* file, Lit p){ vec<Lit> as; as.push(p); toDimacs(file, as); }
inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec<Lit> as; as.push(p); as.push(q); toDimacs(file, as); }
inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec<Lit> as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); }
//=================================================================================================
// Debug etc:
//=================================================================================================
}
#endif

View File

@ -1,426 +0,0 @@
/***********************************************************************************[SolverTypes.h]
MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_SolverTypes_h
#define Minisat_SolverTypes_h
#include <assert.h>
#include "mtl/IntTypes.h"
#include "mtl/Alg.h"
#include "mtl/Vec.h"
#include "mtl/Map.h"
#include "mtl/Alloc.h"
namespace Minisat {
//=================================================================================================
// Variables, literals, lifted booleans, clauses:
// NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N,
// so that they can be used as array indices.
typedef int Var;
#define var_Undef (-1)
struct Lit {
int x;
// Use this as a constructor:
friend Lit mkLit(Var var, bool sign);
bool operator == (Lit p) const { return x == p.x; }
bool operator != (Lit p) const { return x != p.x; }
bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering.
};
inline Lit mkLit (Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; }
inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; }
inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; }
inline bool sign (Lit p) { return p.x & 1; }
inline int var (Lit p) { return p.x >> 1; }
// Mapping Literals to and from compact integers suitable for array indexing:
inline int toInt (Var v) { return v; }
inline int toInt (Lit p) { return p.x; }
inline Lit toLit (int i) { Lit p; p.x = i; return p; }
//const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants.
//const Lit lit_Error = mkLit(var_Undef, true ); // }
const Lit lit_Undef = { -2 }; // }- Useful special constants.
const Lit lit_Error = { -1 }; // }
//=================================================================================================
// Lifted booleans:
//
// NOTE: this implementation is optimized for the case when comparisons between values are mostly
// between one variable and one constant. Some care had to be taken to make sure that gcc
// does enough constant propagation to produce sensible code, and this appears to be somewhat
// fragile unfortunately.
#define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants.
#define l_False (lbool((uint8_t)1))
#define l_Undef (lbool((uint8_t)2))
class lbool {
uint8_t value;
public:
explicit lbool(uint8_t v) : value(v) { }
lbool() : value(0) { }
explicit lbool(bool x) : value(!x) { }
bool operator == (lbool b) const { return ((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value)); }
bool operator != (lbool b) const { return !(*this == b); }
lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); }
lbool operator && (lbool b) const {
uint8_t sel = (this->value << 1) | (b.value << 3);
uint8_t v = (0xF7F755F4 >> sel) & 3;
return lbool(v); }
lbool operator || (lbool b) const {
uint8_t sel = (this->value << 1) | (b.value << 3);
uint8_t v = (0xFCFCF400 >> sel) & 3;
return lbool(v); }
friend int toInt (lbool l);
friend lbool toLbool(int v);
};
inline int toInt (lbool l) { return l.value; }
inline lbool toLbool(int v) { return lbool((uint8_t)v); }
//=================================================================================================
// Clause -- a simple class for representing a clause:
class Clause;
typedef RegionAllocator<uint32_t>::Ref CRef;
class Clause {
struct {
unsigned mark : 2;
unsigned learnt : 1;
unsigned has_extra : 1;
unsigned reloced : 1;
unsigned lbd : 26;
unsigned removable : 1;
unsigned size : 32; } header;
union { Lit lit; float act; uint32_t abs; uint32_t touched; CRef rel; } data[0];
friend class ClauseAllocator;
// NOTE: This constructor cannot be used directly (doesn't allocate enough memory).
template<class V>
Clause(const V& ps, bool use_extra, bool learnt) {
header.mark = 0;
header.learnt = learnt;
header.has_extra = learnt | use_extra;
header.reloced = 0;
header.size = ps.size();
header.lbd = 0;
header.removable = 1;
for (int i = 0; i < ps.size(); i++)
data[i].lit = ps[i];
if (header.has_extra){
if (header.learnt){
data[header.size].act = 0;
data[header.size+1].touched = 0;
}else
calcAbstraction(); }
}
public:
void calcAbstraction() {
assert(header.has_extra);
uint32_t abstraction = 0;
for (int i = 0; i < size(); i++)
abstraction |= 1 << (var(data[i].lit) & 31);
data[header.size].abs = abstraction; }
int size () const { return header.size; }
void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; }
void pop () { shrink(1); }
bool learnt () const { return header.learnt; }
bool has_extra () const { return header.has_extra; }
uint32_t mark () const { return header.mark; }
void mark (uint32_t m) { header.mark = m; }
const Lit& last () const { return data[header.size-1].lit; }
bool reloced () const { return header.reloced; }
CRef relocation () const { return data[0].rel; }
void relocate (CRef c) { header.reloced = 1; data[0].rel = c; }
int lbd () const { return header.lbd; }
void set_lbd (int lbd) { header.lbd = lbd; }
bool removable () const { return header.removable; }
void removable (bool b) { header.removable = b; }
// NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for
// subsumption operations to behave correctly.
Lit& operator [] (int i) { return data[i].lit; }
Lit operator [] (int i) const { return data[i].lit; }
operator const Lit* (void) const { return (Lit*)data; }
uint32_t& touched () { assert(header.has_extra && header.learnt); return data[header.size+1].touched; }
float& activity () { assert(header.has_extra); return data[header.size].act; }
uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; }
Lit subsumes (const Clause& other) const;
void strengthen (Lit p);
};
//=================================================================================================
// ClauseAllocator -- a simple class for allocating memory for clauses:
const CRef CRef_Undef = RegionAllocator<uint32_t>::Ref_Undef;
class ClauseAllocator : public RegionAllocator<uint32_t>
{
static int clauseWord32Size(int size, int extras){
return (sizeof(Clause) + (sizeof(Lit) * (size + extras))) / sizeof(uint32_t); }
public:
bool extra_clause_field;
ClauseAllocator(uint32_t start_cap) : RegionAllocator<uint32_t>(start_cap), extra_clause_field(false){}
ClauseAllocator() : extra_clause_field(false){}
void moveTo(ClauseAllocator& to){
to.extra_clause_field = extra_clause_field;
RegionAllocator<uint32_t>::moveTo(to); }
template<class Lits>
CRef alloc(const Lits& ps, bool learnt = false)
{
assert(sizeof(Lit) == sizeof(uint32_t));
assert(sizeof(float) == sizeof(uint32_t));
int extras = learnt ? 2 : (int)extra_clause_field;
CRef cid = RegionAllocator<uint32_t>::alloc(clauseWord32Size(ps.size(), extras));
new (lea(cid)) Clause(ps, extra_clause_field, learnt);
return cid;
}
// Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
Clause& operator[](Ref r) { return (Clause&)RegionAllocator<uint32_t>::operator[](r); }
const Clause& operator[](Ref r) const { return (Clause&)RegionAllocator<uint32_t>::operator[](r); }
Clause* lea (Ref r) { return (Clause*)RegionAllocator<uint32_t>::lea(r); }
const Clause* lea (Ref r) const { return (Clause*)RegionAllocator<uint32_t>::lea(r); }
Ref ael (const Clause* t){ return RegionAllocator<uint32_t>::ael((uint32_t*)t); }
void free(CRef cid)
{
Clause& c = operator[](cid);
int extras = c.learnt() ? 2 : (int)c.has_extra();
RegionAllocator<uint32_t>::free(clauseWord32Size(c.size(), extras));
}
void reloc(CRef& cr, ClauseAllocator& to)
{
Clause& c = operator[](cr);
if (c.reloced()) { cr = c.relocation(); return; }
cr = to.alloc(c, c.learnt());
c.relocate(cr);
// Copy extra data-fields:
// (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?)
to[cr].mark(c.mark());
if (to[cr].learnt()){
to[cr].touched() = c.touched();
to[cr].activity() = c.activity();
to[cr].set_lbd(c.lbd());
to[cr].removable(c.removable());
}
else if (to[cr].has_extra()) to[cr].calcAbstraction();
}
};
//=================================================================================================
// OccLists -- a class for maintaining occurence lists with lazy deletion:
template<class Idx, class Vec, class Deleted>
class OccLists
{
vec<Vec> occs;
vec<char> dirty;
vec<Idx> dirties;
Deleted deleted;
public:
OccLists(const Deleted& d) : deleted(d) {}
void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); }
const Vec& operator[](const Idx& idx) const { return occs[toInt(idx)]; }
Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; }
Vec& lookup (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; }
void cleanAll ();
void clean (const Idx& idx);
void smudge (const Idx& idx){
if (dirty[toInt(idx)] == 0){
dirty[toInt(idx)] = 1;
dirties.push(idx);
}
}
void clear(bool free = true){
occs .clear(free);
dirty .clear(free);
dirties.clear(free);
}
};
template<class Idx, class Vec, class Deleted>
void OccLists<Idx,Vec,Deleted>::cleanAll()
{
for (int i = 0; i < dirties.size(); i++)
// Dirties may contain duplicates so check here if a variable is already cleaned:
if (dirty[toInt(dirties[i])])
clean(dirties[i]);
dirties.clear();
}
template<class Idx, class Vec, class Deleted>
void OccLists<Idx,Vec,Deleted>::clean(const Idx& idx)
{
Vec& vec = occs[toInt(idx)];
int i, j;
for (i = j = 0; i < vec.size(); i++)
if (!deleted(vec[i]))
vec[j++] = vec[i];
vec.shrink(i - j);
dirty[toInt(idx)] = 0;
}
//=================================================================================================
// CMap -- a class for mapping clauses to values:
template<class T>
class CMap
{
struct CRefHash {
uint32_t operator()(CRef cr) const { return (uint32_t)cr; } };
typedef Map<CRef, T, CRefHash> HashTable;
HashTable map;
public:
// Size-operations:
void clear () { map.clear(); }
int size () const { return map.elems(); }
// Insert/Remove/Test mapping:
void insert (CRef cr, const T& t){ map.insert(cr, t); }
void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility
void remove (CRef cr) { map.remove(cr); }
bool has (CRef cr, T& t) { return map.peek(cr, t); }
// Vector interface (the clause 'c' must already exist):
const T& operator [] (CRef cr) const { return map[cr]; }
T& operator [] (CRef cr) { return map[cr]; }
// Iteration (not transparent at all at the moment):
int bucket_count() const { return map.bucket_count(); }
const vec<typename HashTable::Pair>& bucket(int i) const { return map.bucket(i); }
// Move contents to other map:
void moveTo(CMap& other){ map.moveTo(other.map); }
// TMP debug:
void debug(){
printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); }
};
/*_________________________________________________________________________________________________
|
| subsumes : (other : const Clause&) -> Lit
|
| Description:
| Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other'
| by subsumption resolution.
|
| Result:
| lit_Error - No subsumption or simplification
| lit_Undef - Clause subsumes 'other'
| p - The literal p can be deleted from 'other'
|________________________________________________________________________________________________@*/
inline Lit Clause::subsumes(const Clause& other) const
{
//if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0)
//if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0))
assert(!header.learnt); assert(!other.header.learnt);
assert(header.has_extra); assert(other.header.has_extra);
if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0)
return lit_Error;
Lit ret = lit_Undef;
const Lit* c = (const Lit*)(*this);
const Lit* d = (const Lit*)other;
for (unsigned i = 0; i < header.size; i++) {
// search for c[i] or ~c[i]
for (unsigned j = 0; j < other.header.size; j++)
if (c[i] == d[j])
goto ok;
else if (ret == lit_Undef && c[i] == ~d[j]){
ret = c[i];
goto ok;
}
// did not find it
return lit_Error;
ok:;
}
return ret;
}
inline void Clause::strengthen(Lit p)
{
remove(*this, p);
calcAbstraction();
}
//=================================================================================================
}
#endif

View File

@ -1,79 +0,0 @@
Release Notes for MiniSat 2.2.0
===============================
Changes since version 2.0:
* Started using a more standard release numbering.
* Includes some now well-known heuristics: phase-saving and luby
restarts. The old heuristics are still present and can be activated
if needed.
* Detection/Handling of out-of-memory and vector capacity
overflow. This is fairly new and relatively untested.
* Simple resource controls: CPU-time, memory, number of
conflicts/decisions.
* CPU-time limiting is implemented by a more general, but simple,
asynchronous interruption feature. This means that the solving
procedure can be interrupted from another thread or in a signal
handler.
* Improved portability with respect to building on Solaris and with
Visual Studio. This is not regularly tested and chances are that
this have been broken since, but should be fairly easy to fix if
so.
* Changed C++ file-extention to the less problematic ".cc".
* Source code is now namespace-protected
* Introducing a new Clause Memory Allocator that brings reduced
memory consumption on 64-bit architechtures and improved
performance (to some extent). The allocator uses a region-based
approach were all references to clauses are represented as a 32-bit
index into a global memory region that contains all clauses. To
free up and compact memory it uses a simple copying garbage
collector.
* Improved unit-propagation by Blocking Literals. For each entry in
the watcher lists, pair the pointer to a clause with some
(arbitrary) literal from the clause. The idea is that if the
literal is currently true (i.e. the clause is satisfied) the
watchers of the clause does not need to be altered. This can thus
be detected without touching the clause's memory at all. As often
as can be done cheaply, the blocking literal for entries to the
watcher list of a literal 'p' is set to the other literal watched
in the corresponding clause.
* Basic command-line/option handling system. Makes it easy to specify
options in the class that they affect, and whenever that class is
used in an executable, parsing of options and help messages are
brought in automatically.
* General clean-up and various minor bug-fixes.
* Changed implementation of variable-elimination/model-extension:
- The interface is changed so that arbitrary remembering is no longer
possible. If you need to mention some variable again in the future,
this variable has to be frozen.
- When eliminating a variable, only clauses that contain the variable
with one sign is necessary to store. Thereby making the other sign
a "default" value when extending models.
- The memory consumption for eliminated clauses is further improved
by storing all eliminated clauses in a single contiguous vector.
* Some common utility code (I/O, Parsing, CPU-time, etc) is ripped
out and placed in a separate "utils" directory.
* The DIMACS parse is refactored so that it can be reused in other
applications (not very elegant, but at least possible).
* Some simple improvements to scalability of preprocessing, using
more lazy clause removal from data-structures and a couple of
ad-hoc limits (the longest clause that can be produced in variable
elimination, and the longest clause used in backward subsumption).

View File

@ -1,84 +0,0 @@
/*******************************************************************************************[Alg.h]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Alg_h
#define Minisat_Alg_h
#include "mtl/Vec.h"
namespace Minisat {
//=================================================================================================
// Useful functions on vector-like types:
//=================================================================================================
// Removing and searching for elements:
//
template<class V, class T>
static inline void remove(V& ts, const T& t)
{
int j = 0;
for (; j < ts.size() && ts[j] != t; j++);
assert(j < ts.size());
for (; j < ts.size()-1; j++) ts[j] = ts[j+1];
ts.pop();
}
template<class V, class T>
static inline bool find(V& ts, const T& t)
{
int j = 0;
for (; j < ts.size() && ts[j] != t; j++);
return j < ts.size();
}
//=================================================================================================
// Copying vectors with support for nested vector types:
//
// Base case:
template<class T>
static inline void copy(const T& from, T& to)
{
to = from;
}
// Recursive case:
template<class T>
static inline void copy(const vec<T>& from, vec<T>& to, bool append = false)
{
if (!append)
to.clear();
for (int i = 0; i < from.size(); i++){
to.push();
copy(from[i], to.last());
}
}
template<class T>
static inline void append(const vec<T>& from, vec<T>& to){ copy(from, to, true); }
//=================================================================================================
}
#endif

View File

@ -1,131 +0,0 @@
/*****************************************************************************************[Alloc.h]
Copyright (c) 2008-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Alloc_h
#define Minisat_Alloc_h
#include "mtl/XAlloc.h"
#include "mtl/Vec.h"
namespace Minisat {
//=================================================================================================
// Simple Region-based memory allocator:
template<class T>
class RegionAllocator
{
T* memory;
uint32_t sz;
uint32_t cap;
uint32_t wasted_;
void capacity(uint32_t min_cap);
public:
// TODO: make this a class for better type-checking?
typedef uint32_t Ref;
enum { Ref_Undef = UINT32_MAX };
enum { Unit_Size = sizeof(uint32_t) };
explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); }
~RegionAllocator()
{
if (memory != NULL)
::free(memory);
}
uint32_t size () const { return sz; }
uint32_t wasted () const { return wasted_; }
Ref alloc (int size);
void free (int size) { wasted_ += size; }
// Deref, Load Effective Address (LEA), Inverse of LEA (AEL):
T& operator[](Ref r) { assert(r >= 0 && r < sz); return memory[r]; }
const T& operator[](Ref r) const { assert(r >= 0 && r < sz); return memory[r]; }
T* lea (Ref r) { assert(r >= 0 && r < sz); return &memory[r]; }
const T* lea (Ref r) const { assert(r >= 0 && r < sz); return &memory[r]; }
Ref ael (const T* t) { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]);
return (Ref)(t - &memory[0]); }
void moveTo(RegionAllocator& to) {
if (to.memory != NULL) ::free(to.memory);
to.memory = memory;
to.sz = sz;
to.cap = cap;
to.wasted_ = wasted_;
memory = NULL;
sz = cap = wasted_ = 0;
}
};
template<class T>
void RegionAllocator<T>::capacity(uint32_t min_cap)
{
if (cap >= min_cap) return;
uint32_t prev_cap = cap;
while (cap < min_cap){
// NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the
// result even by clearing the least significant bit. The resulting sequence of capacities
// is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when
// using 'uint32_t' as indices so that as much as possible of this space can be used.
uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1;
cap += delta;
if (cap <= prev_cap)
throw OutOfMemoryException();
}
// printf(" .. (%p) cap = %u\n", this, cap);
assert(cap > 0);
memory = (T*)xrealloc(memory, sizeof(T)*cap);
}
template<class T>
typename RegionAllocator<T>::Ref
RegionAllocator<T>::alloc(int size)
{
// printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout);
assert(size > 0);
capacity(sz + size);
uint32_t prev_sz = sz;
sz += size;
// Handle overflow:
if (sz < prev_sz)
throw OutOfMemoryException();
return prev_sz;
}
//=================================================================================================
}
#endif

View File

@ -1,148 +0,0 @@
/******************************************************************************************[Heap.h]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Heap_h
#define Minisat_Heap_h
#include "mtl/Vec.h"
namespace Minisat {
//=================================================================================================
// A heap implementation with support for decrease/increase key.
template<class Comp>
class Heap {
Comp lt; // The heap is a minimum-heap with respect to this comparator
vec<int> heap; // Heap of integers
vec<int> indices; // Each integers position (index) in the Heap
// Index "traversal" functions
static inline int left (int i) { return i*2+1; }
static inline int right (int i) { return (i+1)*2; }
static inline int parent(int i) { return (i-1) >> 1; }
void percolateUp(int i)
{
int x = heap[i];
int p = parent(i);
while (i != 0 && lt(x, heap[p])){
heap[i] = heap[p];
indices[heap[p]] = i;
i = p;
p = parent(p);
}
heap [i] = x;
indices[x] = i;
}
void percolateDown(int i)
{
int x = heap[i];
while (left(i) < heap.size()){
int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i);
if (!lt(heap[child], x)) break;
heap[i] = heap[child];
indices[heap[i]] = i;
i = child;
}
heap [i] = x;
indices[x] = i;
}
public:
Heap(const Comp& c) : lt(c) { }
int size () const { return heap.size(); }
bool empty () const { return heap.size() == 0; }
bool inHeap (int n) const { return n < indices.size() && indices[n] >= 0; }
int operator[](int index) const { assert(index < heap.size()); return heap[index]; }
void decrease (int n) { assert(inHeap(n)); percolateUp (indices[n]); }
void increase (int n) { assert(inHeap(n)); percolateDown(indices[n]); }
// Safe variant of insert/decrease/increase:
void update(int n)
{
if (!inHeap(n))
insert(n);
else {
percolateUp(indices[n]);
percolateDown(indices[n]); }
}
void insert(int n)
{
indices.growTo(n+1, -1);
assert(!inHeap(n));
indices[n] = heap.size();
heap.push(n);
percolateUp(indices[n]);
}
int removeMin()
{
int x = heap[0];
heap[0] = heap.last();
indices[heap[0]] = 0;
indices[x] = -1;
heap.pop();
if (heap.size() > 1) percolateDown(0);
return x;
}
// Rebuild the heap from scratch, using the elements in 'ns':
void build(const vec<int>& ns) {
for (int i = 0; i < heap.size(); i++)
indices[heap[i]] = -1;
heap.clear();
for (int i = 0; i < ns.size(); i++){
indices[ns[i]] = i;
heap.push(ns[i]); }
for (int i = heap.size() / 2 - 1; i >= 0; i--)
percolateDown(i);
}
void clear(bool dealloc = false)
{
for (int i = 0; i < heap.size(); i++)
indices[heap[i]] = -1;
heap.clear(dealloc);
}
};
//=================================================================================================
}
#endif

View File

@ -1,42 +0,0 @@
/**************************************************************************************[IntTypes.h]
Copyright (c) 2009-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_IntTypes_h
#define Minisat_IntTypes_h
#ifdef __sun
// Not sure if there are newer versions that support C99 headers. The
// needed features are implemented in the headers below though:
# include <sys/int_types.h>
# include <sys/int_fmtio.h>
# include <sys/int_limits.h>
#else
# include <stdint.h>
# include <inttypes.h>
#endif
#include <limits.h>
//=================================================================================================
#endif

View File

@ -1,193 +0,0 @@
/*******************************************************************************************[Map.h]
Copyright (c) 2006-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Map_h
#define Minisat_Map_h
#include "mtl/IntTypes.h"
#include "mtl/Vec.h"
namespace Minisat {
//=================================================================================================
// Default hash/equals functions
//
template<class K> struct Hash { uint32_t operator()(const K& k) const { return hash(k); } };
template<class K> struct Equal { bool operator()(const K& k1, const K& k2) const { return k1 == k2; } };
template<class K> struct DeepHash { uint32_t operator()(const K* k) const { return hash(*k); } };
template<class K> struct DeepEqual { bool operator()(const K* k1, const K* k2) const { return *k1 == *k2; } };
static inline uint32_t hash(uint32_t x){ return x; }
static inline uint32_t hash(uint64_t x){ return (uint32_t)x; }
static inline uint32_t hash(int32_t x) { return (uint32_t)x; }
static inline uint32_t hash(int64_t x) { return (uint32_t)x; }
//=================================================================================================
// Some primes
//
static const int nprimes = 25;
static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 };
//=================================================================================================
// Hash table implementation of Maps
//
template<class K, class D, class H = Hash<K>, class E = Equal<K> >
class Map {
public:
struct Pair { K key; D data; };
private:
H hash;
E equals;
vec<Pair>* table;
int cap;
int size;
// Don't allow copying (error prone):
Map<K,D,H,E>& operator = (Map<K,D,H,E>& other) { assert(0); }
Map (Map<K,D,H,E>& other) { assert(0); }
bool checkCap(int new_size) const { return new_size > cap; }
int32_t index (const K& k) const { return hash(k) % cap; }
void _insert (const K& k, const D& d) {
vec<Pair>& ps = table[index(k)];
ps.push(); ps.last().key = k; ps.last().data = d; }
void rehash () {
const vec<Pair>* old = table;
int old_cap = cap;
int newsize = primes[0];
for (int i = 1; newsize <= cap && i < nprimes; i++)
newsize = primes[i];
table = new vec<Pair>[newsize];
cap = newsize;
for (int i = 0; i < old_cap; i++){
for (int j = 0; j < old[i].size(); j++){
_insert(old[i][j].key, old[i][j].data); }}
delete [] old;
// printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize);
}
public:
Map () : table(NULL), cap(0), size(0) {}
Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){}
~Map () { delete [] table; }
// PRECONDITION: the key must already exist in the map.
const D& operator [] (const K& k) const
{
assert(size != 0);
const D* res = NULL;
const vec<Pair>& ps = table[index(k)];
for (int i = 0; i < ps.size(); i++)
if (equals(ps[i].key, k))
res = &ps[i].data;
assert(res != NULL);
return *res;
}
// PRECONDITION: the key must already exist in the map.
D& operator [] (const K& k)
{
assert(size != 0);
D* res = NULL;
vec<Pair>& ps = table[index(k)];
for (int i = 0; i < ps.size(); i++)
if (equals(ps[i].key, k))
res = &ps[i].data;
assert(res != NULL);
return *res;
}
// PRECONDITION: the key must *NOT* exist in the map.
void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; }
bool peek (const K& k, D& d) const {
if (size == 0) return false;
const vec<Pair>& ps = table[index(k)];
for (int i = 0; i < ps.size(); i++)
if (equals(ps[i].key, k)){
d = ps[i].data;
return true; }
return false;
}
bool has (const K& k) const {
if (size == 0) return false;
const vec<Pair>& ps = table[index(k)];
for (int i = 0; i < ps.size(); i++)
if (equals(ps[i].key, k))
return true;
return false;
}
// PRECONDITION: the key must exist in the map.
void remove(const K& k) {
assert(table != NULL);
vec<Pair>& ps = table[index(k)];
int j = 0;
for (; j < ps.size() && !equals(ps[j].key, k); j++);
assert(j < ps.size());
ps[j] = ps.last();
ps.pop();
size--;
}
void clear () {
cap = size = 0;
delete [] table;
table = NULL;
}
int elems() const { return size; }
int bucket_count() const { return cap; }
// NOTE: the hash and equality objects are not moved by this method:
void moveTo(Map& other){
delete [] other.table;
other.table = table;
other.cap = cap;
other.size = size;
table = NULL;
size = cap = 0;
}
// NOTE: given a bit more time, I could make a more C++-style iterator out of this:
const vec<Pair>& bucket(int i) const { return table[i]; }
};
//=================================================================================================
}
#endif

View File

@ -1,69 +0,0 @@
/*****************************************************************************************[Queue.h]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Queue_h
#define Minisat_Queue_h
#include "mtl/Vec.h"
namespace Minisat {
//=================================================================================================
template<class T>
class Queue {
vec<T> buf;
int first;
int end;
public:
typedef T Key;
Queue() : buf(1), first(0), end(0) {}
void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; }
int size () const { return (end >= first) ? end - first : end - first + buf.size(); }
const T& operator [] (int index) const { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; }
T& operator [] (int index) { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; }
T peek () const { assert(first != end); return buf[first]; }
void pop () { assert(first != end); first++; if (first == buf.size()) first = 0; }
void insert(T elem) { // INVARIANT: buf[end] is always unused
buf[end++] = elem;
if (end == buf.size()) end = 0;
if (first == end){ // Resize:
vec<T> tmp((buf.size()*3 + 1) >> 1);
//**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0);
int i = 0;
for (int j = first; j < buf.size(); j++) tmp[i++] = buf[j];
for (int j = 0 ; j < end ; j++) tmp[i++] = buf[j];
first = 0;
end = buf.size();
tmp.moveTo(buf);
}
}
};
//=================================================================================================
}
#endif

View File

@ -1,98 +0,0 @@
/******************************************************************************************[Sort.h]
Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Sort_h
#define Minisat_Sort_h
#include "mtl/Vec.h"
//=================================================================================================
// Some sorting algorithms for vec's
namespace Minisat {
template<class T>
struct LessThan_default {
bool operator () (T x, T y) { return x < y; }
};
template <class T, class LessThan>
void selectionSort(T* array, int size, LessThan lt)
{
int i, j, best_i;
T tmp;
for (i = 0; i < size-1; i++){
best_i = i;
for (j = i+1; j < size; j++){
if (lt(array[j], array[best_i]))
best_i = j;
}
tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp;
}
}
template <class T> static inline void selectionSort(T* array, int size) {
selectionSort(array, size, LessThan_default<T>()); }
template <class T, class LessThan>
void sort(T* array, int size, LessThan lt)
{
if (size <= 15)
selectionSort(array, size, lt);
else{
T pivot = array[size / 2];
T tmp;
int i = -1;
int j = size;
for(;;){
do i++; while(lt(array[i], pivot));
do j--; while(lt(pivot, array[j]));
if (i >= j) break;
tmp = array[i]; array[i] = array[j]; array[j] = tmp;
}
sort(array , i , lt);
sort(&array[i], size-i, lt);
}
}
template <class T> static inline void sort(T* array, int size) {
sort(array, size, LessThan_default<T>()); }
//=================================================================================================
// For 'vec's:
template <class T, class LessThan> void sort(vec<T>& v, LessThan lt) {
sort((T*)v, v.size(), lt); }
template <class T> void sort(vec<T>& v) {
sort(v, LessThan_default<T>()); }
//=================================================================================================
}
#endif

View File

@ -1,130 +0,0 @@
/*******************************************************************************************[Vec.h]
Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Vec_h
#define Minisat_Vec_h
#include <assert.h>
#include <new>
#include "mtl/IntTypes.h"
#include "mtl/XAlloc.h"
namespace Minisat {
//=================================================================================================
// Automatically resizable arrays
//
// NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc)
template<class T>
class vec {
T* data;
int sz;
int cap;
// Don't allow copying (error prone):
vec<T>& operator = (vec<T>& other) { assert(0); return *this; }
vec (vec<T>& other) { assert(0); }
// Helpers for calculating next capacity:
static inline int imax (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); }
//static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; }
static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; }
public:
// Constructors:
vec() : data(NULL) , sz(0) , cap(0) { }
explicit vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); }
vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); }
~vec() { clear(true); }
// Pointer to first element:
operator T* (void) { return data; }
// Size operations:
int size (void) const { return sz; }
void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); }
void shrink_ (int nelems) { assert(nelems <= sz); sz -= nelems; }
int capacity (void) const { return cap; }
void capacity (int min_cap);
void growTo (int size);
void growTo (int size, const T& pad);
void clear (bool dealloc = false);
// Stack interface:
void push (void) { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; }
void push (const T& elem) { if (sz == cap) capacity(sz+1); data[sz++] = elem; }
void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; }
void pop (void) { assert(sz > 0); sz--, data[sz].~T(); }
// NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but
// in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not
// happen given the way capacities are calculated (below). Essentially, all capacities are
// even, but INT_MAX is odd.
const T& last (void) const { return data[sz-1]; }
T& last (void) { return data[sz-1]; }
// Vector interface:
const T& operator [] (int index) const { return data[index]; }
T& operator [] (int index) { return data[index]; }
// Duplicatation (preferred instead):
void copyTo(vec<T>& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; }
void moveTo(vec<T>& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; }
};
template<class T>
void vec<T>::capacity(int min_cap) {
if (cap >= min_cap) return;
int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2
if (add > INT_MAX - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM)
throw OutOfMemoryException();
}
template<class T>
void vec<T>::growTo(int size, const T& pad) {
if (sz >= size) return;
capacity(size);
for (int i = sz; i < size; i++) data[i] = pad;
sz = size; }
template<class T>
void vec<T>::growTo(int size) {
if (sz >= size) return;
capacity(size);
for (int i = sz; i < size; i++) new (&data[i]) T();
sz = size; }
template<class T>
void vec<T>::clear(bool dealloc) {
if (data != NULL){
for (int i = 0; i < sz; i++) data[i].~T();
sz = 0;
if (dealloc) free(data), data = NULL, cap = 0; } }
//=================================================================================================
}
#endif

View File

@ -1,45 +0,0 @@
/****************************************************************************************[XAlloc.h]
Copyright (c) 2009-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_XAlloc_h
#define Minisat_XAlloc_h
#include <errno.h>
#include <stdlib.h>
namespace Minisat {
//=================================================================================================
// Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing:
class OutOfMemoryException{};
static inline void* xrealloc(void *ptr, size_t size)
{
void* mem = realloc(ptr, size);
if (mem == NULL && errno == ENOMEM){
throw OutOfMemoryException();
}else
return mem;
}
//=================================================================================================
}
#endif

View File

@ -1,6 +0,0 @@
##
## This file is for system specific configurations. For instance, on
## some systems the path to zlib needs to be added. Example:
##
## CFLAGS += -I/usr/local/include
## LFLAGS += -L/usr/local/lib

View File

@ -1,107 +0,0 @@
##
## Template makefile for Standard, Profile, Debug, Release, and Release-static versions
##
## eg: "make rs" for a statically linked release version.
## "make d" for a debug version (no optimizations).
## "make" for the standard version (optimized, but with debug information and assertions active)
PWD = $(shell pwd)
EXEC ?= $(notdir $(PWD))
CSRCS = $(wildcard $(PWD)/*.cc)
DSRCS = $(foreach dir, $(DEPDIR), $(filter-out $(MROOT)/$(dir)/Main.cc, $(wildcard $(MROOT)/$(dir)/*.cc)))
CHDRS = $(wildcard $(PWD)/*.h)
COBJS = $(CSRCS:.cc=.o) $(DSRCS:.cc=.o)
PCOBJS = $(addsuffix p, $(COBJS))
DCOBJS = $(addsuffix d, $(COBJS))
RCOBJS = $(addsuffix r, $(COBJS))
CXX ?= g++
CFLAGS ?= -Wall -Wno-parentheses
LFLAGS ?= -Wall
COPTIMIZE ?= -O3
CFLAGS += -I$(MROOT) -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS
LFLAGS += -lz
.PHONY : s p d r rs clean
s: $(EXEC)
p: $(EXEC)_profile
d: $(EXEC)_debug
r: $(EXEC)_release
rs: $(EXEC)_static
libs: lib$(LIB)_standard.a
libp: lib$(LIB)_profile.a
libd: lib$(LIB)_debug.a
libr: lib$(LIB)_release.a
## Compile options
%.o: CFLAGS +=$(COPTIMIZE) -g -D DEBUG
%.op: CFLAGS +=$(COPTIMIZE) -pg -g -D NDEBUG
%.od: CFLAGS +=-O0 -g -D DEBUG
%.or: CFLAGS +=$(COPTIMIZE) -g -D NDEBUG
## Link options
$(EXEC): LFLAGS += -g
$(EXEC)_profile: LFLAGS += -g -pg
$(EXEC)_debug: LFLAGS += -g
#$(EXEC)_release: LFLAGS += ...
$(EXEC)_static: LFLAGS += --static
## Dependencies
$(EXEC): $(COBJS)
$(EXEC)_profile: $(PCOBJS)
$(EXEC)_debug: $(DCOBJS)
$(EXEC)_release: $(RCOBJS)
$(EXEC)_static: $(RCOBJS)
lib$(LIB)_standard.a: $(filter-out */Main.o, $(COBJS))
lib$(LIB)_profile.a: $(filter-out */Main.op, $(PCOBJS))
lib$(LIB)_debug.a: $(filter-out */Main.od, $(DCOBJS))
lib$(LIB)_release.a: $(filter-out */Main.or, $(RCOBJS))
## Build rule
%.o %.op %.od %.or: %.cc
@echo Compiling: $(subst $(MROOT)/,,$@)
@$(CXX) $(CFLAGS) -c -o $@ $<
## Linking rules (standard/profile/debug/release)
$(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static:
@echo Linking: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )"
@$(CXX) $^ $(LFLAGS) -o $@
## Library rules (standard/profile/debug/release)
lib$(LIB)_standard.a lib$(LIB)_profile.a lib$(LIB)_release.a lib$(LIB)_debug.a:
@echo Making library: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )"
@$(AR) -rcsv $@ $^
## Library Soft Link rule:
libs libp libd libr:
@echo "Making Soft Link: $^ -> lib$(LIB).a"
@ln -sf $^ lib$(LIB).a
## Clean rule
clean:
@rm -f $(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static \
$(COBJS) $(PCOBJS) $(DCOBJS) $(RCOBJS) *.core depend.mk
## Make dependencies
depend.mk: $(CSRCS) $(CHDRS)
@echo Making dependencies
@$(CXX) $(CFLAGS) -I$(MROOT) \
$(CSRCS) -MM | sed 's|\(.*\):|$(PWD)/\1 $(PWD)/\1r $(PWD)/\1d $(PWD)/\1p:|' > depend.mk
@for dir in $(DEPDIR); do \
if [ -r $(MROOT)/$${dir}/depend.mk ]; then \
echo Depends on: $${dir}; \
cat $(MROOT)/$${dir}/depend.mk >> depend.mk; \
fi; \
done
-include $(MROOT)/mtl/config.mk
-include depend.mk

View File

@ -1,251 +0,0 @@
/*****************************************************************************************[Main.cc]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007, Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#include <errno.h>
#include <signal.h>
#include <zlib.h>
#include <sys/resource.h>
#include "utils/System.h"
#include "utils/ParseUtils.h"
#include "utils/Options.h"
#include "core/Dimacs.h"
#include "simp/SimpSolver.h"
using namespace Minisat;
//=================================================================================================
void printStats(Solver& solver)
{
double cpu_time = cpuTime();
// double mem_used = memUsedPeak();
// printf("c restarts : %"PRIu64"\n", solver.starts);
// printf("c conflicts : %-12"PRIu64" (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time);
// printf("c decisions : %-12"PRIu64" (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time);
// printf("c propagations : %-12"PRIu64" (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time);
// printf("c conflict literals : %-12"PRIu64" (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals);
// if (mem_used != 0) printf("c Memory used : %.2f MB\n", mem_used);
printf("c CPU time : %g s\n", cpu_time);
}
static Solver* solver;
// Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case
// for this feature of the Solver as it may take longer than an immediate call to '_exit()'.
static void SIGINT_interrupt(int signum) { solver->interrupt(); }
// Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls
// destructors and may cause deadlocks if a malloc/free function happens to be running (these
// functions are guarded by locks for multithreaded use).
static void SIGINT_exit(int signum) {
printf("\n"); printf("c *** INTERRUPTED ***\n");
if (solver->verbosity > 0){
printStats(*solver);
printf("\n"); printf("c *** INTERRUPTED ***\n"); }
_exit(1); }
//=================================================================================================
// Main:
int main(int argc, char** argv)
{
try {
setUsageHelp("USAGE: %s [options] <input-file> <result-output-file>\n\n where input may be either in plain or gzipped DIMACS.\n");
printf("c This is COMiniSatPS.\n");
#if defined(__linux__)
fpu_control_t oldcw, newcw;
_FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw);
printf("c WARNING: for repeatability, setting FPU to use double precision\n");
#endif
// Extra options:
//
IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2));
BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true);
StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file.");
IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX));
IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX));
BoolOption drup ("MAIN", "drup", "Generate DRUP UNSAT proof.", false);
StringOption drup_file("MAIN", "drup-file", "DRUP UNSAT proof ouput file.", "");
parseOptions(argc, argv, true);
SimpSolver S;
double initial_time = cpuTime();
if (!pre) S.eliminate(true);
S.parsing = true;
S.verbosity = verb;
if (drup || strlen(drup_file)){
S.drup_file = strlen(drup_file) ? fopen(drup_file, "wb") : stdout;
if (S.drup_file == NULL){
S.drup_file = stdout;
printf("c Error opening %s for write.\n", (const char*) drup_file); }
printf("c DRUP proof generation: %s\n", S.drup_file == stdout ? "stdout" : drup_file);
}
solver = &S;
// Use signal handlers that forcibly quit until the solver will be able to respond to
// interrupts:
signal(SIGINT, SIGINT_exit);
signal(SIGXCPU,SIGINT_exit);
// Set limit on CPU-time:
if (cpu_lim != INT32_MAX){
rlimit rl;
getrlimit(RLIMIT_CPU, &rl);
if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){
rl.rlim_cur = cpu_lim;
if (setrlimit(RLIMIT_CPU, &rl) == -1)
printf("c WARNING! Could not set resource limit: CPU-time.\n");
} }
// Set limit on virtual memory:
if (mem_lim != INT32_MAX){
rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024;
rlimit rl;
getrlimit(RLIMIT_AS, &rl);
if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){
rl.rlim_cur = new_mem_lim;
if (setrlimit(RLIMIT_AS, &rl) == -1)
printf("c WARNING! Could not set resource limit: Virtual memory.\n");
} }
if (argc == 1)
printf("c Reading from standard input... Use '--help' for help.\n");
gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb");
if (in == NULL)
printf("c ERROR! Could not open file: %s\n", argc == 1 ? "<stdin>" : argv[1]), exit(1);
if (S.verbosity > 0){
printf("c ============================[ Problem Statistics ]=============================\n");
printf("c | |\n"); }
parse_DIMACS(in, S);
gzclose(in);
FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL;
if (S.verbosity > 0){
printf("c | Number of variables: %12d |\n", S.nVars());
printf("c | Number of clauses: %12d |\n", S.nClauses()); }
double parsed_time = cpuTime();
if (S.verbosity > 0)
printf("c | Parse time: %12.2f s |\n", parsed_time - initial_time);
// Change to signal-handlers that will only notify the solver and allow it to terminate
// voluntarily:
// signal(SIGINT, SIGINT_interrupt);
// signal(SIGXCPU,SIGINT_interrupt);
S.parsing = false;
S.eliminate(true);
double simplified_time = cpuTime();
if (S.verbosity > 0){
printf("c | Simplification time: %12.2f s |\n", simplified_time - parsed_time);
printf("c | |\n"); }
if (!S.okay()){
if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res);
if (S.verbosity > 0){
printf("c ===============================================================================\n");
printf("c Solved by simplification\n");
printStats(S);
printf("\n"); }
printf("s UNSATISFIABLE\n");
if (S.drup_file){
#ifdef BIN_DRUP
fputc('a', S.drup_file); fputc(0, S.drup_file);
#else
fprintf(S.drup_file, "0\n");
#endif
}
if (S.drup_file && S.drup_file != stdout) fclose(S.drup_file);
exit(20);
}
if (dimacs){
if (S.verbosity > 0)
printf("c ==============================[ Writing DIMACS ]===============================\n");
S.toDimacs((const char*)dimacs);
if (S.verbosity > 0)
printStats(S);
exit(0);
}
vec<Lit> dummy;
lbool ret = S.solveLimited(dummy);
if (S.verbosity > 0){
printStats(S);
printf("\n"); }
printf(ret == l_True ? "s SATISFIABLE\n" : ret == l_False ? "s UNSATISFIABLE\n" : "s UNKNOWN\n");
// Do not flush stdout
// if (ret == l_True){
// printf("v ");
// for (int i = 0; i < S.nVars(); i++)
// if (S.model[i] != l_Undef)
// printf("%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
// printf(" 0\n");
// }
if (S.drup_file && ret == l_False){
#ifdef BIN_DRUP
fputc('a', S.drup_file); fputc(0, S.drup_file);
#else
fprintf(S.drup_file, "0\n");
#endif
}
if (S.drup_file && S.drup_file != stdout) fclose(S.drup_file);
if (res != NULL){
if (ret == l_True){
fprintf(res, "SAT\n");
for (int i = 0; i < S.nVars(); i++)
if (S.model[i] != l_Undef)
fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1);
fprintf(res, " 0\n");
}else if (ret == l_False)
fprintf(res, "UNSAT\n");
else
fprintf(res, "INDET\n");
fclose(res);
}
#ifdef NDEBUG
exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver')
#else
return (ret == l_True ? 10 : ret == l_False ? 20 : 0);
#endif
} catch (OutOfMemoryException&){
printf("c ===============================================================================\n");
printf("c Out of memory\n");
printf("s UNKNOWN\n");
exit(0);
}
}

View File

@ -1,4 +0,0 @@
EXEC = minisat
DEPDIR = mtl utils core
include $(MROOT)/mtl/template.mk

View File

@ -1,825 +0,0 @@
/***********************************************************************************[SimpSolver.cc]
MiniSat -- Copyright (c) 2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#include "mtl/Sort.h"
#include "simp/SimpSolver.h"
#include "utils/System.h"
using namespace Minisat;
//=================================================================================================
// Options:
static const char* _cat = "SIMP";
static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false);
static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false);
static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true);
static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0);
static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX));
static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX));
static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false));
//=================================================================================================
// Constructor/Destructor:
SimpSolver::SimpSolver() :
parsing (false)
, grow (opt_grow)
, clause_lim (opt_clause_lim)
, subsumption_lim (opt_subsumption_lim)
, simp_garbage_frac (opt_simp_garbage_frac)
, use_asymm (opt_use_asymm)
, use_rcheck (opt_use_rcheck)
, use_elim (opt_use_elim)
, merges (0)
, asymm_lits (0)
, eliminated_vars (0)
, elimorder (1)
, use_simplification (true)
, occurs (ClauseDeleted(ca))
, elim_heap (ElimLt(n_occ))
, bwdsub_assigns (0)
, n_touched (0)
{
vec<Lit> dummy(1,lit_Undef);
ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below.
bwdsub_tmpunit = ca.alloc(dummy);
remove_satisfied = false;
}
SimpSolver::~SimpSolver()
{
}
Var SimpSolver::newVar(bool sign, bool dvar) {
Var v = Solver::newVar(sign, dvar);
frozen .push((char)false);
eliminated.push((char)false);
if (use_simplification){
n_occ .push(0);
n_occ .push(0);
occurs .init(v);
touched .push(0);
elim_heap .insert(v);
}
return v; }
lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp)
{
vec<Var> extra_frozen;
lbool result = l_True;
do_simp &= use_simplification;
if (do_simp){
// Assumptions must be temporarily frozen to run variable elimination:
for (int i = 0; i < assumptions.size(); i++){
Var v = var(assumptions[i]);
// If an assumption has been eliminated, remember it.
assert(!isEliminated(v));
if (!frozen[v]){
// Freeze and store.
setFrozen(v, true);
extra_frozen.push(v);
} }
result = lbool(eliminate(turn_off_simp));
}
if (result == l_True)
result = Solver::solve_();
else if (verbosity >= 1)
printf("c ===============================================================================\n");
if (result == l_True)
extendModel();
if (do_simp)
// Unfreeze the assumptions that were frozen:
for (int i = 0; i < extra_frozen.size(); i++)
setFrozen(extra_frozen[i], false);
return result;
}
bool SimpSolver::addClause_(vec<Lit>& ps)
{
#ifndef NDEBUG
for (int i = 0; i < ps.size(); i++)
assert(!isEliminated(var(ps[i])));
#endif
int nclauses = clauses.size();
if (use_rcheck && implied(ps))
return true;
if (!Solver::addClause_(ps))
return false;
if (!parsing && drup_file) {
#ifdef BIN_DRUP
binDRUP('a', ps, drup_file);
#else
for (int i = 0; i < ps.size(); i++)
fprintf(drup_file, "%i ", (var(ps[i]) + 1) * (-2 * sign(ps[i]) + 1));
fprintf(drup_file, "0\n");
#endif
}
if (use_simplification && clauses.size() == nclauses + 1){
CRef cr = clauses.last();
const Clause& c = ca[cr];
// NOTE: the clause is added to the queue immediately and then
// again during 'gatherTouchedClauses()'. If nothing happens
// in between, it will only be checked once. Otherwise, it may
// be checked twice unnecessarily. This is an unfortunate
// consequence of how backward subsumption is used to mimic
// forward subsumption.
subsumption_queue.insert(cr);
for (int i = 0; i < c.size(); i++){
occurs[var(c[i])].push(cr);
n_occ[toInt(c[i])]++;
touched[var(c[i])] = 1;
n_touched++;
if (elim_heap.inHeap(var(c[i])))
elim_heap.increase(var(c[i]));
}
}
return true;
}
void SimpSolver::removeClause(CRef cr)
{
const Clause& c = ca[cr];
if (use_simplification)
for (int i = 0; i < c.size(); i++){
n_occ[toInt(c[i])]--;
updateElimHeap(var(c[i]));
occurs.smudge(var(c[i]));
}
Solver::removeClause(cr);
}
bool SimpSolver::strengthenClause(CRef cr, Lit l)
{
Clause& c = ca[cr];
assert(decisionLevel() == 0);
assert(use_simplification);
// FIX: this is too inefficient but would be nice to have (properly implemented)
// if (!find(subsumption_queue, &c))
subsumption_queue.insert(cr);
if (drup_file){
#ifdef BIN_DRUP
binDRUP_strengthen(c, l, drup_file);
#else
for (int i = 0; i < c.size(); i++)
if (c[i] != l) fprintf(drup_file, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1));
fprintf(drup_file, "0\n");
#endif
}
if (c.size() == 2){
removeClause(cr);
c.strengthen(l);
}else{
if (drup_file){
#ifdef BIN_DRUP
binDRUP('d', c, drup_file);
#else
fprintf(drup_file, "d ");
for (int i = 0; i < c.size(); i++)
fprintf(drup_file, "%i ", (var(c[i]) + 1) * (-2 * sign(c[i]) + 1));
fprintf(drup_file, "0\n");
#endif
}
detachClause(cr, true);
c.strengthen(l);
attachClause(cr);
remove(occurs[var(l)], cr);
n_occ[toInt(l)]--;
updateElimHeap(var(l));
}
return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true;
}
// Returns FALSE if clause is always satisfied ('out_clause' should not be used).
bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause)
{
merges++;
out_clause.clear();
bool ps_smallest = _ps.size() < _qs.size();
const Clause& ps = ps_smallest ? _qs : _ps;
const Clause& qs = ps_smallest ? _ps : _qs;
for (int i = 0; i < qs.size(); i++){
if (var(qs[i]) != v){
for (int j = 0; j < ps.size(); j++)
if (var(ps[j]) == var(qs[i]))
if (ps[j] == ~qs[i])
return false;
else
goto next;
out_clause.push(qs[i]);
}
next:;
}
for (int i = 0; i < ps.size(); i++)
if (var(ps[i]) != v)
out_clause.push(ps[i]);
return true;
}
// Returns FALSE if clause is always satisfied.
bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size)
{
merges++;
bool ps_smallest = _ps.size() < _qs.size();
const Clause& ps = ps_smallest ? _qs : _ps;
const Clause& qs = ps_smallest ? _ps : _qs;
const Lit* __ps = (const Lit*)ps;
const Lit* __qs = (const Lit*)qs;
size = ps.size()-1;
for (int i = 0; i < qs.size(); i++){
if (var(__qs[i]) != v){
for (int j = 0; j < ps.size(); j++)
if (var(__ps[j]) == var(__qs[i]))
if (__ps[j] == ~__qs[i])
return false;
else
goto next;
size++;
}
next:;
}
return true;
}
void SimpSolver::gatherTouchedClauses()
{
if (n_touched == 0) return;
int i,j;
for (i = j = 0; i < subsumption_queue.size(); i++)
if (ca[subsumption_queue[i]].mark() == 0)
ca[subsumption_queue[i]].mark(2);
for (i = 0; i < touched.size(); i++)
if (touched[i]){
const vec<CRef>& cs = occurs.lookup(i);
for (j = 0; j < cs.size(); j++)
if (ca[cs[j]].mark() == 0){
subsumption_queue.insert(cs[j]);
ca[cs[j]].mark(2);
}
touched[i] = 0;
}
for (i = 0; i < subsumption_queue.size(); i++)
if (ca[subsumption_queue[i]].mark() == 2)
ca[subsumption_queue[i]].mark(0);
n_touched = 0;
}
bool SimpSolver::implied(const vec<Lit>& c)
{
assert(decisionLevel() == 0);
trail_lim.push(trail.size());
for (int i = 0; i < c.size(); i++)
if (value(c[i]) == l_True){
cancelUntil(0);
return true;
}else if (value(c[i]) != l_False){
assert(value(c[i]) == l_Undef);
uncheckedEnqueue(~c[i]);
}
bool result = propagate() != CRef_Undef;
cancelUntil(0);
return result;
}
// Backward subsumption + backward subsumption resolution
bool SimpSolver::backwardSubsumptionCheck(bool verbose)
{
int cnt = 0;
int subsumed = 0;
int deleted_literals = 0;
assert(decisionLevel() == 0);
while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){
// Empty subsumption queue and return immediately on user-interrupt:
if (asynch_interrupt){
subsumption_queue.clear();
bwdsub_assigns = trail.size();
break; }
// Check top-level assignments by creating a dummy clause and placing it in the queue:
if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){
Lit l = trail[bwdsub_assigns++];
ca[bwdsub_tmpunit][0] = l;
ca[bwdsub_tmpunit].calcAbstraction();
subsumption_queue.insert(bwdsub_tmpunit); }
CRef cr = subsumption_queue.peek(); subsumption_queue.pop();
Clause& c = ca[cr];
if (c.mark()) continue;
if (verbose && verbosity >= 2 && cnt++ % 1000 == 0)
printf("c subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals);
assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point.
// Find best variable to scan:
Var best = var(c[0]);
for (int i = 1; i < c.size(); i++)
if (occurs[var(c[i])].size() < occurs[best].size())
best = var(c[i]);
// Search all candidates:
vec<CRef>& _cs = occurs.lookup(best);
CRef* cs = (CRef*)_cs;
for (int j = 0; j < _cs.size(); j++)
if (c.mark())
break;
else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){
Lit l = c.subsumes(ca[cs[j]]);
if (l == lit_Undef)
subsumed++, removeClause(cs[j]);
else if (l != lit_Error){
deleted_literals++;
if (!strengthenClause(cs[j], ~l))
return false;
// Did current candidate get deleted from cs? Then check candidate at index j again:
if (var(l) == best)
j--;
}
}
}
return true;
}
bool SimpSolver::asymm(Var v, CRef cr)
{
Clause& c = ca[cr];
assert(decisionLevel() == 0);
if (c.mark() || satisfied(c)) return true;
trail_lim.push(trail.size());
Lit l = lit_Undef;
for (int i = 0; i < c.size(); i++)
if (var(c[i]) != v){
if (value(c[i]) != l_False)
uncheckedEnqueue(~c[i]);
}else
l = c[i];
if (propagate() != CRef_Undef){
cancelUntil(0);
asymm_lits++;
if (!strengthenClause(cr, l))
return false;
}else
cancelUntil(0);
return true;
}
bool SimpSolver::asymmVar(Var v)
{
assert(use_simplification);
const vec<CRef>& cls = occurs.lookup(v);
if (value(v) != l_Undef || cls.size() == 0)
return true;
for (int i = 0; i < cls.size(); i++)
if (!asymm(v, cls[i]))
return false;
return backwardSubsumptionCheck();
}
static void mkElimClause(vec<uint32_t>& elimclauses, Lit x)
{
elimclauses.push(toInt(x));
elimclauses.push(1);
}
static void mkElimClause(vec<uint32_t>& elimclauses, Var v, Clause& c)
{
int first = elimclauses.size();
int v_pos = -1;
// Copy clause to elimclauses-vector. Remember position where the
// variable 'v' occurs:
for (int i = 0; i < c.size(); i++){
elimclauses.push(toInt(c[i]));
if (var(c[i]) == v)
v_pos = i + first;
}
assert(v_pos != -1);
// Swap the first literal with the 'v' literal, so that the literal
// containing 'v' will occur first in the clause:
uint32_t tmp = elimclauses[v_pos];
elimclauses[v_pos] = elimclauses[first];
elimclauses[first] = tmp;
// Store the length of the clause last:
elimclauses.push(c.size());
}
bool SimpSolver::eliminateVar(Var v)
{
assert(!frozen[v]);
assert(!isEliminated(v));
assert(value(v) == l_Undef);
// Split the occurrences into positive and negative:
//
const vec<CRef>& cls = occurs.lookup(v);
vec<CRef> pos, neg;
for (int i = 0; i < cls.size(); i++)
(find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]);
// Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no
// clause must exceed the limit on the maximal clause size (if it is set):
//
int cnt = 0;
int clause_size = 0;
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++)
if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) &&
(++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim)))
return true;
// Delete and store old clauses:
eliminated[v] = true;
setDecisionVar(v, false);
eliminated_vars++;
if (pos.size() > neg.size()){
for (int i = 0; i < neg.size(); i++)
mkElimClause(elimclauses, v, ca[neg[i]]);
mkElimClause(elimclauses, mkLit(v));
}else{
for (int i = 0; i < pos.size(); i++)
mkElimClause(elimclauses, v, ca[pos[i]]);
mkElimClause(elimclauses, ~mkLit(v));
}
// Produce clauses in cross product:
vec<Lit>& resolvent = add_tmp;
for (int i = 0; i < pos.size(); i++)
for (int j = 0; j < neg.size(); j++)
if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent))
return false;
for (int i = 0; i < cls.size(); i++)
removeClause(cls[i]);
// Free occurs list for this variable:
occurs[v].clear(true);
// Free watchers lists for this variable, if possible:
watches_bin[ mkLit(v)].clear(true);
watches_bin[~mkLit(v)].clear(true);
watches[ mkLit(v)].clear(true);
watches[~mkLit(v)].clear(true);
return backwardSubsumptionCheck();
}
bool SimpSolver::substitute(Var v, Lit x)
{
assert(!frozen[v]);
assert(!isEliminated(v));
assert(value(v) == l_Undef);
if (!ok) return false;
eliminated[v] = true;
setDecisionVar(v, false);
const vec<CRef>& cls = occurs.lookup(v);
vec<Lit>& subst_clause = add_tmp;
for (int i = 0; i < cls.size(); i++){
Clause& c = ca[cls[i]];
subst_clause.clear();
for (int j = 0; j < c.size(); j++){
Lit p = c[j];
subst_clause.push(var(p) == v ? x ^ sign(p) : p);
}
if (!addClause_(subst_clause))
return ok = false;
removeClause(cls[i]);
}
return true;
}
void SimpSolver::extendModel()
{
int i, j;
Lit x;
for (i = elimclauses.size()-1; i > 0; i -= j){
for (j = elimclauses[i--]; j > 1; j--, i--)
if (modelValue(toLit(elimclauses[i])) != l_False)
goto next;
x = toLit(elimclauses[i]);
model[var(x)] = lbool(!sign(x));
next:;
}
}
// Almost duplicate of Solver::removeSatisfied. Didn't want to make the base method 'virtual'.
void SimpSolver::removeSatisfied()
{
int i, j;
for (i = j = 0; i < clauses.size(); i++){
const Clause& c = ca[clauses[i]];
if (c.mark() == 0)
if (satisfied(c))
removeClause(clauses[i]);
else
clauses[j++] = clauses[i];
}
clauses.shrink(i - j);
}
// The technique and code are by the courtesy of the GlueMiniSat team. Thank you!
// It helps solving certain types of huge problems tremendously.
bool SimpSolver::eliminate(bool turn_off_elim)
{
bool res = true;
int iter = 0;
int n_cls, n_cls_init, n_vars;
if (nVars() == 0) goto cleanup; // User disabling preprocessing.
// Get an initial number of clauses (more accurately).
if (trail.size() != 0) removeSatisfied();
n_cls_init = nClauses();
res = eliminate_(); // The first, usual variable elimination of MiniSat.
if (!res) goto cleanup;
n_cls = nClauses();
n_vars = nFreeVars();
printf("c Reduced to %d vars, %d cls (grow=%d)\n", n_vars, n_cls, grow);
if ((double)n_cls / n_vars >= 5 || n_vars < 10000){
printf("c No iterative elimination performed. (vars=%d, c/v ratio=%.1f)\n", n_vars, (double)n_cls / n_vars);
goto cleanup; }
grow = grow ? grow * 2 : 8;
for (; grow < 10000; grow *= 2){
// Rebuild elimination variable heap.
for (int i = 0; i < clauses.size(); i++){
const Clause& c = ca[clauses[i]];
for (int j = 0; j < c.size(); j++)
if (!elim_heap.inHeap(var(c[j])))
elim_heap.insert(var(c[j]));
else
elim_heap.update(var(c[j])); }
int n_cls_last = nClauses();
int n_vars_last = nFreeVars();
res = eliminate_();
if (!res || n_vars_last == nFreeVars()) break;
iter++;
int n_cls_now = nClauses();
int n_vars_now = nFreeVars();
double cl_inc_rate = (double)n_cls_now / n_cls_last;
double var_dec_rate = (double)n_vars_last / n_vars_now;
printf("c Reduced to %d vars, %d cls (grow=%d)\n", n_vars_now, n_cls_now, grow);
printf("c cl_inc_rate=%.3f, var_dec_rate=%.3f\n", cl_inc_rate, var_dec_rate);
if (n_cls_now > n_cls_init || cl_inc_rate > var_dec_rate) break;
}
printf("c No. effective iterative eliminations: %d\n", iter);
cleanup:
touched .clear(true);
occurs .clear(true);
n_occ .clear(true);
elim_heap.clear(true);
subsumption_queue.clear(true);
use_simplification = false;
remove_satisfied = true;
ca.extra_clause_field = false;
// Force full cleanup (this is safe and desirable since it only happens once):
rebuildOrderHeap();
garbageCollect();
return res;
}
bool SimpSolver::eliminate_()
{
if (!simplify())
return false;
else if (!use_simplification)
return true;
int trail_size_last = trail.size();
// Main simplification loop:
//
while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){
gatherTouchedClauses();
// printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns);
if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) &&
!backwardSubsumptionCheck(true)){
ok = false; goto cleanup; }
// Empty elim_heap and return immediately on user-interrupt:
if (asynch_interrupt){
assert(bwdsub_assigns == trail.size());
assert(subsumption_queue.size() == 0);
assert(n_touched == 0);
elim_heap.clear();
goto cleanup; }
// printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size());
for (int cnt = 0; !elim_heap.empty(); cnt++){
Var elim = elim_heap.removeMin();
if (asynch_interrupt) break;
if (isEliminated(elim) || value(elim) != l_Undef) continue;
if (verbosity >= 2 && cnt % 100 == 0)
printf("c elimination left: %10d\r", elim_heap.size());
if (use_asymm){
// Temporarily freeze variable. Otherwise, it would immediately end up on the queue again:
bool was_frozen = frozen[elim];
frozen[elim] = true;
if (!asymmVar(elim)){
ok = false; goto cleanup; }
frozen[elim] = was_frozen; }
// At this point, the variable may have been set by assymetric branching, so check it
// again. Also, don't eliminate frozen variables:
if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){
ok = false; goto cleanup; }
checkGarbage(simp_garbage_frac);
}
assert(subsumption_queue.size() == 0);
}
cleanup:
// To get an accurate number of clauses.
if (trail_size_last != trail.size())
removeSatisfied();
else{
int i,j;
for (i = j = 0; i < clauses.size(); i++)
if (ca[clauses[i]].mark() == 0)
clauses[j++] = clauses[i];
clauses.shrink(i - j);
}
checkGarbage();
if (verbosity >= 1 && elimclauses.size() > 0)
printf("c | Eliminated clauses: %10.2f Mb |\n",
double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024));
return ok;
}
//=================================================================================================
// Garbage Collection methods:
void SimpSolver::relocAll(ClauseAllocator& to)
{
if (!use_simplification) return;
// All occurs lists:
//
occurs.cleanAll();
for (int i = 0; i < nVars(); i++){
vec<CRef>& cs = occurs[i];
for (int j = 0; j < cs.size(); j++)
ca.reloc(cs[j], to);
}
// Subsumption queue:
//
for (int i = 0; i < subsumption_queue.size(); i++)
ca.reloc(subsumption_queue[i], to);
// Temporary clause:
//
ca.reloc(bwdsub_tmpunit, to);
}
void SimpSolver::garbageCollect()
{
// Initialize the next region to a size corresponding to the estimated utilization degree. This
// is not precise but should avoid some unnecessary reallocations for the new region:
ClauseAllocator to(ca.size() - ca.wasted());
to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields.
relocAll(to);
Solver::relocAll(to);
if (verbosity >= 2)
printf("c | Garbage collection: %12d bytes => %12d bytes |\n",
ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size);
to.moveTo(ca);
}

View File

@ -1,201 +0,0 @@
/************************************************************************************[SimpSolver.h]
MiniSat -- Copyright (c) 2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Chanseok Oh's MiniSat Patch Series -- Copyright (c) 2015, Chanseok Oh
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_SimpSolver_h
#define Minisat_SimpSolver_h
#include "mtl/Queue.h"
#include "core/Solver.h"
namespace Minisat {
//=================================================================================================
class SimpSolver : public Solver {
public:
// Constructor/Destructor:
//
SimpSolver();
~SimpSolver();
// Problem specification:
//
Var newVar (bool polarity = true, bool dvar = true);
bool addClause (const vec<Lit>& ps);
bool addEmptyClause(); // Add the empty clause to the solver.
bool addClause (Lit p); // Add a unit clause to the solver.
bool addClause (Lit p, Lit q); // Add a binary clause to the solver.
bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver.
bool addClause_( vec<Lit>& ps);
bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction).
// Variable mode:
//
void setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated.
bool isEliminated(Var v) const;
// Solving:
//
bool solve (const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
lbool solveLimited(const vec<Lit>& assumps, bool do_simp = true, bool turn_off_simp = false);
bool solve ( bool do_simp = true, bool turn_off_simp = false);
bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false);
bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false);
bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false);
bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification.
bool eliminate_ ();
void removeSatisfied();
// Memory managment:
//
virtual void garbageCollect();
// Generate a (possibly simplified) DIMACS file:
//
#if 0
void toDimacs (const char* file, const vec<Lit>& assumps);
void toDimacs (const char* file);
void toDimacs (const char* file, Lit p);
void toDimacs (const char* file, Lit p, Lit q);
void toDimacs (const char* file, Lit p, Lit q, Lit r);
#endif
// Mode of operation:
//
bool parsing;
int grow; // Allow a variable elimination step to grow by a number of clauses (default to zero).
int clause_lim; // Variables are not eliminated if it produces a resolvent with a length above this limit.
// -1 means no limit.
int subsumption_lim; // Do not check if subsumption against a clause larger than this. -1 means no limit.
double simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac').
bool use_asymm; // Shrink clauses by asymmetric branching.
bool use_rcheck; // Check if a clause is already implied. Prett costly, and subsumes subsumptions :)
bool use_elim; // Perform variable elimination.
// Statistics:
//
int merges;
int asymm_lits;
int eliminated_vars;
protected:
// Helper structures:
//
struct ElimLt {
const vec<int>& n_occ;
explicit ElimLt(const vec<int>& no) : n_occ(no) {}
// TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating
// 32-bit implementation instead then, but this will have to do for now.
uint64_t cost (Var x) const { return (uint64_t)n_occ[toInt(mkLit(x))] * (uint64_t)n_occ[toInt(~mkLit(x))]; }
bool operator()(Var x, Var y) const { return cost(x) < cost(y); }
// TODO: investigate this order alternative more.
// bool operator()(Var x, Var y) const {
// int c_x = cost(x);
// int c_y = cost(y);
// return c_x < c_y || c_x == c_y && x < y; }
};
struct ClauseDeleted {
const ClauseAllocator& ca;
explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {}
bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } };
// Solver state:
//
int elimorder;
bool use_simplification;
vec<uint32_t> elimclauses;
vec<char> touched;
OccLists<Var, vec<CRef>, ClauseDeleted>
occurs;
vec<int> n_occ;
Heap<ElimLt> elim_heap;
Queue<CRef> subsumption_queue;
vec<char> frozen;
vec<char> eliminated;
int bwdsub_assigns;
int n_touched;
// Temporaries:
//
CRef bwdsub_tmpunit;
// Main internal methods:
//
lbool solve_ (bool do_simp = true, bool turn_off_simp = false);
bool asymm (Var v, CRef cr);
bool asymmVar (Var v);
void updateElimHeap (Var v);
void gatherTouchedClauses ();
bool merge (const Clause& _ps, const Clause& _qs, Var v, vec<Lit>& out_clause);
bool merge (const Clause& _ps, const Clause& _qs, Var v, int& size);
bool backwardSubsumptionCheck (bool verbose = false);
bool eliminateVar (Var v);
void extendModel ();
void removeClause (CRef cr);
bool strengthenClause (CRef cr, Lit l);
bool implied (const vec<Lit>& c);
void relocAll (ClauseAllocator& to);
};
//=================================================================================================
// Implementation of inline methods:
inline bool SimpSolver::isEliminated (Var v) const { return eliminated[v]; }
inline void SimpSolver::updateElimHeap(Var v) {
assert(use_simplification);
// if (!frozen[v] && !isEliminated(v) && value(v) == l_Undef)
if (elim_heap.inHeap(v) || (!frozen[v] && !isEliminated(v) && value(v) == l_Undef))
elim_heap.update(v); }
inline bool SimpSolver::addClause (const vec<Lit>& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); }
inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); }
inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); }
inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); }
inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); }
inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } }
inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; }
inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; }
inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; }
inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; }
inline bool SimpSolver::solve (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; }
inline lbool SimpSolver::solveLimited (const vec<Lit>& assumps, bool do_simp, bool turn_off_simp){
assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); }
//=================================================================================================
}
#endif

View File

@ -1,4 +0,0 @@
EXEC = system_test
DEPDIR = mtl
include $(MROOT)/mtl/template.mk

View File

@ -1,91 +0,0 @@
/**************************************************************************************[Options.cc]
Copyright (c) 2008-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#include "mtl/Sort.h"
#include "utils/Options.h"
#include "utils/ParseUtils.h"
using namespace Minisat;
void Minisat::parseOptions(int& argc, char** argv, bool strict)
{
int i, j;
for (i = j = 1; i < argc; i++){
const char* str = argv[i];
if (match(str, "--") && match(str, Option::getHelpPrefixString()) && match(str, "help")){
if (*str == '\0')
printUsageAndExit(argc, argv);
else if (match(str, "-verb"))
printUsageAndExit(argc, argv, true);
} else {
bool parsed_ok = false;
for (int k = 0; !parsed_ok && k < Option::getOptionList().size(); k++){
parsed_ok = Option::getOptionList()[k]->parse(argv[i]);
// fprintf(stderr, "checking %d: %s against flag <%s> (%s)\n", i, argv[i], Option::getOptionList()[k]->name, parsed_ok ? "ok" : "skip");
}
if (!parsed_ok)
if (strict && match(argv[i], "-"))
fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()), exit(1);
else
argv[j++] = argv[i];
}
}
argc -= (i - j);
}
void Minisat::setUsageHelp (const char* str){ Option::getUsageString() = str; }
void Minisat::setHelpPrefixStr (const char* str){ Option::getHelpPrefixString() = str; }
void Minisat::printUsageAndExit (int argc, char** argv, bool verbose)
{
const char* usage = Option::getUsageString();
if (usage != NULL)
fprintf(stderr, usage, argv[0]);
sort(Option::getOptionList(), Option::OptionLt());
const char* prev_cat = NULL;
const char* prev_type = NULL;
for (int i = 0; i < Option::getOptionList().size(); i++){
const char* cat = Option::getOptionList()[i]->category;
const char* type = Option::getOptionList()[i]->type_name;
if (cat != prev_cat)
fprintf(stderr, "\n%s OPTIONS:\n\n", cat);
else if (type != prev_type)
fprintf(stderr, "\n");
Option::getOptionList()[i]->help(verbose);
prev_cat = Option::getOptionList()[i]->category;
prev_type = Option::getOptionList()[i]->type_name;
}
fprintf(stderr, "\nHELP OPTIONS:\n\n");
fprintf(stderr, " --%shelp Print help message.\n", Option::getHelpPrefixString());
fprintf(stderr, " --%shelp-verb Print verbose help message.\n", Option::getHelpPrefixString());
fprintf(stderr, "\n");
exit(0);
}

View File

@ -1,386 +0,0 @@
/***************************************************************************************[Options.h]
Copyright (c) 2008-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_Options_h
#define Minisat_Options_h
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "mtl/IntTypes.h"
#include "mtl/Vec.h"
#include "utils/ParseUtils.h"
namespace Minisat {
//==================================================================================================
// Top-level option parse/help functions:
extern void parseOptions (int& argc, char** argv, bool strict = false);
extern void printUsageAndExit(int argc, char** argv, bool verbose = false);
extern void setUsageHelp (const char* str);
extern void setHelpPrefixStr (const char* str);
//==================================================================================================
// Options is an abstract class that gives the interface for all types options:
class Option
{
protected:
const char* name;
const char* description;
const char* category;
const char* type_name;
static vec<Option*>& getOptionList () { static vec<Option*> options; return options; }
static const char*& getUsageString() { static const char* usage_str; return usage_str; }
static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; }
struct OptionLt {
bool operator()(const Option* x, const Option* y) {
int test1 = strcmp(x->category, y->category);
return test1 < 0 || test1 == 0 && strcmp(x->type_name, y->type_name) < 0;
}
};
Option(const char* name_,
const char* desc_,
const char* cate_,
const char* type_) :
name (name_)
, description(desc_)
, category (cate_)
, type_name (type_)
{
getOptionList().push(this);
}
public:
virtual ~Option() {}
virtual bool parse (const char* str) = 0;
virtual void help (bool verbose = false) = 0;
friend void parseOptions (int& argc, char** argv, bool strict);
friend void printUsageAndExit (int argc, char** argv, bool verbose);
friend void setUsageHelp (const char* str);
friend void setHelpPrefixStr (const char* str);
};
//==================================================================================================
// Range classes with specialization for floating types:
struct IntRange {
int begin;
int end;
IntRange(int b, int e) : begin(b), end(e) {}
};
struct Int64Range {
int64_t begin;
int64_t end;
Int64Range(int64_t b, int64_t e) : begin(b), end(e) {}
};
struct DoubleRange {
double begin;
double end;
bool begin_inclusive;
bool end_inclusive;
DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {}
};
//==================================================================================================
// Double options:
class DoubleOption : public Option
{
protected:
DoubleRange range;
double value;
public:
DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false))
: Option(n, d, c, "<double>"), range(r), value(def) {
// FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly.
}
operator double (void) const { return value; }
operator double& (void) { return value; }
DoubleOption& operator=(double x) { value = x; return *this; }
virtual bool parse(const char* str){
const char* span = str;
if (!match(span, "-") || !match(span, name) || !match(span, "="))
return false;
char* end;
double tmp = strtod(span, &end);
if (end == NULL)
return false;
else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){
fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name);
exit(1);
}else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){
fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name);
exit(1); }
value = tmp;
// fprintf(stderr, "READ VALUE: %g\n", value);
return true;
}
virtual void help (bool verbose = false){
fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n",
name, type_name,
range.begin_inclusive ? '[' : '(',
range.begin,
range.end,
range.end_inclusive ? ']' : ')',
value);
if (verbose){
fprintf(stderr, "\n %s\n", description);
fprintf(stderr, "\n");
}
}
};
//==================================================================================================
// Int options:
class IntOption : public Option
{
protected:
IntRange range;
int32_t value;
public:
IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX))
: Option(n, d, c, "<int32>"), range(r), value(def) {}
operator int32_t (void) const { return value; }
operator int32_t& (void) { return value; }
IntOption& operator= (int32_t x) { value = x; return *this; }
virtual bool parse(const char* str){
const char* span = str;
if (!match(span, "-") || !match(span, name) || !match(span, "="))
return false;
char* end;
int32_t tmp = strtol(span, &end, 10);
if (end == NULL)
return false;
else if (tmp > range.end){
fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name);
exit(1);
}else if (tmp < range.begin){
fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name);
exit(1); }
value = tmp;
return true;
}
virtual void help (bool verbose = false){
fprintf(stderr, " -%-12s = %-8s [", name, type_name);
if (range.begin == INT32_MIN)
fprintf(stderr, "imin");
else
fprintf(stderr, "%4d", range.begin);
fprintf(stderr, " .. ");
if (range.end == INT32_MAX)
fprintf(stderr, "imax");
else
fprintf(stderr, "%4d", range.end);
fprintf(stderr, "] (default: %d)\n", value);
if (verbose){
fprintf(stderr, "\n %s\n", description);
fprintf(stderr, "\n");
}
}
};
// Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll.
#ifndef _MSC_VER
class Int64Option : public Option
{
protected:
Int64Range range;
int64_t value;
public:
Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX))
: Option(n, d, c, "<int64>"), range(r), value(def) {}
operator int64_t (void) const { return value; }
operator int64_t& (void) { return value; }
Int64Option& operator= (int64_t x) { value = x; return *this; }
virtual bool parse(const char* str){
const char* span = str;
if (!match(span, "-") || !match(span, name) || !match(span, "="))
return false;
char* end;
int64_t tmp = strtoll(span, &end, 10);
if (end == NULL)
return false;
else if (tmp > range.end){
fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name);
exit(1);
}else if (tmp < range.begin){
fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name);
exit(1); }
value = tmp;
return true;
}
virtual void help (bool verbose = false){
fprintf(stderr, " -%-12s = %-8s [", name, type_name);
if (range.begin == INT64_MIN)
fprintf(stderr, "imin");
// else
// fprintf(stderr, "%4"PRIi64, range.begin);
fprintf(stderr, " .. ");
if (range.end == INT64_MAX)
fprintf(stderr, "imax");
// else
// fprintf(stderr, "%4"PRIi64, range.end);
// fprintf(stderr, "] (default: %"PRIi64")\n", value);
if (verbose){
fprintf(stderr, "\n %s\n", description);
fprintf(stderr, "\n");
}
}
};
#endif
//==================================================================================================
// String option:
class StringOption : public Option
{
const char* value;
public:
StringOption(const char* c, const char* n, const char* d, const char* def = NULL)
: Option(n, d, c, "<string>"), value(def) {}
operator const char* (void) const { return value; }
operator const char*& (void) { return value; }
StringOption& operator= (const char* x) { value = x; return *this; }
virtual bool parse(const char* str){
const char* span = str;
if (!match(span, "-") || !match(span, name) || !match(span, "="))
return false;
value = span;
return true;
}
virtual void help (bool verbose = false){
fprintf(stderr, " -%-10s = %8s\n", name, type_name);
if (verbose){
fprintf(stderr, "\n %s\n", description);
fprintf(stderr, "\n");
}
}
};
//==================================================================================================
// Bool option:
class BoolOption : public Option
{
bool value;
public:
BoolOption(const char* c, const char* n, const char* d, bool v)
: Option(n, d, c, "<bool>"), value(v) {}
operator bool (void) const { return value; }
operator bool& (void) { return value; }
BoolOption& operator=(bool b) { value = b; return *this; }
virtual bool parse(const char* str){
const char* span = str;
if (match(span, "-")){
bool b = !match(span, "no-");
if (strcmp(span, name) == 0){
value = b;
return true; }
}
return false;
}
virtual void help (bool verbose = false){
fprintf(stderr, " -%s, -no-%s", name, name);
for (uint32_t i = 0; i < 32 - strlen(name)*2; i++)
fprintf(stderr, " ");
fprintf(stderr, " ");
fprintf(stderr, "(default: %s)\n", value ? "on" : "off");
if (verbose){
fprintf(stderr, "\n %s\n", description);
fprintf(stderr, "\n");
}
}
};
//=================================================================================================
}
#endif

View File

@ -1,122 +0,0 @@
/************************************************************************************[ParseUtils.h]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_ParseUtils_h
#define Minisat_ParseUtils_h
#include <stdlib.h>
#include <stdio.h>
#include <zlib.h>
namespace Minisat {
//-------------------------------------------------------------------------------------------------
// A simple buffered character stream class:
static const int buffer_size = 1048576;
class StreamBuffer {
gzFile in;
unsigned char buf[buffer_size];
int pos;
int size;
void assureLookahead() {
if (pos >= size) {
pos = 0;
size = gzread(in, buf, sizeof(buf)); } }
public:
explicit StreamBuffer(gzFile i) : in(i), pos(0), size(0) { assureLookahead(); }
int operator * () const { return (pos >= size) ? EOF : buf[pos]; }
void operator ++ () { pos++; assureLookahead(); }
int position () const { return pos; }
};
//-------------------------------------------------------------------------------------------------
// End-of-file detection functions for StreamBuffer and char*:
static inline bool isEof(StreamBuffer& in) { return *in == EOF; }
static inline bool isEof(const char* in) { return *in == '\0'; }
//-------------------------------------------------------------------------------------------------
// Generic parse functions parametrized over the input-stream type.
template<class B>
static void skipWhitespace(B& in) {
while ((*in >= 9 && *in <= 13) || *in == 32)
++in; }
template<class B>
static void skipLine(B& in) {
for (;;){
if (isEof(in)) return;
if (*in == '\n') { ++in; return; }
++in; } }
template<class B>
static int parseInt(B& in) {
int val = 0;
bool neg = false;
skipWhitespace(in);
if (*in == '-') neg = true, ++in;
else if (*in == '+') ++in;
if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(3);
while (*in >= '0' && *in <= '9')
val = val*10 + (*in - '0'),
++in;
return neg ? -val : val; }
// String matching: in case of a match the input iterator will be advanced the corresponding
// number of characters.
template<class B>
static bool match(B& in, const char* str) {
int i;
for (i = 0; str[i] != '\0'; i++)
if (in[i] != str[i])
return false;
in += i;
return true;
}
// String matching: consumes characters eagerly, but does not require random access iterator.
template<class B>
static bool eagerMatch(B& in, const char* str) {
for (; *str != '\0'; ++str, ++in)
if (*str != *in)
return false;
return true; }
//=================================================================================================
}
#endif

View File

@ -1,92 +0,0 @@
/***************************************************************************************[System.cc]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#include "utils/System.h"
#if defined(__linux__)
#include <stdio.h>
#include <stdlib.h>
using namespace Minisat;
// TODO: split the memory reading functions into two: one for reading high-watermark of RSS, and
// one for reading the current virtual memory size.
static inline int memReadStat(int field)
{
char name[256];
pid_t pid = getpid();
int value;
sprintf(name, "/proc/%d/statm", pid);
FILE* in = fopen(name, "rb");
if (in == NULL) return 0;
for (; field >= 0; field--)
if (fscanf(in, "%d", &value) != 1)
printf("ERROR! Failed to parse memory statistics from \"/proc\".\n"), exit(1);
fclose(in);
return value;
}
static inline int memReadPeak(void)
{
char name[256];
pid_t pid = getpid();
sprintf(name, "/proc/%d/status", pid);
FILE* in = fopen(name, "rb");
if (in == NULL) return 0;
// Find the correct line, beginning with "VmPeak:":
int peak_kb = 0;
while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1)
while (!feof(in) && fgetc(in) != '\n')
;
fclose(in);
return peak_kb;
}
double Minisat::memUsed() { return (double)memReadStat(0) * (double)getpagesize() / (1024*1024); }
#elif defined(__FreeBSD__)
double Minisat::memUsed(void) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
return (double)ru.ru_maxrss / 1024; }
double MiniSat::memUsedPeak(void) { return memUsed(); }
#elif defined(__APPLE__)
#include <malloc/malloc.h>
double Minisat::memUsed(void) {
malloc_statistics_t t;
malloc_zone_statistics(NULL, &t);
return (double)t.max_size_in_use / (1024*1024); }
#else
double Minisat::memUsed() {
return 0; }
#endif

View File

@ -1,60 +0,0 @@
/****************************************************************************************[System.h]
Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
Copyright (c) 2007-2010, Niklas Sorensson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or
substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************************************/
#ifndef Minisat_System_h
#define Minisat_System_h
#if defined(__linux__)
#include <fpu_control.h>
#endif
#include "mtl/IntTypes.h"
//-------------------------------------------------------------------------------------------------
namespace Minisat {
static inline double cpuTime(void); // CPU-time in seconds.
extern double memUsed(); // Memory in mega bytes (returns 0 for unsupported architectures).
//extern double memUsedPeak(); // Peak-memory in mega bytes (returns 0 for unsupported architectures).
}
//-------------------------------------------------------------------------------------------------
// Implementation of inline functions:
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <time.h>
static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; }
#else
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
static inline double Minisat::cpuTime(void) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; }
#endif
#endif

View File

@ -1,5 +0,0 @@
repo: 6ed5fe0ea387ba9808e21048f02c665b16aa8c23
node: bdabbf66b2ad131199059736178664f44c69adaf
branch: 1.3
latesttag: r1.3
latesttagdistance: 11

View File

@ -1,53 +0,0 @@
syntax: glob
*.obj
*.orig
*.rej
*~
*.o
*.log
*.lo
*.tar.*
*.bak
Makefile.in
aclocal.m4
config.h.in
configure
Makefile
config.h
config.log
config.status
libtool
stamp-h1
lemon/lemon.pc
lemon/libemon.la
lemon/stamp-h2
doc/Doxyfile
doc/references.dox
cmake/version.cmake
.dirstamp
.libs/*
.deps/*
demo/*.eps
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
syntax: regexp
(.*/)?\#[^/]*\#$
(.*/)?\.\#[^/]*$
^doc/html/.*
^doc/.*\.tag
^autom4te.cache/.*
^build-aux/.*
^.*objs.*/.*
^test/[a-z_]*$
^tools/[a-z-_]*$
^demo/.*_demo$
^.*build.*/.*
^doc/gen-images/.*
CMakeFiles
DartTestfile.txt
cmake_install.cmake
CMakeCache.txt

View File

@ -1 +0,0 @@
57ab090b6109902536ee34b1e8d4d123474311e3 r1.3

View File

@ -1,26 +0,0 @@
The main developers of release series 1.x are
* Balazs Dezso <deba@inf.elte.hu>
* Alpar Juttner <alpar@cs.elte.hu>
* Peter Kovacs <kpeter@inf.elte.hu>
* Akos Ladanyi <ladanyi@tmit.bme.hu>
For more complete list of contributors, please visit the history of
the LEMON source code repository: http://lemon.cs.elte.hu/hg/lemon
Moreover, this version is heavily based on version 0.x of LEMON. Here
is the list of people who contributed to those versions.
* Mihaly Barasz <klao@cs.elte.hu>
* Johanna Becker <beckerjc@cs.elte.hu>
* Attila Bernath <athos@cs.elte.hu>
* Balazs Dezso <deba@inf.elte.hu>
* Peter Hegyi <hegyi@tmit.bme.hu>
* Alpar Juttner <alpar@cs.elte.hu>
* Peter Kovacs <kpeter@inf.elte.hu>
* Akos Ladanyi <ladanyi@tmit.bme.hu>
* Marton Makai <marci@cs.elte.hu>
* Jacint Szabo <jacint@cs.elte.hu>
Again, please visit the history of the old LEMON repository for more
details: http://lemon.cs.elte.hu/hg/lemon-0.x

View File

@ -1,373 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
SET(PROJECT_NAME "LEMON")
PROJECT(${PROJECT_NAME})
INCLUDE(FindPythonInterp)
INCLUDE(FindWget)
IF(EXISTS ${PROJECT_SOURCE_DIR}/cmake/version.cmake)
INCLUDE(${PROJECT_SOURCE_DIR}/cmake/version.cmake)
ELSEIF(DEFINED ENV{LEMON_VERSION})
SET(LEMON_VERSION $ENV{LEMON_VERSION} CACHE STRING "LEMON version string.")
ELSE()
EXECUTE_PROCESS(
COMMAND
hg log -r. --template "{latesttag}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HG_REVISION_TAG
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(
COMMAND
hg log -r. --template "{latesttagdistance}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HG_REVISION_DIST
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(
COMMAND
hg log -r. --template "{node|short}"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE HG_REVISION_ID
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
IF(HG_REVISION_TAG STREQUAL "")
SET(HG_REVISION_ID "hg-tip")
ELSE()
IF(HG_REVISION_TAG STREQUAL "null")
SET(HG_REVISION_TAG "trunk")
ELSEIF(HG_REVISION_TAG MATCHES "^r")
STRING(SUBSTRING ${HG_REVISION_TAG} 1 -1 HG_REVISION_TAG)
ENDIF()
IF(HG_REVISION_DIST STREQUAL "0")
SET(HG_REVISION ${HG_REVISION_TAG})
ELSE()
SET(HG_REVISION
"${HG_REVISION_TAG}+${HG_REVISION_DIST}-${HG_REVISION_ID}")
ENDIF()
ENDIF()
SET(LEMON_VERSION ${HG_REVISION} CACHE STRING "LEMON version string.")
ENDIF()
SET(PROJECT_VERSION ${LEMON_VERSION})
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
FIND_PACKAGE(Doxygen)
FIND_PACKAGE(Ghostscript)
SET(LEMON_ENABLE_GLPK YES CACHE STRING "Enable GLPK solver backend.")
SET(LEMON_ENABLE_ILOG YES CACHE STRING "Enable ILOG (CPLEX) solver backend.")
SET(LEMON_ENABLE_COIN YES CACHE STRING "Enable COIN solver backend.")
SET(LEMON_ENABLE_SOPLEX YES CACHE STRING "Enable SoPlex solver backend.")
IF(LEMON_ENABLE_GLPK)
FIND_PACKAGE(GLPK 4.33)
ENDIF(LEMON_ENABLE_GLPK)
IF(LEMON_ENABLE_ILOG)
FIND_PACKAGE(ILOG)
ENDIF(LEMON_ENABLE_ILOG)
IF(LEMON_ENABLE_COIN)
FIND_PACKAGE(COIN)
ENDIF(LEMON_ENABLE_COIN)
IF(LEMON_ENABLE_SOPLEX)
FIND_PACKAGE(SOPLEX)
ENDIF(LEMON_ENABLE_SOPLEX)
IF(GLPK_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_MIP TRUE)
SET(LEMON_HAVE_GLPK TRUE)
ENDIF(GLPK_FOUND)
IF(ILOG_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_MIP TRUE)
SET(LEMON_HAVE_CPLEX TRUE)
ENDIF(ILOG_FOUND)
IF(COIN_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_MIP TRUE)
SET(LEMON_HAVE_CLP TRUE)
SET(LEMON_HAVE_CBC TRUE)
ENDIF(COIN_FOUND)
IF(SOPLEX_FOUND)
SET(LEMON_HAVE_LP TRUE)
SET(LEMON_HAVE_SOPLEX TRUE)
ENDIF(SOPLEX_FOUND)
IF(ILOG_FOUND)
SET(DEFAULT_LP "CPLEX")
SET(DEFAULT_MIP "CPLEX")
ELSEIF(COIN_FOUND)
SET(DEFAULT_LP "CLP")
SET(DEFAULT_MIP "CBC")
ELSEIF(GLPK_FOUND)
SET(DEFAULT_LP "GLPK")
SET(DEFAULT_MIP "GLPK")
ELSEIF(SOPLEX_FOUND)
SET(DEFAULT_LP "SOPLEX")
ENDIF()
IF(NOT LEMON_DEFAULT_LP OR
(NOT ILOG_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CPLEX")) OR
(NOT COIN_FOUND AND (LEMON_DEFAULT_LP STREQUAL "CLP")) OR
(NOT GLPK_FOUND AND (LEMON_DEFAULT_LP STREQUAL "GLPK")) OR
(NOT SOPLEX_FOUND AND (LEMON_DEFAULT_LP STREQUAL "SOPLEX")))
SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
"Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)" FORCE)
ELSE()
SET(LEMON_DEFAULT_LP ${DEFAULT_LP} CACHE STRING
"Default LP solver backend (GLPK, CPLEX, CLP or SOPLEX)")
ENDIF()
IF(NOT LEMON_DEFAULT_MIP OR
(NOT ILOG_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CPLEX")) OR
(NOT COIN_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "CBC")) OR
(NOT GLPK_FOUND AND (LEMON_DEFAULT_MIP STREQUAL "GLPK")))
SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
"Default MIP solver backend (GLPK, CPLEX or CBC)" FORCE)
ELSE()
SET(LEMON_DEFAULT_MIP ${DEFAULT_MIP} CACHE STRING
"Default MIP solver backend (GLPK, CPLEX or CBC)")
ENDIF()
IF(DEFINED ENV{LEMON_CXX_WARNING})
SET(CXX_WARNING $ENV{LEMON_CXX_WARNING})
ELSE()
IF(CMAKE_COMPILER_IS_GNUCXX)
SET(CXX_WARNING "-Wall -W -Wunused -Wformat=2 -Wctor-dtor-privacy -Wnon-virtual-dtor -Wno-char-subscripts -Wwrite-strings -Wno-char-subscripts -Wreturn-type -Wcast-qual -Wcast-align -Wsign-promo -Woverloaded-virtual -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas")
SET(CMAKE_CXX_FLAGS_DEBUG CACHE STRING "-ggdb")
SET(CMAKE_C_FLAGS_DEBUG CACHE STRING "-ggdb")
ELSEIF(MSVC)
# This part is unnecessary 'casue the same is set by the lemon/core.h.
# Still keep it as an example.
SET(CXX_WARNING "/wd4250 /wd4355 /wd4503 /wd4800 /wd4996")
# Suppressed warnings:
# C4250: 'class1' : inherits 'class2::member' via dominance
# C4355: 'this' : used in base member initializer list
# C4503: 'function' : decorated name length exceeded, name was truncated
# C4800: 'type' : forcing value to bool 'true' or 'false'
# (performance warning)
# C4996: 'function': was declared deprecated
ELSE()
SET(CXX_WARNING "-Wall")
ENDIF()
ENDIF()
SET(LEMON_CXX_WARNING_FLAGS ${CXX_WARNING} CACHE STRING "LEMON warning flags.")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LEMON_CXX_WARNING_FLAGS}")
IF(MSVC)
SET( CMAKE_CXX_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
"Flags used by the C++ compiler during maintainer builds."
)
SET( CMAKE_C_FLAGS_MAINTAINER "/WX ${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING
"Flags used by the C compiler during maintainer builds."
)
SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
"${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used for linking binaries during maintainer builds."
)
SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used by the shared libraries linker during maintainer builds."
)
ELSE()
SET( CMAKE_CXX_FLAGS_MAINTAINER "-Werror -ggdb -O0" CACHE STRING
"Flags used by the C++ compiler during maintainer builds."
)
SET( CMAKE_C_FLAGS_MAINTAINER "-Werror -O0" CACHE STRING
"Flags used by the C compiler during maintainer builds."
)
SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
"${CMAKE_EXE_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used for linking binaries during maintainer builds."
)
SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG}" CACHE STRING
"Flags used by the shared libraries linker during maintainer builds."
)
ENDIF()
MARK_AS_ADVANCED(
CMAKE_CXX_FLAGS_MAINTAINER
CMAKE_C_FLAGS_MAINTAINER
CMAKE_EXE_LINKER_FLAGS_MAINTAINER
CMAKE_SHARED_LINKER_FLAGS_MAINTAINER )
IF(CMAKE_CONFIGURATION_TYPES)
LIST(APPEND CMAKE_CONFIGURATION_TYPES Maintainer)
LIST(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
"Add the configurations that we need"
FORCE)
endif()
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
ENDIF()
SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel Maintainer."
FORCE )
INCLUDE(CheckTypeSize)
CHECK_TYPE_SIZE("long long" LONG_LONG)
SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
INCLUDE(FindThreads)
IF(NOT LEMON_THREADING)
IF(CMAKE_USE_PTHREADS_INIT)
SET(LEMON_THREADING "Pthread")
ELSEIF(CMAKE_USE_WIN32_THREADS_INIT)
SET(LEMON_THREADING "Win32")
ELSE()
SET(LEMON_THREADING "None")
ENDIF()
ENDIF()
SET( LEMON_THREADING "${LEMON_THREADING}" CACHE STRING
"Choose the threading library, options are: Pthread Win32 None."
FORCE )
IF(LEMON_THREADING STREQUAL "Pthread")
SET(LEMON_USE_PTHREAD TRUE)
ELSEIF(LEMON_THREADING STREQUAL "Win32")
SET(LEMON_USE_WIN32_THREADS TRUE)
ENDIF()
ENABLE_TESTING()
IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND})
ELSE()
ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND})
ENDIF()
ADD_SUBDIRECTORY(lemon)
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
ADD_SUBDIRECTORY(contrib)
ADD_SUBDIRECTORY(demo)
ADD_SUBDIRECTORY(tools)
ADD_SUBDIRECTORY(doc)
ADD_SUBDIRECTORY(test)
ENDIF()
CONFIGURE_FILE(
${PROJECT_SOURCE_DIR}/cmake/LEMONConfig.cmake.in
${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
@ONLY
)
IF(UNIX)
INSTALL(
FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
DESTINATION share/lemon/cmake
)
ELSEIF(WIN32)
INSTALL(
FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
DESTINATION cmake
)
ENDIF()
CONFIGURE_FILE(
${PROJECT_SOURCE_DIR}/cmake/version.cmake.in
${PROJECT_BINARY_DIR}/cmake/version.cmake
@ONLY
)
SET(ARCHIVE_BASE_NAME ${CMAKE_PROJECT_NAME})
STRING(TOLOWER ${ARCHIVE_BASE_NAME} ARCHIVE_BASE_NAME)
SET(ARCHIVE_NAME ${ARCHIVE_BASE_NAME}-${PROJECT_VERSION})
ADD_CUSTOM_TARGET(dist
COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
COMMAND hg archive ${ARCHIVE_NAME}
COMMAND cmake -E copy cmake/version.cmake ${ARCHIVE_NAME}/cmake/version.cmake
COMMAND tar -czf ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_NAME}
COMMAND zip -r ${ARCHIVE_BASE_NAME}-nodoc-${PROJECT_VERSION}.zip ${ARCHIVE_NAME}
COMMAND cmake -E copy_directory doc/html ${ARCHIVE_NAME}/doc/html
COMMAND tar -czf ${ARCHIVE_NAME}.tar.gz ${ARCHIVE_NAME}
COMMAND zip -r ${ARCHIVE_NAME}.zip ${ARCHIVE_NAME}
COMMAND cmake -E copy_directory doc/html ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
COMMAND tar -czf ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.tar.gz ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
COMMAND zip -r ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}.zip ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
COMMAND cmake -E remove_directory ${ARCHIVE_NAME}
COMMAND cmake -E remove_directory ${ARCHIVE_BASE_NAME}-doc-${PROJECT_VERSION}
DEPENDS html
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
# CPACK config (Basically for NSIS)
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
SET(CPACK_PACKAGE_NAME ${PROJECT_NAME})
SET(CPACK_PACKAGE_VENDOR "EGRES")
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"LEMON - Library for Efficient Modeling and Optimization in Networks")
SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
SET(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
SET(CPACK_PACKAGE_INSTALL_DIRECTORY
"${PROJECT_NAME} ${PROJECT_VERSION}")
SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY
"${PROJECT_NAME} ${PROJECT_VERSION}")
SET(CPACK_COMPONENTS_ALL headers library html_documentation bin)
SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ headers")
SET(CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "Dynamic-link library")
SET(CPACK_COMPONENT_BIN_DISPLAY_NAME "Command line utilities")
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DISPLAY_NAME "HTML documentation")
SET(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C++ header files")
SET(CPACK_COMPONENT_LIBRARY_DESCRIPTION
"DLL and import library")
SET(CPACK_COMPONENT_BIN_DESCRIPTION
"Command line utilities")
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DESCRIPTION
"Doxygen generated documentation")
SET(CPACK_COMPONENT_HEADERS_DEPENDS library)
SET(CPACK_COMPONENT_HEADERS_GROUP "Development")
SET(CPACK_COMPONENT_LIBRARY_GROUP "Development")
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_GROUP "Documentation")
SET(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
"Components needed to develop software using LEMON")
SET(CPACK_COMPONENT_GROUP_DOCUMENTATION_DESCRIPTION
"Documentation of LEMON")
SET(CPACK_ALL_INSTALL_TYPES Full Developer)
SET(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
SET(CPACK_COMPONENT_LIBRARY_INSTALL_TYPES Developer Full)
SET(CPACK_COMPONENT_HTML_DOCUMENTATION_INSTALL_TYPES Full)
SET(CPACK_GENERATOR "NSIS")
SET(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis/lemon.ico")
SET(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}/cmake/nsis/uninstall.ico")
#SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis\\\\installer.bmp")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\lemon.ico")
SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}")
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\lemon.cs.elte.hu")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\lemon.cs.elte.hu")
SET(CPACK_NSIS_CONTACT "lemon-user@lemon.cs.elte.hu")
SET(CPACK_NSIS_CREATE_ICONS_EXTRA "
CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documentation.lnk\\\" \\\"$INSTDIR\\\\share\\\\doc\\\\index.html\\\"
")
SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
!insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Documentation.lnk\\\"
")
INCLUDE(CPack)
ENDIF()

View File

@ -1,167 +0,0 @@
Installation Instructions
=========================
This file contains instructions for building and installing LEMON from
source on Linux. The process on Windows is similar.
Note that it is not necessary to install LEMON in order to use
it. Instead, you can easily integrate it with your own code
directly. For instructions, see
https://lemon.cs.elte.hu/trac/lemon/wiki/HowToCompile
In order to install LEMON from the extracted source tarball you have to
issue the following commands:
1. Step into the root of the source directory.
$ cd lemon-x.y.z
2. Create a build subdirectory and step into it.
$ mkdir build
$ cd build
3. Perform system checks and create the makefiles.
$ cmake ..
4. Build LEMON.
$ make
This command compiles the non-template part of LEMON into
libemon.a file. It also compiles the programs in the 'tools' and
'demo' subdirectories.
5. [Optional] Compile and run the self-tests.
$ make check
5. [Optional] Generate the user documentation.
$ make html
The release tarballs already include the documentation.
Note that for this step you need to have the following tools
installed: Python, Doxygen, Graphviz, Ghostscript, LaTeX.
6. [Optional] Install LEMON
$ make install
This command installs LEMON under /usr/local (you will need root
privileges to be able to do that). If you want to install it to
some other location, then pass the
-DCMAKE_INSTALL_PREFIX=DIRECTORY flag to cmake in Step 3.
For example:
$ cmake -DCMAKE_INSTALL_PREFIX=/home/username/lemon'
Configure Options and Variables
===============================
In Step 3, you can customize the build process by passing options to CMAKE.
$ cmake [OPTIONS] ..
You find a list of the most useful options below.
-DCMAKE_INSTALL_PREFIX=PREFIX
Set the installation prefix to PREFIX. By default it is /usr/local.
-DCMAKE_BUILD_TYPE=[Release|Debug|Maintainer|...]
This sets the compiler options. The choices are the following
'Release': A strong optimization is turned on (-O3 with gcc). This
is the default setting and we strongly recommend using this for
the final compilation.
'Debug': Optimization is turned off and debug info is added (-O0
-ggdb with gcc). If is recommended during the development.
'Maintainer': The same as 'Debug' but the compiler warnings are
converted to errors (-Werror with gcc). In addition, 'make' will
also automatically compile and execute the test codes. It is the
best way of ensuring that LEMON codebase is clean and safe.
'RelWithDebInfo': Optimized build with debug info.
'MinSizeRel': Size optimized build (-Os with gcc)
-DTEST_WITH_VALGRIND=YES
Using this, the test codes will be executed using valgrind. It is a
very effective way of identifying indexing problems and memory leaks.
-DCMAKE_CXX_COMPILER=path-to-compiler
Change the compiler to be used.
-DBUILD_SHARED_LIBS=TRUE
Build shared library instead of static one. Think twice if you
really want to use this option.
-DLEMON_DOC_SOURCE_BROWSER=YES
Include the browsable cross referenced LEMON source code into the
doc. It makes the doc quite bloated, but may be useful for
developing LEMON itself.
-DLEMON_DOC_USE_MATHJAX=YES
Use MathJax (http://mathjax.org) for rendering the math formulae in
the doc. It of much higher quality compared to the default LaTeX
generated static images and it allows copy&paste of the formulae to
LaTeX, Open Office, MS Word etc. documents.
On the other hand, it needs either Internet access or a locally
installed version of MathJax to properly render the doc.
-DLEMON_DOC_MATHJAX_RELPATH=DIRECTORY
The location of the MathJax library. It defaults to
http://www.mathjax.org/mathjax, which necessitates Internet access
for proper rendering. The easiest way to make it usable offline is
to set this parameter to 'mathjax' and copy all files of the MathJax
library into the 'doc/html/mathjax' subdirectory of the build
location.
See http://docs.mathjax.org/en/latest/installation.html for more details.
-DLEMON_ENABLE_GLPK=NO
-DLEMON_ENABLE_COIN=NO
-DLEMON_ENABLE_ILOG=NO
Enable optional third party libraries. They are all enabled by default.
-DLEMON_DEFAULT_LP=GLPK
Sets the default LP solver backend. The supported values are
CPLEX, CLP and GLPK. By default, it is set to the first one which
is enabled and succesfully discovered.
-DLEMON_DEFAULT_MIP=GLPK
Sets the default MIP solver backend. The supported values are
CPLEX, CBC and GLPK. By default, it is set to the first one which
is enabled and succesfully discovered.
-DGLPK_ROOT_DIR=DIRECTORY
-DCOIN_ROOT_DIR=DIRECTORY
-DILOG_ROOT_DIR=DIRECTORY
Root directory prefixes of optional third party libraries.
Makefile Variables
==================
make VERBOSE=1
This results in a more verbose output by showing the full
compiler and linker commands.

View File

@ -1,32 +0,0 @@
LEMON code without an explicit copyright notice is covered by the following
copyright/license.
Copyright (C) 2003-2012 Egervary Jeno Kombinatorikus Optimalizalasi
Kutatocsoport (Egervary Combinatorial Optimization Research Group,
EGRES).
===========================================================================
Boost Software License, Version 1.0
===========================================================================
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -1,337 +0,0 @@
2014-07-07 Version 1.3.1 released
Bugfix release.
#484: Require CMAKE 2.8
#471, #472, #480: Various clang compatibility fixes
#481, #482: Fix shared lib build and versioning
#476: Fix invalid map query in NearestNeighborTsp
#478: Bugfix in debug checking and lower bound handling
in min cost flow algorithms
#479, #465: Bugfix in default LP/MIP backend settings
#476: Bugfix in tsp_test
#487: Add missing include header and std:: namespace spec.
#474: Fix division by zero error in NetworkSimplex
2013-08-10 Version 1.3 released
This is major feature release
* New data structures
#69 : Bipartite graph concepts and implementations
* New algorithms
#177: Port Edmonds-Karp algorithm
#380, #405: Heuristic algorithm for the max clique problem
#386: Heuristic algorithms for symmetric TSP
----: Nagamochi-Ibaraki algorithm [5087694945e4]
#397, #56: Max. cardinality search
* Other new features
#223: Thread safe graph and graph map implementations
#442: Different TimeStamp print formats
#457: File export functionality to LpBase
#362: Bidirectional iterator support for radixSort()
* Implementation improvements
----: Network Simplex
#391: Better update process, pivot rule and arc mixing
#435: Improved Altering List pivot rule
#417: Various fine tunings in CostScaling
#438: Optional iteration limit in HowardMmc
#436: Ensure strongly polynomial running time for CycleCanceling
while keeping the same performance
----: Make the CBC interface be compatible with latest CBC releases
[ee581a0ecfbf]
* CMAKE has become the default build environment (#434)
----: Autotool support has been dropped
----: Improved LP/MIP configuration
#465: Enable/disable options for LP/MIP backends
#446: Better CPLEX discovery
#460: Add cmake config to find SoPlex
----: Allow CPACK configuration on all platforms
#390: Add 'Maintainer' CMAKE build type
#388: Add 'check' target.
#401: Add contrib dir
#389: Better version string setting in CMAKE
#433: Support shared library build
#416: Support testing with valgrind
* Doc improvements
#395: SOURCE_BROWSER Doxygen switch is configurable from CMAKE
update-external-tags CMAKE target
#455: Optionally use MathJax for rendering the math formulae
#402, #437, #459, #456, #463: Various doc improvements
* Bugfixes (compared to release 1.2):
#432: Add missing doc/template.h and doc/references.bib to release
tarball
----: Intel C++ compatibility fixes
#441: Fix buggy reinitialization in _solver_bits::VarIndex::clear()
#444: Bugfix in path copy constructors and assignment operators
#447: Bugfix in AllArcLookUp<>
#448: Bugfix in adaptor_test.cc
#449: Fix clang compilation warnings and errors
#440: Fix a bug + remove redundant typedefs in dimacs-solver
#453: Avoid GCC 4.7 compiler warnings
#445: Fix missing initialization in CplexEnv::CplexEnv()
#428: Add missing lemon/lemon.pc.cmake to the release tarball
#393: Create and install lemon.pc
#429: Fix VS warnings
#430: Fix LpBase::Constr two-side limit bug
#392: Bug fix in Dfs::start(s,t)
#414: Fix wrong initialization in Preflow
#418: Better Win CodeBlock/MinGW support
#419: Build environment improvements
- Build of mip_test and lp_test precede the running of the tests
- Also search for coin libs under ${COIN_ROOT_DIR}/lib/coin
- Do not look for COIN_VOL libraries
#382: Allow lgf file without Arc maps
#417: Bug fix in CostScaling
#366: Fix Pred[Matrix]MapPath::empty()
#371: Bug fix in (di)graphCopy()
The target graph is cleared before adding nodes and arcs/edges.
#364: Add missing UndirectedTags
#368: Fix the usage of std::numeric_limits<>::min() in Network Simplex
#372: Fix a critical bug in preflow
#461: Bugfix in assert.h
#470: Fix compilation issues related to various gcc versions
#446: Fix #define indicating CPLEX availability
#294: Add explicit namespace to
ignore_unused_variable_warning() usages
#420: Bugfix in IterableValueMap
#439: Bugfix in biNodeConnected()
2010-03-19 Version 1.2 released
This is major feature release
* New algorithms
* Bellman-Ford algorithm (#51)
* Minimum mean cycle algorithms (#179)
* Karp, Hartman-Orlin and Howard algorithms
* New minimum cost flow algorithms (#180)
* Cost Scaling algorithms
* Capacity Scaling algorithm
* Cycle-Canceling algorithms
* Planarity related algorithms (#62)
* Planarity checking algorithm
* Planar embedding algorithm
* Schnyder's planar drawing algorithm
* Coloring planar graphs with five or six colors
* Fractional matching algorithms (#314)
* New data structures
* StaticDigraph structure (#68)
* Several new priority queue structures (#50, #301)
* Fibonacci, Radix, Bucket, Pairing, Binomial
D-ary and fourary heaps (#301)
* Iterable map structures (#73)
* Other new tools and functionality
* Map utility functions (#320)
* Reserve functions are added to ListGraph and SmartGraph (#311)
* A resize() function is added to HypercubeGraph (#311)
* A count() function is added to CrossRefMap (#302)
* Support for multiple targets in Suurballe using fullInit() (#181)
* Traits class and named parameters for Suurballe (#323)
* Separate reset() and resetParams() functions in NetworkSimplex
to handle graph changes (#327)
* tolerance() functions are added to HaoOrlin (#306)
* Implementation improvements
* Improvements in weighted matching algorithms (#314)
* Jumpstart initialization
* ArcIt iteration is based on out-arc lists instead of in-arc lists
in ListDigraph (#311)
* Faster add row operation in CbcMip (#203)
* Better implementation for split() in ListDigraph (#311)
* ArgParser can also throw exception instead of exit(1) (#332)
* Miscellaneous
* A simple interactive bootstrap script
* Doc improvements (#62,#180,#299,#302,#303,#304,#307,#311,#331,#315,
#316,#319)
* BibTeX references in the doc (#184)
* Optionally use valgrind when running tests
* Also check ReferenceMapTag in concept checks (#312)
* dimacs-solver uses long long type by default.
* Several bugfixes (compared to release 1.1):
#295: Suppress MSVC warnings using pragmas
----: Various CMAKE related improvements
* Remove duplications from doc/CMakeLists.txt
* Rename documentation install folder from 'docs' to 'html'
* Add tools/CMakeLists.txt to the tarball
* Generate and install LEMONConfig.cmake
* Change the label of the html project in Visual Studio
* Fix the check for the 'long long' type
* Put the version string into config.h
* Minor CMake improvements
* Set the version to 'hg-tip' if everything fails
#311: Add missing 'explicit' keywords
#302: Fix the implementation and doc of CrossRefMap
#308: Remove duplicate list_graph.h entry from source list
#307: Bugfix in Preflow and Circulation
#305: Bugfix and extension in the rename script
#312: Also check ReferenceMapTag in concept checks
#250: Bugfix in pathSource() and pathTarget()
#321: Use pathCopy(from,to) instead of copyPath(to,from)
#322: Distribure LEMONConfig.cmake.in
#330: Bug fix in map_extender.h
#336: Fix the date field comment of graphToEps() output
#323: Bug fix in Suurballe
#335: Fix clear() function in ExtendFindEnum
#337: Use void* as the LPX object pointer
#317: Fix (and improve) error message in mip_test.cc
Remove unnecessary OsiCbc dependency
#356: Allow multiple executions of weighted matching algorithms (#356)
2009-05-13 Version 1.1 released
This is the second stable release of the 1.x series. It
features a better coverage of the tools available in the 0.x
series, a thoroughly reworked LP/MIP interface plus various
improvements in the existing tools.
* Much improved M$ Windows support
* Various improvements in the CMAKE build system
* Compilation warnings are fixed/suppressed
* Support IBM xlC compiler
* New algorithms
* Connectivity related algorithms (#61)
* Euler walks (#65)
* Preflow push-relabel max. flow algorithm (#176)
* Circulation algorithm (push-relabel based) (#175)
* Suurballe algorithm (#47)
* Gomory-Hu algorithm (#66)
* Hao-Orlin algorithm (#58)
* Edmond's maximum cardinality and weighted matching algorithms
in general graphs (#48,#265)
* Minimum cost arborescence/branching (#60)
* Network Simplex min. cost flow algorithm (#234)
* New data structures
* Full graph structure (#57)
* Grid graph structure (#57)
* Hypercube graph structure (#57)
* Graph adaptors (#67)
* ArcSet and EdgeSet classes (#67)
* Elevator class (#174)
* Other new tools
* LP/MIP interface (#44)
* Support for GLPK, CPLEX, Soplex, COIN-OR CLP and CBC
* Reader for the Nauty file format (#55)
* DIMACS readers (#167)
* Radix sort algorithms (#72)
* RangeIdMap and CrossRefMap (#160)
* New command line tools
* DIMACS to LGF converter (#182)
* lgf-gen - a graph generator (#45)
* DIMACS solver utility (#226)
* Other code improvements
* Lognormal distribution added to Random (#102)
* Better (i.e. O(1) time) item counting in SmartGraph (#3)
* The standard maps of graphs are guaranteed to be
reference maps (#190)
* Miscellaneous
* Various doc improvements
* Improved 0.x -> 1.x converter script
* Several bugfixes (compared to release 1.0):
#170: Bugfix SmartDigraph::split()
#171: Bugfix in SmartGraph::restoreSnapshot()
#172: Extended test cases for graphs and digraphs
#173: Bugfix in Random
* operator()s always return a double now
* the faulty real<Num>(Num) and real<Num>(Num,Num)
have been removed
#187: Remove DijkstraWidestPathOperationTraits
#61: Bugfix in DfsVisit
#193: Bugfix in GraphReader::skipSection()
#195: Bugfix in ConEdgeIt()
#197: Bugfix in heap unionfind
* This bug affects Edmond's general matching algorithms
#207: Fix 'make install' without 'make html' using CMAKE
#208: Suppress or fix VS2008 compilation warnings
----: Update the LEMON icon
----: Enable the component-based installer
(in installers made by CPACK)
----: Set the proper version for CMAKE in the tarballs
(made by autotools)
----: Minor clarification in the LICENSE file
----: Add missing unistd.h include to time_measure.h
#204: Compilation bug fixed in graph_to_eps.h with VS2005
#214,#215: windows.h should never be included by LEMON headers
#230: Build systems check the availability of 'long long' type
#229: Default implementation of Tolerance<> is used for integer types
#211,#212: Various fixes for compiling on AIX
----: Improvements in CMAKE config
- docs is installed in share/doc/
- detects newer versions of Ghostscript
#239: Fix missing 'inline' specifier in time_measure.h
#274,#280: Install lemon/config.h
#275: Prefix macro names with LEMON_ in lemon/config.h
----: Small script for making the release tarballs added
----: Minor improvement in unify-sources.sh (a76f55d7d397)
2009-03-27 LEMON joins to the COIN-OR initiative
COIN-OR (Computational Infrastructure for Operations Research,
http://www.coin-or.org) project is an initiative to spur the
development of open-source software for the operations research
community.
2008-10-13 Version 1.0 released
This is the first stable release of LEMON. Compared to the 0.x
release series, it features a considerably smaller but more
matured set of tools. The API has also completely revised and
changed in several places.
* The major name changes compared to the 0.x series (see the
Migration Guide in the doc for more details)
* Graph -> Digraph, UGraph -> Graph
* Edge -> Arc, UEdge -> Edge
* source(UEdge)/target(UEdge) -> u(Edge)/v(Edge)
* Other improvements
* Better documentation
* Reviewed and cleaned up codebase
* CMake based build system (along with the autotools based one)
* Contents of the library (ported from 0.x)
* Algorithms
* breadth-first search (bfs.h)
* depth-first search (dfs.h)
* Dijkstra's algorithm (dijkstra.h)
* Kruskal's algorithm (kruskal.h)
* Data structures
* graph data structures (list_graph.h, smart_graph.h)
* path data structures (path.h)
* binary heap data structure (bin_heap.h)
* union-find data structures (unionfind.h)
* miscellaneous property maps (maps.h)
* two dimensional vector and bounding box (dim2.h)
* Concepts
* graph structure concepts (concepts/digraph.h, concepts/graph.h,
concepts/graph_components.h)
* concepts for other structures (concepts/heap.h, concepts/maps.h,
concepts/path.h)
* Tools
* Mersenne twister random number generator (random.h)
* tools for measuring cpu and wall clock time (time_measure.h)
* tools for counting steps and events (counter.h)
* tool for parsing command line arguments (arg_parser.h)
* tool for visualizing graphs (graph_to_eps.h)
* tools for reading and writing data in LEMON Graph Format
(lgf_reader.h, lgf_writer.h)
* tools to handle the anomalies of calculations with
floating point numbers (tolerance.h)
* tools to manage RGB colors (color.h)
* Infrastructure
* extended assertion handling (assert.h)
* exception classes and error handling (error.h)
* concept checking (concept_check.h)
* commonly used mathematical constants (math.h)

View File

@ -1,50 +0,0 @@
=====================================================================
LEMON - a Library for Efficient Modeling and Optimization in Networks
=====================================================================
LEMON is an open source library written in C++. It provides
easy-to-use implementations of common data structures and algorithms
in the area of optimization and helps implementing new ones. The main
focus is on graphs and graph algorithms, thus it is especially
suitable for solving design and optimization problems of
telecommunication networks. To achieve wide usability its data
structures and algorithms provide generic interfaces.
Contents
========
LICENSE
Copying, distribution and modification conditions and terms.
NEWS
News and version history.
INSTALL
General building and installation instructions.
lemon/
Source code of LEMON library.
doc/
Documentation of LEMON. The starting page is doc/html/index.html.
demo/
Some example programs to make you easier to get familiar with LEMON.
scripts/
Scripts that make it easier to develop LEMON.
test/
Programs to check the integrity and correctness of LEMON.
tools/
Various utilities related to LEMON.

View File

@ -1,110 +0,0 @@
SET(COIN_ROOT_DIR "" CACHE PATH "COIN root directory")
FIND_PATH(COIN_INCLUDE_DIR coin/CoinUtilsConfig.h
HINTS ${COIN_ROOT_DIR}/include
)
FIND_LIBRARY(COIN_CBC_LIBRARY
NAMES Cbc libCbc
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_CBC_SOLVER_LIBRARY
NAMES CbcSolver libCbcSolver
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_CGL_LIBRARY
NAMES Cgl libCgl
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_CLP_LIBRARY
NAMES Clp libClp
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_COIN_UTILS_LIBRARY
NAMES CoinUtils libCoinUtils
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_LIBRARY
NAMES Osi libOsi
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_CBC_LIBRARY
NAMES OsiCbc libOsiCbc
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_CLP_LIBRARY
NAMES OsiClp libOsiClp
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_OSI_VOL_LIBRARY
NAMES OsiVol libOsiVol
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_VOL_LIBRARY
NAMES Vol libVol
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_ZLIB_LIBRARY
NAMES z libz
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
FIND_LIBRARY(COIN_BZ2_LIBRARY
NAMES bz2 libbz2
HINTS ${COIN_ROOT_DIR}/lib/coin
HINTS ${COIN_ROOT_DIR}/lib
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(COIN DEFAULT_MSG
COIN_INCLUDE_DIR
COIN_CBC_LIBRARY
COIN_CBC_SOLVER_LIBRARY
COIN_CGL_LIBRARY
COIN_CLP_LIBRARY
COIN_COIN_UTILS_LIBRARY
COIN_OSI_LIBRARY
COIN_OSI_CBC_LIBRARY
COIN_OSI_CLP_LIBRARY
# COIN_OSI_VOL_LIBRARY
# COIN_VOL_LIBRARY
)
IF(COIN_FOUND)
SET(COIN_INCLUDE_DIRS ${COIN_INCLUDE_DIR})
SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARY};${COIN_COIN_UTILS_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY}")
IF(COIN_ZLIB_LIBRARY)
SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_ZLIB_LIBRARY}")
ENDIF(COIN_ZLIB_LIBRARY)
IF(COIN_BZ2_LIBRARY)
SET(COIN_CLP_LIBRARIES "${COIN_CLP_LIBRARIES};${COIN_BZ2_LIBRARY}")
ENDIF(COIN_BZ2_LIBRARY)
SET(COIN_CBC_LIBRARIES "${COIN_CBC_LIBRARY};${COIN_CBC_SOLVER_LIBRARY};${COIN_CGL_LIBRARY};${COIN_OSI_LIBRARY};${COIN_OSI_CBC_LIBRARY};${COIN_OSI_CLP_LIBRARY};${COIN_ZLIB_LIBRARY};${COIN_BZ2_LIBRARY};${COIN_CLP_LIBRARIES}")
SET(COIN_LIBRARIES ${COIN_CBC_LIBRARIES})
ENDIF(COIN_FOUND)
MARK_AS_ADVANCED(
COIN_INCLUDE_DIR
COIN_CBC_LIBRARY
COIN_CBC_SOLVER_LIBRARY
COIN_CGL_LIBRARY
COIN_CLP_LIBRARY
COIN_COIN_UTILS_LIBRARY
COIN_OSI_LIBRARY
COIN_OSI_CBC_LIBRARY
COIN_OSI_CLP_LIBRARY
COIN_OSI_VOL_LIBRARY
COIN_VOL_LIBRARY
COIN_ZLIB_LIBRARY
COIN_BZ2_LIBRARY
)

View File

@ -1,55 +0,0 @@
SET(GLPK_ROOT_DIR "" CACHE PATH "GLPK root directory")
SET(GLPK_REGKEY "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Glpk;InstallPath]")
GET_FILENAME_COMPONENT(GLPK_ROOT_PATH ${GLPK_REGKEY} ABSOLUTE)
FIND_PATH(GLPK_INCLUDE_DIR
glpk.h
PATHS ${GLPK_REGKEY}/include
HINTS ${GLPK_ROOT_DIR}/include
)
FIND_LIBRARY(GLPK_LIBRARY
glpk
PATHS ${GLPK_REGKEY}/lib
HINTS ${GLPK_ROOT_DIR}/lib
)
IF(GLPK_INCLUDE_DIR AND GLPK_LIBRARY)
FILE(READ ${GLPK_INCLUDE_DIR}/glpk.h GLPK_GLPK_H)
STRING(REGEX MATCH "define[ ]+GLP_MAJOR_VERSION[ ]+[0-9]+" GLPK_MAJOR_VERSION_LINE "${GLPK_GLPK_H}")
STRING(REGEX REPLACE "define[ ]+GLP_MAJOR_VERSION[ ]+([0-9]+)" "\\1" GLPK_VERSION_MAJOR "${GLPK_MAJOR_VERSION_LINE}")
STRING(REGEX MATCH "define[ ]+GLP_MINOR_VERSION[ ]+[0-9]+" GLPK_MINOR_VERSION_LINE "${GLPK_GLPK_H}")
STRING(REGEX REPLACE "define[ ]+GLP_MINOR_VERSION[ ]+([0-9]+)" "\\1" GLPK_VERSION_MINOR "${GLPK_MINOR_VERSION_LINE}")
SET(GLPK_VERSION_STRING "${GLPK_VERSION_MAJOR}.${GLPK_VERSION_MINOR}")
IF(GLPK_FIND_VERSION)
IF(GLPK_FIND_VERSION_COUNT GREATER 2)
MESSAGE(SEND_ERROR "unexpected version string")
ENDIF(GLPK_FIND_VERSION_COUNT GREATER 2)
MATH(EXPR GLPK_REQUESTED_VERSION "${GLPK_FIND_VERSION_MAJOR}*100 + ${GLPK_FIND_VERSION_MINOR}")
MATH(EXPR GLPK_FOUND_VERSION "${GLPK_VERSION_MAJOR}*100 + ${GLPK_VERSION_MINOR}")
IF(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
SET(GLPK_PROPER_VERSION_FOUND FALSE)
ELSE(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
SET(GLPK_PROPER_VERSION_FOUND TRUE)
ENDIF(GLPK_FOUND_VERSION LESS GLPK_REQUESTED_VERSION)
ELSE(GLPK_FIND_VERSION)
SET(GLPK_PROPER_VERSION_FOUND TRUE)
ENDIF(GLPK_FIND_VERSION)
ENDIF(GLPK_INCLUDE_DIR AND GLPK_LIBRARY)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLPK DEFAULT_MSG GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_PROPER_VERSION_FOUND)
IF(GLPK_FOUND)
SET(GLPK_INCLUDE_DIRS ${GLPK_INCLUDE_DIR})
SET(GLPK_LIBRARIES ${GLPK_LIBRARY})
SET(GLPK_BIN_DIR ${GLPK_ROOT_PATH}/bin)
ENDIF(GLPK_FOUND)
MARK_AS_ADVANCED(GLPK_LIBRARY GLPK_INCLUDE_DIR GLPK_BIN_DIR)

View File

@ -1,10 +0,0 @@
INCLUDE(FindPackageHandleStandardArgs)
FIND_PROGRAM(GHOSTSCRIPT_EXECUTABLE
NAMES gs gswin32c
PATHS "$ENV{ProgramFiles}/gs"
PATH_SUFFIXES gs8.61/bin gs8.62/bin gs8.63/bin gs8.64/bin gs8.65/bin
DOC "Ghostscript: PostScript and PDF language interpreter and previewer."
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ghostscript DEFAULT_MSG GHOSTSCRIPT_EXECUTABLE)

View File

@ -1,102 +0,0 @@
FIND_PATH(ILOG_ROOT_DIR
NAMES cplex
DOC "CPLEX STUDIO root directory"
PATHS /opt/ibm/ILOG /usr/local/ibm/ILOG /usr/local/ILOG /usr/local/ilog
PATHS "$ENV{HOME}/ILOG" "$ENV{HOME}/.local/ILOG"
PATHS "$ENV{HOME}/ibm/ILOG" "$ENV{HOME}/.local/ibm/ILOG"
PATHS "C:/Program Files/IBM/ILOG"
PATH_SUFFIXES "CPLEX_Studio126" "CPLEX_Studio125"
"CPLEX_Studio124" "CPLEX_Studio123" "CPLEX_Studio122"
NO_DEFAULT_PATH
)
IF(WIN32)
IF(MSVC_VERSION STREQUAL "1400")
SET(ILOG_WIN_COMPILER "windows_vs2005")
ELSEIF(MSVC_VERSION STREQUAL "1500")
SET(ILOG_WIN_COMPILER "windows_vs2008")
ELSEIF(MSVC_VERSION STREQUAL "1600")
SET(ILOG_WIN_COMPILER "windows_vs2010")
ELSE()
SET(ILOG_WIN_COMPILER "windows_vs2008")
ENDIF()
IF(CMAKE_CL_64)
SET(ILOG_WIN_COMPILER "x64_${ILOG_WIN_COMPILER}")
SET(ILOG_WIN_PLATFORM "x64_win32")
ELSE()
SET(ILOG_WIN_COMPILER "x86_${ILOG_WIN_COMPILER}")
SET(ILOG_WIN_PLATFORM "x86_win32")
ENDIF()
ENDIF()
FIND_PATH(ILOG_CPLEX_ROOT_DIR
NAMES include/ilcplex
HINTS ${ILOG_ROOT_DIR}/cplex ${ILOG_ROOT_DIR}/cplex121
${ILOG_ROOT_DIR}/cplex122 ${ILOG_ROOT_DIR}/cplex123
DOC "CPLEX root directory"
NO_DEFAULT_PATH
)
FIND_PATH(ILOG_CONCERT_ROOT_DIR
NAMES include/ilconcert
HINTS ${ILOG_ROOT_DIR}/concert ${ILOG_ROOT_DIR}/concert29
DOC "CONCERT root directory"
NO_DEFAULT_PATH
)
FIND_PATH(ILOG_CPLEX_INCLUDE_DIR
ilcplex/cplex.h
HINTS ${ILOG_CPLEX_ROOT_DIR}/include
NO_DEFAULT_PATH
)
FIND_PATH(ILOG_CONCERT_INCLUDE_DIR
ilconcert/ilobasic.h
HINTS ${ILOG_CONCERT_ROOT_DIR}/include
NO_DEFAULT_PATH
)
FIND_LIBRARY(ILOG_CPLEX_LIBRARY
cplex cplex121 cplex122 cplex123 cplex124
HINTS ${ILOG_CPLEX_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
${ILOG_CPLEX_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
NO_DEFAULT_PATH
)
FIND_LIBRARY(ILOG_CONCERT_LIBRARY
concert
HINTS ${ILOG_CONCERT_ROOT_DIR}/lib/x86_sles10_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_sles10_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/x86_debian4.0_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/x86-64_debian4.0_4.1/static_pic
${ILOG_CONCERT_ROOT_DIR}/lib/${ILOG_WIN_COMPILER}/stat_mda
NO_DEFAULT_PATH
)
FIND_FILE(ILOG_CPLEX_DLL
cplex121.dll cplex122.dll cplex123.dll cplex124.dll
HINTS ${ILOG_CPLEX_ROOT_DIR}/bin/${ILOG_WIN_PLATFORM}
NO_DEFAULT_PATH
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ILOG
DEFAULT_MSG ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR
)
IF(ILOG_FOUND)
SET(ILOG_INCLUDE_DIRS ${ILOG_CPLEX_INCLUDE_DIR} ${ILOG_CONCERT_INCLUDE_DIR})
SET(ILOG_LIBRARIES ${ILOG_CPLEX_LIBRARY} ${ILOG_CONCERT_LIBRARY})
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
# SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread")
SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread")
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
ENDIF(ILOG_FOUND)
MARK_AS_ADVANCED(
ILOG_CPLEX_LIBRARY ILOG_CPLEX_INCLUDE_DIR ILOG_CPLEX_DLL
ILOG_CONCERT_LIBRARY ILOG_CONCERT_INCLUDE_DIR ILOG_CONCERT_DLL
)

View File

@ -1,23 +0,0 @@
SET(SOPLEX_ROOT_DIR "" CACHE PATH "SoPlex root directory")
FIND_PATH(SOPLEX_INCLUDE_DIR
soplex.h
HINTS ${SOPLEX_ROOT_DIR}/src
)
FIND_LIBRARY(SOPLEX_LIBRARY
soplex
HINTS ${SOPLEX_ROOT_DIR}/lib
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SOPLEX DEFAULT_MSG SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)
IF(SOPLEX_FOUND)
SET(SOPLEX_INCLUDE_DIRS ${SOPLEX_INCLUDE_DIR})
SET(SOPLEX_LIBRARIES ${SOPLEX_LIBRARY})
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
SET(SOPLEX_LIBRARIES "${SOPLEX_LIBRARIES};z")
ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
ENDIF(SOPLEX_FOUND)
MARK_AS_ADVANCED(SOPLEX_LIBRARY SOPLEX_INCLUDE_DIR)

View File

@ -1,13 +0,0 @@
SET(LEMON_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include" CACHE PATH "LEMON include directory")
SET(LEMON_INCLUDE_DIRS "${LEMON_INCLUDE_DIR}")
IF(UNIX)
SET(LEMON_LIB_NAME "libemon.a")
ELSEIF(WIN32)
SET(LEMON_LIB_NAME "lemon.lib")
ENDIF(UNIX)
SET(LEMON_LIBRARY "@CMAKE_INSTALL_PREFIX@/lib/${LEMON_LIB_NAME}" CACHE FILEPATH "LEMON library")
SET(LEMON_LIBRARIES "${LEMON_LIBRARY}")
MARK_AS_ADVANCED(LEMON_LIBRARY LEMON_INCLUDE_DIR)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1 +0,0 @@
SET(LEMON_VERSION "1.3.1" CACHE STRING "LEMON version string.")

View File

@ -1 +0,0 @@
SET(LEMON_VERSION "@LEMON_VERSION@" CACHE STRING "LEMON version string.")

View File

@ -1,19 +0,0 @@
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
LINK_DIRECTORIES(
${PROJECT_BINARY_DIR}/lemon
)
# Uncomment (and adjust) the following two lines. 'myprog' is the name
# of the final executable ('.exe' will automatically be added to the
# name on Windows) and 'myprog-main.cc' is the source code it is
# compiled from. You can add more source files separated by
# whitespaces. Moreover, you can add multiple similar blocks if you
# want to build more than one executables.
# ADD_EXECUTABLE(myprog myprog-main.cc)
# TARGET_LINK_LIBRARIES(myprog lemon)

View File

@ -1,19 +0,0 @@
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
LINK_DIRECTORIES(
${PROJECT_BINARY_DIR}/lemon
)
SET(DEMOS
arg_parser_demo
graph_to_eps_demo
lgf_demo
)
FOREACH(DEMO_NAME ${DEMOS})
ADD_EXECUTABLE(${DEMO_NAME} ${DEMO_NAME}.cc)
TARGET_LINK_LIBRARIES(${DEMO_NAME} lemon)
ENDFOREACH()

View File

@ -1,112 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\ingroup demos
///\file
///\brief Argument parser demo
///
/// This example shows how the argument parser can be used.
///
/// \include arg_parser_demo.cc
#include <lemon/arg_parser.h>
using namespace lemon;
int main(int argc, char **argv)
{
// Initialize the argument parser
ArgParser ap(argc, argv);
int i;
std::string s;
double d = 1.0;
bool b, nh;
bool g1, g2, g3;
// Add a mandatory integer option with storage reference
ap.refOption("n", "An integer input.", i, true);
// Add a double option with storage reference (the default value is 1.0)
ap.refOption("val", "A double input.", d);
// Add a double option without storage reference (the default value is 3.14)
ap.doubleOption("val2", "A double input.", 3.14);
// Set synonym for -val option
ap.synonym("vals", "val");
// Add a string option
ap.refOption("name", "A string input.", s);
// Add bool options
ap.refOption("f", "A switch.", b)
.refOption("nohelp", "", nh)
.refOption("gra", "Choice A", g1)
.refOption("grb", "Choice B", g2)
.refOption("grc", "Choice C", g3);
// Bundle -gr* options into a group
ap.optionGroup("gr", "gra")
.optionGroup("gr", "grb")
.optionGroup("gr", "grc");
// Set the group mandatory
ap.mandatoryGroup("gr");
// Set the options of the group exclusive (only one option can be given)
ap.onlyOneGroup("gr");
// Add non-parsed arguments (e.g. input files)
ap.other("infile", "The input file.")
.other("...");
// Throw an exception when problems occurs. The default behavior is to
// exit(1) on these cases, but this makes Valgrind falsely warn
// about memory leaks.
ap.throwOnProblems();
// Perform the parsing process
// (in case of any error it terminates the program)
// The try {} construct is necessary only if the ap.trowOnProblems()
// setting is in use.
try {
ap.parse();
} catch (ArgParserException &) { return 1; }
// Check each option if it has been given and print its value
std::cout << "Parameters of '" << ap.commandName() << "':\n";
std::cout << " Value of -n: " << i << std::endl;
if(ap.given("val")) std::cout << " Value of -val: " << d << std::endl;
if(ap.given("val2")) {
d = ap["val2"];
std::cout << " Value of -val2: " << d << std::endl;
}
if(ap.given("name")) std::cout << " Value of -name: " << s << std::endl;
if(ap.given("f")) std::cout << " -f is given\n";
if(ap.given("nohelp")) std::cout << " Value of -nohelp: " << nh << std::endl;
if(ap.given("gra")) std::cout << " -gra is given\n";
if(ap.given("grb")) std::cout << " -grb is given\n";
if(ap.given("grc")) std::cout << " -grc is given\n";
switch(ap.files().size()) {
case 0:
std::cout << " No file argument was given.\n";
break;
case 1:
std::cout << " 1 file argument was given. It is:\n";
break;
default:
std::cout << " "
<< ap.files().size() << " file arguments were given. They are:\n";
}
for(unsigned int i=0;i<ap.files().size();++i)
std::cout << " '" << ap.files()[i] << "'\n";
return 0;
}

View File

@ -1,29 +0,0 @@
@nodes
label
0
1
2
3
4
5
6
7
@arcs
label capacity
0 1 0 16
0 2 1 12
0 3 2 20
1 2 3 10
1 4 4 10
1 5 5 13
2 3 6 10
2 4 7 8
2 6 8 8
5 3 9 20
3 6 10 25
4 7 11 15
5 7 12 15
6 7 13 18
@attributes
source 0
target 7

View File

@ -1,206 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
/// \ingroup demos
/// \file
/// \brief Demo of the graph drawing function \ref graphToEps()
///
/// This demo program shows examples how to use the function \ref
/// graphToEps(). It takes no input but simply creates seven
/// <tt>.eps</tt> files demonstrating the capability of \ref
/// graphToEps(), and showing how to draw directed graphs,
/// how to handle parallel egdes, how to change the properties (like
/// color, shape, size, title etc.) of nodes and arcs individually
/// using appropriate graph maps.
///
/// \include graph_to_eps_demo.cc
#include<lemon/list_graph.h>
#include<lemon/graph_to_eps.h>
#include<lemon/math.h>
using namespace std;
using namespace lemon;
int main()
{
Palette palette;
Palette paletteW(true);
// Create a small digraph
ListDigraph g;
typedef ListDigraph::Node Node;
typedef ListDigraph::NodeIt NodeIt;
typedef ListDigraph::Arc Arc;
typedef dim2::Point<int> Point;
Node n1=g.addNode();
Node n2=g.addNode();
Node n3=g.addNode();
Node n4=g.addNode();
Node n5=g.addNode();
ListDigraph::NodeMap<Point> coords(g);
ListDigraph::NodeMap<double> sizes(g);
ListDigraph::NodeMap<int> colors(g);
ListDigraph::NodeMap<int> shapes(g);
ListDigraph::ArcMap<int> acolors(g);
ListDigraph::ArcMap<int> widths(g);
coords[n1]=Point(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0;
coords[n2]=Point(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2;
coords[n3]=Point(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0;
coords[n4]=Point(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1;
coords[n5]=Point(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2;
Arc a;
a=g.addArc(n1,n2); acolors[a]=0; widths[a]=1;
a=g.addArc(n2,n3); acolors[a]=0; widths[a]=1;
a=g.addArc(n3,n5); acolors[a]=0; widths[a]=3;
a=g.addArc(n5,n4); acolors[a]=0; widths[a]=1;
a=g.addArc(n4,n1); acolors[a]=0; widths[a]=1;
a=g.addArc(n2,n4); acolors[a]=1; widths[a]=2;
a=g.addArc(n3,n4); acolors[a]=2; widths[a]=1;
IdMap<ListDigraph,Node> id(g);
// Create .eps files showing the digraph with different options
cout << "Create 'graph_to_eps_demo_out_1_pure.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_1_pure.eps").
coords(coords).
title("Sample .eps figure").
copyright("(C) 2003-2009 LEMON Project").
run();
cout << "Create 'graph_to_eps_demo_out_2.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_2.eps").
coords(coords).
title("Sample .eps figure").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeScale(2).nodeSizes(sizes).
nodeShapes(shapes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.4).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
run();
cout << "Create 'graph_to_eps_demo_out_3_arr.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_3_arr.eps").
title("Sample .eps figure (with arrowheads)").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeColors(composeMap(palette,colors)).
coords(coords).
nodeScale(2).nodeSizes(sizes).
nodeShapes(shapes).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.4).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
drawArrows().arrowWidth(2).arrowLength(2).
run();
// Add more arcs to the digraph
a=g.addArc(n1,n4); acolors[a]=2; widths[a]=1;
a=g.addArc(n4,n1); acolors[a]=1; widths[a]=2;
a=g.addArc(n1,n2); acolors[a]=1; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=2; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=3; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=4; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=5; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=6; widths[a]=1;
a=g.addArc(n1,n2); acolors[a]=7; widths[a]=1;
cout << "Create 'graph_to_eps_demo_out_4_par.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_4_par.eps").
title("Sample .eps figure (parallel arcs)").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeShapes(shapes).
coords(coords).
nodeScale(2).nodeSizes(sizes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.4).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
enableParallel().parArcDist(1.5).
run();
cout << "Create 'graph_to_eps_demo_out_5_par_arr.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_5_par_arr.eps").
title("Sample .eps figure (parallel arcs and arrowheads)").
copyright("(C) 2003-2009 LEMON Project").
absoluteNodeSizes().absoluteArcWidths().
nodeScale(2).nodeSizes(sizes).
coords(coords).
nodeShapes(shapes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.3).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
enableParallel().parArcDist(1).
drawArrows().arrowWidth(1).arrowLength(1).
run();
cout << "Create 'graph_to_eps_demo_out_6_par_arr_a4.eps'" << endl;
graphToEps(g,"graph_to_eps_demo_out_6_par_arr_a4.eps").
title("Sample .eps figure (fits to A4)").
copyright("(C) 2003-2009 LEMON Project").
scaleToA4().
absoluteNodeSizes().absoluteArcWidths().
nodeScale(2).nodeSizes(sizes).
coords(coords).
nodeShapes(shapes).
nodeColors(composeMap(palette,colors)).
arcColors(composeMap(palette,acolors)).
arcWidthScale(.3).arcWidths(widths).
nodeTexts(id).nodeTextSize(3).
enableParallel().parArcDist(1).
drawArrows().arrowWidth(1).arrowLength(1).
run();
// Create an .eps file showing the colors of a default Palette
ListDigraph h;
ListDigraph::NodeMap<int> hcolors(h);
ListDigraph::NodeMap<Point> hcoords(h);
int cols=int(std::sqrt(double(palette.size())));
for(int i=0;i<int(paletteW.size());i++) {
Node n=h.addNode();
hcoords[n]=Point(1+i%cols,1+i/cols);
hcolors[n]=i;
}
cout << "Create 'graph_to_eps_demo_out_7_colors.eps'" << endl;
graphToEps(h,"graph_to_eps_demo_out_7_colors.eps").
scale(60).
title("Sample .eps figure (Palette demo)").
copyright("(C) 2003-2009 LEMON Project").
coords(hcoords).
absoluteNodeSizes().absoluteArcWidths().
nodeScale(.45).
distantColorNodeTexts().
nodeTexts(hcolors).nodeTextSize(.6).
nodeColors(composeMap(paletteW,hcolors)).
run();
return 0;
}

View File

@ -1,70 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2009
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\ingroup demos
///\file
///\brief Demonstrating graph input and output
///
/// This program gives an example of how to read and write a digraph
/// and additional maps from/to a stream or a file using the
/// \ref lgf-format "LGF" format.
///
/// The \c "digraph.lgf" file:
/// \include digraph.lgf
///
/// And the program which reads it and prints the digraph to the
/// standard output:
/// \include lgf_demo.cc
#include <iostream>
#include <lemon/smart_graph.h>
#include <lemon/lgf_reader.h>
#include <lemon/lgf_writer.h>
using namespace lemon;
int main() {
SmartDigraph g;
SmartDigraph::ArcMap<int> cap(g);
SmartDigraph::Node s, t;
try {
digraphReader(g, "digraph.lgf"). // read the directed graph into g
arcMap("capacity", cap). // read the 'capacity' arc map into cap
node("source", s). // read 'source' node to s
node("target", t). // read 'target' node to t
run();
} catch (Exception& error) { // check if there was any error
std::cerr << "Error: " << error.what() << std::endl;
return -1;
}
std::cout << "A digraph is read from 'digraph.lgf'." << std::endl;
std::cout << "Number of nodes: " << countNodes(g) << std::endl;
std::cout << "Number of arcs: " << countArcs(g) << std::endl;
std::cout << "We can write it to the standard output:" << std::endl;
digraphWriter(g). // write g to the standard output
arcMap("capacity", cap). // write cap into 'capacity'
node("source", s). // write s to 'source'
node("target", t). // write t to 'target'
run();
return 0;
}

View File

@ -1,91 +0,0 @@
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}
${PROJECT_BINARY_DIR}
)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h
)
CONFIGURE_FILE(
${CMAKE_CURRENT_SOURCE_DIR}/lemon.pc.in
${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
@ONLY
)
SET(LEMON_SOURCES
arg_parser.cc
base.cc
color.cc
lp_base.cc
lp_skeleton.cc
random.cc
bits/windows.cc
)
IF(LEMON_HAVE_GLPK)
SET(LEMON_SOURCES ${LEMON_SOURCES} glpk.cc)
INCLUDE_DIRECTORIES(${GLPK_INCLUDE_DIRS})
IF(WIN32)
INSTALL(FILES ${GLPK_BIN_DIR}/glpk.dll DESTINATION bin)
INSTALL(FILES ${GLPK_BIN_DIR}/libltdl3.dll DESTINATION bin)
INSTALL(FILES ${GLPK_BIN_DIR}/zlib1.dll DESTINATION bin)
ENDIF()
ENDIF()
IF(LEMON_HAVE_CPLEX)
SET(LEMON_SOURCES ${LEMON_SOURCES} cplex.cc)
INCLUDE_DIRECTORIES(${ILOG_INCLUDE_DIRS})
ENDIF()
IF(LEMON_HAVE_CLP)
SET(LEMON_SOURCES ${LEMON_SOURCES} clp.cc)
INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
ENDIF()
IF(LEMON_HAVE_CBC)
SET(LEMON_SOURCES ${LEMON_SOURCES} cbc.cc)
INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
ENDIF()
IF(LEMON_HAVE_SOPLEX)
SET(LEMON_SOURCES ${LEMON_SOURCES} soplex.cc)
INCLUDE_DIRECTORIES(${SOPLEX_INCLUDE_DIRS})
ENDIF()
ADD_LIBRARY(lemon ${LEMON_SOURCES})
TARGET_LINK_LIBRARIES(lemon
${GLPK_LIBRARIES} ${COIN_LIBRARIES} ${ILOG_LIBRARIES} ${SOPLEX_LIBRARIES}
)
IF(UNIX)
SET_TARGET_PROPERTIES(lemon PROPERTIES OUTPUT_NAME emon VERSION ${LEMON_VERSION} SOVERSION ${LEMON_VERSION})
ENDIF()
INSTALL(
TARGETS lemon
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
COMPONENT library
)
INSTALL(
DIRECTORY . bits concepts
DESTINATION include/lemon
COMPONENT headers
FILES_MATCHING PATTERN "*.h"
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h
DESTINATION include/lemon
COMPONENT headers
)
INSTALL(
FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
DESTINATION lib/pkgconfig
)

File diff suppressed because it is too large Load Diff

View File

@ -1,474 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#include <lemon/arg_parser.h>
namespace lemon {
void ArgParser::_terminate(ArgParserException::Reason reason) const
{
if(_exit_on_problems)
exit(1);
else throw(ArgParserException(reason));
}
void ArgParser::_showHelp(void *p)
{
(static_cast<ArgParser*>(p))->showHelp();
(static_cast<ArgParser*>(p))->_terminate(ArgParserException::HELP);
}
ArgParser::ArgParser(int argc, const char * const *argv)
:_argc(argc), _argv(argv), _command_name(argv[0]),
_exit_on_problems(true) {
funcOption("-help","Print a short help message",_showHelp,this);
synonym("help","-help");
synonym("h","-help");
}
ArgParser::~ArgParser()
{
for(Opts::iterator i=_opts.begin();i!=_opts.end();++i)
if(i->second.self_delete)
switch(i->second.type) {
case BOOL:
delete i->second.bool_p;
break;
case STRING:
delete i->second.string_p;
break;
case DOUBLE:
delete i->second.double_p;
break;
case INTEGER:
delete i->second.int_p;
break;
case UNKNOWN:
break;
case FUNC:
break;
}
}
ArgParser &ArgParser::intOption(const std::string &name,
const std::string &help,
int value, bool obl)
{
ParData p;
p.int_p=new int(value);
p.self_delete=true;
p.help=help;
p.type=INTEGER;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::doubleOption(const std::string &name,
const std::string &help,
double value, bool obl)
{
ParData p;
p.double_p=new double(value);
p.self_delete=true;
p.help=help;
p.type=DOUBLE;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::boolOption(const std::string &name,
const std::string &help,
bool value, bool obl)
{
ParData p;
p.bool_p=new bool(value);
p.self_delete=true;
p.help=help;
p.type=BOOL;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::stringOption(const std::string &name,
const std::string &help,
std::string value, bool obl)
{
ParData p;
p.string_p=new std::string(value);
p.self_delete=true;
p.help=help;
p.type=STRING;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
int &ref, bool obl)
{
ParData p;
p.int_p=&ref;
p.self_delete=false;
p.help=help;
p.type=INTEGER;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
double &ref, bool obl)
{
ParData p;
p.double_p=&ref;
p.self_delete=false;
p.help=help;
p.type=DOUBLE;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
bool &ref, bool obl)
{
ParData p;
p.bool_p=&ref;
p.self_delete=false;
p.help=help;
p.type=BOOL;
p.mandatory=obl;
_opts[name]=p;
ref = false;
return *this;
}
ArgParser &ArgParser::refOption(const std::string &name,
const std::string &help,
std::string &ref, bool obl)
{
ParData p;
p.string_p=&ref;
p.self_delete=false;
p.help=help;
p.type=STRING;
p.mandatory=obl;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::funcOption(const std::string &name,
const std::string &help,
void (*func)(void *),void *data)
{
ParData p;
p.func_p.p=func;
p.func_p.data=data;
p.self_delete=false;
p.help=help;
p.type=FUNC;
p.mandatory=false;
_opts[name]=p;
return *this;
}
ArgParser &ArgParser::optionGroup(const std::string &group,
const std::string &opt)
{
Opts::iterator i = _opts.find(opt);
LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
LEMON_ASSERT(!(i->second.ingroup),
"Option already in option group: '"+opt+"'");
GroupData &g=_groups[group];
g.opts.push_back(opt);
i->second.ingroup=true;
return *this;
}
ArgParser &ArgParser::onlyOneGroup(const std::string &group)
{
GroupData &g=_groups[group];
g.only_one=true;
return *this;
}
ArgParser &ArgParser::synonym(const std::string &syn,
const std::string &opt)
{
Opts::iterator o = _opts.find(opt);
Opts::iterator s = _opts.find(syn);
LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'");
LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
ParData p;
p.help=opt;
p.mandatory=false;
p.syn=true;
_opts[syn]=p;
o->second.has_syn=true;
return *this;
}
ArgParser &ArgParser::mandatoryGroup(const std::string &group)
{
GroupData &g=_groups[group];
g.mandatory=true;
return *this;
}
ArgParser &ArgParser::other(const std::string &name,
const std::string &help)
{
_others_help.push_back(OtherArg(name,help));
return *this;
}
void ArgParser::show(std::ostream &os,Opts::const_iterator i) const
{
os << "-" << i->first;
if(i->second.has_syn)
for(Opts::const_iterator j=_opts.begin();j!=_opts.end();++j)
if(j->second.syn&&j->second.help==i->first)
os << "|-" << j->first;
switch(i->second.type) {
case STRING:
os << " str";
break;
case INTEGER:
os << " int";
break;
case DOUBLE:
os << " num";
break;
default:
break;
}
}
void ArgParser::show(std::ostream &os,Groups::const_iterator i) const
{
GroupData::Opts::const_iterator o=i->second.opts.begin();
while(o!=i->second.opts.end()) {
show(os,_opts.find(*o));
++o;
if(o!=i->second.opts.end()) os<<'|';
}
}
void ArgParser::showHelp(Opts::const_iterator i) const
{
if(i->second.help.size()==0||i->second.syn) return;
std::cerr << " ";
show(std::cerr,i);
std::cerr << std::endl;
std::cerr << " " << i->second.help << std::endl;
}
void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::const_iterator i)
const
{
if(i->help.size()==0) return;
std::cerr << " " << i->name << std::endl
<< " " << i->help << std::endl;
}
void ArgParser::shortHelp() const
{
const unsigned int LINE_LEN=77;
const std::string indent(" ");
std::cerr << "Usage:\n " << _command_name;
int pos=_command_name.size()+2;
for(Groups::const_iterator g=_groups.begin();g!=_groups.end();++g) {
std::ostringstream cstr;
cstr << ' ';
if(!g->second.mandatory) cstr << '[';
show(cstr,g);
if(!g->second.mandatory) cstr << ']';
if(pos+cstr.str().size()>LINE_LEN) {
std::cerr << std::endl << indent;
pos=indent.size();
}
std::cerr << cstr.str();
pos+=cstr.str().size();
}
for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
if(!i->second.ingroup&&!i->second.syn) {
std::ostringstream cstr;
cstr << ' ';
if(!i->second.mandatory) cstr << '[';
show(cstr,i);
if(!i->second.mandatory) cstr << ']';
if(pos+cstr.str().size()>LINE_LEN) {
std::cerr << std::endl << indent;
pos=indent.size();
}
std::cerr << cstr.str();
pos+=cstr.str().size();
}
for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
i!=_others_help.end();++i)
{
std::ostringstream cstr;
cstr << ' ' << i->name;
if(pos+cstr.str().size()>LINE_LEN) {
std::cerr << std::endl << indent;
pos=indent.size();
}
std::cerr << cstr.str();
pos+=cstr.str().size();
}
std::cerr << std::endl;
}
void ArgParser::showHelp() const
{
shortHelp();
std::cerr << "Where:\n";
for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
i!=_others_help.end();++i) showHelp(i);
for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
_terminate(ArgParserException::HELP);
}
void ArgParser::unknownOpt(std::string arg) const
{
std::cerr << "\nUnknown option: " << arg << "\n";
std::cerr << "\nType '" << _command_name <<
" --help' to obtain a short summary on the usage.\n\n";
_terminate(ArgParserException::UNKNOWN_OPT);
}
void ArgParser::requiresValue(std::string arg, OptType t) const
{
std::cerr << "Argument '" << arg << "' requires a";
switch(t) {
case STRING:
std::cerr << " string";
break;
case INTEGER:
std::cerr << "n integer";
break;
case DOUBLE:
std::cerr << " floating point";
break;
default:
break;
}
std::cerr << " value\n\n";
showHelp();
}
void ArgParser::checkMandatories() const
{
bool ok=true;
for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i)
if(i->second.mandatory&&!i->second.set)
{
if(ok)
std::cerr << _command_name
<< ": The following mandatory arguments are missing.\n";
ok=false;
showHelp(i);
}
for(Groups::const_iterator i=_groups.begin();i!=_groups.end();++i)
if(i->second.mandatory||i->second.only_one)
{
int set=0;
for(GroupData::Opts::const_iterator o=i->second.opts.begin();
o!=i->second.opts.end();++o)
if(_opts.find(*o)->second.set) ++set;
if(i->second.mandatory&&!set) {
std::cerr << _command_name <<
": At least one of the following arguments is mandatory.\n";
ok=false;
for(GroupData::Opts::const_iterator o=i->second.opts.begin();
o!=i->second.opts.end();++o)
showHelp(_opts.find(*o));
}
if(i->second.only_one&&set>1) {
std::cerr << _command_name <<
": At most one of the following arguments can be given.\n";
ok=false;
for(GroupData::Opts::const_iterator o=i->second.opts.begin();
o!=i->second.opts.end();++o)
showHelp(_opts.find(*o));
}
}
if(!ok) {
std::cerr << "\nType '" << _command_name <<
" --help' to obtain a short summary on the usage.\n\n";
_terminate(ArgParserException::INVALID_OPT);
}
}
ArgParser &ArgParser::parse()
{
for(int ar=1; ar<_argc; ++ar) {
std::string arg(_argv[ar]);
if (arg[0] != '-' || arg.size() == 1) {
_file_args.push_back(arg);
}
else {
Opts::iterator i = _opts.find(arg.substr(1));
if(i==_opts.end()) unknownOpt(arg);
else {
if(i->second.syn) i=_opts.find(i->second.help);
ParData &p(i->second);
if (p.type==BOOL) *p.bool_p=true;
else if (p.type==FUNC) p.func_p.p(p.func_p.data);
else if(++ar==_argc) requiresValue(arg, p.type);
else {
std::string val(_argv[ar]);
std::istringstream vals(val);
switch(p.type) {
case STRING:
*p.string_p=val;
break;
case INTEGER:
vals >> *p.int_p;
break;
case DOUBLE:
vals >> *p.double_p;
break;
default:
break;
}
if(p.type!=STRING&&(!vals||!vals.eof()))
requiresValue(arg, p.type);
}
p.set = true;
}
}
}
checkMandatories();
return *this;
}
}

View File

@ -1,440 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_ARG_PARSER_H
#define LEMON_ARG_PARSER_H
#include <vector>
#include <map>
#include <list>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <lemon/assert.h>
///\ingroup misc
///\file
///\brief A tool to parse command line arguments.
namespace lemon {
///Exception used by ArgParser
///Exception used by ArgParser.
///
class ArgParserException : public Exception {
public:
/// Reasons for failure
/// Reasons for failure.
///
enum Reason {
HELP, ///< <tt>--help</tt> option was given.
UNKNOWN_OPT, ///< Unknown option was given.
INVALID_OPT ///< Invalid combination of options.
};
private:
Reason _reason;
public:
///Constructor
ArgParserException(Reason r) throw() : _reason(r) {}
///Virtual destructor
virtual ~ArgParserException() throw() {}
///A short description of the exception
virtual const char* what() const throw() {
switch(_reason)
{
case HELP:
return "lemon::ArgParseException: ask for help";
break;
case UNKNOWN_OPT:
return "lemon::ArgParseException: unknown option";
break;
case INVALID_OPT:
return "lemon::ArgParseException: invalid combination of options";
break;
}
return "";
}
///Return the reason for the failure
Reason reason() const {return _reason; }
};
///Command line arguments parser
///\ingroup misc
///Command line arguments parser.
///
///For a complete example see the \ref arg_parser_demo.cc demo file.
class ArgParser {
static void _showHelp(void *p);
protected:
int _argc;
const char * const *_argv;
enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
class ParData {
public:
union {
bool *bool_p;
int *int_p;
double *double_p;
std::string *string_p;
struct {
void (*p)(void *);
void *data;
} func_p;
};
std::string help;
bool mandatory;
OptType type;
bool set;
bool ingroup;
bool has_syn;
bool syn;
bool self_delete;
ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false),
has_syn(false), syn(false), self_delete(false) {}
};
typedef std::map<std::string,ParData> Opts;
Opts _opts;
class GroupData
{
public:
typedef std::list<std::string> Opts;
Opts opts;
bool only_one;
bool mandatory;
GroupData() :only_one(false), mandatory(false) {}
};
typedef std::map<std::string,GroupData> Groups;
Groups _groups;
struct OtherArg
{
std::string name;
std::string help;
OtherArg(std::string n, std::string h) :name(n), help(h) {}
};
std::vector<OtherArg> _others_help;
std::vector<std::string> _file_args;
std::string _command_name;
private:
//Bind a function to an option.
//\param name The name of the option. The leading '-' must be omitted.
//\param help A help string.
//\retval func The function to be called when the option is given. It
// must be of type "void f(void *)"
//\param data Data to be passed to \c func
ArgParser &funcOption(const std::string &name,
const std::string &help,
void (*func)(void *),void *data);
bool _exit_on_problems;
void _terminate(ArgParserException::Reason reason) const;
public:
///Constructor
ArgParser(int argc, const char * const *argv);
~ArgParser();
///\name Options
///
///@{
///Add a new integer type option
///Add a new integer type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
ArgParser &intOption(const std::string &name,
const std::string &help,
int value=0, bool obl=false);
///Add a new floating point type option
///Add a new floating point type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
ArgParser &doubleOption(const std::string &name,
const std::string &help,
double value=0, bool obl=false);
///Add a new bool type option
///Add a new bool type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
///\note A mandatory bool obtion is of very little use.
ArgParser &boolOption(const std::string &name,
const std::string &help,
bool value=false, bool obl=false);
///Add a new string type option
///Add a new string type option.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param value A default value for the option.
///\param obl Indicate if the option is mandatory.
ArgParser &stringOption(const std::string &name,
const std::string &help,
std::string value="", bool obl=false);
///Give help string for non-parsed arguments.
///With this function you can give help string for non-parsed arguments.
///The parameter \c name will be printed in the short usage line, while
///\c help gives a more detailed description.
ArgParser &other(const std::string &name,
const std::string &help="");
///@}
///\name Options with External Storage
///Using this functions, the value of the option will be directly written
///into a variable once the option appears in the command line.
///@{
///Add a new integer type option with a storage reference
///Add a new integer type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
ArgParser &refOption(const std::string &name,
const std::string &help,
int &ref, bool obl=false);
///Add a new floating type option with a storage reference
///Add a new floating type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
ArgParser &refOption(const std::string &name,
const std::string &help,
double &ref, bool obl=false);
///Add a new bool type option with a storage reference
///Add a new bool type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
///\note A mandatory bool obtion is of very little use.
ArgParser &refOption(const std::string &name,
const std::string &help,
bool &ref, bool obl=false);
///Add a new string type option with a storage reference
///Add a new string type option with a storage reference.
///\param name The name of the option. The leading '-' must be omitted.
///\param help A help string.
///\param obl Indicate if the option is mandatory.
///\retval ref The value of the argument will be written to this variable.
ArgParser &refOption(const std::string &name,
const std::string &help,
std::string &ref, bool obl=false);
///@}
///\name Option Groups and Synonyms
///
///@{
///Bundle some options into a group
/// You can group some option by calling this function repeatedly for each
/// option to be grouped with the same groupname.
///\param group The group name.
///\param opt The option name.
ArgParser &optionGroup(const std::string &group,
const std::string &opt);
///Make the members of a group exclusive
///If you call this function for a group, than at most one of them can be
///given at the same time.
ArgParser &onlyOneGroup(const std::string &group);
///Make a group mandatory
///Using this function, at least one of the members of \c group
///must be given.
ArgParser &mandatoryGroup(const std::string &group);
///Create synonym to an option
///With this function you can create a synonym \c syn of the
///option \c opt.
ArgParser &synonym(const std::string &syn,
const std::string &opt);
///@}
private:
void show(std::ostream &os,Opts::const_iterator i) const;
void show(std::ostream &os,Groups::const_iterator i) const;
void showHelp(Opts::const_iterator i) const;
void showHelp(std::vector<OtherArg>::const_iterator i) const;
void unknownOpt(std::string arg) const;
void requiresValue(std::string arg, OptType t) const;
void checkMandatories() const;
void shortHelp() const;
void showHelp() const;
public:
///Start the parsing process
ArgParser &parse();
/// Synonym for parse()
ArgParser &run()
{
return parse();
}
///Give back the command name (the 0th argument)
const std::string &commandName() const { return _command_name; }
///Check if an opion has been given to the command.
bool given(std::string op) const
{
Opts::const_iterator i = _opts.find(op);
return i!=_opts.end()?i->second.set:false;
}
///Magic type for operator[]
///This is the type of the return value of ArgParser::operator[]().
///It automatically converts to \c int, \c double, \c bool or
///\c std::string if the type of the option matches, which is checked
///with an \ref LEMON_ASSERT "assertion" (i.e. it performs runtime
///type checking).
class RefType
{
const ArgParser &_parser;
std::string _name;
public:
///\e
RefType(const ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
///\e
operator bool()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::BOOL,
std::string()+"'"+_name+"' is a bool option");
return *(i->second.bool_p);
}
///\e
operator std::string()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::STRING,
std::string()+"'"+_name+"' is a string option");
return *(i->second.string_p);
}
///\e
operator double()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::DOUBLE ||
i->second.type==ArgParser::INTEGER,
std::string()+"'"+_name+"' is a floating point option");
return i->second.type==ArgParser::DOUBLE ?
*(i->second.double_p) : *(i->second.int_p);
}
///\e
operator int()
{
Opts::const_iterator i = _parser._opts.find(_name);
LEMON_ASSERT(i!=_parser._opts.end(),
std::string()+"Unkown option: '"+_name+"'");
LEMON_ASSERT(i->second.type==ArgParser::INTEGER,
std::string()+"'"+_name+"' is an integer option");
return *(i->second.int_p);
}
};
///Give back the value of an option
///Give back the value of an option.
///\sa RefType
RefType operator[](const std::string &n) const
{
return RefType(*this, n);
}
///Give back the non-option type arguments.
///Give back a reference to a vector consisting of the program arguments
///not starting with a '-' character.
const std::vector<std::string> &files() const { return _file_args; }
///Throw instead of exit in case of problems
void throwOnProblems()
{
_exit_on_problems=false;
}
};
}
#endif // LEMON_ARG_PARSER_H

View File

@ -1,214 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_ASSERT_H
#define LEMON_ASSERT_H
/// \ingroup exceptions
/// \file
/// \brief Extended assertion handling
#include <lemon/error.h>
namespace lemon {
inline void assert_fail_abort(const char *file, int line,
const char *function, const char* message,
const char *assertion)
{
std::cerr << file << ":" << line << ": ";
if (function)
std::cerr << function << ": ";
std::cerr << message;
if (assertion)
std::cerr << " (assertion '" << assertion << "' failed)";
std::cerr << std::endl;
std::abort();
}
namespace _assert_bits {
inline const char* cstringify(const std::string& str) {
return str.c_str();
}
inline const char* cstringify(const char* str) {
return str;
}
}
}
#endif // LEMON_ASSERT_H
#undef LEMON_ASSERT
#undef LEMON_DEBUG
#if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
#error "LEMON assertion system is not set properly"
#endif
#if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \
defined(LEMON_ENABLE_ASSERTS)) && \
(defined(LEMON_DISABLE_ASSERTS) || \
defined(NDEBUG))
#error "LEMON assertion system is not set properly"
#endif
#if defined LEMON_ASSERT_ABORT
# undef LEMON_ASSERT_HANDLER
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
#elif defined LEMON_ASSERT_CUSTOM
# undef LEMON_ASSERT_HANDLER
# ifndef LEMON_CUSTOM_ASSERT_HANDLER
# error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
# endif
# define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
#elif defined LEMON_DISABLE_ASSERTS
# undef LEMON_ASSERT_HANDLER
#elif defined NDEBUG
# undef LEMON_ASSERT_HANDLER
#else
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
#endif
#ifndef LEMON_FUNCTION_NAME
# if defined __GNUC__
# define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
# elif defined _MSC_VER
# define LEMON_FUNCTION_NAME (__FUNCSIG__)
# elif __STDC_VERSION__ >= 199901L
# define LEMON_FUNCTION_NAME (__func__)
# else
# define LEMON_FUNCTION_NAME ("<unknown>")
# endif
#endif
#ifdef DOXYGEN
/// \ingroup exceptions
///
/// \brief Macro for assertion with customizable message
///
/// Macro for assertion with customizable message.
/// \param exp An expression that must be convertible to \c bool. If it is \c
/// false, then an assertion is raised. The concrete behaviour depends on the
/// settings of the assertion system.
/// \param msg A <tt>const char*</tt> parameter, which can be used to provide
/// information about the circumstances of the failed assertion.
///
/// The assertions are enabled in the default behaviour.
/// You can disable them with the following code:
/// \code
/// #define LEMON_DISABLE_ASSERTS
/// \endcode
/// or with compilation parameters:
/// \code
/// g++ -DLEMON_DISABLE_ASSERTS
/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
/// \endcode
/// The checking is also disabled when the standard macro \c NDEBUG is defined.
///
/// As a default behaviour the failed assertion prints a short log message to
/// the standard error and aborts the execution.
///
/// However, the following modes can be used in the assertion system:
/// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
/// the standard error and aborts the program. It is the default behaviour.
/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
/// function.
/// \code
/// void custom_assert_handler(const char* file, int line,
/// const char* function, const char* message,
/// const char* assertion);
/// \endcode
/// The name of the function should be defined as the \c
/// LEMON_CUSTOM_ASSERT_HANDLER macro name.
/// \code
/// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
/// \endcode
/// Whenever an assertion is occured, the custom assertion
/// handler is called with appropiate parameters.
///
/// The assertion mode can also be changed within one compilation unit.
/// If the macros are redefined with other settings and the
/// \ref lemon/assert.h "assert.h" file is reincluded, then the
/// behaviour is changed appropiately to the new settings.
# define LEMON_ASSERT(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), #exp), 0)))
/// \ingroup exceptions
///
/// \brief Macro for internal assertions
///
/// Macro for internal assertions, it is used in the library to check
/// the consistency of results of algorithms, several pre- and
/// postconditions and invariants. The checking is disabled by
/// default, but it can be turned on with the macro \c
/// LEMON_ENABLE_DEBUG.
/// \code
/// #define LEMON_ENABLE_DEBUG
/// \endcode
/// or with compilation parameters:
/// \code
/// g++ -DLEMON_ENABLE_DEBUG
/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
/// \endcode
///
/// This macro works like the \c LEMON_ASSERT macro, therefore the
/// current behaviour depends on the settings of \c LEMON_ASSERT
/// macro.
///
/// \see LEMON_ASSERT
# define LEMON_DEBUG(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), #exp), 0)))
#else
# ifndef LEMON_ASSERT_HANDLER
# define LEMON_ASSERT(exp, msg) (static_cast<void>(0))
# define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
# else
# define LEMON_ASSERT(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), \
#exp), 0)))
# if defined LEMON_ENABLE_DEBUG
# define LEMON_DEBUG(exp, msg) \
(static_cast<void> (!!(exp) ? 0 : ( \
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
LEMON_FUNCTION_NAME, \
::lemon::_assert_bits::cstringify(msg), \
#exp), 0)))
# else
# define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
# endif
# endif
#endif

View File

@ -1,37 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
///\file
///\brief Some basic non-inline functions and static global data.
#include<lemon/tolerance.h>
#include<lemon/core.h>
#include<lemon/time_measure.h>
namespace lemon {
float Tolerance<float>::def_epsilon = static_cast<float>(1e-4);
double Tolerance<double>::def_epsilon = 1e-10;
long double Tolerance<long double>::def_epsilon = 1e-14;
#ifndef LEMON_ONLY_TEMPLATES
const Invalid INVALID = Invalid();
#endif
TimeStamp::Format TimeStamp::_format = TimeStamp::NORMAL;
} //namespace lemon

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,347 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BIN_HEAP_H
#define LEMON_BIN_HEAP_H
///\ingroup heaps
///\file
///\brief Binary heap implementation.
#include <vector>
#include <utility>
#include <functional>
namespace lemon {
/// \ingroup heaps
///
/// \brief Binary heap data structure.
///
/// This class implements the \e binary \e heap data structure.
/// It fully conforms to the \ref concepts::Heap "heap concept".
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
#ifdef DOXYGEN
template <typename PR, typename IM, typename CMP>
#else
template <typename PR, typename IM, typename CMP = std::less<PR> >
#endif
class BinHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Type of the item-priority pairs.
typedef std::pair<Item,Prio> Pair;
/// Functor type for comparing the priorities.
typedef CMP Compare;
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
private:
std::vector<Pair> _data;
Compare _comp;
ItemIntMap &_iim;
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit BinHeap(ItemIntMap &map) : _iim(map) {}
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
BinHeap(ItemIntMap &map, const Compare &comp)
: _iim(map), _comp(comp) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _data.size(); }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _data.empty(); }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear();
}
private:
static int parent(int i) { return (i-1)/2; }
static int secondChild(int i) { return 2*i+2; }
bool less(const Pair &p1, const Pair &p2) const {
return _comp(p1.second, p2.second);
}
int bubbleUp(int hole, Pair p) {
int par = parent(hole);
while( hole>0 && less(p,_data[par]) ) {
move(_data[par],hole);
hole = par;
par = parent(hole);
}
move(p, hole);
return hole;
}
int bubbleDown(int hole, Pair p, int length) {
int child = secondChild(hole);
while(child < length) {
if( less(_data[child-1], _data[child]) ) {
--child;
}
if( !less(_data[child], p) )
goto ok;
move(_data[child], hole);
hole = child;
child = secondChild(hole);
}
child--;
if( child<length && less(_data[child], p) ) {
move(_data[child], hole);
hole=child;
}
ok:
move(p, hole);
return hole;
}
void move(const Pair &p, int i) {
_data[i] = p;
_iim.set(p.first, i);
}
public:
/// \brief Insert a pair of item and priority into the heap.
///
/// This function inserts \c p.first to the heap with priority
/// \c p.second.
/// \param p The pair to insert.
/// \pre \c p.first must not be stored in the heap.
void push(const Pair &p) {
int n = _data.size();
_data.resize(n+1);
bubbleUp(n, p);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param i The item to insert.
/// \param p The priority of the item.
/// \pre \e i must not be stored in the heap.
void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const {
return _data[0].first;
}
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const {
return _data[0].second;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
int n = _data.size()-1;
_iim.set(_data[0].first, POST_HEAP);
if (n > 0) {
bubbleDown(0, _data[n], n);
}
_data.pop_back();
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param i The item to delete.
/// \pre \e i must be in the heap.
void erase(const Item &i) {
int h = _iim[i];
int n = _data.size()-1;
_iim.set(_data[h].first, POST_HEAP);
if( h < n ) {
if ( bubbleUp(h, _data[n]) == h) {
bubbleDown(h, _data[n], n);
}
}
_data.pop_back();
}
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param i The item.
/// \pre \e i must be in the heap.
Prio operator[](const Item &i) const {
int idx = _iim[i];
return _data[idx].second;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param i The item.
/// \param p The priority.
void set(const Item &i, const Prio &p) {
int idx = _iim[i];
if( idx < 0 ) {
push(i,p);
}
else if( _comp(p, _data[idx].second) ) {
bubbleUp(idx, Pair(i,p));
}
else {
bubbleDown(idx, Pair(i,p), _data.size());
}
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at least \e p.
void decrease(const Item &i, const Prio &p) {
int idx = _iim[i];
bubbleUp(idx, Pair(i,p));
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param i The item.
/// \param p The priority.
/// \pre \e i must be stored in the heap with priority at most \e p.
void increase(const Item &i, const Prio &p) {
int idx = _iim[i];
bubbleDown(idx, Pair(i,p), _data.size());
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param i The item.
State state(const Item &i) const {
int s = _iim[i];
if( s>=0 )
s=0;
return State(s);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) {
erase(i);
}
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
/// \brief Replace an item in the heap.
///
/// This function replaces item \c i with item \c j.
/// Item \c i must be in the heap, while \c j must be out of the heap.
/// After calling this method, item \c i will be out of the
/// heap and \c j will be in the heap with the same prioriority
/// as item \c i had before.
void replace(const Item& i, const Item& j) {
int idx = _iim[i];
_iim.set(i, _iim[j]);
_iim.set(j, idx);
_data[idx].first = j;
}
}; // class BinHeap
} // namespace lemon
#endif // LEMON_BIN_HEAP_H

View File

@ -1,445 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2010
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BINOMIAL_HEAP_H
#define LEMON_BINOMIAL_HEAP_H
///\file
///\ingroup heaps
///\brief Binomial Heap implementation.
#include <vector>
#include <utility>
#include <functional>
#include <lemon/math.h>
#include <lemon/counter.h>
namespace lemon {
/// \ingroup heaps
///
///\brief Binomial heap data structure.
///
/// This class implements the \e binomial \e heap data structure.
/// It fully conforms to the \ref concepts::Heap "heap concept".
///
/// The methods \ref increase() and \ref erase() are not efficient
/// in a binomial heap. In case of many calls of these operations,
/// it is better to use other heap structure, e.g. \ref BinHeap
/// "binary heap".
///
/// \tparam PR Type of the priorities of the items.
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam CMP A functor class for comparing the priorities.
/// The default is \c std::less<PR>.
#ifdef DOXYGEN
template <typename PR, typename IM, typename CMP>
#else
template <typename PR, typename IM, typename CMP = std::less<PR> >
#endif
class BinomialHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef PR Prio;
/// Type of the items stored in the heap.
typedef typename ItemIntMap::Key Item;
/// Functor type for comparing the priorities.
typedef CMP Compare;
/// \brief Type to represent the states of the items.
///
/// Each item has a state associated to it. It can be "in heap",
/// "pre-heap" or "post-heap". The latter two are indifferent from the
/// heap's point of view, but may be useful to the user.
///
/// The item-int map must be initialized in such way that it assigns
/// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
enum State {
IN_HEAP = 0, ///< = 0.
PRE_HEAP = -1, ///< = -1.
POST_HEAP = -2 ///< = -2.
};
private:
class Store;
std::vector<Store> _data;
int _min, _head;
ItemIntMap &_iim;
Compare _comp;
int _num_items;
public:
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
explicit BinomialHeap(ItemIntMap &map)
: _min(0), _head(-1), _iim(map), _num_items(0) {}
/// \brief Constructor.
///
/// Constructor.
/// \param map A map that assigns \c int values to the items.
/// It is used internally to handle the cross references.
/// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
/// \param comp The function object used for comparing the priorities.
BinomialHeap(ItemIntMap &map, const Compare &comp)
: _min(0), _head(-1), _iim(map), _comp(comp), _num_items(0) {}
/// \brief The number of items stored in the heap.
///
/// This function returns the number of items stored in the heap.
int size() const { return _num_items; }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _num_items==0; }
/// \brief Make the heap empty.
///
/// This functon makes the heap empty.
/// It does not change the cross reference map. If you want to reuse
/// a heap that is not surely empty, you should first clear it and
/// then you should set the cross reference map to \c PRE_HEAP
/// for each item.
void clear() {
_data.clear(); _min=0; _num_items=0; _head=-1;
}
/// \brief Set the priority of an item or insert it, if it is
/// not stored in the heap.
///
/// This method sets the priority of the given item if it is
/// already stored in the heap. Otherwise it inserts the given
/// item into the heap with the given priority.
/// \param item The item.
/// \param value The priority.
void set (const Item& item, const Prio& value) {
int i=_iim[item];
if ( i >= 0 && _data[i].in ) {
if ( _comp(value, _data[i].prio) ) decrease(item, value);
if ( _comp(_data[i].prio, value) ) increase(item, value);
} else push(item, value);
}
/// \brief Insert an item into the heap with the given priority.
///
/// This function inserts the given item into the heap with the
/// given priority.
/// \param item The item to insert.
/// \param value The priority of the item.
/// \pre \e item must not be stored in the heap.
void push (const Item& item, const Prio& value) {
int i=_iim[item];
if ( i<0 ) {
int s=_data.size();
_iim.set( item,s );
Store st;
st.name=item;
st.prio=value;
_data.push_back(st);
i=s;
}
else {
_data[i].parent=_data[i].right_neighbor=_data[i].child=-1;
_data[i].degree=0;
_data[i].in=true;
_data[i].prio=value;
}
if( 0==_num_items ) {
_head=i;
_min=i;
} else {
merge(i);
if( _comp(_data[i].prio, _data[_min].prio) ) _min=i;
}
++_num_items;
}
/// \brief Return the item having minimum priority.
///
/// This function returns the item having minimum priority.
/// \pre The heap must be non-empty.
Item top() const { return _data[_min].name; }
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const { return _data[_min].prio; }
/// \brief The priority of the given item.
///
/// This function returns the priority of the given item.
/// \param item The item.
/// \pre \e item must be in the heap.
const Prio& operator[](const Item& item) const {
return _data[_iim[item]].prio;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
_data[_min].in=false;
int head_child=-1;
if ( _data[_min].child!=-1 ) {
int child=_data[_min].child;
int neighb;
while( child!=-1 ) {
neighb=_data[child].right_neighbor;
_data[child].parent=-1;
_data[child].right_neighbor=head_child;
head_child=child;
child=neighb;
}
}
if ( _data[_head].right_neighbor==-1 ) {
// there was only one root
_head=head_child;
}
else {
// there were more roots
if( _head!=_min ) { unlace(_min); }
else { _head=_data[_head].right_neighbor; }
merge(head_child);
}
_min=findMin();
--_num_items;
}
/// \brief Remove the given item from the heap.
///
/// This function removes the given item from the heap if it is
/// already stored.
/// \param item The item to delete.
/// \pre \e item must be in the heap.
void erase (const Item& item) {
int i=_iim[item];
if ( i >= 0 && _data[i].in ) {
decrease( item, _data[_min].prio-1 );
pop();
}
}
/// \brief Decrease the priority of an item to the given value.
///
/// This function decreases the priority of an item to the given value.
/// \param item The item.
/// \param value The priority.
/// \pre \e item must be stored in the heap with priority at least \e value.
void decrease (Item item, const Prio& value) {
int i=_iim[item];
int p=_data[i].parent;
_data[i].prio=value;
while( p!=-1 && _comp(value, _data[p].prio) ) {
_data[i].name=_data[p].name;
_data[i].prio=_data[p].prio;
_data[p].name=item;
_data[p].prio=value;
_iim[_data[i].name]=i;
i=p;
p=_data[p].parent;
}
_iim[item]=i;
if ( _comp(value, _data[_min].prio) ) _min=i;
}
/// \brief Increase the priority of an item to the given value.
///
/// This function increases the priority of an item to the given value.
/// \param item The item.
/// \param value The priority.
/// \pre \e item must be stored in the heap with priority at most \e value.
void increase (Item item, const Prio& value) {
erase(item);
push(item, value);
}
/// \brief Return the state of an item.
///
/// This method returns \c PRE_HEAP if the given item has never
/// been in the heap, \c IN_HEAP if it is in the heap at the moment,
/// and \c POST_HEAP otherwise.
/// In the latter case it is possible that the item will get back
/// to the heap again.
/// \param item The item.
State state(const Item &item) const {
int i=_iim[item];
if( i>=0 ) {
if ( _data[i].in ) i=0;
else i=-2;
}
return State(i);
}
/// \brief Set the state of an item in the heap.
///
/// This function sets the state of the given item in the heap.
/// It can be used to manually clear the heap when it is important
/// to achive better time complexity.
/// \param i The item.
/// \param st The state. It should not be \c IN_HEAP.
void state(const Item& i, State st) {
switch (st) {
case POST_HEAP:
case PRE_HEAP:
if (state(i) == IN_HEAP) {
erase(i);
}
_iim[i] = st;
break;
case IN_HEAP:
break;
}
}
private:
// Find the minimum of the roots
int findMin() {
if( _head!=-1 ) {
int min_loc=_head, min_val=_data[_head].prio;
for( int x=_data[_head].right_neighbor; x!=-1;
x=_data[x].right_neighbor ) {
if( _comp( _data[x].prio,min_val ) ) {
min_val=_data[x].prio;
min_loc=x;
}
}
return min_loc;
}
else return -1;
}
// Merge the heap with another heap starting at the given position
void merge(int a) {
if( _head==-1 || a==-1 ) return;
if( _data[a].right_neighbor==-1 &&
_data[a].degree<=_data[_head].degree ) {
_data[a].right_neighbor=_head;
_head=a;
} else {
interleave(a);
}
if( _data[_head].right_neighbor==-1 ) return;
int x=_head;
int x_prev=-1, x_next=_data[x].right_neighbor;
while( x_next!=-1 ) {
if( _data[x].degree!=_data[x_next].degree ||
( _data[x_next].right_neighbor!=-1 &&
_data[_data[x_next].right_neighbor].degree==_data[x].degree ) ) {
x_prev=x;
x=x_next;
}
else {
if( _comp(_data[x_next].prio,_data[x].prio) ) {
if( x_prev==-1 ) {
_head=x_next;
} else {
_data[x_prev].right_neighbor=x_next;
}
fuse(x,x_next);
x=x_next;
}
else {
_data[x].right_neighbor=_data[x_next].right_neighbor;
fuse(x_next,x);
}
}
x_next=_data[x].right_neighbor;
}
}
// Interleave the elements of the given list into the list of the roots
void interleave(int a) {
int p=_head, q=a;
int curr=_data.size();
_data.push_back(Store());
while( p!=-1 || q!=-1 ) {
if( q==-1 || ( p!=-1 && _data[p].degree<_data[q].degree ) ) {
_data[curr].right_neighbor=p;
curr=p;
p=_data[p].right_neighbor;
}
else {
_data[curr].right_neighbor=q;
curr=q;
q=_data[q].right_neighbor;
}
}
_head=_data.back().right_neighbor;
_data.pop_back();
}
// Lace node a under node b
void fuse(int a, int b) {
_data[a].parent=b;
_data[a].right_neighbor=_data[b].child;
_data[b].child=a;
++_data[b].degree;
}
// Unlace node a (if it has siblings)
void unlace(int a) {
int neighb=_data[a].right_neighbor;
int other=_head;
while( _data[other].right_neighbor!=a )
other=_data[other].right_neighbor;
_data[other].right_neighbor=neighb;
}
private:
class Store {
friend class BinomialHeap;
Item name;
int parent;
int right_neighbor;
int child;
int degree;
bool in;
Prio prio;
Store() : parent(-1), right_neighbor(-1), child(-1), degree(0),
in(true) {}
};
};
} //namespace lemon
#endif //LEMON_BINOMIAL_HEAP_H

View File

@ -1,472 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H
#define LEMON_BITS_ALTERATION_NOTIFIER_H
#include <vector>
#include <list>
#include <lemon/core.h>
#include <lemon/bits/lock.h>
//\ingroup graphbits
//\file
//\brief Observer notifier for graph alteration observers.
namespace lemon {
// \ingroup graphbits
//
// \brief Notifier class to notify observes about alterations in
// a container.
//
// The simple graphs can be refered as two containers: a node container
// and an edge container. But they do not store values directly, they
// are just key continars for more value containers, which are the
// node and edge maps.
//
// The node and edge sets of the graphs can be changed as we add or erase
// nodes and edges in the graph. LEMON would like to handle easily
// that the node and edge maps should contain values for all nodes or
// edges. If we want to check on every indicing if the map contains
// the current indicing key that cause a drawback in the performance
// in the library. We use another solution: we notify all maps about
// an alteration in the graph, which cause only drawback on the
// alteration of the graph.
//
// This class provides an interface to a node or edge container.
// The first() and next() member functions make possible
// to iterate on the keys of the container.
// The id() function returns an integer id for each key.
// The maxId() function gives back an upper bound of the ids.
//
// For the proper functonality of this class, we should notify it
// about each alteration in the container. The alterations have four type:
// add(), erase(), build() and clear(). The add() and
// erase() signal that only one or few items added or erased to or
// from the graph. If all items are erased from the graph or if a new graph
// is built from an empty graph, then it can be signaled with the
// clear() and build() members. Important rule that if we erase items
// from graphs we should first signal the alteration and after that erase
// them from the container, on the other way on item addition we should
// first extend the container and just after that signal the alteration.
//
// The alteration can be observed with a class inherited from the
// ObserverBase nested class. The signals can be handled with
// overriding the virtual functions defined in the base class. The
// observer base can be attached to the notifier with the
// attach() member and can be detached with detach() function. The
// alteration handlers should not call any function which signals
// an other alteration in the same notifier and should not
// detach any observer from the notifier.
//
// Alteration observers try to be exception safe. If an add() or
// a clear() function throws an exception then the remaining
// observeres will not be notified and the fulfilled additions will
// be rolled back by calling the erase() or clear() functions.
// Hence erase() and clear() should not throw exception.
// Actullay, they can throw only \ref ImmediateDetach exception,
// which detach the observer from the notifier.
//
// There are some cases, when the alteration observing is not completly
// reliable. If we want to carry out the node degree in the graph
// as in the \ref InDegMap and we use the reverseArc(), then it cause
// unreliable functionality. Because the alteration observing signals
// only erasing and adding but not the reversing, it will stores bad
// degrees. Apart form that the subgraph adaptors cannot even signal
// the alterations because just a setting in the filter map can modify
// the graph and this cannot be watched in any way.
//
// \param _Container The container which is observed.
// \param _Item The item type which is obserbved.
template <typename _Container, typename _Item>
class AlterationNotifier {
public:
typedef True Notifier;
typedef _Container Container;
typedef _Item Item;
// \brief Exception which can be called from clear() and
// erase().
//
// From the clear() and erase() function only this
// exception is allowed to throw. The exception immediatly
// detaches the current observer from the notifier. Because the
// clear() and erase() should not throw other exceptions
// it can be used to invalidate the observer.
struct ImmediateDetach {};
// \brief ObserverBase is the base class for the observers.
//
// ObserverBase is the abstract base class for the observers.
// It will be notified about an item was inserted into or
// erased from the graph.
//
// The observer interface contains some pure virtual functions
// to override. The add() and erase() functions are
// to notify the oberver when one item is added or erased.
//
// The build() and clear() members are to notify the observer
// about the container is built from an empty container or
// is cleared to an empty container.
class ObserverBase {
protected:
typedef AlterationNotifier Notifier;
friend class AlterationNotifier;
// \brief Default constructor.
//
// Default constructor for ObserverBase.
ObserverBase() : _notifier(0) {}
// \brief Constructor which attach the observer into notifier.
//
// Constructor which attach the observer into notifier.
ObserverBase(AlterationNotifier& nf) {
attach(nf);
}
// \brief Constructor which attach the obserever to the same notifier.
//
// Constructor which attach the obserever to the same notifier as
// the other observer is attached to.
ObserverBase(const ObserverBase& copy) {
if (copy.attached()) {
attach(*copy.notifier());
}
}
// \brief Destructor
virtual ~ObserverBase() {
if (attached()) {
detach();
}
}
// \brief Attaches the observer into an AlterationNotifier.
//
// This member attaches the observer into an AlterationNotifier.
void attach(AlterationNotifier& nf) {
nf.attach(*this);
}
// \brief Detaches the observer into an AlterationNotifier.
//
// This member detaches the observer from an AlterationNotifier.
void detach() {
_notifier->detach(*this);
}
// \brief Gives back a pointer to the notifier which the map
// attached into.
//
// This function gives back a pointer to the notifier which the map
// attached into.
Notifier* notifier() const { return const_cast<Notifier*>(_notifier); }
// Gives back true when the observer is attached into a notifier.
bool attached() const { return _notifier != 0; }
private:
ObserverBase& operator=(const ObserverBase& copy);
protected:
Notifier* _notifier;
typename std::list<ObserverBase*>::iterator _index;
// \brief The member function to notificate the observer about an
// item is added to the container.
//
// The add() member function notificates the observer about an item
// is added to the container. It have to be overrided in the
// subclasses.
virtual void add(const Item&) = 0;
// \brief The member function to notificate the observer about
// more item is added to the container.
//
// The add() member function notificates the observer about more item
// is added to the container. It have to be overrided in the
// subclasses.
virtual void add(const std::vector<Item>& items) = 0;
// \brief The member function to notificate the observer about an
// item is erased from the container.
//
// The erase() member function notificates the observer about an
// item is erased from the container. It have to be overrided in
// the subclasses.
virtual void erase(const Item&) = 0;
// \brief The member function to notificate the observer about
// more item is erased from the container.
//
// The erase() member function notificates the observer about more item
// is erased from the container. It have to be overrided in the
// subclasses.
virtual void erase(const std::vector<Item>& items) = 0;
// \brief The member function to notificate the observer about the
// container is built.
//
// The build() member function notificates the observer about the
// container is built from an empty container. It have to be
// overrided in the subclasses.
virtual void build() = 0;
// \brief The member function to notificate the observer about all
// items are erased from the container.
//
// The clear() member function notificates the observer about all
// items are erased from the container. It have to be overrided in
// the subclasses.
virtual void clear() = 0;
};
protected:
const Container* container;
typedef std::list<ObserverBase*> Observers;
Observers _observers;
lemon::bits::Lock _lock;
public:
// \brief Default constructor.
//
// The default constructor of the AlterationNotifier.
// It creates an empty notifier.
AlterationNotifier()
: container(0) {}
// \brief Constructor.
//
// Constructor with the observed container parameter.
AlterationNotifier(const Container& _container)
: container(&_container) {}
// \brief Copy Constructor of the AlterationNotifier.
//
// Copy constructor of the AlterationNotifier.
// It creates only an empty notifier because the copiable
// notifier's observers have to be registered still into that notifier.
AlterationNotifier(const AlterationNotifier& _notifier)
: container(_notifier.container) {}
// \brief Destructor.
//
// Destructor of the AlterationNotifier.
~AlterationNotifier() {
typename Observers::iterator it;
for (it = _observers.begin(); it != _observers.end(); ++it) {
(*it)->_notifier = 0;
}
}
// \brief Sets the container.
//
// Sets the container.
void setContainer(const Container& _container) {
container = &_container;
}
protected:
AlterationNotifier& operator=(const AlterationNotifier&);
public:
// \brief First item in the container.
//
// Returns the first item in the container. It is
// for start the iteration on the container.
void first(Item& item) const {
container->first(item);
}
// \brief Next item in the container.
//
// Returns the next item in the container. It is
// for iterate on the container.
void next(Item& item) const {
container->next(item);
}
// \brief Returns the id of the item.
//
// Returns the id of the item provided by the container.
int id(const Item& item) const {
return container->id(item);
}
// \brief Returns the maximum id of the container.
//
// Returns the maximum id of the container.
int maxId() const {
return container->maxId(Item());
}
protected:
void attach(ObserverBase& observer) {
_lock.lock();
observer._index = _observers.insert(_observers.begin(), &observer);
observer._notifier = this;
_lock.unlock();
}
void detach(ObserverBase& observer) {
_lock.lock();
_observers.erase(observer._index);
observer._index = _observers.end();
observer._notifier = 0;
_lock.unlock();
}
public:
// \brief Notifies all the registed observers about an item added to
// the container.
//
// It notifies all the registed observers about an item added to
// the container.
void add(const Item& item) {
typename Observers::reverse_iterator it;
try {
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
(*it)->add(item);
}
} catch (...) {
typename Observers::iterator jt;
for (jt = it.base(); jt != _observers.end(); ++jt) {
(*jt)->erase(item);
}
throw;
}
}
// \brief Notifies all the registed observers about more item added to
// the container.
//
// It notifies all the registed observers about more item added to
// the container.
void add(const std::vector<Item>& items) {
typename Observers::reverse_iterator it;
try {
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
(*it)->add(items);
}
} catch (...) {
typename Observers::iterator jt;
for (jt = it.base(); jt != _observers.end(); ++jt) {
(*jt)->erase(items);
}
throw;
}
}
// \brief Notifies all the registed observers about an item erased from
// the container.
//
// It notifies all the registed observers about an item erased from
// the container.
void erase(const Item& item) throw() {
typename Observers::iterator it = _observers.begin();
while (it != _observers.end()) {
try {
(*it)->erase(item);
++it;
} catch (const ImmediateDetach&) {
(*it)->_index = _observers.end();
(*it)->_notifier = 0;
it = _observers.erase(it);
}
}
}
// \brief Notifies all the registed observers about more item erased
// from the container.
//
// It notifies all the registed observers about more item erased from
// the container.
void erase(const std::vector<Item>& items) {
typename Observers::iterator it = _observers.begin();
while (it != _observers.end()) {
try {
(*it)->erase(items);
++it;
} catch (const ImmediateDetach&) {
(*it)->_index = _observers.end();
(*it)->_notifier = 0;
it = _observers.erase(it);
}
}
}
// \brief Notifies all the registed observers about the container is
// built.
//
// Notifies all the registed observers about the container is built
// from an empty container.
void build() {
typename Observers::reverse_iterator it;
try {
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
(*it)->build();
}
} catch (...) {
typename Observers::iterator jt;
for (jt = it.base(); jt != _observers.end(); ++jt) {
(*jt)->clear();
}
throw;
}
}
// \brief Notifies all the registed observers about all items are
// erased.
//
// Notifies all the registed observers about all items are erased
// from the container.
void clear() {
typename Observers::iterator it = _observers.begin();
while (it != _observers.end()) {
try {
(*it)->clear();
++it;
} catch (const ImmediateDetach&) {
(*it)->_index = _observers.end();
(*it)->_notifier = 0;
it = _observers.erase(it);
}
}
}
};
}
#endif

View File

@ -1,351 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_ARRAY_MAP_H
#define LEMON_BITS_ARRAY_MAP_H
#include <memory>
#include <lemon/bits/traits.h>
#include <lemon/bits/alteration_notifier.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
// \ingroup graphbits
// \file
// \brief Graph map based on the array storage.
namespace lemon {
// \ingroup graphbits
//
// \brief Graph map based on the array storage.
//
// The ArrayMap template class is graph map structure that automatically
// updates the map when a key is added to or erased from the graph.
// This map uses the allocators to implement the container functionality.
//
// The template parameters are the Graph, the current Item type and
// the Value type of the map.
template <typename _Graph, typename _Item, typename _Value>
class ArrayMap
: public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
public:
// The graph type.
typedef _Graph GraphType;
// The item type.
typedef _Item Item;
// The reference map tag.
typedef True ReferenceMapTag;
// The key type of the map.
typedef _Item Key;
// The value type of the map.
typedef _Value Value;
// The const reference type of the map.
typedef const _Value& ConstReference;
// The reference type of the map.
typedef _Value& Reference;
// The map type.
typedef ArrayMap Map;
// The notifier type.
typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
private:
// The MapBase of the Map which imlements the core regisitry function.
typedef typename Notifier::ObserverBase Parent;
typedef std::allocator<Value> Allocator;
public:
// \brief Graph initialized map constructor.
//
// Graph initialized map constructor.
explicit ArrayMap(const GraphType& graph) {
Parent::attach(graph.notifier(Item()));
allocate_memory();
Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), Value());
}
}
// \brief Constructor to use default value to initialize the map.
//
// It constructs a map and initialize all of the the map.
ArrayMap(const GraphType& graph, const Value& value) {
Parent::attach(graph.notifier(Item()));
allocate_memory();
Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), value);
}
}
private:
// \brief Constructor to copy a map of the same map type.
//
// Constructor to copy a map of the same map type.
ArrayMap(const ArrayMap& copy) : Parent() {
if (copy.attached()) {
attach(*copy.notifier());
}
capacity = copy.capacity;
if (capacity == 0) return;
values = allocator.allocate(capacity);
Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), copy.values[id]);
}
}
// \brief Assign operator.
//
// This operator assigns for each item in the map the
// value mapped to the same item in the copied map.
// The parameter map should be indiced with the same
// itemset because this assign operator does not change
// the container of the map.
ArrayMap& operator=(const ArrayMap& cmap) {
return operator=<ArrayMap>(cmap);
}
// \brief Template assign operator.
//
// The given parameter should conform to the ReadMap
// concecpt and could be indiced by the current item set of
// the NodeMap. In this case the value for each item
// is assigned by the value of the given ReadMap.
template <typename CMap>
ArrayMap& operator=(const CMap& cmap) {
checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
const typename Parent::Notifier* nf = Parent::notifier();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
set(it, cmap[it]);
}
return *this;
}
public:
// \brief The destructor of the map.
//
// The destructor of the map.
virtual ~ArrayMap() {
if (attached()) {
clear();
detach();
}
}
protected:
using Parent::attach;
using Parent::detach;
using Parent::attached;
public:
// \brief The subscript operator.
//
// The subscript operator. The map can be subscripted by the
// actual keys of the graph.
Value& operator[](const Key& key) {
int id = Parent::notifier()->id(key);
return values[id];
}
// \brief The const subscript operator.
//
// The const subscript operator. The map can be subscripted by the
// actual keys of the graph.
const Value& operator[](const Key& key) const {
int id = Parent::notifier()->id(key);
return values[id];
}
// \brief Setter function of the map.
//
// Setter function of the map. Equivalent with map[key] = val.
// This is a compatibility feature with the not dereferable maps.
void set(const Key& key, const Value& val) {
(*this)[key] = val;
}
protected:
// \brief Adds a new key to the map.
//
// It adds a new key to the map. It is called by the observer notifier
// and it overrides the add() member function of the observer base.
virtual void add(const Key& key) {
Notifier* nf = Parent::notifier();
int id = nf->id(key);
if (id >= capacity) {
int new_capacity = (capacity == 0 ? 1 : capacity);
while (new_capacity <= id) {
new_capacity <<= 1;
}
Value* new_values = allocator.allocate(new_capacity);
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int jd = nf->id(it);;
if (id != jd) {
allocator.construct(&(new_values[jd]), values[jd]);
allocator.destroy(&(values[jd]));
}
}
if (capacity != 0) allocator.deallocate(values, capacity);
values = new_values;
capacity = new_capacity;
}
allocator.construct(&(values[id]), Value());
}
// \brief Adds more new keys to the map.
//
// It adds more new keys to the map. It is called by the observer notifier
// and it overrides the add() member function of the observer base.
virtual void add(const std::vector<Key>& keys) {
Notifier* nf = Parent::notifier();
int max_id = -1;
for (int i = 0; i < int(keys.size()); ++i) {
int id = nf->id(keys[i]);
if (id > max_id) {
max_id = id;
}
}
if (max_id >= capacity) {
int new_capacity = (capacity == 0 ? 1 : capacity);
while (new_capacity <= max_id) {
new_capacity <<= 1;
}
Value* new_values = allocator.allocate(new_capacity);
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);
bool found = false;
for (int i = 0; i < int(keys.size()); ++i) {
int jd = nf->id(keys[i]);
if (id == jd) {
found = true;
break;
}
}
if (found) continue;
allocator.construct(&(new_values[id]), values[id]);
allocator.destroy(&(values[id]));
}
if (capacity != 0) allocator.deallocate(values, capacity);
values = new_values;
capacity = new_capacity;
}
for (int i = 0; i < int(keys.size()); ++i) {
int id = nf->id(keys[i]);
allocator.construct(&(values[id]), Value());
}
}
// \brief Erase a key from the map.
//
// Erase a key from the map. It is called by the observer notifier
// and it overrides the erase() member function of the observer base.
virtual void erase(const Key& key) {
int id = Parent::notifier()->id(key);
allocator.destroy(&(values[id]));
}
// \brief Erase more keys from the map.
//
// Erase more keys from the map. It is called by the observer notifier
// and it overrides the erase() member function of the observer base.
virtual void erase(const std::vector<Key>& keys) {
for (int i = 0; i < int(keys.size()); ++i) {
int id = Parent::notifier()->id(keys[i]);
allocator.destroy(&(values[id]));
}
}
// \brief Builds the map.
//
// It builds the map. It is called by the observer notifier
// and it overrides the build() member function of the observer base.
virtual void build() {
Notifier* nf = Parent::notifier();
allocate_memory();
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);;
allocator.construct(&(values[id]), Value());
}
}
// \brief Clear the map.
//
// It erase all items from the map. It is called by the observer notifier
// and it overrides the clear() member function of the observer base.
virtual void clear() {
Notifier* nf = Parent::notifier();
if (capacity != 0) {
Item it;
for (nf->first(it); it != INVALID; nf->next(it)) {
int id = nf->id(it);
allocator.destroy(&(values[id]));
}
allocator.deallocate(values, capacity);
capacity = 0;
}
}
private:
void allocate_memory() {
int max_id = Parent::notifier()->maxId();
if (max_id == -1) {
capacity = 0;
values = 0;
return;
}
capacity = 1;
while (capacity <= max_id) {
capacity <<= 1;
}
values = allocator.allocate(capacity);
}
int capacity;
Value* values;
Allocator allocator;
};
}
#endif

View File

@ -1,174 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BEZIER_H
#define LEMON_BEZIER_H
//\ingroup misc
//\file
//\brief Classes to compute with Bezier curves.
//
//Up to now this file is used internally by \ref graph_to_eps.h
#include<lemon/dim2.h>
namespace lemon {
namespace dim2 {
class BezierBase {
public:
typedef lemon::dim2::Point<double> Point;
protected:
static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
};
class Bezier1 : public BezierBase
{
public:
Point p1,p2;
Bezier1() {}
Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
Point operator()(double t) const
{
// return conv(conv(p1,p2,t),conv(p2,p3,t),t);
return conv(p1,p2,t);
}
Bezier1 before(double t) const
{
return Bezier1(p1,conv(p1,p2,t));
}
Bezier1 after(double t) const
{
return Bezier1(conv(p1,p2,t),p2);
}
Bezier1 revert() const { return Bezier1(p2,p1);}
Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
Point grad() const { return p2-p1; }
Point norm() const { return rot90(p2-p1); }
Point grad(double) const { return grad(); }
Point norm(double t) const { return rot90(grad(t)); }
};
class Bezier2 : public BezierBase
{
public:
Point p1,p2,p3;
Bezier2() {}
Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
Point operator()(double t) const
{
// return conv(conv(p1,p2,t),conv(p2,p3,t),t);
return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
}
Bezier2 before(double t) const
{
Point q(conv(p1,p2,t));
Point r(conv(p2,p3,t));
return Bezier2(p1,q,conv(q,r,t));
}
Bezier2 after(double t) const
{
Point q(conv(p1,p2,t));
Point r(conv(p2,p3,t));
return Bezier2(conv(q,r,t),r,p3);
}
Bezier2 revert() const { return Bezier2(p3,p2,p1);}
Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
Point grad(double t) const { return grad()(t); }
Point norm(double t) const { return rot90(grad(t)); }
};
class Bezier3 : public BezierBase
{
public:
Point p1,p2,p3,p4;
Bezier3() {}
Bezier3(Point _p1, Point _p2, Point _p3, Point _p4)
: p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)),
p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
Point operator()(double t) const
{
// return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
(3*t*t*(1-t))*p3+(t*t*t)*p4;
}
Bezier3 before(double t) const
{
Point p(conv(p1,p2,t));
Point q(conv(p2,p3,t));
Point r(conv(p3,p4,t));
Point a(conv(p,q,t));
Point b(conv(q,r,t));
Point c(conv(a,b,t));
return Bezier3(p1,p,a,c);
}
Bezier3 after(double t) const
{
Point p(conv(p1,p2,t));
Point q(conv(p2,p3,t));
Point r(conv(p3,p4,t));
Point a(conv(p,q,t));
Point b(conv(q,r,t));
Point c(conv(a,b,t));
return Bezier3(c,b,r,p4);
}
Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
3.0*rot90(p3-p2),
3.0*rot90(p4-p3)); }
Point grad(double t) const { return grad()(t); }
Point norm(double t) const { return rot90(grad(t)); }
template<class R,class F,class S,class D>
R recSplit(F &_f,const S &_s,D _d) const
{
const Point a=(p1+p2)/2;
const Point b=(p2+p3)/2;
const Point c=(p3+p4)/2;
const Point d=(a+b)/2;
const Point e=(b+c)/2;
// const Point f=(d+e)/2;
R f1=_f(Bezier3(p1,a,d,e),_d);
R f2=_f(Bezier3(e,d,c,p4),_d);
return _s(f1,f2);
}
};
} //END OF NAMESPACE dim2
} //END OF NAMESPACE lemon
#endif // LEMON_BEZIER_H

View File

@ -1,182 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_DEFAULT_MAP_H
#define LEMON_BITS_DEFAULT_MAP_H
#include <lemon/config.h>
#include <lemon/bits/array_map.h>
#include <lemon/bits/vector_map.h>
//#include <lemon/bits/debug_map.h>
//\ingroup graphbits
//\file
//\brief Graph maps that construct and destruct their elements dynamically.
namespace lemon {
//#ifndef LEMON_USE_DEBUG_MAP
template <typename _Graph, typename _Item, typename _Value>
struct DefaultMapSelector {
typedef ArrayMap<_Graph, _Item, _Value> Map;
};
// bool
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, bool> {
typedef VectorMap<_Graph, _Item, bool> Map;
};
// char
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, char> {
typedef VectorMap<_Graph, _Item, char> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed char> {
typedef VectorMap<_Graph, _Item, signed char> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned char> {
typedef VectorMap<_Graph, _Item, unsigned char> Map;
};
// int
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed int> {
typedef VectorMap<_Graph, _Item, signed int> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned int> {
typedef VectorMap<_Graph, _Item, unsigned int> Map;
};
// short
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed short> {
typedef VectorMap<_Graph, _Item, signed short> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned short> {
typedef VectorMap<_Graph, _Item, unsigned short> Map;
};
// long
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed long> {
typedef VectorMap<_Graph, _Item, signed long> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned long> {
typedef VectorMap<_Graph, _Item, unsigned long> Map;
};
#if defined LEMON_HAVE_LONG_LONG
// long long
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, signed long long> {
typedef VectorMap<_Graph, _Item, signed long long> Map;
};
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, unsigned long long> {
typedef VectorMap<_Graph, _Item, unsigned long long> Map;
};
#endif
// float
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, float> {
typedef VectorMap<_Graph, _Item, float> Map;
};
// double
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, double> {
typedef VectorMap<_Graph, _Item, double> Map;
};
// long double
template <typename _Graph, typename _Item>
struct DefaultMapSelector<_Graph, _Item, long double> {
typedef VectorMap<_Graph, _Item, long double> Map;
};
// pointer
template <typename _Graph, typename _Item, typename _Ptr>
struct DefaultMapSelector<_Graph, _Item, _Ptr*> {
typedef VectorMap<_Graph, _Item, _Ptr*> Map;
};
// #else
// template <typename _Graph, typename _Item, typename _Value>
// struct DefaultMapSelector {
// typedef DebugMap<_Graph, _Item, _Value> Map;
// };
// #endif
// DefaultMap class
template <typename _Graph, typename _Item, typename _Value>
class DefaultMap
: public DefaultMapSelector<_Graph, _Item, _Value>::Map {
typedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent;
public:
typedef DefaultMap<_Graph, _Item, _Value> Map;
typedef typename Parent::GraphType GraphType;
typedef typename Parent::Value Value;
explicit DefaultMap(const GraphType& graph) : Parent(graph) {}
DefaultMap(const GraphType& graph, const Value& value)
: Parent(graph, value) {}
DefaultMap& operator=(const DefaultMap& cmap) {
return operator=<DefaultMap>(cmap);
}
template <typename CMap>
DefaultMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
}
#endif

View File

@ -1,627 +0,0 @@
/* -*- mode: C++; indent-tabs-mode: nil; -*-
*
* This file is a part of LEMON, a generic C++ optimization library.
*
* Copyright (C) 2003-2013
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_BITS_EDGE_SET_EXTENDER_H
#define LEMON_BITS_EDGE_SET_EXTENDER_H
#include <lemon/core.h>
#include <lemon/error.h>
#include <lemon/bits/default_map.h>
#include <lemon/bits/map_extender.h>
//\ingroup digraphbits
//\file
//\brief Extenders for the arc set types
namespace lemon {
// \ingroup digraphbits
//
// \brief Extender for the ArcSets
template <typename Base>
class ArcSetExtender : public Base {
typedef Base Parent;
public:
typedef ArcSetExtender Digraph;
// Base extensions
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
int maxId(Node) const {
return Parent::maxNodeId();
}
int maxId(Arc) const {
return Parent::maxArcId();
}
Node fromId(int id, Node) const {
return Parent::nodeFromId(id);
}
Arc fromId(int id, Arc) const {
return Parent::arcFromId(id);
}
Node oppositeNode(const Node &n, const Arc &e) const {
if (n == Parent::source(e))
return Parent::target(e);
else if(n==Parent::target(e))
return Parent::source(e);
else
return INVALID;
}
// Alteration notifier extensions
// The arc observer registry.
typedef AlterationNotifier<ArcSetExtender, Arc> ArcNotifier;
protected:
mutable ArcNotifier arc_notifier;
public:
using Parent::notifier;
// Gives back the arc alteration notifier.
ArcNotifier& notifier(Arc) const {
return arc_notifier;
}
// Iterable extensions
class NodeIt : public Node {
const Digraph* digraph;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Digraph& _graph) : digraph(&_graph) {
_graph.first(static_cast<Node&>(*this));
}
NodeIt(const Digraph& _graph, const Node& node)
: Node(node), digraph(&_graph) {}
NodeIt& operator++() {
digraph->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Digraph* digraph;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Digraph& _graph) : digraph(&_graph) {
_graph.first(static_cast<Arc&>(*this));
}
ArcIt(const Digraph& _graph, const Arc& e) :
Arc(e), digraph(&_graph) { }
ArcIt& operator++() {
digraph->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Digraph* digraph;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Digraph& _graph, const Node& node)
: digraph(&_graph) {
_graph.firstOut(*this, node);
}
OutArcIt(const Digraph& _graph, const Arc& arc)
: Arc(arc), digraph(&_graph) {}
OutArcIt& operator++() {
digraph->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Digraph* digraph;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Digraph& _graph, const Node& node)
: digraph(&_graph) {
_graph.firstIn(*this, node);
}
InArcIt(const Digraph& _graph, const Arc& arc) :
Arc(arc), digraph(&_graph) {}
InArcIt& operator++() {
digraph->nextIn(*this);
return *this;
}
};
// \brief Base node of the iterator
//
// Returns the base node (ie. the source in this case) of the iterator
Node baseNode(const OutArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the target in this case) of the
// iterator
Node runningNode(const OutArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Base node of the iterator
//
// Returns the base node (ie. the target in this case) of the iterator
Node baseNode(const InArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the source in this case) of the
// iterator
Node runningNode(const InArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
using Parent::first;
// Mappable extension
template <typename _Value>
class ArcMap
: public MapExtender<DefaultMap<Digraph, Arc, _Value> > {
typedef MapExtender<DefaultMap<Digraph, Arc, _Value> > Parent;
public:
explicit ArcMap(const Digraph& _g)
: Parent(_g) {}
ArcMap(const Digraph& _g, const _Value& _v)
: Parent(_g, _v) {}
ArcMap& operator=(const ArcMap& cmap) {
return operator=<ArcMap>(cmap);
}
template <typename CMap>
ArcMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
// Alteration extension
Arc addArc(const Node& from, const Node& to) {
Arc arc = Parent::addArc(from, to);
notifier(Arc()).add(arc);
return arc;
}
void clear() {
notifier(Arc()).clear();
Parent::clear();
}
void erase(const Arc& arc) {
notifier(Arc()).erase(arc);
Parent::erase(arc);
}
ArcSetExtender() {
arc_notifier.setContainer(*this);
}
~ArcSetExtender() {
arc_notifier.clear();
}
};
// \ingroup digraphbits
//
// \brief Extender for the EdgeSets
template <typename Base>
class EdgeSetExtender : public Base {
typedef Base Parent;
public:
typedef EdgeSetExtender Graph;
typedef True UndirectedTag;
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
typedef typename Parent::Edge Edge;
int maxId(Node) const {
return Parent::maxNodeId();
}
int maxId(Arc) const {
return Parent::maxArcId();
}
int maxId(Edge) const {
return Parent::maxEdgeId();
}
Node fromId(int id, Node) const {
return Parent::nodeFromId(id);
}
Arc fromId(int id, Arc) const {
return Parent::arcFromId(id);
}
Edge fromId(int id, Edge) const {
return Parent::edgeFromId(id);
}
Node oppositeNode(const Node &n, const Edge &e) const {
if( n == Parent::u(e))
return Parent::v(e);
else if( n == Parent::v(e))
return Parent::u(e);
else
return INVALID;
}
Arc oppositeArc(const Arc &e) const {
return Parent::direct(e, !Parent::direction(e));
}
using Parent::direct;
Arc direct(const Edge &e, const Node &s) const {
return Parent::direct(e, Parent::u(e) == s);
}
typedef AlterationNotifier<EdgeSetExtender, Arc> ArcNotifier;
typedef AlterationNotifier<EdgeSetExtender, Edge> EdgeNotifier;
protected:
mutable ArcNotifier arc_notifier;
mutable EdgeNotifier edge_notifier;
public:
using Parent::notifier;
ArcNotifier& notifier(Arc) const {
return arc_notifier;
}
EdgeNotifier& notifier(Edge) const {
return edge_notifier;
}
class NodeIt : public Node {
const Graph* graph;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Graph& _graph) : graph(&_graph) {
_graph.first(static_cast<Node&>(*this));
}
NodeIt(const Graph& _graph, const Node& node)
: Node(node), graph(&_graph) {}
NodeIt& operator++() {
graph->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Graph* graph;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Graph& _graph) : graph(&_graph) {
_graph.first(static_cast<Arc&>(*this));
}
ArcIt(const Graph& _graph, const Arc& e) :
Arc(e), graph(&_graph) { }
ArcIt& operator++() {
graph->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Graph* graph;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Graph& _graph, const Node& node)
: graph(&_graph) {
_graph.firstOut(*this, node);
}
OutArcIt(const Graph& _graph, const Arc& arc)
: Arc(arc), graph(&_graph) {}
OutArcIt& operator++() {
graph->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Graph* graph;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Graph& _graph, const Node& node)
: graph(&_graph) {
_graph.firstIn(*this, node);
}
InArcIt(const Graph& _graph, const Arc& arc) :
Arc(arc), graph(&_graph) {}
InArcIt& operator++() {
graph->nextIn(*this);
return *this;
}
};
class EdgeIt : public Parent::Edge {
const Graph* graph;
public:
EdgeIt() { }
EdgeIt(Invalid i) : Edge(i) { }
explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
_graph.first(static_cast<Edge&>(*this));
}
EdgeIt(const Graph& _graph, const Edge& e) :
Edge(e), graph(&_graph) { }
EdgeIt& operator++() {
graph->next(*this);
return *this;
}
};
class IncEdgeIt : public Parent::Edge {
friend class EdgeSetExtender;
const Graph* graph;
bool direction;
public:
IncEdgeIt() { }
IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {
_graph.firstInc(*this, direction, n);
}
IncEdgeIt(const Graph& _graph, const Edge &ue, const Node &n)
: graph(&_graph), Edge(ue) {
direction = (_graph.source(ue) == n);
}
IncEdgeIt& operator++() {
graph->nextInc(*this, direction);
return *this;
}
};
// \brief Base node of the iterator
//
// Returns the base node (ie. the source in this case) of the iterator
Node baseNode(const OutArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the target in this case) of the
// iterator
Node runningNode(const OutArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Base node of the iterator
//
// Returns the base node (ie. the target in this case) of the iterator
Node baseNode(const InArcIt &e) const {
return Parent::target(static_cast<const Arc&>(e));
}
// \brief Running node of the iterator
//
// Returns the running node (ie. the source in this case) of the
// iterator
Node runningNode(const InArcIt &e) const {
return Parent::source(static_cast<const Arc&>(e));
}
// Base node of the iterator
//
// Returns the base node of the iterator
Node baseNode(const IncEdgeIt &e) const {
return e.direction ? this->u(e) : this->v(e);
}
// Running node of the iterator
//
// Returns the running node of the iterator
Node runningNode(const IncEdgeIt &e) const {
return e.direction ? this->v(e) : this->u(e);
}
template <typename _Value>
class ArcMap
: public MapExtender<DefaultMap<Graph, Arc, _Value> > {
typedef MapExtender<DefaultMap<Graph, Arc, _Value> > Parent;
public:
explicit ArcMap(const Graph& _g)
: Parent(_g) {}
ArcMap(const Graph& _g, const _Value& _v)
: Parent(_g, _v) {}
ArcMap& operator=(const ArcMap& cmap) {
return operator=<ArcMap>(cmap);
}
template <typename CMap>
ArcMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
template <typename _Value>
class EdgeMap
: public MapExtender<DefaultMap<Graph, Edge, _Value> > {
typedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;
public:
explicit EdgeMap(const Graph& _g)
: Parent(_g) {}
EdgeMap(const Graph& _g, const _Value& _v)
: Parent(_g, _v) {}
EdgeMap& operator=(const EdgeMap& cmap) {
return operator=<EdgeMap>(cmap);
}
template <typename CMap>
EdgeMap& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
};
// Alteration extension
Edge addEdge(const Node& from, const Node& to) {
Edge edge = Parent::addEdge(from, to);
notifier(Edge()).add(edge);
std::vector<Arc> arcs;
arcs.push_back(Parent::direct(edge, true));
arcs.push_back(Parent::direct(edge, false));
notifier(Arc()).add(arcs);
return edge;
}
void clear() {
notifier(Arc()).clear();
notifier(Edge()).clear();
Parent::clear();
}
void erase(const Edge& edge) {
std::vector<Arc> arcs;
arcs.push_back(Parent::direct(edge, true));
arcs.push_back(Parent::direct(edge, false));
notifier(Arc()).erase(arcs);
notifier(Edge()).erase(edge);
Parent::erase(edge);
}
EdgeSetExtender() {
arc_notifier.setContainer(*this);
edge_notifier.setContainer(*this);
}
~EdgeSetExtender() {
edge_notifier.clear();
arc_notifier.clear();
}
};
}
#endif

Some files were not shown because too many files have changed in this diff Show More