Jeremy Hu 2019-12-28 14:51:59 +09:30
parent e9113ec822
commit dd628b6af7
283 changed files with 126316 additions and 1 deletions

View File

@ -1225,3 +1225,9 @@ https://www.reddit.com/r/gamedev/comments/5iuf3h/i_am_writting_a_3d_monster_mode
A Fast Parallel Algorithm for Thinning Digital Patterns
https://dl.acm.org/citation.cfm?id=358023
</pre>
<h1>Huang, Jingwei and Zhou, Yichao and Niessner, Matthias and Shewchuk, Jonathan Richard and Guibas, Leonidas J.</h1>
<pre>
QuadriFlow: A Scalable and Robust Method for Quadrangulation
http://stanford.edu/~jingweih/papers/quadriflow/
</pre>

View File

@ -483,10 +483,64 @@ HEADERS += src/imageskeletonextractor.h
SOURCES += src/contourtopartconverter.cpp
HEADERS += src/contourtopartconverter.h
SOURCES += src/remesher.cpp
HEADERS += src/remesher.h
SOURCES += src/main.cpp
HEADERS += src/version.h
INCLUDEPATH += thirdparty/QuadriFlow
INCLUDEPATH += thirdparty/QuadriFlow/3rd/pcg32
INCLUDEPATH += thirdparty/QuadriFlow/3rd/pss
INCLUDEPATH += thirdparty/QuadriFlow/3rd/lemon-1.3.1
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

View File

@ -16,6 +16,7 @@
#include "imageforever.h"
#include "gridmeshbuilder.h"
#include "triangulatefaces.h"
#include "remesher.h"
MeshGenerator::MeshGenerator(Snapshot *snapshot) :
m_snapshot(snapshot)
@ -1310,6 +1311,25 @@ void MeshGenerator::generate()
m_outcome->vertices = combinedVertices;
m_outcome->triangles = combinedFaces;
m_outcome->paintMaps = componentCache.outcomePaintMaps;
/*
Remesher remesher;
remesher.setMesh(combinedVertices, combinedFaces);
remesher.remesh();
m_outcome->vertices = remesher.getRemeshedVertices();
const auto &remeshedFaces = remesher.getRemeshedFaces();
m_outcome->triangleAndQuads = remeshedFaces;
m_outcome->triangles.clear();
m_outcome->triangles.reserve(remeshedFaces.size() * 2);
for (const auto &it: remeshedFaces) {
m_outcome->triangles.push_back(std::vector<size_t> {
it[0], it[1], it[2]
});
m_outcome->triangles.push_back(std::vector<size_t> {
it[2], it[3], it[0]
});
}
*/
}
// Recursively check uncombined components

109
src/remesher.cpp Normal file
View File

@ -0,0 +1,109 @@
#include <config.hpp>
#include <field-math.hpp>
#include <optimizer.hpp>
#include <parametrizer.hpp>
#ifdef WITH_CUDA
#include <cuda_runtime.h>
#endif
#include "remesher.h"
using namespace qflow;
Remesher::~Remesher()
{
}
void Remesher::setMesh(const std::vector<QVector3D> &vertices,
const std::vector<std::vector<size_t>> &triangles)
{
m_vertices = vertices;
m_triangles = triangles;
}
const std::vector<QVector3D> &Remesher::getRemeshedVertices()
{
return m_remeshedVertices;
}
const std::vector<std::vector<size_t>> &Remesher::getRemeshedFaces()
{
return m_remeshedFaces;
}
void Remesher::remesh()
{
Parametrizer field;
#ifdef WITH_CUDA
cudaFree(0);
#endif
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++) {
const auto &vertex = m_vertices[i];
field.V.col(i) << (double)vertex.x(), (double)vertex.y(), (double)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];
}
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) {
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]
});
}
printf("m_remeshedVertices.size:%lu\r\n", m_remeshedVertices.size());
printf("m_remeshedFaces.size:%lu\r\n", m_remeshedFaces.size());
}

24
src/remesher.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef DUST3D_REMESHER_H
#define DUST3D_REMESHER_H
#include <QObject>
#include <vector>
#include <QVector3D>
class Remesher : public QObject
{
Q_OBJECT
public:
~Remesher();
void setMesh(const std::vector<QVector3D> &vertices,
const std::vector<std::vector<size_t>> &triangles);
void remesh();
const std::vector<QVector3D> &getRemeshedVertices();
const std::vector<std::vector<size_t>> &getRemeshedFaces();
private:
std::vector<QVector3D> m_vertices;
std::vector<std::vector<size_t>> m_triangles;
std::vector<QVector3D> m_remeshedVertices;
std::vector<std::vector<size_t>> m_remeshedFaces;
};
#endif

5
thirdparty/QuadriFlow/.clang-format vendored Executable file
View File

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

293
thirdparty/QuadriFlow/.gitignore vendored Executable file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

26
thirdparty/QuadriFlow/3rd/lemon-1.3.1/AUTHORS vendored Executable file
View File

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

View File

@ -0,0 +1,373 @@
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()

167
thirdparty/QuadriFlow/3rd/lemon-1.3.1/INSTALL vendored Executable file
View File

@ -0,0 +1,167 @@
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.

32
thirdparty/QuadriFlow/3rd/lemon-1.3.1/LICENSE vendored Executable file
View File

@ -0,0 +1,32 @@
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.

337
thirdparty/QuadriFlow/3rd/lemon-1.3.1/NEWS vendored Executable file
View File

@ -0,0 +1,337 @@
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)

