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
parent
ee53e3ed4f
commit
2d05583937
13
.travis.yml
13
.travis.yml
|
@ -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
|
||||
|
|
|
@ -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>
|
50
appveyor.yml
50
appveyor.yml
|
@ -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\
|
||||
|
|
121
dust3d.pro
121
dust3d.pro
|
@ -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")
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
QMAKE_CXXFLAGS += -fopenmp
|
||||
DEFINES += WITH_OMP
|
||||
LIBS += -lgomp
|
||||
LIBS += -ldl
|
||||
}
|
||||
}
|
||||
|
||||
win32 {
|
||||
# Fix error LNK2001: unresolved external symbol "struct lemon::Invalid const lemon::INVALID" (?INVALID@lemon@@3UInvalid@1@B)
|
||||
DEFINES += LEMON_ONLY_TEMPLATES
|
||||
DEFINES += _USE_MATH_DEFINES
|
||||
LIBS += -Lthirdparty/instant-meshes/build/RelWithDebInfo -linstant-meshes
|
||||
LIBS += -Lthirdparty/instant-meshes/build/ext_build/tbb/RelWithDebInfo -ltbb
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
210
src/document.cpp
210
src/document.cpp
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -177,7 +177,6 @@ private:
|
|||
QAction *m_showRigAction;
|
||||
QAction *m_showPosesAction;
|
||||
QAction *m_showMotionsAction;
|
||||
QAction *m_showScriptAction;
|
||||
|
||||
QMenu *m_helpMenu;
|
||||
QAction *m_gotoHomepageAction;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
174
src/remesher.cpp
174
src/remesher.cpp
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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 ¢er)
|
||||
{
|
||||
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:
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 4
|
||||
Standard: Cpp11
|
||||
ColumnLimit: 99
|
|
@ -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
|
|
@ -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}
|
||||
)
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
EXEC = minisat
|
||||
DEPDIR = mtl utils
|
||||
|
||||
include $(MROOT)/mtl/template.mk
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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
|
|
@ -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).
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
EXEC = minisat
|
||||
DEPDIR = mtl utils core
|
||||
|
||||
include $(MROOT)/mtl/template.mk
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
EXEC = system_test
|
||||
DEPDIR = mtl
|
||||
|
||||
include $(MROOT)/mtl/template.mk
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,5 +0,0 @@
|
|||
repo: 6ed5fe0ea387ba9808e21048f02c665b16aa8c23
|
||||
node: bdabbf66b2ad131199059736178664f44c69adaf
|
||||
branch: 1.3
|
||||
latesttag: r1.3
|
||||
latesttagdistance: 11
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
57ab090b6109902536ee34b1e8d4d123474311e3 r1.3
|
|
@ -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
|
|
@ -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()
|
|
@ -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.
|
|
@ -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.
|
|
@ -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)
|
|
@ -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.
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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)
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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 |
|
@ -1 +0,0 @@
|
|||
SET(LEMON_VERSION "1.3.1" CACHE STRING "LEMON version string.")
|
|
@ -1 +0,0 @@
|
|||
SET(LEMON_VERSION "@LEMON_VERSION@" CACHE STRING "LEMON version string.")
|
|
@ -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)
|
||||
|
|
@ -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()
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
Loading…
Reference in New Issue