50
thirdparty/QuadriFlow/3rd/lemon-1.3.1/README vendored Executable file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,13 @@
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.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,627 @@
/* -*- 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

View File

@ -0,0 +1,131 @@
/* -*- 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.
*
*/
// This file contains a modified version of the enable_if library from BOOST.
// See the appropriate copyright notice below.
// Boost enable_if library
// Copyright 2003 (c) The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef LEMON_BITS_ENABLE_IF_H
#define LEMON_BITS_ENABLE_IF_H
//\file
//\brief Miscellaneous basic utilities
namespace lemon
{
// Basic type for defining "tags". A "YES" condition for \c enable_if.
// Basic type for defining "tags". A "YES" condition for \c enable_if.
//
//\sa False
struct True {
//\e
static const bool value = true;
};
// Basic type for defining "tags". A "NO" condition for \c enable_if.
// Basic type for defining "tags". A "NO" condition for \c enable_if.
//
//\sa True
struct False {
//\e
static const bool value = false;
};
template <typename T>
struct Wrap {
const T &value;
Wrap(const T &t) : value(t) {}
};
/**************** dummy class to avoid ambiguity ****************/
template<int T> struct dummy { dummy(int) {} };
/**************** enable_if from BOOST ****************/
template <typename Type, typename T = void>
struct exists {
typedef T type;
};
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace lemon
#endif

View File

@ -0,0 +1,401 @@
/* -*- 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_GRAPH_ADAPTOR_EXTENDER_H
#define LEMON_BITS_GRAPH_ADAPTOR_EXTENDER_H
#include <lemon/core.h>
#include <lemon/error.h>
namespace lemon {
template <typename _Digraph>
class DigraphAdaptorExtender : public _Digraph {
typedef _Digraph Parent;
public:
typedef _Digraph Digraph;
typedef DigraphAdaptorExtender Adaptor;
// 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;
}
class NodeIt : public Node {
const Adaptor* _adaptor;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Node&>(*this));
}
NodeIt(const Adaptor& adaptor, const Node& node)
: Node(node), _adaptor(&adaptor) {}
NodeIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Adaptor* _adaptor;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Arc&>(*this));
}
ArcIt(const Adaptor& adaptor, const Arc& e) :
Arc(e), _adaptor(&adaptor) { }
ArcIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Adaptor* _adaptor;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstOut(*this, node);
}
OutArcIt(const Adaptor& adaptor, const Arc& arc)
: Arc(arc), _adaptor(&adaptor) {}
OutArcIt& operator++() {
_adaptor->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Adaptor* _adaptor;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstIn(*this, node);
}
InArcIt(const Adaptor& adaptor, const Arc& arc) :
Arc(arc), _adaptor(&adaptor) {}
InArcIt& operator++() {
_adaptor->nextIn(*this);
return *this;
}
};
Node baseNode(const OutArcIt &e) const {
return Parent::source(e);
}
Node runningNode(const OutArcIt &e) const {
return Parent::target(e);
}
Node baseNode(const InArcIt &e) const {
return Parent::target(e);
}
Node runningNode(const InArcIt &e) const {
return Parent::source(e);
}
};
template <typename _Graph>
class GraphAdaptorExtender : public _Graph {
typedef _Graph Parent;
public:
typedef _Graph Graph;
typedef GraphAdaptorExtender Adaptor;
typedef True UndirectedTag;
typedef typename Parent::Node Node;
typedef typename Parent::Arc Arc;
typedef typename Parent::Edge Edge;
// Graph extension
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 &a) const {
return Parent::direct(a, !Parent::direction(a));
}
using Parent::direct;
Arc direct(const Edge &e, const Node &s) const {
return Parent::direct(e, Parent::u(e) == s);
}
class NodeIt : public Node {
const Adaptor* _adaptor;
public:
NodeIt() {}
NodeIt(Invalid i) : Node(i) { }
explicit NodeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Node&>(*this));
}
NodeIt(const Adaptor& adaptor, const Node& node)
: Node(node), _adaptor(&adaptor) {}
NodeIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class ArcIt : public Arc {
const Adaptor* _adaptor;
public:
ArcIt() { }
ArcIt(Invalid i) : Arc(i) { }
explicit ArcIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Arc&>(*this));
}
ArcIt(const Adaptor& adaptor, const Arc& e) :
Arc(e), _adaptor(&adaptor) { }
ArcIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class OutArcIt : public Arc {
const Adaptor* _adaptor;
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstOut(*this, node);
}
OutArcIt(const Adaptor& adaptor, const Arc& arc)
: Arc(arc), _adaptor(&adaptor) {}
OutArcIt& operator++() {
_adaptor->nextOut(*this);
return *this;
}
};
class InArcIt : public Arc {
const Adaptor* _adaptor;
public:
InArcIt() { }
InArcIt(Invalid i) : Arc(i) { }
InArcIt(const Adaptor& adaptor, const Node& node)
: _adaptor(&adaptor) {
_adaptor->firstIn(*this, node);
}
InArcIt(const Adaptor& adaptor, const Arc& arc) :
Arc(arc), _adaptor(&adaptor) {}
InArcIt& operator++() {
_adaptor->nextIn(*this);
return *this;
}
};
class EdgeIt : public Parent::Edge {
const Adaptor* _adaptor;
public:
EdgeIt() { }
EdgeIt(Invalid i) : Edge(i) { }
explicit EdgeIt(const Adaptor& adaptor) : _adaptor(&adaptor) {
_adaptor->first(static_cast<Edge&>(*this));
}
EdgeIt(const Adaptor& adaptor, const Edge& e) :
Edge(e), _adaptor(&adaptor) { }
EdgeIt& operator++() {
_adaptor->next(*this);
return *this;
}
};
class IncEdgeIt : public Edge {
friend class GraphAdaptorExtender;
const Adaptor* _adaptor;
bool direction;
public:
IncEdgeIt() { }
IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
IncEdgeIt(const Adaptor& adaptor, const Node &n) : _adaptor(&adaptor) {
_adaptor->firstInc(static_cast<Edge&>(*this), direction, n);
}
IncEdgeIt(const Adaptor& adaptor, const Edge &e, const Node &n)
: _adaptor(&adaptor), Edge(e) {
direction = (_adaptor->u(e) == n);
}
IncEdgeIt& operator++() {
_adaptor->nextInc(*this, direction);
return *this;
}
};
Node baseNode(const OutArcIt &a) const {
return Parent::source(a);
}
Node runningNode(const OutArcIt &a) const {
return Parent::target(a);
}
Node baseNode(const InArcIt &a) const {
return Parent::target(a);
}
Node runningNode(const InArcIt &a) const {
return Parent::source(a);
}
Node baseNode(const IncEdgeIt &e) const {
return e.direction ? Parent::u(e) : Parent::v(e);
}
Node runningNode(const IncEdgeIt &e) const {
return e.direction ? Parent::v(e) : Parent::u(e);
}
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
/* -*- 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_LOCK_H
#define LEMON_BITS_LOCK_H
#include <lemon/config.h>
#if defined(LEMON_USE_PTHREAD)
#include <pthread.h>
#elif defined(LEMON_USE_WIN32_THREADS)
#include <lemon/bits/windows.h>
#endif
namespace lemon {
namespace bits {
#if defined(LEMON_USE_PTHREAD)
class Lock {
public:
Lock() {
pthread_mutex_init(&_lock, 0);
}
~Lock() {
pthread_mutex_destroy(&_lock);
}
void lock() {
pthread_mutex_lock(&_lock);
}
void unlock() {
pthread_mutex_unlock(&_lock);
}
private:
pthread_mutex_t _lock;
};
#elif defined(LEMON_USE_WIN32_THREADS)
class Lock : public WinLock {};
#else
class Lock {
public:
Lock() {}
~Lock() {}
void lock() {}
void unlock() {}
};
#endif
}
}
#endif

View File

@ -0,0 +1,332 @@
/* -*- 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_MAP_EXTENDER_H
#define LEMON_BITS_MAP_EXTENDER_H
#include <iterator>
#include <lemon/bits/traits.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
//\file
//\brief Extenders for iterable maps.
namespace lemon {
// \ingroup graphbits
//
// \brief Extender for maps
template <typename _Map>
class MapExtender : public _Map {
typedef _Map Parent;
typedef typename Parent::GraphType GraphType;
public:
typedef MapExtender Map;
typedef typename Parent::Key Item;
typedef typename Parent::Key Key;
typedef typename Parent::Value Value;
typedef typename Parent::Reference Reference;
typedef typename Parent::ConstReference ConstReference;
typedef typename Parent::ReferenceMapTag ReferenceMapTag;
class MapIt;
class ConstMapIt;
friend class MapIt;
friend class ConstMapIt;
public:
MapExtender(const GraphType& graph)
: Parent(graph) {}
MapExtender(const GraphType& graph, const Value& value)
: Parent(graph, value) {}
private:
MapExtender& operator=(const MapExtender& cmap) {
return operator=<MapExtender>(cmap);
}
template <typename CMap>
MapExtender& operator=(const CMap& cmap) {
Parent::operator=(cmap);
return *this;
}
public:
class MapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
MapIt() : map(NULL) {}
MapIt(Invalid i) : Parent(i), map(NULL) {}
explicit MapIt(Map& _map) : map(&_map) {
map->notifier()->first(*this);
}
MapIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
MapIt& operator++() {
map->notifier()->next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return (*map)[*this];
}
typename MapTraits<Map>::ReturnValue operator*() {
return (*map)[*this];
}
void set(const Value& value) {
map->set(*this, value);
}
protected:
Map* map;
};
class ConstMapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
ConstMapIt() : map(NULL) {}
ConstMapIt(Invalid i) : Parent(i), map(NULL) {}
explicit ConstMapIt(Map& _map) : map(&_map) {
map->notifier()->first(*this);
}
ConstMapIt(const Map& _map, const Item& item)
: Parent(item), map(_map) {}
ConstMapIt& operator++() {
map->notifier()->next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return map[*this];
}
protected:
const Map* map;
};
class ItemIt : public Item {
typedef Item Parent;
public:
ItemIt() : map(NULL) {}
ItemIt(Invalid i) : Parent(i), map(NULL) {}
explicit ItemIt(Map& _map) : map(&_map) {
map->notifier()->first(*this);
}
ItemIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
ItemIt& operator++() {
map->notifier()->next(*this);
return *this;
}
protected:
const Map* map;
};
};
// \ingroup graphbits
//
// \brief Extender for maps which use a subset of the items.
template <typename _Graph, typename _Map>
class SubMapExtender : public _Map {
typedef _Map Parent;
typedef _Graph GraphType;
public:
typedef SubMapExtender Map;
typedef typename Parent::Key Item;
typedef typename Parent::Key Key;
typedef typename Parent::Value Value;
typedef typename Parent::Reference Reference;
typedef typename Parent::ConstReference ConstReference;
typedef typename Parent::ReferenceMapTag ReferenceMapTag;
class MapIt;
class ConstMapIt;
friend class MapIt;
friend class ConstMapIt;
public:
SubMapExtender(const GraphType& _graph)
: Parent(_graph), graph(_graph) {}
SubMapExtender(const GraphType& _graph, const Value& _value)
: Parent(_graph, _value), graph(_graph) {}
private:
SubMapExtender& operator=(const SubMapExtender& cmap) {
return operator=<MapExtender>(cmap);
}
template <typename CMap>
SubMapExtender& operator=(const CMap& cmap) {
checkConcept<concepts::ReadMap<Key, Value>, CMap>();
Item it;
for (graph.first(it); it != INVALID; graph.next(it)) {
Parent::set(it, cmap[it]);
}
return *this;
}
public:
class MapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
MapIt() : map(NULL) {}
MapIt(Invalid i) : Parent(i), map(NULL) { }
explicit MapIt(Map& _map) : map(&_map) {
map->graph.first(*this);
}
MapIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
MapIt& operator++() {
map->graph.next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return (*map)[*this];
}
typename MapTraits<Map>::ReturnValue operator*() {
return (*map)[*this];
}
void set(const Value& value) {
map->set(*this, value);
}
protected:
Map* map;
};
class ConstMapIt : public Item {
typedef Item Parent;
public:
typedef typename Map::Value Value;
ConstMapIt() : map(NULL) {}
ConstMapIt(Invalid i) : Parent(i), map(NULL) { }
explicit ConstMapIt(Map& _map) : map(&_map) {
map->graph.first(*this);
}
ConstMapIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
ConstMapIt& operator++() {
map->graph.next(*this);
return *this;
}
typename MapTraits<Map>::ConstReturnValue operator*() const {
return (*map)[*this];
}
protected:
const Map* map;
};
class ItemIt : public Item {
typedef Item Parent;
public:
ItemIt() : map(NULL) {}
ItemIt(Invalid i) : Parent(i), map(NULL) { }
explicit ItemIt(Map& _map) : map(&_map) {
map->graph.first(*this);
}
ItemIt(const Map& _map, const Item& item)
: Parent(item), map(&_map) {}
ItemIt& operator++() {
map->graph.next(*this);
return *this;
}
protected:
const Map* map;
};
private:
const GraphType& graph;
};
}
#endif

View File

@ -0,0 +1,177 @@
/* -*- 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_PATH_DUMP_H
#define LEMON_BITS_PATH_DUMP_H
#include <lemon/core.h>
#include <lemon/concept_check.h>
namespace lemon {
template <typename _Digraph, typename _PredMap>
class PredMapPath {
public:
typedef True RevPathTag;
typedef _Digraph Digraph;
typedef typename Digraph::Arc Arc;
typedef _PredMap PredMap;
PredMapPath(const Digraph& _digraph, const PredMap& _predMap,
typename Digraph::Node _target)
: digraph(_digraph), predMap(_predMap), target(_target) {}
int length() const {
int len = 0;
typename Digraph::Node node = target;
typename Digraph::Arc arc;
while ((arc = predMap[node]) != INVALID) {
node = digraph.source(arc);
++len;
}
return len;
}
bool empty() const {
return predMap[target] == INVALID;
}
class RevArcIt {
public:
RevArcIt() {}
RevArcIt(Invalid) : path(0), current(INVALID) {}
RevArcIt(const PredMapPath& _path)
: path(&_path), current(_path.target) {
if (path->predMap[current] == INVALID) current = INVALID;
}
operator const typename Digraph::Arc() const {
return path->predMap[current];
}
RevArcIt& operator++() {
current = path->digraph.source(path->predMap[current]);
if (path->predMap[current] == INVALID) current = INVALID;
return *this;
}
bool operator==(const RevArcIt& e) const {
return current == e.current;
}
bool operator!=(const RevArcIt& e) const {
return current != e.current;
}
bool operator<(const RevArcIt& e) const {
return current < e.current;
}
private:
const PredMapPath* path;
typename Digraph::Node current;
};
private:
const Digraph& digraph;
const PredMap& predMap;
typename Digraph::Node target;
};
template <typename _Digraph, typename _PredMatrixMap>
class PredMatrixMapPath {
public:
typedef True RevPathTag;
typedef _Digraph Digraph;
typedef typename Digraph::Arc Arc;
typedef _PredMatrixMap PredMatrixMap;
PredMatrixMapPath(const Digraph& _digraph,
const PredMatrixMap& _predMatrixMap,
typename Digraph::Node _source,
typename Digraph::Node _target)
: digraph(_digraph), predMatrixMap(_predMatrixMap),
source(_source), target(_target) {}
int length() const {
int len = 0;
typename Digraph::Node node = target;
typename Digraph::Arc arc;
while ((arc = predMatrixMap(source, node)) != INVALID) {
node = digraph.source(arc);
++len;
}
return len;
}
bool empty() const {
return predMatrixMap(source, target) == INVALID;
}
class RevArcIt {
public:
RevArcIt() {}
RevArcIt(Invalid) : path(0), current(INVALID) {}
RevArcIt(const PredMatrixMapPath& _path)
: path(&_path), current(_path.target) {
if (path->predMatrixMap(path->source, current) == INVALID)
current = INVALID;
}
operator const typename Digraph::Arc() const {
return path->predMatrixMap(path->source, current);
}
RevArcIt& operator++() {
current =
path->digraph.source(path->predMatrixMap(path->source, current));
if (path->predMatrixMap(path->source, current) == INVALID)
current = INVALID;
return *this;
}
bool operator==(const RevArcIt& e) const {
return current == e.current;
}
bool operator!=(const RevArcIt& e) const {
return current != e.current;
}
bool operator<(const RevArcIt& e) const {
return current < e.current;
}
private:
const PredMatrixMapPath* path;
typename Digraph::Node current;
};
private:
const Digraph& digraph;
const PredMatrixMap& predMatrixMap;
typename Digraph::Node source;
typename Digraph::Node target;
};
}
#endif

View File

@ -0,0 +1,194 @@
/* -*- 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_SOLVER_BITS_H
#define LEMON_BITS_SOLVER_BITS_H
#include <vector>
namespace lemon {
namespace _solver_bits {
class VarIndex {
private:
struct ItemT {
int prev, next;
int index;
};
std::vector<ItemT> items;
int first_item, last_item, first_free_item;
std::vector<int> cross;
public:
VarIndex()
: first_item(-1), last_item(-1), first_free_item(-1) {
}
void clear() {
first_item = -1;
last_item = -1;
first_free_item = -1;
items.clear();
cross.clear();
}
int addIndex(int idx) {
int n;
if (first_free_item == -1) {
n = items.size();
items.push_back(ItemT());
} else {
n = first_free_item;
first_free_item = items[n].next;
if (first_free_item != -1) {
items[first_free_item].prev = -1;
}
}
items[n].index = idx;
if (static_cast<int>(cross.size()) <= idx) {
cross.resize(idx + 1, -1);
}
cross[idx] = n;
items[n].prev = last_item;
items[n].next = -1;
if (last_item != -1) {
items[last_item].next = n;
} else {
first_item = n;
}
last_item = n;
return n;
}
int addIndex(int idx, int n) {
while (n >= static_cast<int>(items.size())) {
items.push_back(ItemT());
items.back().prev = -1;
items.back().next = first_free_item;
if (first_free_item != -1) {
items[first_free_item].prev = items.size() - 1;
}
first_free_item = items.size() - 1;
}
if (items[n].next != -1) {
items[items[n].next].prev = items[n].prev;
}
if (items[n].prev != -1) {
items[items[n].prev].next = items[n].next;
} else {
first_free_item = items[n].next;
}
items[n].index = idx;
if (static_cast<int>(cross.size()) <= idx) {
cross.resize(idx + 1, -1);
}
cross[idx] = n;
items[n].prev = last_item;
items[n].next = -1;
if (last_item != -1) {
items[last_item].next = n;
} else {
first_item = n;
}
last_item = n;
return n;
}
void eraseIndex(int idx) {
int n = cross[idx];
if (items[n].prev != -1) {
items[items[n].prev].next = items[n].next;
} else {
first_item = items[n].next;
}
if (items[n].next != -1) {
items[items[n].next].prev = items[n].prev;
} else {
last_item = items[n].prev;
}
if (first_free_item != -1) {
items[first_free_item].prev = n;
}
items[n].next = first_free_item;
items[n].prev = -1;
first_free_item = n;
while (!cross.empty() && cross.back() == -1) {
cross.pop_back();
}
}
int maxIndex() const {
return cross.size() - 1;
}
void shiftIndices(int idx) {
for (int i = idx + 1; i < static_cast<int>(cross.size()); ++i) {
cross[i - 1] = cross[i];
if (cross[i] != -1) {
--items[cross[i]].index;
}
}
cross.back() = -1;
cross.pop_back();
while (!cross.empty() && cross.back() == -1) {
cross.pop_back();
}
}
void relocateIndex(int idx, int jdx) {
cross[idx] = cross[jdx];
items[cross[jdx]].index = idx;
cross[jdx] = -1;
while (!cross.empty() && cross.back() == -1) {
cross.pop_back();
}
}
int operator[](int idx) const {
return cross[idx];
}
int operator()(int fdx) const {
return items[fdx].index;
}
void firstItem(int& fdx) const {
fdx = first_item;
}
void nextItem(int& fdx) const {
fdx = items[fdx].next;
}
};
}
}
#endif

View File

@ -0,0 +1,388 @@
/* -*- 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_TRAITS_H
#define LEMON_BITS_TRAITS_H
//\file
//\brief Traits for graphs and maps
//
#include <lemon/bits/enable_if.h>
namespace lemon {
struct InvalidType {};
template <typename GR, typename _Item>
class ItemSetTraits {};
template <typename GR, typename Enable = void>
struct NodeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct NodeNotifierIndicator<
GR,
typename enable_if<typename GR::NodeNotifier::Notifier, void>::type
> {
typedef typename GR::NodeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::Node> {
public:
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::Node Item;
typedef typename GR::NodeIt ItemIt;
typedef typename NodeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template NodeMap<V> {
typedef typename GR::template NodeMap<V> Parent;
public:
typedef typename GR::template NodeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _digraph) : Parent(_digraph) {}
Map(const GR& _digraph, const Value& _value)
: Parent(_digraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct ArcNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct ArcNotifierIndicator<
GR,
typename enable_if<typename GR::ArcNotifier::Notifier, void>::type
> {
typedef typename GR::ArcNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::Arc> {
public:
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::Arc Item;
typedef typename GR::ArcIt ItemIt;
typedef typename ArcNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template ArcMap<V> {
typedef typename GR::template ArcMap<V> Parent;
public:
typedef typename GR::template ArcMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _digraph) : Parent(_digraph) {}
Map(const GR& _digraph, const Value& _value)
: Parent(_digraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct EdgeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct EdgeNotifierIndicator<
GR,
typename enable_if<typename GR::EdgeNotifier::Notifier, void>::type
> {
typedef typename GR::EdgeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::Edge> {
public:
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::Edge Item;
typedef typename GR::EdgeIt ItemIt;
typedef typename EdgeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template EdgeMap<V> {
typedef typename GR::template EdgeMap<V> Parent;
public:
typedef typename GR::template EdgeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _digraph) : Parent(_digraph) {}
Map(const GR& _digraph, const Value& _value)
: Parent(_digraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct RedNodeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct RedNodeNotifierIndicator<
GR,
typename enable_if<typename GR::RedNodeNotifier::Notifier, void>::type
> {
typedef typename GR::RedNodeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::RedNode> {
public:
typedef GR BpGraph;
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::RedNode Item;
typedef typename GR::RedNodeIt ItemIt;
typedef typename RedNodeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template RedNodeMap<V> {
typedef typename GR::template RedNodeMap<V> Parent;
public:
typedef typename GR::template RedNodeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _bpgraph) : Parent(_bpgraph) {}
Map(const GR& _bpgraph, const Value& _value)
: Parent(_bpgraph, _value) {}
};
};
template <typename GR, typename Enable = void>
struct BlueNodeNotifierIndicator {
typedef InvalidType Type;
};
template <typename GR>
struct BlueNodeNotifierIndicator<
GR,
typename enable_if<typename GR::BlueNodeNotifier::Notifier, void>::type
> {
typedef typename GR::BlueNodeNotifier Type;
};
template <typename GR>
class ItemSetTraits<GR, typename GR::BlueNode> {
public:
typedef GR BpGraph;
typedef GR Graph;
typedef GR Digraph;
typedef typename GR::BlueNode Item;
typedef typename GR::BlueNodeIt ItemIt;
typedef typename BlueNodeNotifierIndicator<GR>::Type ItemNotifier;
template <typename V>
class Map : public GR::template BlueNodeMap<V> {
typedef typename GR::template BlueNodeMap<V> Parent;
public:
typedef typename GR::template BlueNodeMap<V> Type;
typedef typename Parent::Value Value;
Map(const GR& _bpgraph) : Parent(_bpgraph) {}
Map(const GR& _bpgraph, const Value& _value)
: Parent(_bpgraph, _value) {}
};
};
template <typename Map, typename Enable = void>
struct MapTraits {
typedef False ReferenceMapTag;
typedef typename Map::Key Key;
typedef typename Map::Value Value;
typedef Value ConstReturnValue;
typedef Value ReturnValue;
};
template <typename Map>
struct MapTraits<
Map, typename enable_if<typename Map::ReferenceMapTag, void>::type >
{
typedef True ReferenceMapTag;
typedef typename Map::Key Key;
typedef typename Map::Value Value;
typedef typename Map::ConstReference ConstReturnValue;
typedef typename Map::Reference ReturnValue;
typedef typename Map::ConstReference ConstReference;
typedef typename Map::Reference Reference;
};
template <typename MatrixMap, typename Enable = void>
struct MatrixMapTraits {
typedef False ReferenceMapTag;
typedef typename MatrixMap::FirstKey FirstKey;
typedef typename MatrixMap::SecondKey SecondKey;
typedef typename MatrixMap::Value Value;
typedef Value ConstReturnValue;
typedef Value ReturnValue;
};
template <typename MatrixMap>
struct MatrixMapTraits<
MatrixMap, typename enable_if<typename MatrixMap::ReferenceMapTag,
void>::type >
{
typedef True ReferenceMapTag;
typedef typename MatrixMap::FirstKey FirstKey;
typedef typename MatrixMap::SecondKey SecondKey;
typedef typename MatrixMap::Value Value;
typedef typename MatrixMap::ConstReference ConstReturnValue;
typedef typename MatrixMap::Reference ReturnValue;
typedef typename MatrixMap::ConstReference ConstReference;
typedef typename MatrixMap::Reference Reference;
};
// Indicators for the tags
template <typename GR, typename Enable = void>
struct NodeNumTagIndicator {
static const bool value = false;
};
template <typename GR>
struct NodeNumTagIndicator<
GR,
typename enable_if<typename GR::NodeNumTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct ArcNumTagIndicator {
static const bool value = false;
};
template <typename GR>
struct ArcNumTagIndicator<
GR,
typename enable_if<typename GR::ArcNumTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct EdgeNumTagIndicator {
static const bool value = false;
};
template <typename GR>
struct EdgeNumTagIndicator<
GR,
typename enable_if<typename GR::EdgeNumTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct FindArcTagIndicator {
static const bool value = false;
};
template <typename GR>
struct FindArcTagIndicator<
GR,
typename enable_if<typename GR::FindArcTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct FindEdgeTagIndicator {
static const bool value = false;
};
template <typename GR>
struct FindEdgeTagIndicator<
GR,
typename enable_if<typename GR::FindEdgeTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct UndirectedTagIndicator {
static const bool value = false;
};
template <typename GR>
struct UndirectedTagIndicator<
GR,
typename enable_if<typename GR::UndirectedTag, void>::type
> {
static const bool value = true;
};
template <typename GR, typename Enable = void>
struct BuildTagIndicator {
static const bool value = false;
};
template <typename GR>
struct BuildTagIndicator<
GR,
typename enable_if<typename GR::BuildTag, void>::type
> {
static const bool value = true;
};
}
#endif

View File

@ -0,0 +1,494 @@
/* -*- 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.
*
*/
#ifndef LEMON_BITS_VARIANT_H
#define LEMON_BITS_VARIANT_H
#include <lemon/assert.h>
// \file
// \brief Variant types
namespace lemon {
namespace _variant_bits {
template <int left, int right>
struct CTMax {
static const int value = left < right ? right : left;
};
}
// \brief Simple Variant type for two types
//
// Simple Variant type for two types. The Variant type is a type-safe
// union. C++ has strong limitations for using unions, for
// example you cannot store a type with non-default constructor or
// destructor in a union. This class always knowns the current
// state of the variant and it cares for the proper construction
// and destruction.
template <typename _First, typename _Second>
class BiVariant {
public:
// \brief The \c First type.
typedef _First First;
// \brief The \c Second type.
typedef _Second Second;
// \brief Constructor
//
// This constructor initalizes to the default value of the \c First
// type.
BiVariant() {
flag = true;
new(reinterpret_cast<First*>(data)) First();
}
// \brief Constructor
//
// This constructor initalizes to the given value of the \c First
// type.
BiVariant(const First& f) {
flag = true;
new(reinterpret_cast<First*>(data)) First(f);
}
// \brief Constructor
//
// This constructor initalizes to the given value of the \c
// Second type.
BiVariant(const Second& s) {
flag = false;
new(reinterpret_cast<Second*>(data)) Second(s);
}
// \brief Copy constructor
//
// Copy constructor
BiVariant(const BiVariant& bivariant) {
flag = bivariant.flag;
if (flag) {
new(reinterpret_cast<First*>(data)) First(bivariant.first());
} else {
new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
}
}
// \brief Destrcutor
//
// Destructor
~BiVariant() {
destroy();
}
// \brief Set to the default value of the \c First type.
//
// This function sets the variant to the default value of the \c
// First type.
BiVariant& setFirst() {
destroy();
flag = true;
new(reinterpret_cast<First*>(data)) First();
return *this;
}
// \brief Set to the given value of the \c First type.
//
// This function sets the variant to the given value of the \c
// First type.
BiVariant& setFirst(const First& f) {
destroy();
flag = true;
new(reinterpret_cast<First*>(data)) First(f);
return *this;
}
// \brief Set to the default value of the \c Second type.
//
// This function sets the variant to the default value of the \c
// Second type.
BiVariant& setSecond() {
destroy();
flag = false;
new(reinterpret_cast<Second*>(data)) Second();
return *this;
}
// \brief Set to the given value of the \c Second type.
//
// This function sets the variant to the given value of the \c
// Second type.
BiVariant& setSecond(const Second& s) {
destroy();
flag = false;
new(reinterpret_cast<Second*>(data)) Second(s);
return *this;
}
// \brief Operator form of the \c setFirst()
BiVariant& operator=(const First& f) {
return setFirst(f);
}
// \brief Operator form of the \c setSecond()
BiVariant& operator=(const Second& s) {
return setSecond(s);
}
// \brief Assign operator
BiVariant& operator=(const BiVariant& bivariant) {
if (this == &bivariant) return *this;
destroy();
flag = bivariant.flag;
if (flag) {
new(reinterpret_cast<First*>(data)) First(bivariant.first());
} else {
new(reinterpret_cast<Second*>(data)) Second(bivariant.second());
}
return *this;
}
// \brief Reference to the value
//
// Reference to the value of the \c First type.
// \pre The BiVariant should store value of \c First type.
First& first() {
LEMON_DEBUG(flag, "Variant wrong state");
return *reinterpret_cast<First*>(data);
}
// \brief Const reference to the value
//
// Const reference to the value of the \c First type.
// \pre The BiVariant should store value of \c First type.
const First& first() const {
LEMON_DEBUG(flag, "Variant wrong state");
return *reinterpret_cast<const First*>(data);
}
// \brief Operator form of the \c first()
operator First&() { return first(); }
// \brief Operator form of the const \c first()
operator const First&() const { return first(); }
// \brief Reference to the value
//
// Reference to the value of the \c Second type.
// \pre The BiVariant should store value of \c Second type.
Second& second() {
LEMON_DEBUG(!flag, "Variant wrong state");
return *reinterpret_cast<Second*>(data);
}
// \brief Const reference to the value
//
// Const reference to the value of the \c Second type.
// \pre The BiVariant should store value of \c Second type.
const Second& second() const {
LEMON_DEBUG(!flag, "Variant wrong state");
return *reinterpret_cast<const Second*>(data);
}
// \brief Operator form of the \c second()
operator Second&() { return second(); }
// \brief Operator form of the const \c second()
operator const Second&() const { return second(); }
// \brief %True when the variant is in the first state
//
// %True when the variant stores value of the \c First type.
bool firstState() const { return flag; }
// \brief %True when the variant is in the second state
//
// %True when the variant stores value of the \c Second type.
bool secondState() const { return !flag; }
private:
void destroy() {
if (flag) {
reinterpret_cast<First*>(data)->~First();
} else {
reinterpret_cast<Second*>(data)->~Second();
}
}
char data[_variant_bits::CTMax<sizeof(First), sizeof(Second)>::value];
bool flag;
};
namespace _variant_bits {
template <int _idx, typename _TypeMap>
struct Memory {
typedef typename _TypeMap::template Map<_idx>::Type Current;
static void destroy(int index, char* place) {
if (index == _idx) {
reinterpret_cast<Current*>(place)->~Current();
} else {
Memory<_idx - 1, _TypeMap>::destroy(index, place);
}
}
static void copy(int index, char* to, const char* from) {
if (index == _idx) {
new (reinterpret_cast<Current*>(to))
Current(reinterpret_cast<const Current*>(from));
} else {
Memory<_idx - 1, _TypeMap>::copy(index, to, from);
}
}
};
template <typename _TypeMap>
struct Memory<-1, _TypeMap> {
static void destroy(int, char*) {
LEMON_DEBUG(false, "Variant wrong index.");
}
static void copy(int, char*, const char*) {
LEMON_DEBUG(false, "Variant wrong index.");
}
};
template <int _idx, typename _TypeMap>
struct Size {
static const int value =
CTMax<sizeof(typename _TypeMap::template Map<_idx>::Type),
Size<_idx - 1, _TypeMap>::value>::value;
};
template <typename _TypeMap>
struct Size<0, _TypeMap> {
static const int value =
sizeof(typename _TypeMap::template Map<0>::Type);
};
}
// \brief Variant type
//
// Simple Variant type. The Variant type is a type-safe union.
// C++ has strong limitations for using unions, for example you
// cannot store type with non-default constructor or destructor in
// a union. This class always knowns the current state of the
// variant and it cares for the proper construction and
// destruction.
//
// \param _num The number of the types which can be stored in the
// variant type.
// \param _TypeMap This class describes the types of the Variant. The
// _TypeMap::Map<index>::Type should be a valid type for each index
// in the range {0, 1, ..., _num - 1}. The \c VariantTypeMap is helper
// class to define such type mappings up to 10 types.
//
// And the usage of the class:
//\code
// typedef Variant<3, VariantTypeMap<int, std::string, double> > MyVariant;
// MyVariant var;
// var.set<0>(12);
// std::cout << var.get<0>() << std::endl;
// var.set<1>("alpha");
// std::cout << var.get<1>() << std::endl;
// var.set<2>(0.75);
// std::cout << var.get<2>() << std::endl;
//\endcode
//
// The result of course:
//\code
// 12
// alpha
// 0.75
//\endcode
template <int _num, typename _TypeMap>
class Variant {
public:
static const int num = _num;
typedef _TypeMap TypeMap;
// \brief Constructor
//
// This constructor initalizes to the default value of the \c type
// with 0 index.
Variant() {
flag = 0;
new(reinterpret_cast<typename TypeMap::template Map<0>::Type*>(data))
typename TypeMap::template Map<0>::Type();
}
// \brief Copy constructor
//
// Copy constructor
Variant(const Variant& variant) {
flag = variant.flag;
_variant_bits::Memory<num - 1, TypeMap>::copy(flag, data, variant.data);
}
// \brief Assign operator
//
// Assign operator
Variant& operator=(const Variant& variant) {
if (this == &variant) return *this;
_variant_bits::Memory<num - 1, TypeMap>::
destroy(flag, data);
flag = variant.flag;
_variant_bits::Memory<num - 1, TypeMap>::
copy(flag, data, variant.data);
return *this;
}
// \brief Destrcutor
//
// Destructor
~Variant() {
_variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
}
// \brief Set to the default value of the type with \c _idx index.
//
// This function sets the variant to the default value of the
// type with \c _idx index.
template <int _idx>
Variant& set() {
_variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
flag = _idx;
new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
typename TypeMap::template Map<_idx>::Type();
return *this;
}
// \brief Set to the given value of the type with \c _idx index.
//
// This function sets the variant to the given value of the type
// with \c _idx index.
template <int _idx>
Variant& set(const typename _TypeMap::template Map<_idx>::Type& init) {
_variant_bits::Memory<num - 1, TypeMap>::destroy(flag, data);
flag = _idx;
new(reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>(data))
typename TypeMap::template Map<_idx>::Type(init);
return *this;
}
// \brief Gets the current value of the type with \c _idx index.
//
// Gets the current value of the type with \c _idx index.
template <int _idx>
const typename TypeMap::template Map<_idx>::Type& get() const {
LEMON_DEBUG(_idx == flag, "Variant wrong index");
return *reinterpret_cast<const typename TypeMap::
template Map<_idx>::Type*>(data);
}
// \brief Gets the current value of the type with \c _idx index.
//
// Gets the current value of the type with \c _idx index.
template <int _idx>
typename _TypeMap::template Map<_idx>::Type& get() {
LEMON_DEBUG(_idx == flag, "Variant wrong index");
return *reinterpret_cast<typename TypeMap::template Map<_idx>::Type*>
(data);
}
// \brief Returns the current state of the variant.
//
// Returns the current state of the variant.
int state() const {
return flag;
}
private:
char data[_variant_bits::Size<num - 1, TypeMap>::value];
int flag;
};
namespace _variant_bits {
template <int _index, typename _List>
struct Get {
typedef typename Get<_index - 1, typename _List::Next>::Type Type;
};
template <typename _List>
struct Get<0, _List> {
typedef typename _List::Type Type;
};
struct List {};
template <typename _Type, typename _List>
struct Insert {
typedef _List Next;
typedef _Type Type;
};
template <int _idx, typename _T0, typename _T1, typename _T2,
typename _T3, typename _T4, typename _T5, typename _T6,
typename _T7, typename _T8, typename _T9>
struct Mapper {
typedef List L10;
typedef Insert<_T9, L10> L9;
typedef Insert<_T8, L9> L8;
typedef Insert<_T7, L8> L7;
typedef Insert<_T6, L7> L6;
typedef Insert<_T5, L6> L5;
typedef Insert<_T4, L5> L4;
typedef Insert<_T3, L4> L3;
typedef Insert<_T2, L3> L2;
typedef Insert<_T1, L2> L1;
typedef Insert<_T0, L1> L0;
typedef typename Get<_idx, L0>::Type Type;
};
}
// \brief Helper class for Variant
//
// Helper class to define type mappings for Variant. This class
// converts the template parameters to be mappable by integer.
// \see Variant
template <
typename _T0,
typename _T1 = void, typename _T2 = void, typename _T3 = void,
typename _T4 = void, typename _T5 = void, typename _T6 = void,
typename _T7 = void, typename _T8 = void, typename _T9 = void>
struct VariantTypeMap {
template <int _idx>
struct Map {
typedef typename _variant_bits::
Mapper<_idx, _T0, _T1, _T2, _T3, _T4, _T5, _T6, _T7, _T8, _T9>::Type
Type;
};
};
}
#endif

View File

@ -0,0 +1,244 @@
/* -*- 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.
*
*/
#ifndef LEMON_BITS_VECTOR_MAP_H
#define LEMON_BITS_VECTOR_MAP_H
#include <vector>
#include <algorithm>
#include <lemon/core.h>
#include <lemon/bits/alteration_notifier.h>
#include <lemon/concept_check.h>
#include <lemon/concepts/maps.h>
//\ingroup graphbits
//
//\file
//\brief Vector based graph maps.
namespace lemon {
// \ingroup graphbits
//
// \brief Graph map based on the std::vector storage.
//
// The VectorMap template class is graph map structure that automatically
// updates the map when a key is added to or erased from the graph.
// This map type uses std::vector to store the values.
//
// \tparam _Graph The graph this map is attached to.
// \tparam _Item The item type of the graph items.
// \tparam _Value The value type of the map.
template <typename _Graph, typename _Item, typename _Value>
class VectorMap
: public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
private:
// The container type of the map.
typedef std::vector<_Value> Container;
public:
// The graph type of the map.
typedef _Graph GraphType;
// The item type of the map.
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 notifier type.
typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
// The map type.
typedef VectorMap Map;
// The reference type of the map;
typedef typename Container::reference Reference;
// The const reference type of the map;
typedef typename Container::const_reference ConstReference;
private:
// The base class of the map.
typedef typename Notifier::ObserverBase Parent;
public:
// \brief Constructor to attach the new map into the notifier.
//
// It constructs a map and attachs it into the notifier.
// It adds all the items of the graph to the map.
VectorMap(const GraphType& graph) {
Parent::attach(graph.notifier(Item()));
container.resize(Parent::notifier()->maxId() + 1);
}
// \brief Constructor uses given value to initialize the map.
//
// It constructs a map uses a given value to initialize the map.
// It adds all the items of the graph to the map.
VectorMap(const GraphType& graph, const Value& value) {
Parent::attach(graph.notifier(Item()));
container.resize(Parent::notifier()->maxId() + 1, value);
}
private:
// \brief Copy constructor
//
// Copy constructor.
VectorMap(const VectorMap& _copy) : Parent() {
if (_copy.attached()) {
Parent::attach(*_copy.notifier());
container = _copy.container;
}
}
// \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.
VectorMap& operator=(const VectorMap& cmap) {
return operator=<VectorMap>(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>
VectorMap& 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 subcript operator.
//
// The subscript operator. The map can be subscripted by the
// actual items of the graph.
Reference operator[](const Key& key) {
return container[Parent::notifier()->id(key)];
}
// \brief The const subcript operator.
//
// The const subscript operator. The map can be subscripted by the
// actual items of the graph.
ConstReference operator[](const Key& key) const {
return container[Parent::notifier()->id(key)];
}
// \brief The setter function of the map.
//
// It the same as operator[](key) = value expression.
void set(const Key& key, const Value& value) {
(*this)[key] = value;
}
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) {
int id = Parent::notifier()->id(key);
if (id >= int(container.size())) {
container.resize(id + 1);
}
}
// \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) {
int max = container.size() - 1;
for (int i = 0; i < int(keys.size()); ++i) {
int id = Parent::notifier()->id(keys[i]);
if (id >= max) {
max = id;
}
}
container.resize(max + 1);
}
// \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) {
container[Parent::notifier()->id(key)] = Value();
}
// \brief Erase more keys from the map.
//
// It erases 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) {
container[Parent::notifier()->id(keys[i])] = Value();
}
}
// \brief Build 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() {
int size = Parent::notifier()->maxId() + 1;
container.reserve(size);
container.resize(size);
}
// \brief Clear the map.
//
// It erases 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() {
container.clear();
}
private:
Container container;
};
}
#endif

View File

@ -0,0 +1,166 @@
/* -*- 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/bits/windows.h>
#ifdef WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifdef UNICODE
#undef UNICODE
#endif
#include <windows.h>
#ifdef LOCALE_INVARIANT
#define MY_LOCALE LOCALE_INVARIANT
#else
#define MY_LOCALE LOCALE_NEUTRAL
#endif
#else
#include <unistd.h>
#include <ctime>
#ifndef WIN32
#include <sys/times.h>
#endif
#include <sys/time.h>
#endif
#include <cmath>
#include <sstream>
namespace lemon {
namespace bits {
void getWinProcTimes(double &rtime,
double &utime, double &stime,
double &cutime, double &cstime)
{
#ifdef WIN32
static const double ch = 4294967296.0e-7;
static const double cl = 1.0e-7;
FILETIME system;
GetSystemTimeAsFileTime(&system);
rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime;
FILETIME create, exit, kernel, user;
if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
cutime = 0;
cstime = 0;
} else {
rtime = 0;
utime = 0;
stime = 0;
cutime = 0;
cstime = 0;
}
#else
timeval tv;
gettimeofday(&tv, 0);
rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
tms ts;
double tck=sysconf(_SC_CLK_TCK);
times(&ts);
utime=ts.tms_utime/tck;
stime=ts.tms_stime/tck;
cutime=ts.tms_cutime/tck;
cstime=ts.tms_cstime/tck;
#endif
}
std::string getWinFormattedDate()
{
std::ostringstream os;
#ifdef WIN32
SYSTEMTIME time;
GetSystemTime(&time);
char buf1[11], buf2[9], buf3[5];
if (GetDateFormat(MY_LOCALE, 0, &time,
("ddd MMM dd"), buf1, 11) &&
GetTimeFormat(MY_LOCALE, 0, &time,
("HH':'mm':'ss"), buf2, 9) &&
GetDateFormat(MY_LOCALE, 0, &time,
("yyyy"), buf3, 5)) {
os << buf1 << ' ' << buf2 << ' ' << buf3;
}
else os << "unknown";
#else
timeval tv;
gettimeofday(&tv, 0);
char cbuf[26];
ctime_r(&tv.tv_sec,cbuf);
os << cbuf;
#endif
return os.str();
}
int getWinRndSeed()
{
#ifdef WIN32
FILETIME time;
GetSystemTimeAsFileTime(&time);
return GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime;
#else
timeval tv;
gettimeofday(&tv, 0);
return getpid() + tv.tv_sec + tv.tv_usec;
#endif
}
WinLock::WinLock() {
#ifdef WIN32
CRITICAL_SECTION *lock = new CRITICAL_SECTION;
InitializeCriticalSection(lock);
_repr = lock;
#else
_repr = 0; //Just to avoid 'unused variable' warning with clang
#endif
}
WinLock::~WinLock() {
#ifdef WIN32
CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
DeleteCriticalSection(lock);
delete lock;
#endif
}
void WinLock::lock() {
#ifdef WIN32
CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
EnterCriticalSection(lock);
#endif
}
void WinLock::unlock() {
#ifdef WIN32
CRITICAL_SECTION *lock = static_cast<CRITICAL_SECTION*>(_repr);
LeaveCriticalSection(lock);
#endif
}
}
}

View File

@ -0,0 +1,44 @@
/* -*- 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_WINDOWS_H
#define LEMON_BITS_WINDOWS_H
#include <string>
namespace lemon {
namespace bits {
void getWinProcTimes(double &rtime,
double &utime, double &stime,
double &cutime, double &cstime);
std::string getWinFormattedDate();
int getWinRndSeed();
class WinLock {
public:
WinLock();
~WinLock();
void lock();
void unlock();
private:
void *_repr;
};
}
}
#endif

View File

@ -0,0 +1,594 @@
/* -*- 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_BUCKET_HEAP_H
#define LEMON_BUCKET_HEAP_H
///\ingroup heaps
///\file
///\brief Bucket heap implementation.
#include <vector>
#include <utility>
#include <functional>
namespace lemon {
namespace _bucket_heap_bits {
template <bool MIN>
struct DirectionTraits {
static bool less(int left, int right) {
return left < right;
}
static void increase(int& value) {
++value;
}
};
template <>
struct DirectionTraits<false> {
static bool less(int left, int right) {
return left > right;
}
static void increase(int& value) {
--value;
}
};
}
/// \ingroup heaps
///
/// \brief Bucket heap data structure.
///
/// This class implements the \e bucket \e heap data structure.
/// It practically conforms to the \ref concepts::Heap "heap concept",
/// but it has some limitations.
///
/// The bucket heap is a very simple structure. It can store only
/// \c int priorities and it maintains a list of items for each priority
/// in the range <tt>[0..C)</tt>. So it should only be used when the
/// priorities are small. It is not intended to use as a Dijkstra heap.
///
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
/// The default is \e min-heap. If this parameter is set to \c false,
/// then the comparison is reversed, so the top(), prio() and pop()
/// functions deal with the item having maximum priority instead of the
/// minimum.
///
/// \sa SimpleBucketHeap
template <typename IM, bool MIN = true>
class BucketHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef int 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;
private:
typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
public:
/// \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.
};
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 BucketHeap(ItemIntMap &map) : _iim(map), _minimum(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 _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(); _first.clear(); _minimum = 0;
}
private:
void relocateLast(int idx) {
if (idx + 1 < int(_data.size())) {
_data[idx] = _data.back();
if (_data[idx].prev != -1) {
_data[_data[idx].prev].next = idx;
} else {
_first[_data[idx].value] = idx;
}
if (_data[idx].next != -1) {
_data[_data[idx].next].prev = idx;
}
_iim[_data[idx].item] = idx;
}
_data.pop_back();
}
void unlace(int idx) {
if (_data[idx].prev != -1) {
_data[_data[idx].prev].next = _data[idx].next;
} else {
_first[_data[idx].value] = _data[idx].next;
}
if (_data[idx].next != -1) {
_data[_data[idx].next].prev = _data[idx].prev;
}
}
void lace(int idx) {
if (int(_first.size()) <= _data[idx].value) {
_first.resize(_data[idx].value + 1, -1);
}
_data[idx].next = _first[_data[idx].value];
if (_data[idx].next != -1) {
_data[_data[idx].next].prev = idx;
}
_first[_data[idx].value] = idx;
_data[idx].prev = -1;
}
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) {
push(p.first, p.second);
}
/// \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) {
int idx = _data.size();
_iim[i] = idx;
_data.push_back(BucketItem(i, p));
lace(idx);
if (Direction::less(p, _minimum)) {
_minimum = 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 {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _data[_first[_minimum]].item;
}
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _minimum;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
int idx = _first[_minimum];
_iim[_data[idx].item] = -2;
unlace(idx);
relocateLast(idx);
}
/// \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 idx = _iim[i];
_iim[_data[idx].item] = -2;
unlace(idx);
relocateLast(idx);
}
/// \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].value;
}
/// \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 (Direction::less(p, _data[idx].value)) {
decrease(i, p);
} else {
increase(i, p);
}
}
/// \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];
unlace(idx);
_data[idx].value = p;
if (Direction::less(p, _minimum)) {
_minimum = p;
}
lace(idx);
}
/// \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];
unlace(idx);
_data[idx].value = p;
lace(idx);
}
/// \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 idx = _iim[i];
if (idx >= 0) idx = 0;
return State(idx);
}
/// \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:
struct BucketItem {
BucketItem(const Item& _item, int _value)
: item(_item), value(_value) {}
Item item;
int value;
int prev, next;
};
ItemIntMap& _iim;
std::vector<int> _first;
std::vector<BucketItem> _data;
mutable int _minimum;
}; // class BucketHeap
/// \ingroup heaps
///
/// \brief Simplified bucket heap data structure.
///
/// This class implements a simplified \e bucket \e heap data
/// structure. It does not provide some functionality, but it is
/// faster and simpler than BucketHeap. The main difference is
/// that BucketHeap stores a doubly-linked list for each key while
/// this class stores only simply-linked lists. It supports erasing
/// only for the item having minimum priority and it does not support
/// key increasing and decreasing.
///
/// Note that this implementation does not conform to the
/// \ref concepts::Heap "heap concept" due to the lack of some
/// functionality.
///
/// \tparam IM A read-writable item map with \c int values, used
/// internally to handle the cross references.
/// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
/// The default is \e min-heap. If this parameter is set to \c false,
/// then the comparison is reversed, so the top(), prio() and pop()
/// functions deal with the item having maximum priority instead of the
/// minimum.
///
/// \sa BucketHeap
template <typename IM, bool MIN = true >
class SimpleBucketHeap {
public:
/// Type of the item-int map.
typedef IM ItemIntMap;
/// Type of the priorities.
typedef int 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;
private:
typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
public:
/// \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.
};
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 SimpleBucketHeap(ItemIntMap &map)
: _iim(map), _free(-1), _num(0), _minimum(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; }
/// \brief Check if the heap is empty.
///
/// This function returns \c true if the heap is empty.
bool empty() const { return _num == 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(); _first.clear(); _free = -1; _num = 0; _minimum = 0;
}
/// \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) {
push(p.first, p.second);
}
/// \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) {
int idx;
if (_free == -1) {
idx = _data.size();
_data.push_back(BucketItem(i));
} else {
idx = _free;
_free = _data[idx].next;
_data[idx].item = i;
}
_iim[i] = idx;
if (p >= int(_first.size())) _first.resize(p + 1, -1);
_data[idx].next = _first[p];
_first[p] = idx;
if (Direction::less(p, _minimum)) {
_minimum = p;
}
++_num;
}
/// \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 {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _data[_first[_minimum]].item;
}
/// \brief The minimum priority.
///
/// This function returns the minimum priority.
/// \pre The heap must be non-empty.
Prio prio() const {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
return _minimum;
}
/// \brief Remove the item having minimum priority.
///
/// This function removes the item having minimum priority.
/// \pre The heap must be non-empty.
void pop() {
while (_first[_minimum] == -1) {
Direction::increase(_minimum);
}
int idx = _first[_minimum];
_iim[_data[idx].item] = -2;
_first[_minimum] = _data[idx].next;
_data[idx].next = _free;
_free = idx;
--_num;
}
/// \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.
/// \warning This operator is not a constant time function because
/// it scans the whole data structure to find the proper value.
Prio operator[](const Item &i) const {
for (int k = 0; k < int(_first.size()); ++k) {
int idx = _first[k];
while (idx != -1) {
if (_data[idx].item == i) {
return k;
}
idx = _data[idx].next;
}
}
return -1;
}
/// \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 idx = _iim[i];
if (idx >= 0) idx = 0;
return State(idx);
}
private:
struct BucketItem {
BucketItem(const Item& _item)
: item(_item) {}
Item item;
int next;
};
ItemIntMap& _iim;
std::vector<int> _first;
std::vector<BucketItem> _data;
int _free, _num;
mutable int _minimum;
}; // class SimpleBucketHeap
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,460 @@
/* -*- 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 Implementation of the CBC MIP solver interface.
#include "cbc.h"
#include <coin/CoinModel.hpp>
#include <coin/CbcModel.hpp>
#include <coin/OsiSolverInterface.hpp>
#include "coin/OsiClpSolverInterface.hpp"
#include "coin/CbcCutGenerator.hpp"
#include "coin/CbcHeuristicLocal.hpp"
#include "coin/CbcHeuristicGreedy.hpp"
#include "coin/CbcHeuristicFPump.hpp"
#include "coin/CbcHeuristicRINS.hpp"
#include "coin/CglGomory.hpp"
#include "coin/CglProbing.hpp"
#include "coin/CglKnapsackCover.hpp"
#include "coin/CglOddHole.hpp"
#include "coin/CglClique.hpp"
#include "coin/CglFlowCover.hpp"
#include "coin/CglMixedIntegerRounding.hpp"
#include "coin/CbcHeuristic.hpp"
namespace lemon {
CbcMip::CbcMip() {
_prob = new CoinModel();
_prob->setProblemName("LEMON");
_osi_solver = 0;
_cbc_model = 0;
messageLevel(MESSAGE_NOTHING);
}
CbcMip::CbcMip(const CbcMip& other) {
_prob = new CoinModel(*other._prob);
_prob->setProblemName("LEMON");
_osi_solver = 0;
_cbc_model = 0;
messageLevel(MESSAGE_NOTHING);
}
CbcMip::~CbcMip() {
delete _prob;
if (_osi_solver) delete _osi_solver;
if (_cbc_model) delete _cbc_model;
}
const char* CbcMip::_solverName() const { return "CbcMip"; }
int CbcMip::_addCol() {
_prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0, 0, false);
return _prob->numberColumns() - 1;
}
CbcMip* CbcMip::newSolver() const {
CbcMip* newlp = new CbcMip;
return newlp;
}
CbcMip* CbcMip::cloneSolver() const {
CbcMip* copylp = new CbcMip(*this);
return copylp;
}
int CbcMip::_addRow() {
_prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
return _prob->numberRows() - 1;
}
int CbcMip::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
std::vector<int> indexes;
std::vector<Value> values;
for(ExprIterator it = b; it != e; ++it) {
indexes.push_back(it->first);
values.push_back(it->second);
}
_prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
return _prob->numberRows() - 1;
}
void CbcMip::_eraseCol(int i) {
_prob->deleteColumn(i);
}
void CbcMip::_eraseRow(int i) {
_prob->deleteRow(i);
}
void CbcMip::_eraseColId(int i) {
cols.eraseIndex(i);
}
void CbcMip::_eraseRowId(int i) {
rows.eraseIndex(i);
}
void CbcMip::_getColName(int c, std::string& name) const {
name = _prob->getColumnName(c);
}
void CbcMip::_setColName(int c, const std::string& name) {
_prob->setColumnName(c, name.c_str());
}
int CbcMip::_colByName(const std::string& name) const {
return _prob->column(name.c_str());
}
void CbcMip::_getRowName(int r, std::string& name) const {
name = _prob->getRowName(r);
}
void CbcMip::_setRowName(int r, const std::string& name) {
_prob->setRowName(r, name.c_str());
}
int CbcMip::_rowByName(const std::string& name) const {
return _prob->row(name.c_str());
}
void CbcMip::_setRowCoeffs(int i, ExprIterator b, ExprIterator e) {
for (ExprIterator it = b; it != e; ++it) {
_prob->setElement(i, it->first, it->second);
}
}
void CbcMip::_getRowCoeffs(int ix, InsertIterator b) const {
int length = _prob->numberRows();
std::vector<int> indices(length);
std::vector<Value> values(length);
length = _prob->getRow(ix, &indices[0], &values[0]);
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
++b;
}
}
void CbcMip::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
for (ExprIterator it = b; it != e; ++it) {
_prob->setElement(it->first, ix, it->second);
}
}
void CbcMip::_getColCoeffs(int ix, InsertIterator b) const {
int length = _prob->numberColumns();
std::vector<int> indices(length);
std::vector<Value> values(length);
length = _prob->getColumn(ix, &indices[0], &values[0]);
for (int i = 0; i < length; ++i) {
*b = std::make_pair(indices[i], values[i]);
++b;
}
}
void CbcMip::_setCoeff(int ix, int jx, Value value) {
_prob->setElement(ix, jx, value);
}
CbcMip::Value CbcMip::_getCoeff(int ix, int jx) const {
return _prob->getElement(ix, jx);
}
void CbcMip::_setColLowerBound(int i, Value lo) {
LEMON_ASSERT(lo != INF, "Invalid bound");
_prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
CbcMip::Value CbcMip::_getColLowerBound(int i) const {
double val = _prob->getColumnLower(i);
return val == - COIN_DBL_MAX ? - INF : val;
}
void CbcMip::_setColUpperBound(int i, Value up) {
LEMON_ASSERT(up != -INF, "Invalid bound");
_prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
}
CbcMip::Value CbcMip::_getColUpperBound(int i) const {
double val = _prob->getColumnUpper(i);
return val == COIN_DBL_MAX ? INF : val;
}
void CbcMip::_setRowLowerBound(int i, Value lo) {
LEMON_ASSERT(lo != INF, "Invalid bound");
_prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
CbcMip::Value CbcMip::_getRowLowerBound(int i) const {
double val = _prob->getRowLower(i);
return val == - COIN_DBL_MAX ? - INF : val;
}
void CbcMip::_setRowUpperBound(int i, Value up) {
LEMON_ASSERT(up != -INF, "Invalid bound");
_prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
}
CbcMip::Value CbcMip::_getRowUpperBound(int i) const {
double val = _prob->getRowUpper(i);
return val == COIN_DBL_MAX ? INF : val;
}
void CbcMip::_setObjCoeffs(ExprIterator b, ExprIterator e) {
int num = _prob->numberColumns();
for (int i = 0; i < num; ++i) {
_prob->setColumnObjective(i, 0.0);
}
for (ExprIterator it = b; it != e; ++it) {
_prob->setColumnObjective(it->first, it->second);
}
}
void CbcMip::_getObjCoeffs(InsertIterator b) const {
int num = _prob->numberColumns();
for (int i = 0; i < num; ++i) {
Value coef = _prob->getColumnObjective(i);
if (coef != 0.0) {
*b = std::make_pair(i, coef);
++b;
}
}
}
void CbcMip::_setObjCoeff(int i, Value obj_coef) {
_prob->setColumnObjective(i, obj_coef);
}
CbcMip::Value CbcMip::_getObjCoeff(int i) const {
return _prob->getColumnObjective(i);
}
CbcMip::SolveExitStatus CbcMip::_solve() {
if (_osi_solver) {
delete _osi_solver;
}
_osi_solver = new OsiClpSolverInterface();
_osi_solver->loadFromCoinModel(*_prob);
if (_cbc_model) {
delete _cbc_model;
}
_cbc_model= new CbcModel(*_osi_solver);
_osi_solver->messageHandler()->setLogLevel(_message_level);
_cbc_model->setLogLevel(_message_level);
_cbc_model->initialSolve();
_cbc_model->solver()->setHintParam(OsiDoReducePrint, true, OsiHintTry);
if (!_cbc_model->isInitialSolveAbandoned() &&
_cbc_model->isInitialSolveProvenOptimal() &&
!_cbc_model->isInitialSolveProvenPrimalInfeasible() &&
!_cbc_model->isInitialSolveProvenDualInfeasible()) {
CglProbing generator1;
generator1.setUsingObjective(true);
generator1.setMaxPass(3);
generator1.setMaxProbe(100);
generator1.setMaxLook(50);
generator1.setRowCuts(3);
_cbc_model->addCutGenerator(&generator1, -1, "Probing");
CglGomory generator2;
generator2.setLimit(300);
_cbc_model->addCutGenerator(&generator2, -1, "Gomory");
CglKnapsackCover generator3;
_cbc_model->addCutGenerator(&generator3, -1, "Knapsack");
CglOddHole generator4;
generator4.setMinimumViolation(0.005);
generator4.setMinimumViolationPer(0.00002);
generator4.setMaximumEntries(200);
_cbc_model->addCutGenerator(&generator4, -1, "OddHole");
CglClique generator5;
generator5.setStarCliqueReport(false);
generator5.setRowCliqueReport(false);
_cbc_model->addCutGenerator(&generator5, -1, "Clique");
CglMixedIntegerRounding mixedGen;
_cbc_model->addCutGenerator(&mixedGen, -1, "MixedIntegerRounding");
CglFlowCover flowGen;
_cbc_model->addCutGenerator(&flowGen, -1, "FlowCover");
OsiClpSolverInterface* osiclp =
dynamic_cast<OsiClpSolverInterface*>(_cbc_model->solver());
if (osiclp->getNumRows() < 300 && osiclp->getNumCols() < 500) {
osiclp->setupForRepeatedUse(2, 0);
}
CbcRounding heuristic1(*_cbc_model);
heuristic1.setWhen(3);
_cbc_model->addHeuristic(&heuristic1);
CbcHeuristicLocal heuristic2(*_cbc_model);
heuristic2.setWhen(3);
_cbc_model->addHeuristic(&heuristic2);
CbcHeuristicGreedyCover heuristic3(*_cbc_model);
heuristic3.setAlgorithm(11);
heuristic3.setWhen(3);
_cbc_model->addHeuristic(&heuristic3);
CbcHeuristicFPump heuristic4(*_cbc_model);
heuristic4.setWhen(3);
_cbc_model->addHeuristic(&heuristic4);
CbcHeuristicRINS heuristic5(*_cbc_model);
heuristic5.setWhen(3);
_cbc_model->addHeuristic(&heuristic5);
if (_cbc_model->getNumCols() < 500) {
_cbc_model->setMaximumCutPassesAtRoot(-100);
} else if (_cbc_model->getNumCols() < 5000) {
_cbc_model->setMaximumCutPassesAtRoot(100);
} else {
_cbc_model->setMaximumCutPassesAtRoot(20);
}
if (_cbc_model->getNumCols() < 5000) {
_cbc_model->setNumberStrong(10);
}
_cbc_model->solver()->setIntParam(OsiMaxNumIterationHotStart, 100);
_cbc_model->branchAndBound();
}
if (_cbc_model->isAbandoned()) {
return UNSOLVED;
} else {
return SOLVED;
}
}
CbcMip::Value CbcMip::_getSol(int i) const {
return _cbc_model->getColSolution()[i];
}
CbcMip::Value CbcMip::_getSolValue() const {
return _cbc_model->getObjValue();
}
CbcMip::ProblemType CbcMip::_getType() const {
if (_cbc_model->isProvenOptimal()) {
return OPTIMAL;
} else if (_cbc_model->isContinuousUnbounded()) {
return UNBOUNDED;
}
return FEASIBLE;
}
void CbcMip::_setSense(Sense sense) {
switch (sense) {
case MIN:
_prob->setOptimizationDirection(1.0);
break;
case MAX:
_prob->setOptimizationDirection(- 1.0);
break;
}
}
CbcMip::Sense CbcMip::_getSense() const {
if (_prob->optimizationDirection() > 0.0) {
return MIN;
} else if (_prob->optimizationDirection() < 0.0) {
return MAX;
} else {
LEMON_ASSERT(false, "Wrong sense");
return CbcMip::Sense();
}
}
void CbcMip::_setColType(int i, CbcMip::ColTypes col_type) {
switch (col_type){
case INTEGER:
_prob->setInteger(i);
break;
case REAL:
_prob->setContinuous(i);
break;
default:;
LEMON_ASSERT(false, "Wrong sense");
}
}
CbcMip::ColTypes CbcMip::_getColType(int i) const {
return _prob->getColumnIsInteger(i) ? INTEGER : REAL;
}
void CbcMip::_clear() {
delete _prob;
if (_osi_solver) {
delete _osi_solver;
_osi_solver = 0;
}
if (_cbc_model) {
delete _cbc_model;
_cbc_model = 0;
}
_prob = new CoinModel();
}
void CbcMip::_messageLevel(MessageLevel level) {
switch (level) {
case MESSAGE_NOTHING:
_message_level = 0;
break;
case MESSAGE_ERROR:
_message_level = 1;
break;
case MESSAGE_WARNING:
_message_level = 1;
break;
case MESSAGE_NORMAL:
_message_level = 2;
break;
case MESSAGE_VERBOSE:
_message_level = 3;
break;
}
}
} //END OF NAMESPACE LEMON

View File

@ -0,0 +1,129 @@
/* -*- 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_CBC_H
#define LEMON_CBC_H
///\file
///\brief Header of the LEMON-CBC mip solver interface.
///\ingroup lp_group
#include <lemon/lp_base.h>
class CoinModel;
class OsiSolverInterface;
class CbcModel;
namespace lemon {
/// \brief Interface for the CBC MIP solver
///
/// This class implements an interface for the CBC MIP solver.
///\ingroup lp_group
class CbcMip : public MipSolver {
protected:
CoinModel *_prob;
OsiSolverInterface *_osi_solver;
CbcModel *_cbc_model;
public:
/// \e
CbcMip();
/// \e
CbcMip(const CbcMip&);
/// \e
~CbcMip();
/// \e
virtual CbcMip* newSolver() const;
/// \e
virtual CbcMip* cloneSolver() const;
protected:
virtual const char* _solverName() const;
virtual int _addCol();
virtual int _addRow();
virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
virtual void _eraseCol(int i);
virtual void _eraseRow(int i);
virtual void _eraseColId(int i);
virtual void _eraseRowId(int i);
virtual void _getColName(int col, std::string& name) const;
virtual void _setColName(int col, const std::string& name);
virtual int _colByName(const std::string& name) const;
virtual void _getRowName(int row, std::string& name) const;
virtual void _setRowName(int row, const std::string& name);
virtual int _rowByName(const std::string& name) const;
virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getRowCoeffs(int i, InsertIterator b) const;
virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getColCoeffs(int i, InsertIterator b) const;
virtual void _setCoeff(int row, int col, Value value);
virtual Value _getCoeff(int row, int col) const;
virtual void _setColLowerBound(int i, Value value);
virtual Value _getColLowerBound(int i) const;
virtual void _setColUpperBound(int i, Value value);
virtual Value _getColUpperBound(int i) const;
virtual void _setRowLowerBound(int i, Value value);
virtual Value _getRowLowerBound(int i) const;
virtual void _setRowUpperBound(int i, Value value);
virtual Value _getRowUpperBound(int i) const;
virtual void _setObjCoeffs(ExprIterator b, ExprIterator e);
virtual void _getObjCoeffs(InsertIterator b) const;
virtual void _setObjCoeff(int i, Value obj_coef);
virtual Value _getObjCoeff(int i) const;
virtual void _setSense(Sense sense);
virtual Sense _getSense() const;
virtual ColTypes _getColType(int col) const;
virtual void _setColType(int col, ColTypes col_type);
virtual SolveExitStatus _solve();
virtual ProblemType _getType() const;
virtual Value _getSol(int i) const;
virtual Value _getSolValue() const;
virtual void _clear();
virtual void _messageLevel(MessageLevel level);
void _applyMessageLevel();
int _message_level;
};
}
#endif

View File

@ -0,0 +1,254 @@
/* -*- 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_CHRISTOFIDES_TSP_H
#define LEMON_CHRISTOFIDES_TSP_H
/// \ingroup tsp
/// \file
/// \brief Christofides algorithm for symmetric TSP
#include <lemon/full_graph.h>
#include <lemon/smart_graph.h>
#include <lemon/kruskal.h>
#include <lemon/matching.h>
#include <lemon/euler.h>
namespace lemon {
/// \ingroup tsp
///
/// \brief Christofides algorithm for symmetric TSP.
///
/// ChristofidesTsp implements Christofides' heuristic for solving
/// symmetric \ref tsp "TSP".
///
/// This a well-known approximation method for the TSP problem with
/// metric cost function.
/// It has a guaranteed approximation factor of 3/2 (i.e. it finds a tour
/// whose total cost is at most 3/2 of the optimum), but it usually
/// provides better solutions in practice.
/// This implementation runs in O(n<sup>3</sup>log(n)) time.
///
/// The algorithm starts with a \ref spantree "minimum cost spanning tree" and
/// finds a \ref MaxWeightedPerfectMatching "minimum cost perfect matching"
/// in the subgraph induced by the nodes that have odd degree in the
/// spanning tree.
/// Finally, it constructs the tour from the \ref EulerIt "Euler traversal"
/// of the union of the spanning tree and the matching.
/// During this last step, the algorithm simply skips the visited nodes
/// (i.e. creates shortcuts) assuming that the triangle inequality holds
/// for the cost function.
///
/// \tparam CM Type of the cost map.
///
/// \warning CM::Value must be a signed number type.
template <typename CM>
class ChristofidesTsp
{
public:
/// Type of the cost map
typedef CM CostMap;
/// Type of the edge costs
typedef typename CM::Value Cost;
private:
GRAPH_TYPEDEFS(FullGraph);
const FullGraph &_gr;
const CostMap &_cost;
std::vector<Node> _path;
Cost _sum;
public:
/// \brief Constructor
///
/// Constructor.
/// \param gr The \ref FullGraph "full graph" the algorithm runs on.
/// \param cost The cost map.
ChristofidesTsp(const FullGraph &gr, const CostMap &cost)
: _gr(gr), _cost(cost) {}
/// \name Execution Control
/// @{
/// \brief Runs the algorithm.
///
/// This function runs the algorithm.
///
/// \return The total cost of the found tour.
Cost run() {
_path.clear();
if (_gr.nodeNum() == 0) return _sum = 0;
else if (_gr.nodeNum() == 1) {
_path.push_back(_gr(0));
return _sum = 0;
}
else if (_gr.nodeNum() == 2) {
_path.push_back(_gr(0));
_path.push_back(_gr(1));
return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))];
}
// Compute min. cost spanning tree
std::vector<Edge> tree;
kruskal(_gr, _cost, std::back_inserter(tree));
FullGraph::NodeMap<int> deg(_gr, 0);
for (int i = 0; i != int(tree.size()); ++i) {
Edge e = tree[i];
++deg[_gr.u(e)];
++deg[_gr.v(e)];
}
// Copy the induced subgraph of odd nodes
std::vector<Node> odd_nodes;
for (NodeIt u(_gr); u != INVALID; ++u) {
if (deg[u] % 2 == 1) odd_nodes.push_back(u);
}
SmartGraph sgr;
SmartGraph::EdgeMap<Cost> scost(sgr);
for (int i = 0; i != int(odd_nodes.size()); ++i) {
sgr.addNode();
}
for (int i = 0; i != int(odd_nodes.size()); ++i) {
for (int j = 0; j != int(odd_nodes.size()); ++j) {
if (j == i) continue;
SmartGraph::Edge e =
sgr.addEdge(sgr.nodeFromId(i), sgr.nodeFromId(j));
scost[e] = -_cost[_gr.edge(odd_nodes[i], odd_nodes[j])];
}
}
// Compute min. cost perfect matching
MaxWeightedPerfectMatching<SmartGraph, SmartGraph::EdgeMap<Cost> >
mwpm(sgr, scost);
mwpm.run();
for (SmartGraph::EdgeIt e(sgr); e != INVALID; ++e) {
if (mwpm.matching(e)) {
tree.push_back( _gr.edge(odd_nodes[sgr.id(sgr.u(e))],
odd_nodes[sgr.id(sgr.v(e))]) );
}
}
// Join the spanning tree and the matching
sgr.clear();
for (int i = 0; i != _gr.nodeNum(); ++i) {
sgr.addNode();
}
for (int i = 0; i != int(tree.size()); ++i) {
int ui = _gr.id(_gr.u(tree[i])),
vi = _gr.id(_gr.v(tree[i]));
sgr.addEdge(sgr.nodeFromId(ui), sgr.nodeFromId(vi));
}
// Compute the tour from the Euler traversal
SmartGraph::NodeMap<bool> visited(sgr, false);
for (EulerIt<SmartGraph> e(sgr); e != INVALID; ++e) {
SmartGraph::Node n = sgr.target(e);
if (!visited[n]) {
_path.push_back(_gr(sgr.id(n)));
visited[n] = true;
}
}
_sum = _cost[_gr.edge(_path.back(), _path.front())];
for (int i = 0; i < int(_path.size())-1; ++i) {
_sum += _cost[_gr.edge(_path[i], _path[i+1])];
}
return _sum;
}
/// @}
/// \name Query Functions
/// @{
/// \brief The total cost of the found tour.
///
/// This function returns the total cost of the found tour.
///
/// \pre run() must be called before using this function.
Cost tourCost() const {
return _sum;
}
/// \brief Returns a const reference to the node sequence of the
/// found tour.
///
/// This function returns a const reference to a vector
/// that stores the node sequence of the found tour.
///
/// \pre run() must be called before using this function.
const std::vector<Node>& tourNodes() const {
return _path;
}
/// \brief Gives back the node sequence of the found tour.
///
/// This function copies the node sequence of the found tour into
/// an STL container through the given output iterator. The
/// <tt>value_type</tt> of the container must be <tt>FullGraph::Node</tt>.
/// For example,
/// \code
/// std::vector<FullGraph::Node> nodes(countNodes(graph));
/// tsp.tourNodes(nodes.begin());
/// \endcode
/// or
/// \code
/// std::list<FullGraph::Node> nodes;
/// tsp.tourNodes(std::back_inserter(nodes));
/// \endcode
///
/// \pre run() must be called before using this function.
template <typename Iterator>
void tourNodes(Iterator out) const {
std::copy(_path.begin(), _path.end(), out);
}
/// \brief Gives back the found tour as a path.
///
/// This function copies the found tour as a list of arcs/edges into
/// the given \ref lemon::concepts::Path "path structure".
///
/// \pre run() must be called before using this function.
template <typename Path>
void tour(Path &path) const {
path.clear();
for (int i = 0; i < int(_path.size()) - 1; ++i) {
path.addBack(_gr.arc(_path[i], _path[i+1]));
}
if (int(_path.size()) >= 2) {
path.addBack(_gr.arc(_path.back(), _path.front()));
}
}
/// @}
};
}; // namespace lemon
#endif

View File

@ -0,0 +1,807 @@
/* -*- 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_CIRCULATION_H
#define LEMON_CIRCULATION_H
#include <lemon/tolerance.h>
#include <lemon/elevator.h>
#include <limits>
///\ingroup max_flow
///\file
///\brief Push-relabel algorithm for finding a feasible circulation.
///
namespace lemon {
/// \brief Default traits class of Circulation class.
///
/// Default traits class of Circulation class.
///
/// \tparam GR Type of the digraph the algorithm runs on.
/// \tparam LM The type of the lower bound map.
/// \tparam UM The type of the upper bound (capacity) map.
/// \tparam SM The type of the supply map.
template <typename GR, typename LM,
typename UM, typename SM>
struct CirculationDefaultTraits {
/// \brief The type of the digraph the algorithm runs on.
typedef GR Digraph;
/// \brief The type of the lower bound map.
///
/// The type of the map that stores the lower bounds on the arcs.
/// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
typedef LM LowerMap;
/// \brief The type of the upper bound (capacity) map.
///
/// The type of the map that stores the upper bounds (capacities)
/// on the arcs.
/// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
typedef UM UpperMap;
/// \brief The type of supply map.
///
/// The type of the map that stores the signed supply values of the
/// nodes.
/// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
typedef SM SupplyMap;
/// \brief The type of the flow and supply values.
typedef typename SupplyMap::Value Value;
/// \brief The type of the map that stores the flow values.
///
/// The type of the map that stores the flow values.
/// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
/// concept.
#ifdef DOXYGEN
typedef GR::ArcMap<Value> FlowMap;
#else
typedef typename Digraph::template ArcMap<Value> FlowMap;
#endif
/// \brief Instantiates a FlowMap.
///
/// This function instantiates a \ref FlowMap.
/// \param digraph The digraph for which we would like to define
/// the flow map.
static FlowMap* createFlowMap(const Digraph& digraph) {
return new FlowMap(digraph);
}
/// \brief The elevator type used by the algorithm.
///
/// The elevator type used by the algorithm.
///
/// \sa Elevator, LinkedElevator
#ifdef DOXYGEN
typedef lemon::Elevator<GR, GR::Node> Elevator;
#else
typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
#endif
/// \brief Instantiates an Elevator.
///
/// This function instantiates an \ref Elevator.
/// \param digraph The digraph for which we would like to define
/// the elevator.
/// \param max_level The maximum level of the elevator.
static Elevator* createElevator(const Digraph& digraph, int max_level) {
return new Elevator(digraph, max_level);
}
/// \brief The tolerance used by the algorithm
///
/// The tolerance used by the algorithm to handle inexact computation.
typedef lemon::Tolerance<Value> Tolerance;
};
/**
\brief Push-relabel algorithm for the network circulation problem.
\ingroup max_flow
This class implements a push-relabel algorithm for the \e network
\e circulation problem.
It is to find a feasible circulation when lower and upper bounds
are given for the flow values on the arcs and lower bounds are
given for the difference between the outgoing and incoming flow
at the nodes.
The exact formulation of this problem is the following.
Let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$
\f$upper: A\rightarrow\mathbf{R}\cup\{\infty\}\f$ denote the lower and
upper bounds on the arcs, for which \f$lower(uv) \leq upper(uv)\f$
holds for all \f$uv\in A\f$, and \f$sup: V\rightarrow\mathbf{R}\f$
denotes the signed supply values of the nodes.
If \f$sup(u)>0\f$, then \f$u\f$ is a supply node with \f$sup(u)\f$
supply, if \f$sup(u)<0\f$, then \f$u\f$ is a demand node with
\f$-sup(u)\f$ demand.
A feasible circulation is an \f$f: A\rightarrow\mathbf{R}\f$
solution of the following problem.
\f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu)
\geq sup(u) \quad \forall u\in V, \f]
\f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A. \f]
The sum of the supply values, i.e. \f$\sum_{u\in V} sup(u)\f$ must be
zero or negative in order to have a feasible solution (since the sum
of the expressions on the left-hand side of the inequalities is zero).
It means that the total demand must be greater or equal to the total
supply and all the supplies have to be carried out from the supply nodes,
but there could be demands that are not satisfied.
If \f$\sum_{u\in V} sup(u)\f$ is zero, then all the supply/demand
constraints have to be satisfied with equality, i.e. all demands
have to be satisfied and all supplies have to be used.
If you need the opposite inequalities in the supply/demand constraints
(i.e. the total demand is less than the total supply and all the demands
have to be satisfied while there could be supplies that are not used),
then you could easily transform the problem to the above form by reversing
the direction of the arcs and taking the negative of the supply values
(e.g. using \ref ReverseDigraph and \ref NegMap adaptors).
This algorithm either calculates a feasible circulation, or provides
a \ref barrier() "barrier", which prooves that a feasible soultion
cannot exist.
Note that this algorithm also provides a feasible solution for the
\ref min_cost_flow "minimum cost flow problem".
\tparam GR The type of the digraph the algorithm runs on.
\tparam LM The type of the lower bound map. The default
map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
\tparam UM The type of the upper bound (capacity) map.
The default map type is \c LM.
\tparam SM The type of the supply map. The default map type is
\ref concepts::Digraph::NodeMap "GR::NodeMap<UM::Value>".
\tparam TR The traits class that defines various types used by the
algorithm. By default, it is \ref CirculationDefaultTraits
"CirculationDefaultTraits<GR, LM, UM, SM>".
In most cases, this parameter should not be set directly,
consider to use the named template parameters instead.
*/
#ifdef DOXYGEN
template< typename GR,
typename LM,
typename UM,
typename SM,
typename TR >
#else
template< typename GR,
typename LM = typename GR::template ArcMap<int>,
typename UM = LM,
typename SM = typename GR::template NodeMap<typename UM::Value>,
typename TR = CirculationDefaultTraits<GR, LM, UM, SM> >
#endif
class Circulation {
public:
/// \brief The \ref lemon::CirculationDefaultTraits "traits class"
/// of the algorithm.
typedef TR Traits;
///The type of the digraph the algorithm runs on.
typedef typename Traits::Digraph Digraph;
///The type of the flow and supply values.
typedef typename Traits::Value Value;
///The type of the lower bound map.
typedef typename Traits::LowerMap LowerMap;
///The type of the upper bound (capacity) map.
typedef typename Traits::UpperMap UpperMap;
///The type of the supply map.
typedef typename Traits::SupplyMap SupplyMap;
///The type of the flow map.
typedef typename Traits::FlowMap FlowMap;
///The type of the elevator.
typedef typename Traits::Elevator Elevator;
///The type of the tolerance.
typedef typename Traits::Tolerance Tolerance;
private:
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
const Digraph &_g;
int _node_num;
const LowerMap *_lo;
const UpperMap *_up;
const SupplyMap *_supply;
FlowMap *_flow;
bool _local_flow;
Elevator* _level;
bool _local_level;
typedef typename Digraph::template NodeMap<Value> ExcessMap;
ExcessMap* _excess;
Tolerance _tol;
int _el;
public:
typedef Circulation Create;
///\name Named Template Parameters
///@{
template <typename T>
struct SetFlowMapTraits : public Traits {
typedef T FlowMap;
static FlowMap *createFlowMap(const Digraph&) {
LEMON_ASSERT(false, "FlowMap is not initialized");
return 0; // ignore warnings
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// FlowMap type
///
/// \ref named-templ-param "Named parameter" for setting FlowMap
/// type.
template <typename T>
struct SetFlowMap
: public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetFlowMapTraits<T> > {
typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetFlowMapTraits<T> > Create;
};
template <typename T>
struct SetElevatorTraits : public Traits {
typedef T Elevator;
static Elevator *createElevator(const Digraph&, int) {
LEMON_ASSERT(false, "Elevator is not initialized");
return 0; // ignore warnings
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// Elevator type
///
/// \ref named-templ-param "Named parameter" for setting Elevator
/// type. If this named parameter is used, then an external
/// elevator object must be passed to the algorithm using the
/// \ref elevator(Elevator&) "elevator()" function before calling
/// \ref run() or \ref init().
/// \sa SetStandardElevator
template <typename T>
struct SetElevator
: public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetElevatorTraits<T> > {
typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetElevatorTraits<T> > Create;
};
template <typename T>
struct SetStandardElevatorTraits : public Traits {
typedef T Elevator;
static Elevator *createElevator(const Digraph& digraph, int max_level) {
return new Elevator(digraph, max_level);
}
};
/// \brief \ref named-templ-param "Named parameter" for setting
/// Elevator type with automatic allocation
///
/// \ref named-templ-param "Named parameter" for setting Elevator
/// type with automatic allocation.
/// The Elevator should have standard constructor interface to be
/// able to automatically created by the algorithm (i.e. the
/// digraph and the maximum level should be passed to it).
/// However, an external elevator object could also be passed to the
/// algorithm with the \ref elevator(Elevator&) "elevator()" function
/// before calling \ref run() or \ref init().
/// \sa SetElevator
template <typename T>
struct SetStandardElevator
: public Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetStandardElevatorTraits<T> > {
typedef Circulation<Digraph, LowerMap, UpperMap, SupplyMap,
SetStandardElevatorTraits<T> > Create;
};
/// @}
protected:
Circulation() {}
public:
/// Constructor.
/// The constructor of the class.
///
/// \param graph The digraph the algorithm runs on.
/// \param lower The lower bounds for the flow values on the arcs.
/// \param upper The upper bounds (capacities) for the flow values
/// on the arcs.
/// \param supply The signed supply values of the nodes.
Circulation(const Digraph &graph, const LowerMap &lower,
const UpperMap &upper, const SupplyMap &supply)
: _g(graph), _lo(&lower), _up(&upper), _supply(&supply),
_flow(NULL), _local_flow(false), _level(NULL), _local_level(false),
_excess(NULL) {}
/// Destructor.
~Circulation() {
destroyStructures();
}
private:
bool checkBoundMaps() {
for (ArcIt e(_g);e!=INVALID;++e) {
if (_tol.less((*_up)[e], (*_lo)[e])) return false;
}
return true;
}
void createStructures() {
_node_num = _el = countNodes(_g);
if (!_flow) {
_flow = Traits::createFlowMap(_g);
_local_flow = true;
}
if (!_level) {
_level = Traits::createElevator(_g, _node_num);
_local_level = true;
}
if (!_excess) {
_excess = new ExcessMap(_g);
}
}
void destroyStructures() {
if (_local_flow) {
delete _flow;
}
if (_local_level) {
delete _level;
}
if (_excess) {
delete _excess;
}
}
public:
/// Sets the lower bound map.
/// Sets the lower bound map.
/// \return <tt>(*this)</tt>
Circulation& lowerMap(const LowerMap& map) {
_lo = &map;
return *this;
}
/// Sets the upper bound (capacity) map.
/// Sets the upper bound (capacity) map.
/// \return <tt>(*this)</tt>
Circulation& upperMap(const UpperMap& map) {
_up = &map;
return *this;
}
/// Sets the supply map.
/// Sets the supply map.
/// \return <tt>(*this)</tt>
Circulation& supplyMap(const SupplyMap& map) {
_supply = &map;
return *this;
}
/// \brief Sets the flow map.
///
/// Sets the flow map.
/// If you don't use this function before calling \ref run() or
/// \ref init(), an instance will be allocated automatically.
/// The destructor deallocates this automatically allocated map,
/// of course.
/// \return <tt>(*this)</tt>
Circulation& flowMap(FlowMap& map) {
if (_local_flow) {
delete _flow;
_local_flow = false;
}
_flow = &map;
return *this;
}
/// \brief Sets the elevator used by algorithm.
///
/// Sets the elevator used by algorithm.
/// If you don't use this function before calling \ref run() or
/// \ref init(), an instance will be allocated automatically.
/// The destructor deallocates this automatically allocated elevator,
/// of course.
/// \return <tt>(*this)</tt>
Circulation& elevator(Elevator& elevator) {
if (_local_level) {
delete _level;
_local_level = false;
}
_level = &elevator;
return *this;
}
/// \brief Returns a const reference to the elevator.
///
/// Returns a const reference to the elevator.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
const Elevator& elevator() const {
return *_level;
}
/// \brief Sets the tolerance used by the algorithm.
///
/// Sets the tolerance object used by the algorithm.
/// \return <tt>(*this)</tt>
Circulation& tolerance(const Tolerance& tolerance) {
_tol = tolerance;
return *this;
}
/// \brief Returns a const reference to the tolerance.
///
/// Returns a const reference to the tolerance object used by
/// the algorithm.
const Tolerance& tolerance() const {
return _tol;
}
/// \name Execution Control
/// The simplest way to execute the algorithm is to call \ref run().\n
/// If you need better control on the initial solution or the execution,
/// you have to call one of the \ref init() functions first, then
/// the \ref start() function.
///@{
/// Initializes the internal data structures.
/// Initializes the internal data structures and sets all flow values
/// to the lower bound.
void init()
{
LEMON_DEBUG(checkBoundMaps(),
"Upper bounds must be greater or equal to the lower bounds");
createStructures();
for(NodeIt n(_g);n!=INVALID;++n) {
(*_excess)[n] = (*_supply)[n];
}
for (ArcIt e(_g);e!=INVALID;++e) {
_flow->set(e, (*_lo)[e]);
(*_excess)[_g.target(e)] += (*_flow)[e];
(*_excess)[_g.source(e)] -= (*_flow)[e];
}
// global relabeling tested, but in general case it provides
// worse performance for random digraphs
_level->initStart();
for(NodeIt n(_g);n!=INVALID;++n)
_level->initAddItem(n);
_level->initFinish();
for(NodeIt n(_g);n!=INVALID;++n)
if(_tol.positive((*_excess)[n]))
_level->activate(n);
}
/// Initializes the internal data structures using a greedy approach.
/// Initializes the internal data structures using a greedy approach
/// to construct the initial solution.
void greedyInit()
{
LEMON_DEBUG(checkBoundMaps(),
"Upper bounds must be greater or equal to the lower bounds");
createStructures();
for(NodeIt n(_g);n!=INVALID;++n) {
(*_excess)[n] = (*_supply)[n];
}
for (ArcIt e(_g);e!=INVALID;++e) {
if (!_tol.less(-(*_excess)[_g.target(e)], (*_up)[e])) {
_flow->set(e, (*_up)[e]);
(*_excess)[_g.target(e)] += (*_up)[e];
(*_excess)[_g.source(e)] -= (*_up)[e];
} else if (_tol.less(-(*_excess)[_g.target(e)], (*_lo)[e])) {
_flow->set(e, (*_lo)[e]);
(*_excess)[_g.target(e)] += (*_lo)[e];
(*_excess)[_g.source(e)] -= (*_lo)[e];
} else {
Value fc = -(*_excess)[_g.target(e)];
_flow->set(e, fc);
(*_excess)[_g.target(e)] = 0;
(*_excess)[_g.source(e)] -= fc;
}
}
_level->initStart();
for(NodeIt n(_g);n!=INVALID;++n)
_level->initAddItem(n);
_level->initFinish();
for(NodeIt n(_g);n!=INVALID;++n)
if(_tol.positive((*_excess)[n]))
_level->activate(n);
}
///Executes the algorithm
///This function executes the algorithm.
///
///\return \c true if a feasible circulation is found.
///
///\sa barrier()
///\sa barrierMap()
bool start()
{
Node act;
while((act=_level->highestActive())!=INVALID) {
int actlevel=(*_level)[act];
int mlevel=_node_num;
Value exc=(*_excess)[act];
for(OutArcIt e(_g,act);e!=INVALID; ++e) {
Node v = _g.target(e);
Value fc=(*_up)[e]-(*_flow)[e];
if(!_tol.positive(fc)) continue;
if((*_level)[v]<actlevel) {
if(!_tol.less(fc, exc)) {
_flow->set(e, (*_flow)[e] + exc);
(*_excess)[v] += exc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
(*_excess)[act] = 0;
_level->deactivate(act);
goto next_l;
}
else {
_flow->set(e, (*_up)[e]);
(*_excess)[v] += fc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
exc-=fc;
}
}
else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
}
for(InArcIt e(_g,act);e!=INVALID; ++e) {
Node v = _g.source(e);
Value fc=(*_flow)[e]-(*_lo)[e];
if(!_tol.positive(fc)) continue;
if((*_level)[v]<actlevel) {
if(!_tol.less(fc, exc)) {
_flow->set(e, (*_flow)[e] - exc);
(*_excess)[v] += exc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
(*_excess)[act] = 0;
_level->deactivate(act);
goto next_l;
}
else {
_flow->set(e, (*_lo)[e]);
(*_excess)[v] += fc;
if(!_level->active(v) && _tol.positive((*_excess)[v]))
_level->activate(v);
exc-=fc;
}
}
else if((*_level)[v]<mlevel) mlevel=(*_level)[v];
}
(*_excess)[act] = exc;
if(!_tol.positive(exc)) _level->deactivate(act);
else if(mlevel==_node_num) {
_level->liftHighestActiveToTop();
_el = _node_num;
return false;
}
else {
_level->liftHighestActive(mlevel+1);
if(_level->onLevel(actlevel)==0) {
_el = actlevel;
return false;
}
}
next_l:
;
}
return true;
}
/// Runs the algorithm.
/// This function runs the algorithm.
///
/// \return \c true if a feasible circulation is found.
///
/// \note Apart from the return value, c.run() is just a shortcut of
/// the following code.
/// \code
/// c.greedyInit();
/// c.start();
/// \endcode
bool run() {
greedyInit();
return start();
}
/// @}
/// \name Query Functions
/// The results of the circulation algorithm can be obtained using
/// these functions.\n
/// Either \ref run() or \ref start() should be called before
/// using them.
///@{
/// \brief Returns the flow value on the given arc.
///
/// Returns the flow value on the given arc.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
Value flow(const Arc& arc) const {
return (*_flow)[arc];
}
/// \brief Returns a const reference to the flow map.
///
/// Returns a const reference to the arc map storing the found flow.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
const FlowMap& flowMap() const {
return *_flow;
}
/**
\brief Returns \c true if the given node is in a barrier.
Barrier is a set \e B of nodes for which
\f[ \sum_{uv\in A: u\in B} upper(uv) -
\sum_{uv\in A: v\in B} lower(uv) < \sum_{v\in B} sup(v) \f]
holds. The existence of a set with this property prooves that a
feasible circualtion cannot exist.
This function returns \c true if the given node is in the found
barrier. If a feasible circulation is found, the function
gives back \c false for every node.
\pre Either \ref run() or \ref init() must be called before
using this function.
\sa barrierMap()
\sa checkBarrier()
*/
bool barrier(const Node& node) const
{
return (*_level)[node] >= _el;
}
/// \brief Gives back a barrier.
///
/// This function sets \c bar to the characteristic vector of the
/// found barrier. \c bar should be a \ref concepts::WriteMap "writable"
/// node map with \c bool (or convertible) value type.
///
/// If a feasible circulation is found, the function gives back an
/// empty set, so \c bar[v] will be \c false for all nodes \c v.
///
/// \note This function calls \ref barrier() for each node,
/// so it runs in O(n) time.
///
/// \pre Either \ref run() or \ref init() must be called before
/// using this function.
///
/// \sa barrier()
/// \sa checkBarrier()
template<class BarrierMap>
void barrierMap(BarrierMap &bar) const
{
for(NodeIt n(_g);n!=INVALID;++n)
bar.set(n, (*_level)[n] >= _el);
}
/// @}
/// \name Checker Functions
/// The feasibility of the results can be checked using
/// these functions.\n
/// Either \ref run() or \ref start() should be called before
/// using them.
///@{
///Check if the found flow is a feasible circulation
///Check if the found flow is a feasible circulation,
///
bool checkFlow() const {
for(ArcIt e(_g);e!=INVALID;++e)
if((*_flow)[e]<(*_lo)[e]||(*_flow)[e]>(*_up)[e]) return false;
for(NodeIt n(_g);n!=INVALID;++n)
{
Value dif=-(*_supply)[n];
for(InArcIt e(_g,n);e!=INVALID;++e) dif-=(*_flow)[e];
for(OutArcIt e(_g,n);e!=INVALID;++e) dif+=(*_flow)[e];
if(_tol.negative(dif)) return false;
}
return true;
}
///Check whether or not the last execution provides a barrier
///Check whether or not the last execution provides a barrier.
///\sa barrier()
///\sa barrierMap()
bool checkBarrier() const
{
Value delta=0;
Value inf_cap = std::numeric_limits<Value>::has_infinity ?
std::numeric_limits<Value>::infinity() :
std::numeric_limits<Value>::max();
for(NodeIt n(_g);n!=INVALID;++n)
if(barrier(n))
delta-=(*_supply)[n];
for(ArcIt e(_g);e!=INVALID;++e)
{
Node s=_g.source(e);
Node t=_g.target(e);
if(barrier(s)&&!barrier(t)) {
if (_tol.less(inf_cap - (*_up)[e], delta)) return false;
delta+=(*_up)[e];
}
else if(barrier(t)&&!barrier(s)) delta-=(*_lo)[e];
}
return _tol.negative(delta);
}
/// @}
};
}
#endif

View File

@ -0,0 +1,464 @@
/* -*- 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.
*
*/
#include <lemon/clp.h>
#include <coin/ClpSimplex.hpp>
namespace lemon {
ClpLp::ClpLp() {
_prob = new ClpSimplex();
_init_temporals();
messageLevel(MESSAGE_NOTHING);
}
ClpLp::ClpLp(const ClpLp& other) {
_prob = new ClpSimplex(*other._prob);
rows = other.rows;
cols = other.cols;
_init_temporals();
messageLevel(MESSAGE_NOTHING);
}
ClpLp::~ClpLp() {
delete _prob;
_clear_temporals();
}
void ClpLp::_init_temporals() {
_primal_ray = 0;
_dual_ray = 0;
}
void ClpLp::_clear_temporals() {
if (_primal_ray) {
delete[] _primal_ray;
_primal_ray = 0;
}
if (_dual_ray) {
delete[] _dual_ray;
_dual_ray = 0;
}
}
ClpLp* ClpLp::newSolver() const {
ClpLp* newlp = new ClpLp;
return newlp;
}
ClpLp* ClpLp::cloneSolver() const {
ClpLp* copylp = new ClpLp(*this);
return copylp;
}
const char* ClpLp::_solverName() const { return "ClpLp"; }
int ClpLp::_addCol() {
_prob->addColumn(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX, 0.0);
return _prob->numberColumns() - 1;
}
int ClpLp::_addRow() {
_prob->addRow(0, 0, 0, -COIN_DBL_MAX, COIN_DBL_MAX);
return _prob->numberRows() - 1;
}
int ClpLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
std::vector<int> indexes;
std::vector<Value> values;
for(ExprIterator it = b; it != e; ++it) {
indexes.push_back(it->first);
values.push_back(it->second);
}
_prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
return _prob->numberRows() - 1;
}
void ClpLp::_eraseCol(int c) {
_col_names_ref.erase(_prob->getColumnName(c));
_prob->deleteColumns(1, &c);
}
void ClpLp::_eraseRow(int r) {
_row_names_ref.erase(_prob->getRowName(r));
_prob->deleteRows(1, &r);
}
void ClpLp::_eraseColId(int i) {
cols.eraseIndex(i);
cols.shiftIndices(i);
}
void ClpLp::_eraseRowId(int i) {
rows.eraseIndex(i);
rows.shiftIndices(i);
}
void ClpLp::_getColName(int c, std::string& name) const {
name = _prob->getColumnName(c);
}
void ClpLp::_setColName(int c, const std::string& name) {
_prob->setColumnName(c, const_cast<std::string&>(name));
_col_names_ref[name] = c;
}
int ClpLp::_colByName(const std::string& name) const {
std::map<std::string, int>::const_iterator it = _col_names_ref.find(name);
return it != _col_names_ref.end() ? it->second : -1;
}
void ClpLp::_getRowName(int r, std::string& name) const {
name = _prob->getRowName(r);
}
void ClpLp::_setRowName(int r, const std::string& name) {
_prob->setRowName(r, const_cast<std::string&>(name));
_row_names_ref[name] = r;
}
int ClpLp::_rowByName(const std::string& name) const {
std::map<std::string, int>::const_iterator it = _row_names_ref.find(name);
return it != _row_names_ref.end() ? it->second : -1;
}
void ClpLp::_setRowCoeffs(int ix, ExprIterator b, ExprIterator e) {
std::map<int, Value> coeffs;
int n = _prob->clpMatrix()->getNumCols();
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (int i = 0; i < n; ++i) {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
const int* it = std::lower_bound(indices + begin, indices + end, ix);
if (it != indices + end && *it == ix && elements[it - indices] != 0.0) {
coeffs[i] = 0.0;
}
}
for (ExprIterator it = b; it != e; ++it) {
coeffs[it->first] = it->second;
}
for (std::map<int, Value>::iterator it = coeffs.begin();
it != coeffs.end(); ++it) {
_prob->modifyCoefficient(ix, it->first, it->second);
}
}
void ClpLp::_getRowCoeffs(int ix, InsertIterator b) const {
int n = _prob->clpMatrix()->getNumCols();
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (int i = 0; i < n; ++i) {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[i];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[i];
const int* it = std::lower_bound(indices + begin, indices + end, ix);
if (it != indices + end && *it == ix) {
*b = std::make_pair(i, elements[it - indices]);
}
}
}
void ClpLp::_setColCoeffs(int ix, ExprIterator b, ExprIterator e) {
std::map<int, Value> coeffs;
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (CoinBigIndex i = begin; i != end; ++i) {
if (elements[i] != 0.0) {
coeffs[indices[i]] = 0.0;
}
}
for (ExprIterator it = b; it != e; ++it) {
coeffs[it->first] = it->second;
}
for (std::map<int, Value>::iterator it = coeffs.begin();
it != coeffs.end(); ++it) {
_prob->modifyCoefficient(it->first, ix, it->second);
}
}
void ClpLp::_getColCoeffs(int ix, InsertIterator b) const {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
for (CoinBigIndex i = begin; i != end; ++i) {
*b = std::make_pair(indices[i], elements[i]);
++b;
}
}
void ClpLp::_setCoeff(int ix, int jx, Value value) {
_prob->modifyCoefficient(ix, jx, value);
}
ClpLp::Value ClpLp::_getCoeff(int ix, int jx) const {
CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
const int* indices = _prob->clpMatrix()->getIndices();
const double* elements = _prob->clpMatrix()->getElements();
const int* it = std::lower_bound(indices + begin, indices + end, jx);
if (it != indices + end && *it == jx) {
return elements[it - indices];
} else {
return 0.0;
}
}
void ClpLp::_setColLowerBound(int i, Value lo) {
_prob->setColumnLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
ClpLp::Value ClpLp::_getColLowerBound(int i) const {
double val = _prob->getColLower()[i];
return val == - COIN_DBL_MAX ? - INF : val;
}
void ClpLp::_setColUpperBound(int i, Value up) {
_prob->setColumnUpper(i, up == INF ? COIN_DBL_MAX : up);
}
ClpLp::Value ClpLp::_getColUpperBound(int i) const {
double val = _prob->getColUpper()[i];
return val == COIN_DBL_MAX ? INF : val;
}
void ClpLp::_setRowLowerBound(int i, Value lo) {
_prob->setRowLower(i, lo == - INF ? - COIN_DBL_MAX : lo);
}
ClpLp::Value ClpLp::_getRowLowerBound(int i) const {
double val = _prob->getRowLower()[i];
return val == - COIN_DBL_MAX ? - INF : val;
}
void ClpLp::_setRowUpperBound(int i, Value up) {
_prob->setRowUpper(i, up == INF ? COIN_DBL_MAX : up);
}
ClpLp::Value ClpLp::_getRowUpperBound(int i) const {
double val = _prob->getRowUpper()[i];
return val == COIN_DBL_MAX ? INF : val;
}
void ClpLp::_setObjCoeffs(ExprIterator b, ExprIterator e) {
int num = _prob->clpMatrix()->getNumCols();
for (int i = 0; i < num; ++i) {
_prob->setObjectiveCoefficient(i, 0.0);
}
for (ExprIterator it = b; it != e; ++it) {
_prob->setObjectiveCoefficient(it->first, it->second);
}
}
void ClpLp::_getObjCoeffs(InsertIterator b) const {
int num = _prob->clpMatrix()->getNumCols();
for (int i = 0; i < num; ++i) {
Value coef = _prob->getObjCoefficients()[i];
if (coef != 0.0) {
*b = std::make_pair(i, coef);
++b;
}
}
}
void ClpLp::_setObjCoeff(int i, Value obj_coef) {
_prob->setObjectiveCoefficient(i, obj_coef);
}
ClpLp::Value ClpLp::_getObjCoeff(int i) const {
return _prob->getObjCoefficients()[i];
}
ClpLp::SolveExitStatus ClpLp::_solve() {
return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::SolveExitStatus ClpLp::solvePrimal() {
return _prob->primal() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::SolveExitStatus ClpLp::solveDual() {
return _prob->dual() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::SolveExitStatus ClpLp::solveBarrier() {
return _prob->barrier() >= 0 ? SOLVED : UNSOLVED;
}
ClpLp::Value ClpLp::_getPrimal(int i) const {
return _prob->primalColumnSolution()[i];
}
ClpLp::Value ClpLp::_getPrimalValue() const {
return _prob->objectiveValue();
}
ClpLp::Value ClpLp::_getDual(int i) const {
return _prob->dualRowSolution()[i];
}
ClpLp::Value ClpLp::_getPrimalRay(int i) const {
if (!_primal_ray) {
_primal_ray = _prob->unboundedRay();
LEMON_ASSERT(_primal_ray != 0, "Primal ray is not provided");
}
return _primal_ray[i];
}
ClpLp::Value ClpLp::_getDualRay(int i) const {
if (!_dual_ray) {
_dual_ray = _prob->infeasibilityRay();
LEMON_ASSERT(_dual_ray != 0, "Dual ray is not provided");
}
return _dual_ray[i];
}
ClpLp::VarStatus ClpLp::_getColStatus(int i) const {
switch (_prob->getColumnStatus(i)) {
case ClpSimplex::basic:
return BASIC;
case ClpSimplex::isFree:
return FREE;
case ClpSimplex::atUpperBound:
return UPPER;
case ClpSimplex::atLowerBound:
return LOWER;
case ClpSimplex::isFixed:
return FIXED;
case ClpSimplex::superBasic:
return FREE;
default:
LEMON_ASSERT(false, "Wrong column status");
return VarStatus();
}
}
ClpLp::VarStatus ClpLp::_getRowStatus(int i) const {
switch (_prob->getColumnStatus(i)) {
case ClpSimplex::basic:
return BASIC;
case ClpSimplex::isFree:
return FREE;
case ClpSimplex::atUpperBound:
return UPPER;
case ClpSimplex::atLowerBound:
return LOWER;
case ClpSimplex::isFixed:
return FIXED;
case ClpSimplex::superBasic:
return FREE;
default:
LEMON_ASSERT(false, "Wrong row status");
return VarStatus();
}
}
ClpLp::ProblemType ClpLp::_getPrimalType() const {
if (_prob->isProvenOptimal()) {
return OPTIMAL;
} else if (_prob->isProvenPrimalInfeasible()) {
return INFEASIBLE;
} else if (_prob->isProvenDualInfeasible()) {
return UNBOUNDED;
} else {
return UNDEFINED;
}
}
ClpLp::ProblemType ClpLp::_getDualType() const {
if (_prob->isProvenOptimal()) {
return OPTIMAL;
} else if (_prob->isProvenDualInfeasible()) {
return INFEASIBLE;
} else if (_prob->isProvenPrimalInfeasible()) {
return INFEASIBLE;
} else {
return UNDEFINED;
}
}
void ClpLp::_setSense(ClpLp::Sense sense) {
switch (sense) {
case MIN:
_prob->setOptimizationDirection(1);
break;
case MAX:
_prob->setOptimizationDirection(-1);
break;
}
}
ClpLp::Sense ClpLp::_getSense() const {
double dir = _prob->optimizationDirection();
if (dir > 0.0) {
return MIN;
} else {
return MAX;
}
}
void ClpLp::_clear() {
delete _prob;
_prob = new ClpSimplex();
_col_names_ref.clear();
_clear_temporals();
}
void ClpLp::_messageLevel(MessageLevel level) {
switch (level) {
case MESSAGE_NOTHING:
_prob->setLogLevel(0);
break;
case MESSAGE_ERROR:
_prob->setLogLevel(1);
break;
case MESSAGE_WARNING:
_prob->setLogLevel(2);
break;
case MESSAGE_NORMAL:
_prob->setLogLevel(3);
break;
case MESSAGE_VERBOSE:
_prob->setLogLevel(4);
break;
}
}
} //END OF NAMESPACE LEMON

View File

@ -0,0 +1,164 @@
/* -*- 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_CLP_H
#define LEMON_CLP_H
///\file
///\brief Header of the LEMON-CLP lp solver interface.
#include <vector>
#include <string>
#include <lemon/lp_base.h>
class ClpSimplex;
namespace lemon {
/// \ingroup lp_group
///
/// \brief Interface for the CLP solver
///
/// This class implements an interface for the Clp LP solver. The
/// Clp library is an object oriented lp solver library developed at
/// the IBM. The CLP is part of the COIN-OR package and it can be
/// used with Common Public License.
class ClpLp : public LpSolver {
protected:
ClpSimplex* _prob;
std::map<std::string, int> _col_names_ref;
std::map<std::string, int> _row_names_ref;
public:
/// \e
ClpLp();
/// \e
ClpLp(const ClpLp&);
/// \e
~ClpLp();
/// \e
virtual ClpLp* newSolver() const;
/// \e
virtual ClpLp* cloneSolver() const;
protected:
mutable double* _primal_ray;
mutable double* _dual_ray;
void _init_temporals();
void _clear_temporals();
protected:
virtual const char* _solverName() const;
virtual int _addCol();
virtual int _addRow();
virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
virtual void _eraseCol(int i);
virtual void _eraseRow(int i);
virtual void _eraseColId(int i);
virtual void _eraseRowId(int i);
virtual void _getColName(int col, std::string& name) const;
virtual void _setColName(int col, const std::string& name);
virtual int _colByName(const std::string& name) const;
virtual void _getRowName(int row, std::string& name) const;
virtual void _setRowName(int row, const std::string& name);
virtual int _rowByName(const std::string& name) const;
virtual void _setRowCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getRowCoeffs(int i, InsertIterator b) const;
virtual void _setColCoeffs(int i, ExprIterator b, ExprIterator e);
virtual void _getColCoeffs(int i, InsertIterator b) const;
virtual void _setCoeff(int row, int col, Value value);
virtual Value _getCoeff(int row, int col) const;
virtual void _setColLowerBound(int i, Value value);
virtual Value _getColLowerBound(int i) const;
virtual void _setColUpperBound(int i, Value value);
virtual Value _getColUpperBound(int i) const;
virtual void _setRowLowerBound(int i, Value value);
virtual Value _getRowLowerBound(int i) const;
virtual void _setRowUpperBound(int i, Value value);
virtual Value _getRowUpperBound(int i) const;
virtual void _setObjCoeffs(ExprIterator, ExprIterator);
virtual void _getObjCoeffs(InsertIterator) const;
virtual void _setObjCoeff(int i, Value obj_coef);
virtual Value _getObjCoeff(int i) const;
virtual void _setSense(Sense sense);
virtual Sense _getSense() const;
virtual SolveExitStatus _solve();
virtual Value _getPrimal(int i) const;
virtual Value _getDual(int i) const;
virtual Value _getPrimalValue() const;
virtual Value _getPrimalRay(int i) const;
virtual Value _getDualRay(int i) const;
virtual VarStatus _getColStatus(int i) const;
virtual VarStatus _getRowStatus(int i) const;
virtual ProblemType _getPrimalType() const;
virtual ProblemType _getDualType() const;
virtual void _clear();
virtual void _messageLevel(MessageLevel);
public:
///Solves LP with primal simplex method.
SolveExitStatus solvePrimal();
///Solves LP with dual simplex method.
SolveExitStatus solveDual();
///Solves LP with barrier method.
SolveExitStatus solveBarrier();
///Returns the constraint identifier understood by CLP.
int clpRow(Row r) const { return rows(id(r)); }
///Returns the variable identifier understood by CLP.
int clpCol(Col c) const { return cols(id(c)); }
};
} //END OF NAMESPACE LEMON
#endif //LEMON_CLP_H

View File

@ -0,0 +1,44 @@
/* -*- 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.
*
*/
///\file
///\brief Color constants
#include<lemon/color.h>
namespace lemon {
const Color WHITE(1,1,1);
const Color BLACK(0,0,0);
const Color RED(1,0,0);
const Color GREEN(0,1,0);
const Color BLUE(0,0,1);
const Color YELLOW(1,1,0);
const Color MAGENTA(1,0,1);
const Color CYAN(0,1,1);
const Color GREY(0,0,0);
const Color DARK_RED(.5,0,0);
const Color DARK_GREEN(0,.5,0);
const Color DARK_BLUE(0,0,.5);
const Color DARK_YELLOW(.5,.5,0);
const Color DARK_MAGENTA(.5,0,.5);
const Color DARK_CYAN(0,.5,.5);
} //namespace lemon

View File

@ -0,0 +1,204 @@
/* -*- 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.
*
*/
#ifndef LEMON_COLOR_H
#define LEMON_COLOR_H
#include<vector>
#include<lemon/math.h>
#include<lemon/maps.h>
///\ingroup misc
///\file
///\brief Tools to manage RGB colors.
namespace lemon {
/// \addtogroup misc
/// @{
///Data structure representing RGB colors.
///Data structure representing RGB colors.
class Color
{
double _r,_g,_b;
public:
///Default constructor
Color() {}
///Constructor
Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
///Set the red component
double & red() {return _r;}
///Return the red component
const double & red() const {return _r;}
///Set the green component
double & green() {return _g;}
///Return the green component
const double & green() const {return _g;}
///Set the blue component
double & blue() {return _b;}
///Return the blue component
const double & blue() const {return _b;}
///Set the color components
void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
};
/// White color constant
extern const Color WHITE;
/// Black color constant
extern const Color BLACK;
/// Red color constant
extern const Color RED;
/// Green color constant
extern const Color GREEN;
/// Blue color constant
extern const Color BLUE;
/// Yellow color constant
extern const Color YELLOW;
/// Magenta color constant
extern const Color MAGENTA;
/// Cyan color constant
extern const Color CYAN;
/// Grey color constant
extern const Color GREY;
/// Dark red color constant
extern const Color DARK_RED;
/// Dark green color constant
extern const Color DARK_GREEN;
/// Drak blue color constant
extern const Color DARK_BLUE;
/// Dark yellow color constant
extern const Color DARK_YELLOW;
/// Dark magenta color constant
extern const Color DARK_MAGENTA;
/// Dark cyan color constant
extern const Color DARK_CYAN;
///Map <tt>int</tt>s to different <tt>Color</tt>s
///This map assigns one of the predefined \ref Color "Color"s to
///each <tt>int</tt>. It is possible to change the colors as well as
///their number. The integer range is cyclically mapped to the
///provided set of colors.
///
///This is a true \ref concepts::ReferenceMap "reference map", so
///you can also change the actual colors.
class Palette : public MapBase<int,Color>
{
std::vector<Color> colors;
public:
///Constructor
///Constructor.
///\param have_white Indicates whether white is among the
///provided initial colors (\c true) or not (\c false). If it is true,
///white will be assigned to \c 0.
///\param num The number of the allocated colors. If it is \c -1,
///the default color configuration is set up (26 color plus optionaly the
///white). If \c num is less then 26/27 then the default color
///list is cut. Otherwise the color list is filled repeatedly with
///the default color list. (The colors can be changed later on.)
Palette(bool have_white=false,int num=-1)
{
if (num==0) return;
do {
if(have_white) colors.push_back(Color(1,1,1));
colors.push_back(Color(0,0,0));
colors.push_back(Color(1,0,0));
colors.push_back(Color(0,1,0));
colors.push_back(Color(0,0,1));
colors.push_back(Color(1,1,0));
colors.push_back(Color(1,0,1));
colors.push_back(Color(0,1,1));
colors.push_back(Color(.5,0,0));
colors.push_back(Color(0,.5,0));
colors.push_back(Color(0,0,.5));
colors.push_back(Color(.5,.5,0));
colors.push_back(Color(.5,0,.5));
colors.push_back(Color(0,.5,.5));
colors.push_back(Color(.5,.5,.5));
colors.push_back(Color(1,.5,.5));
colors.push_back(Color(.5,1,.5));
colors.push_back(Color(.5,.5,1));
colors.push_back(Color(1,1,.5));
colors.push_back(Color(1,.5,1));
colors.push_back(Color(.5,1,1));
colors.push_back(Color(1,.5,0));
colors.push_back(Color(.5,1,0));
colors.push_back(Color(1,0,.5));
colors.push_back(Color(0,1,.5));
colors.push_back(Color(0,.5,1));
colors.push_back(Color(.5,0,1));
} while(int(colors.size())<num);
if(num>=0) colors.resize(num);
}
///\e
Color &operator[](int i)
{
return colors[i%colors.size()];
}
///\e
const Color &operator[](int i) const
{
return colors[i%colors.size()];
}
///\e
void set(int i,const Color &c)
{
colors[i%colors.size()]=c;
}
///Adds a new color to the end of the color list.
void add(const Color &c)
{
colors.push_back(c);
}
///Sets the number of the existing colors.
void resize(int s) { colors.resize(s);}
///Returns the number of the existing colors.
int size() const { return int(colors.size());}
};
///Returns a visibly distinct \ref Color
///Returns a \ref Color which is as different from the given parameter
///as it is possible.
inline Color distantColor(const Color &c)
{
return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0);
}
///Returns black for light colors and white for the dark ones.
///Returns black for light colors and white for the dark ones.
inline Color distantBW(const Color &c){
return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK;
}
/// @}
} //END OF NAMESPACE LEMON
#endif // LEMON_COLOR_H

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