- added CoMISo library

This commit is contained in:
Guido Ranzuglia granzuglia 2013-02-08 15:50:03 +00:00
parent c05bd3fd1f
commit 7e09115bca
148 changed files with 27588 additions and 0 deletions

38
src/external/CoMISo/CHANGELOG vendored Normal file
View File

@ -0,0 +1,38 @@
#============================================================================================
CoMISo 1.0-rc1:
- Initial release
CoMISo 1.1:
- Only 2 external dependencies: header libraries GMM++ and Eigen3
- Efficient re-solve with updated (system and/or constraints) right hand sides
Features:
- /NSolver -- simple non-linear solver c++ interfaces:
* Gurobi [1],
* IPOPT [2],
* TAO/PETSc [3],
* CPLEX [4],
* an the inhouse Newton Solver and more!
- /EigenSolver -- interface for large-scale eigenvalue problems ARPACK [5]
- /Solver -- several interfaces for common linear system solvers:
* sparse Cholesky (Cholmod, LDLT)
* SparseQR [6]
* TAUCS [7]
* UMFPACK [8]
and of course the Constrained and Constrained Mixed Integer Solvers (CoMISo)
References:
[1] www.gurobi.com
[2] https://projects.coin-or.org/Ipopt
[3] http://www.mcs.anl.gov/research/projects/tao/
[4] http://www-01.ibm.com/software/integration/optimization/cplex-optimizer/
[5] http://www.caam.rice.edu/software/ARPACK/
[6] http://www.cise.ufl.edu/research/sparse/SPQR/
[7] http://www.tau.ac.il/~stoledo/taucs/
[8] http://www.cise.ufl.edu/research/sparse/umfpack/

371
src/external/CoMISo/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,371 @@
cmake_minimum_required (VERSION 2.6)
project(CoMISo)
# add our macro directory to cmake search path
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
include (ACGCommon)
acg_qt4 ()
# change to 0 if QT should not be used
set( WANT_COMISO_QT 1 )
if( QT4_FOUND)
#message( WARNING " QT4 FOUND" )
if( WANT_COMISO_QT )
add_definitions (-DQT4_FOUND)
# message( WARNING " USING QT4" )
endif ()
set (COMISO_QT4_CONFIG_FILE_SETTINGS "#define COMISO_QT4_AVAILABLE 1" )
else()
set (COMISO_QT4_CONFIG_FILE_SETTINGS "#define COMISO_QT4_AVAILABLE 0" )
endif ()
acg_get_version ()
include (ACGOutput)
set(COMISO_INCLUDE_DIRECTORIES "")
set(COMISO_LINK_DIRECTORIES "")
set(COMISO_LINK_LIBRARIES "")
FIND_PACKAGE( Boost 1.42.0 COMPONENTS system filesystem regex )
if(Boost_FOUND)
set (COMISO_BOOST_CONFIG_FILE_SETTINGS "#define COMISO_BOOST_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS} )
# list( APPEND COMISO_LINK_DIRECTORIES ${Boost_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${Boost_LIBRARIES} )
else()
set (COMISO_BOOST_CONFIG_FILE_SETTINGS "#define COMISO_BOOST_AVAILABLE 0" )
message (STATUS "Boost not found!")
endif ()
find_package (GMM)
if (GMM_FOUND)
set (COMISO_GMM_CONFIG_FILE_SETTINGS "#define COMISO_GMM_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${GMM_INCLUDE_DIR} )
else()
set (COMISO_GMM_CONFIG_FILE_SETTINGS "#define COMISO_GMM_AVAILABLE 0" )
message (FATAL_ERROR "GMM not found!")
endif ()
# We require cgal with its blas on windows
find_package(CGAL)
if (CGAL_FOUND)
set (COMISO_CGAL_CONFIG_FILE_SETTINGS "#define COMISO_CGAL_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${CGAL_INCLUDE_DIR} )
list( APPEND COMISO_LINK_DIRECTORIES ${CGAL_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${CGAL_LIBRARIES} )
else()
set (COMISO_CGAL_CONFIG_FILE_SETTINGS "#define COMISO_CGAL_AVAILABLE 0" )
message (STATUS "CGAL not found!")
endif()
find_package (BLAS)
if (BLAS_FOUND )
set (COMISO_BLAS_CONFIG_FILE_SETTINGS "#define COMISO_BLAS_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${BLAS_INCLUDE_DIRS} )
list( APPEND COMISO_LINK_DIRECTORIES ${BLAS_LIBRARY_DIRS} )
list( APPEND COMISO_LINK_LIBRARIES ${BLAS_LIBRARIES} )
else()
set (COMISO_BLAS_CONFIG_FILE_SETTINGS "#define COMISO_BLAS_AVAILABLE 0" )
message (STATUS "BLAS not found!")
endif ()
find_package (ADOLC)
if (ADOLC_FOUND)
set (COMISO_ADOLC_CONFIG_FILE_SETTINGS "#define COMISO_ADOLC_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${ADOLC_INCLUDE_DIR} )
list( APPEND COMISO_LINK_DIRECTORIES ${ADOLC_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${ADOLC_LIBRARIES} )
else ()
set (COMISO_ADOLC_CONFIG_FILE_SETTINGS "#define COMISO_ADOLC_AVAILABLE 0" )
message (STATUS "ADOLC not found!")
endif ()
find_package (SUITESPARSE)
if (SUITESPARSE_FOUND )
set (COMISO_SUITESPARSE_CONFIG_FILE_SETTINGS "#define COMISO_SUITESPARSE_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${SUITESPARSE_INCLUDE_DIRS} )
list( APPEND COMISO_LINK_DIRECTORIES ${SUITESPARSE_LIBRARY_DIRS} )
list( APPEND COMISO_LINK_LIBRARIES ${SUITESPARSE_LIBRARIES} )
else ()
message (STATUS "SUITESPARSE not found!")
set (COMISO_SUITESPARSE_CONFIG_FILE_SETTINGS "#define COMISO_SUITESPARSE_AVAILABLE 0" )
endif ()
# special handling, since spqr is incorrect in several distributions
if(SUITESPARSE_SPQR_VALID)
set (COMISO_SUITESPARSE_SPQR_CONFIG_FILE_SETTINGS "#define COMISO_SUITESPARSE_SPQR_AVAILABLE 1" )
else()
message (STATUS "SUITESPARSE SPQR seems to be invalid!")
set (COMISO_SUITESPARSE_SPQR_CONFIG_FILE_SETTINGS "#define COMISO_SUITESPARSE_SPQR_AVAILABLE 0" )
endif()
find_package (MPI)
if (MPI_FOUND )
set (COMISO_MPI_CONFIG_FILE_SETTINGS "#define COMISO_MPI_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${MPI_INCLUDE_PATH} )
list( APPEND COMISO_LINK_LIBRARIES ${MPI_CXX_LIBRARIES} )
else ()
message (STATUS "MPI not found!")
set (COMISO_MPI_CONFIG_FILE_SETTINGS "#define COMISO_MPI_AVAILABLE 0" )
endif ()
find_package (PETSC)
if (PETSC_FOUND AND MPI_FOUND)
set (COMISO_PETSC_CONFIG_FILE_SETTINGS "#define COMISO_PETSC_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${PETSC_INCLUDE_DIRS} )
list( APPEND COMISO_LINK_DIRECTORIES ${PETSC_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${PETSC_LIBRARY} )
else ()
message (STATUS "PETSC or dependency not found!")
set (COMISO_PETSC_CONFIG_FILE_SETTINGS "#define COMISO_PETSC_AVAILABLE 0" )
endif ()
find_package (TAO)
if (TAO_FOUND AND PETSC_FOUND AND MPI_FOUND)
set (COMISO_TAO_CONFIG_FILE_SETTINGS "#define COMISO_TAO_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${TAO_INCLUDE_DIRS} )
list( APPEND COMISO_LINK_DIRECTORIES ${TAO_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${TAO_LIBRARY} )
else ()
message (STATUS "TAO or dependency not found!")
set (COMISO_TAO_CONFIG_FILE_SETTINGS "#define COMISO_TAO_AVAILABLE 0" )
endif ()
find_package (METIS)
if (METIS_FOUND )
set (COMISO_METIS_CONFIG_FILE_SETTINGS "#define COMISO_METIS_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${METIS_INCLUDE_DIRS} )
list( APPEND COMISO_LINK_DIRECTORIES ${METIS_LIBRARY_DIRS} )
list( APPEND COMISO_LINK_LIBRARIES ${METIS_LIBRARIES} )
else()
set (COMISO_METIS_CONFIG_FILE_SETTINGS "#define COMISO_METIS_AVAILABLE 0" )
message (STATUS "METIS not found!")
endif ()
find_package (MUMPS)
if (MUMPS_FOUND )
set (COMISO_MUMPS_CONFIG_FILE_SETTINGS "#define COMISO_MUMPS_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${MUMPS_INCLUDE_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${MUMPS_LIBRARY} )
else ()
message (STATUS "MUMPS not found!")
set (COMISO_MUMPS_CONFIG_FILE_SETTINGS "#define COMISO_MUMPS_AVAILABLE 0" )
endif ()
find_package (IPOPT)
if (IPOPT_FOUND)
set (COMISO_IPOPT_CONFIG_FILE_SETTINGS "#define COMISO_IPOPT_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${IPOPT_INCLUDE_DIR} )
list( APPEND COMISO_LINK_DIRECTORIES ${IPOPT_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${IPOPT_LIBRARY} )
if ( IPOPT_HSL_LIBRARY_DIR )
set (COMISO_HSL_CONFIG_FILE_SETTINGS "#define COMISO_HSL_AVAILABLE 1" )
else ()
set (COMISO_HSL_CONFIG_FILE_SETTINGS "#define COMISO_HSL_AVAILABLE 0" )
endif()
else ()
message (STATUS "IPOPT or dependency not found!")
set (COMISO_IPOPT_CONFIG_FILE_SETTINGS "#define COMISO_IPOPT_AVAILABLE 0" )
set (COMISO_HSL_CONFIG_FILE_SETTINGS "#define COMISO_HSL_AVAILABLE 0" )
endif ()
find_package (EIGEN3)
if (EIGEN3_FOUND )
set (COMISO_EIGEN3_CONFIG_FILE_SETTINGS "#define COMISO_EIGEN3_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${EIGEN3_INCLUDE_DIR} )
else ()
message (STATUS "EIGEN3 not found!")
set (COMISO_EIGEN3_CONFIG_FILE_SETTINGS "#define COMISO_EIGEN3_AVAILABLE 0" )
endif ()
find_package (Taucs)
if (TAUCS_FOUND )
set (COMISO_TAUCS_CONFIG_FILE_SETTINGS "#define COMISO_TAUCS_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${TAUCS_INCLUDE_DIR} )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${LAPACK_INCLUDE_DIR} )
list( APPEND COMISO_LINK_DIRECTORIES ${LAPACK_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${TAUCS_LIBRARY} )
list( APPEND COMISO_LINK_LIBRARIES ${LAPACK_LIBRARIES} )
else ()
message (STATUS "TAUCS not found!")
set (COMISO_TAUCS_CONFIG_FILE_SETTINGS "#define COMISO_TAUCS_AVAILABLE 0" )
endif ()
find_package (GUROBI)
if (GUROBI_FOUND )
set (COMISO_GUROBI_CONFIG_FILE_SETTINGS "#define COMISO_GUROBI_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${GUROBI_INCLUDE_DIRS} )
# list( APPEND COMISO_LINK_DIRECTORIES ${GUROBI_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${GUROBI_LIBRARIES} )
else ()
message (STATUS "GUROBI not found!")
set (COMISO_GUROBI_CONFIG_FILE_SETTINGS "#define COMISO_GUROBI_AVAILABLE 0" )
endif ()
find_package (ARPACK)
if (ARPACK_FOUND )
set (COMISO_ARPACK_CONFIG_FILE_SETTINGS "#define COMISO_ARPACK_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${ARPACK_INCLUDE_DIR} )
# list( APPEND COMISO_LINK_DIRECTORIES ${ARPACK_LIBRARY_DIR} )
list( APPEND COMISO_LINK_LIBRARIES ${ARPACK_LIBRARY} )
else ()
message (STATUS "ARPACK not found!")
set (COMISO_ARPACK_CONFIG_FILE_SETTINGS "#define COMISO_ARPACK_AVAILABLE 0" )
endif ()
find_package (CPLEX)
if (CPLEX_FOUND )
set (COMISO_CPLEX_CONFIG_FILE_SETTINGS "#define COMISO_CPLEX_AVAILABLE 1" )
list( APPEND COMISO_INCLUDE_DIRECTORIES ${CPLEX_INCLUDE_DIRS} )
list( APPEND COMISO_LINK_LIBRARIES ${CPLEX_LIBRARIES} )
#enable c++ support
add_definitions(-DIL_STD)
else ()
message (STATUS "CPLEX not found!")
set (COMISO_CPLEX_CONFIG_FILE_SETTINGS "#define COMISO_CPLEX_AVAILABLE 0" )
endif ()
include_directories (
..
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_BINARY_DIR}
${COMISO_INCLUDE_DIRECTORIES}
)
# generate dllexport macros on windows
if (WIN32)
add_definitions(-DCOMISODLL)
add_definitions(-D_SCL_SECURE_NO_DEPRECATE)
endif ()
link_directories (
${COMISO_LINK_DIRECTORIES}
)
# source code directories
set (directories
.
Solver
NSolver
EigenSolver
Config
Utils
QtWidgets
)
if (WIN32)
add_definitions(
-D_USE_MATH_DEFINES -DNOMINMAX
)
endif ()
# collect all header,source and ui files
acg_append_files (headers "*.hh" ${directories})
acg_append_files (sources "*.cc" ${directories})
acg_append_files (ui "*.ui" ${directories})
macro (of_list_filter _list)
if (WIN32)
foreach (_element ${${_list}})
if (_element MATCHES "gnuplot_i\\.(cc|hh)$")
list (REMOVE_ITEM ${_list} ${_element})
endif ()
endforeach ()
endif ()
endmacro ()
of_list_filter ( headers )
of_list_filter ( sources )
# remove template cc files from source file list
acg_drop_templates (sources)
if( QT4_FOUND)
# genereate uic and moc targets
acg_qt4_autouic (uic_targets ${ui})
acg_qt4_automoc (moc_targets ${headers})
endif()
acg_add_library (CoMISo SHARED ${uic_targets} ${sources} ${headers} ${moc_targets})
if (NOT APPLE)
target_link_libraries (CoMISo
${QT_LIBRARIES}
${COMISO_LINK_LIBRARIES}
)
else(NOT APPLE)
target_link_libraries (CoMISo
${QT_LIBRARIES}
${COMISO_LINK_LIBRARIES}
)
endif(NOT APPLE)
# display results
acg_print_configure_header (COMISO "CoMISo")
# write config file
configure_file ("${CMAKE_CURRENT_SOURCE_DIR}/Config/config.hh.in"
"${CMAKE_CURRENT_SOURCE_DIR}/Config/config.hh" @ONLY IMMEDIATE)
#######################################################################
# Configure the examples last to be sure, that all configure files
# of the library are already there
#######################################################################
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/factored_solver/CMakeLists.txt" )
add_subdirectory (Examples/factored_solver)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/quadratic_solver/CMakeLists.txt" )
add_subdirectory (Examples/quadratic_solver)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/test2/CMakeLists.txt" )
add_subdirectory (Examples/test2)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_quadratic_example/CMakeLists.txt" )
add_subdirectory (Examples/small_quadratic_example)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_factored_example/CMakeLists.txt" )
add_subdirectory (Examples/small_factored_example)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/super_sparse_matrix/CMakeLists.txt" )
add_subdirectory (Examples/super_sparse_matrix)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/eigen_solver/CMakeLists.txt" )
add_subdirectory (Examples/eigen_solver)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_nsolver/CMakeLists.txt" )
add_subdirectory (Examples/small_nsolver)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_eigenproblem/CMakeLists.txt" )
add_subdirectory (Examples/small_eigenproblem)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_miqp/CMakeLists.txt" )
add_subdirectory (Examples/small_miqp)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_nleast_squares/CMakeLists.txt" )
add_subdirectory (Examples/small_nleast_squares)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_sparseqr/CMakeLists.txt" )
add_subdirectory (Examples/small_sparseqr)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_quadratic_resolve_example/CMakeLists.txt" )
add_subdirectory (Examples/small_quadratic_resolve_example)
endif()
if( EXISTS "${CMAKE_SOURCE_DIR}/Examples/small_cplex_soc/CMakeLists.txt" )
add_subdirectory (Examples/small_cplex_soc)
endif()

675
src/external/CoMISo/COPYING vendored Normal file
View File

@ -0,0 +1,675 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

2
src/external/CoMISo/CoMISo.cmake vendored Normal file
View File

@ -0,0 +1,2 @@
# add our macro directory to cmake search path
set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)

View File

@ -0,0 +1,48 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#ifndef COMISODLLEXPORT
#ifdef WIN32
#ifdef COMISODLL
#ifdef USECOMISO
#define COMISODLLEXPORT __declspec(dllimport)
#define COMISODLLEXPORTONLY
#else
#define COMISODLLEXPORT __declspec(dllexport)
#define COMISODLLEXPORTONLY __declspec(dllexport)
#endif
#else
#define COMISODLLEXPORT
#define COMISODLLEXPORTONLY
#endif
#else
#define COMISODLLEXPORT
#define COMISODLLEXPORTONLY
#endif
#endif
#undef min
#undef max

24
src/external/CoMISo/Config/config.hh.in vendored Normal file
View File

@ -0,0 +1,24 @@
// Build time dependencies for CoMiso
@COMISO_QT4_CONFIG_FILE_SETTINGS@
@COMISO_BOOST_CONFIG_FILE_SETTINGS@
@COMISO_BLAS_CONFIG_FILE_SETTINGS@
@COMISO_GMM_CONFIG_FILE_SETTINGS@
@COMISO_ADOLC_CONFIG_FILE_SETTINGS@
@COMISO_SUITESPARSE_CONFIG_FILE_SETTINGS@
@COMISO_SUITESPARSE_SPQR_CONFIG_FILE_SETTINGS@
@COMISO_MPI_CONFIG_FILE_SETTINGS@
@COMISO_HSL_CONFIG_FILE_SETTINGS@
@COMISO_PETSC_CONFIG_FILE_SETTINGS@
@COMISO_TAO_CONFIG_FILE_SETTINGS@
@COMISO_IPOPT_CONFIG_FILE_SETTINGS@
@COMISO_MUMPS_CONFIG_FILE_SETTINGS@
@COMISO_METIS_CONFIG_FILE_SETTINGS@
@COMISO_CGAL_CONFIG_FILE_SETTINGS@
@COMISO_TAUCS_CONFIG_FILE_SETTINGS@
@COMISO_GUROBI_CONFIG_FILE_SETTINGS@
@COMISO_ARPACK_CONFIG_FILE_SETTINGS@
@COMISO_CPLEX_CONFIG_FILE_SETTINGS@
@COMISO_EIGEN3_CONFIG_FILE_SETTINGS@

View File

@ -0,0 +1,131 @@
//=============================================================================
//
// CLASS ArpackSolver - IMPLEMENTATION
//
//=============================================================================
#define COMISO_ARPACKSOLVER_C
//== INCLUDES =================================================================
#include "ArpackSolver.hh"
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#if (COMISO_ARPACK_AVAILABLE && COMISO_SUITESPARSE_AVAILABLE && COMISO_EIGEN3_AVAILABLE)
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
template<class MatrixT,class MatrixT2>
void
ArpackSolver::
solve(const MatrixT& _A,
std::vector<double>& _eigenvalues,
MatrixT2& _eigenvectors,
const int _n_eigvalues,
const char* _which_eigs )
{
Matrix A(_A);
// ARSymStdEig<double, Matrix> eig_prob(A.matrix().cols(), _n_eigvalues, &A, &Matrix::mult_Mv, (char*)_which_eigs,
// 0, 0.0, 2000);
ARSymStdEig<double, Matrix> eig_prob(A.matrix().cols(), _n_eigvalues, &A, &Matrix::mult_Mv, (char*)_which_eigs,
0, 0.0, 100000);
int n_converged = eig_prob.FindEigenvectors();
// store result
_eigenvalues.resize(n_converged);
_eigenvectors.resize(A.matrix().rows(),n_converged);
for( int i=0; i<n_converged; ++i)
{
_eigenvalues[i] = eig_prob.Eigenvalue(i);
for(int j = 0; j<A.matrix().rows(); ++j)
_eigenvectors.coeffRef(j,i) = eig_prob.RawEigenvector(i)[j];
}
}
//-----------------------------------------------------------------------------
template<class MatrixT,class MatrixT2>
void
ArpackSolver::
solve_inverse(const MatrixT& _A,
std::vector<double>& _eigenvalues,
MatrixT2& _eigenvectors,
const int _n_eigvalues,
const char* _which_eigs)
{
Matrix A(_A,true);
ARSymStdEig<double, Matrix> eig_prob(A.matrix().cols(), _n_eigvalues, &A, &Matrix::mult_M_inv_v, (char*)_which_eigs,
0, 0.0, 2000);
// ARSymStdEig(int np, int nevp, ARFOP* objOPp,
// void (ARFOP::* MultOPxp)(ARFLOAT[], ARFLOAT[]),
// char* whichp = "LM", int ncvp = 0, ARFLOAT tolp = 0.0,
// int maxitp = 0, ARFLOAT* residp = NULL, bool ishiftp = true);
int n_converged = eig_prob.FindEigenvectors();
// store result
_eigenvalues.resize(n_converged);
_eigenvectors.resize(A.matrix().rows(),n_converged);
for( int i=0; i<n_converged; ++i)
{
_eigenvalues[i] = eig_prob.Eigenvalue(i);
for(int j = 0; j<A.matrix().rows(); ++j)
_eigenvectors.coeffRef(j,i) = eig_prob.RawEigenvector(i)[j];
}
}
//-----------------------------------------------------------------------------
template<class MatrixT,class MatrixT2>
void
ArpackSolver::
check_result(const MatrixT& _A, std::vector<double>& _eigenvalues, MatrixT2& _eigenvectors)
{
int n=_eigenvectors.rows();
if(n<20)
std::cerr << _A << std::endl;
for(unsigned int i=0; i<_eigenvalues.size(); ++i)
{
std::cerr << "eigenvalue " << i << ": " << _eigenvalues[i] << ", ";
if(n < 20)
{
std::cerr << "eigenvector: ";
for(int j=0; j<n; ++j)
{
std::cerr << _eigenvectors.coeffRef(j,i) << ", ";
}
}
// compute residuum
Eigen::Matrix<double, Eigen::Dynamic, 1> v = _eigenvectors.block(0,i,n,1);
std::cerr << "residuum norm: " << (_A*v - _eigenvalues[i]*v).norm() << std::endl;
}
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,98 @@
//=============================================================================
//
// CLASS ArpackSolver
//
//=============================================================================
#ifndef COMISO_ARPACKSOLVER_HH
#define COMISO_ARPACKSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if (COMISO_ARPACK_AVAILABLE && COMISO_SUITESPARSE_AVAILABLE && COMISO_EIGEN3_AVAILABLE)
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <Eigen/Eigen>
#include "EigenArpackMatrixT.hh"
#include <arpack++/arssym.h>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class ArpackSolver ArpackSolver.hh <COMISO/.../ArpackSolver.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT ArpackSolver
{
public:
// sparse matrix type
typedef EigenArpackMatrixT<double,Eigen::SparseMatrix<double,Eigen::ColMajor> > Matrix;
/// Constructor
ArpackSolver() {}
/// Destructor
~ArpackSolver() {}
// solve eigenproblem
// number of desired eigenvalues -> _n_eigenvalues
// which eigenvalues -> one of {LA (largest algebraic), SA (smalles algebraic), LM (largest magnitude), SM(smallest magnitued), BE(both ends)}
template<class MatrixT,class MatrixT2>
void solve(const MatrixT& _A,
std::vector<double>& _eigenvalues,
MatrixT2& _eigenvectors,
const int _n_eigvalues = 1,
const char* _which_eigs = "SM");
// solve eigenproblem
// number of desired eigenvalues -> _n_eigenvalues
// which eigenvalues -> one of {LA (largest algebraic), SA (smalles algebraic), LM (largest magnitude), SM(smallest magnitued), BE(both ends)}
template<class MatrixT,class MatrixT2>
void solve_inverse(const MatrixT& _A,
std::vector<double>& _eigenvalues,
MatrixT2& _eigenvectors,
const int _n_eigvalues = 1,
const char* _which_eigs = "LM");
// check resulting eigenvalues/eigenvectors
template<class MatrixT,class MatrixT2>
void check_result(const MatrixT& _A, std::vector<double>& _eigenvalues, MatrixT2& _eigenvectors);
private:
};
//=============================================================================
} // namespace ACG
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_ARPACKSOLVER_C)
#define COMISO_ARPACKSOLVER_TEMPLATES
#include "ArpackSolver.cc"
#endif
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================
#endif // ACG_ARPACKSOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,35 @@
//=============================================================================
//
// CLASS EigenArpackMatrixT - IMPLEMENTATION
//
//=============================================================================
#define COMISO_EIGENARPACKMATRIXT_C
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_SUITESPARSE_AVAILABLE
//=============================================================================
//== INCLUDES =================================================================
#include "EigenArpackMatrixT.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace ACG
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,126 @@
//=============================================================================
//
// CLASS EigenArpackMatrixT
//
//=============================================================================
#ifndef COMISO_EIGENARPACKMATRIXT_HH
#define COMISO_EIGENARPACKMATRIXT_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if (COMISO_SUITESPARSE_AVAILABLE && COMISO_EIGEN3_AVAILABLE)
//=============================================================================
//== INCLUDES =================================================================
#include <iostream>
#include <Eigen/Eigen>
#if EIGEN_VERSION_AT_LEAST(3,1,0)
#include <Eigen/CholmodSupport>
#else
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <unsupported/Eigen/CholmodSupport>
#endif
#include <Eigen/Sparse>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class EigenArpackMatrixT EigenArpackMatrixT.hh <COMISO/.../EigenArpackMatrixT.hh>
Brief Description.
A more elaborate description follows.
*/
template <class RealT,class MatrixT>
class EigenArpackMatrixT
{
public:
typedef MatrixT Matrix;
typedef RealT Real;
/// Constructor
template<class MatrixT2>
EigenArpackMatrixT(const MatrixT2& _m, bool _use_inverse = false)
{
mat_ = _m;
if(_use_inverse)
{
sllt_.compute(mat_);
#if EIGEN_VERSION_AT_LEAST(3,1,0)
if ( !sllt_.info() != Eigen::Success )
#else
if ( !sllt_.succeeded() )
#endif
std::cout << "[ERROR] EigenArpackMatrix(): Could not compute llt factorization." << std::endl;
}
}
/// Destructor
~EigenArpackMatrixT() {}
// get reference on matrix
Matrix& matrix() { return mat_; }
// matrix-vector multiplication _w = mat_*_v
void mult_Mv(Real* _v, Real* _w)
{
Eigen::Map<Eigen::Matrix<Real, Eigen::Dynamic, 1> > v(_v,mat_.rows()); // uses v as a ArrayXf object
Eigen::Map<Eigen::Matrix<Real, Eigen::Dynamic, 1> > w(_w,mat_.cols()); // uses w as a ArrayXf object
w = mat_*v;
}
// matrix-vector multiplication _w = mat_*_v
void mult_M_inv_v(Real* _v, Real* _w)
{
Eigen::Map<Eigen::Matrix<Real, Eigen::Dynamic, 1> > v(_v,mat_.rows()); // uses v as a ArrayXf object
Eigen::Map<Eigen::Matrix<Real, Eigen::Dynamic, 1> > w(_w,mat_.cols()); // uses w as a ArrayXf object
w = sllt_.solve(v);
// std::cerr << "input:" << std::endl;
// std::cerr << v << std::endl;
// std::cerr << "output:" << std::endl;
// std::cerr << w << std::endl;
}
private:
Matrix mat_;
#if EIGEN_VERSION_AT_LEAST(3,1,0)
Eigen::CholmodSupernodalLLT<Eigen::SparseMatrix<Real> > sllt_;
#else
Eigen::SparseLLT<Eigen::SparseMatrix<Real>, Eigen::Cholmod> sllt_;
#endif
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_EIGENARPACKMATRIXT_C)
#define COMISO_EIGENARPACKMATRIXT_TEMPLATES
#include "EigenArpackMatrixT.cc"
#endif
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================
#endif // COMISO_EIGENARPACKMATRIXT_HH defined
//=============================================================================

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (factored_solver WIN32 ${sources} ${headers} )
else ()
acg_add_executable (factored_solver ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(factored_solver PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (factored_solver
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,193 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <vector>
#include <CoMISo/Solver/ConstrainedSolver.hh>
#include <CoMISo/Solver/MISolver.hh>
#include <CoMISo/Solver/GMM_Tools.hh>
/// function to setup a random sparse row matrix of dimension _m x _n
/// for the simplicity of this example only integer valued entries are used
template<class MatrixT>
void random_sparse_row_matrix( MatrixT& _B, int _m, int _n, double _density = 0.7)
{
gmm::resize(_B, _m, _n);
for( int i=0; i<_m; ++i)
for( int j=0; j<_n; ++j)
if( (rand()-1.0*_density*RAND_MAX)/RAND_MAX> 0) // for sparseness
_B(i,j) = round(((rand()-0.4*RAND_MAX)/RAND_MAX)*10.0);
}
/// function to setup a random sparse constraint row matrix of dimension _c x _n
/// for the simplicity of the example only -1, 0, 1 constraints are used
template<class MatrixT>
void simple_constraint_row_matrix( MatrixT& _C, int _c, int _n, double _distribution = 0.2)
{
gmm::resize( _C, _c, _n);
for( int i=0; i<_c; ++i)
for( int j=0; j<_n; ++j)
{
double randnum = (double(rand())/double(RAND_MAX));
if ( randnum < _distribution)
_C( i,j) = -1;
else if( randnum > (1.0-_distribution))
_C( i,j) = 1;
else
_C( i,j) = 0;
}
}
/// function to print the equations corresponding to the matrices of an equation system
template<class MatrixT>
void print_equations( const MatrixT& _B)
{
int m = gmm::mat_nrows( _B);
int n = gmm::mat_ncols( _B);
for( int i = 0; i < m; ++i)
{
for( int j = 0; j < n-1; ++j)
{
if( _B(i,j) != 0.0)
std::cout << _B(i,j) << "*x" << j;
else
std::cout << " 0 ";
if( j < n-2 ) std::cout << " + ";
}
std::cout << " = " << _B(i, n-1) << std::endl;
}
}
// Example main
int main(void)
{
std::cout << "---------- 1) setup an (m x n) sparse row matrix B (i.e. the B in the system ((Bx)^T)Bx)" << std::endl;
int m = 9;
int n = 5+1;
gmm::row_matrix< gmm::wsvector< double > > B;
random_sparse_row_matrix( B, m, n, 0.85);
std::cout << B << std::endl << std::endl;
//gmm::inspect_matrix( B );
std::cout << std::endl;
std::cout << "---------- 2) define a set of linear constraints as an (c x n) row matrix C" << std::endl;
int c = 2;
gmm::row_matrix< gmm::wsvector< double > > C;
simple_constraint_row_matrix( C, c, n);
std::cout << C << std::endl;
std::cout << "corresponding to the following linear equations : " << std::endl;
print_equations( C );
std::cout << std::endl;
std::cout << "---------- 3) we now explicitly carry out the steps performed internally by the constrained solver and compare the two results at the end..." << std::endl;
// copy the matrices
gmm::row_matrix< gmm::wsvector< double > > Bcpy( B );
gmm::row_matrix< gmm::wsvector< double > > Ccpy( C );
// create a constrained solver
COMISO::ConstrainedSolver cs;
// vector of indices to round (this is the mixed-integer part)
std::vector< int > ids_to_round;
// lets say we want to round the third variable
ids_to_round.push_back(2);
// vector of independent variables to be eliminated (computed by the make_constraints_independent function)
std::vector< int > ids_to_elim;
std::cout << "---------- ---------- 3.1) make the constraints independent (gauss elimination on C)" << std::endl;
print_equations( Ccpy );
cs.make_constraints_independent( Ccpy, ids_to_round, ids_to_elim);
std::cout << " constraints after gauss elimination..." << std::endl;
std::cout << Ccpy << std::endl;
std::cout << " the variables to be eliminated are: " << std::endl;
std::cout << ids_to_elim << std::endl << std::endl;
std::cout << "---------- ---------- 3.2) eliminate constraints from system matrix B" << std::endl;
// this is the column matrix later used by the solver, it is setup by the eliminate_constraints function
gmm::col_matrix< gmm::wsvector< double > > Bcol;
// this re-indexing is also used by the solver, to know which variables are still there (!=-1) and which have been eliminated (=-1) it is setup by eliminate_constraints
std::vector< int > new_idx;
cs.eliminate_constraints( Ccpy, Bcpy, ids_to_round, ids_to_elim, new_idx, Bcol);
std::cout << " B matrix after elimination of constraints..." << std::endl;
std::cout << Bcol << std::endl;
std::cout << "---------- ---------- 3.3) setup the linear system Ax=b, where by forming B^TB and extracting the right hand side" << std::endl;
// this is the solution vector x
std::vector< double > x;
int new_n = gmm::mat_ncols( Bcol);
// set up B transposed
gmm::col_matrix< gmm::wsvector< double > > Bt( new_n, m);
gmm::copy( gmm::transposed( Bcol), Bt);
// setup BtB
gmm::col_matrix< gmm::wsvector< double > > BtB( new_n, new_n);
gmm::mult( Bt, Bcol, BtB);
// extract rhs
std::vector< double > rhs( new_n);
gmm::copy( gmm::scaled(gmm::mat_const_col( BtB, new_n - 1),-1.0), rhs);
rhs.resize( new_n - 1);
// resize BtB to only contain the actual system matrix (and not the rhs)
gmm::resize( BtB, new_n - 1, new_n - 1);
x.resize( new_n - 1);
// BtB -> CSC
gmm::csc_matrix<double> BtBCSC;
BtBCSC.init_with_good_format( BtB);
std::cout << " the linear system now looks like..." << std::endl;
std::cout << " Matrix A\n " << BtBCSC << std::endl;
std::cout << " Right hand side b\n" << rhs << std::endl << std::endl;
std::cout << "---------- ---------- 3.4) solve the system using the mixed-integer solver..." << std::endl;
// create solver
COMISO::MISolver miso;
// miso solve
miso.solve( BtBCSC, x, rhs, ids_to_round);
std::cout << " solution vector x is\n" << x << std::endl << std::endl;
std::cout << "---------- ---------- 3.5) now the solution must be re-indexed to the expected/original form/size...." << std::endl;
cs.restore_eliminated_vars( Ccpy, x, ids_to_elim, new_idx);
std::cout << " fullsize solution vector x is\n" << x << std::endl << std::endl;
std::cout << "---------- ---------- 4) the same result is obtained by one call to the constrained solver, which takes care of re-indexing etc. internally..." << std::endl;
// ids_to_round is altered by previous steps...
ids_to_round.clear();
ids_to_round.push_back(2);
cs.solve( C, B, x, ids_to_round, 0.0, false, true);
std::cout << " fullsize solution vector x is\n" << x << std::endl << std::endl;
return -1;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (quadratic_solver WIN32 ${sources} ${headers} )
else ()
acg_add_executable (quadratic_solver ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(quadratic_solver PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (quadratic_solver
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,199 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <vector>
#include <CoMISo/Solver/ConstrainedSolver.hh>
#include <CoMISo/Solver/MISolver.hh>
#include <CoMISo/Solver/GMM_Tools.hh>
/// function to setup a random sparse row matrix of dimension _m x _n
/// for the simplicity of this example only integer valued entries are used
template<class MatrixT>
void random_sparse_row_matrix( MatrixT& _B, int _m, int _n, double _density = 0.7)
{
gmm::resize(_B, _m, _n);
for( int i=0; i<_m; ++i)
for( int j=0; j<_n; ++j)
if( (rand()-1.0*_density*RAND_MAX)/RAND_MAX> 0) // for sparseness
_B(i,j) = round(((rand()-0.4*RAND_MAX)/RAND_MAX)*10.0);
}
/// function to extract the actual system Ax=b of linear equation from a B^tB matrix
template<class RMatrixT, class CMatrixT>
void extract_Axb( const RMatrixT& _B, CMatrixT& _A, std::vector< double >& _b)
{
int dimm = gmm::mat_nrows(_B);
int dimn = gmm::mat_ncols(_B);
gmm::col_matrix< gmm::wsvector< double > > Btcol;
gmm::col_matrix< gmm::wsvector< double > > Bcol;
gmm::resize( Btcol, dimn, dimm);
gmm::resize( Bcol, dimm, dimn);
gmm::resize( _A, dimn, dimn);
gmm::copy( _B, Bcol);
gmm::copy( gmm::transposed( Bcol), Btcol);
gmm::mult( Btcol, Bcol, _A);
_b.resize( dimn);
gmm::copy( _A.col(dimn-1), _b);
_b.resize( dimn-1);
gmm::resize( _A, dimn-1, dimn-1);
gmm::scale(_b, -1.0);
}
/// function to setup a random sparse constraint row matrix of dimension _c x _n
/// for the simplicity of the example only -1, 0, 1 constraints are used
template<class MatrixT>
void simple_constraint_row_matrix( MatrixT& _C, int _c, int _n, double _distribution = 0.2)
{
gmm::resize( _C, _c, _n);
for( int i=0; i<_c; ++i)
for( int j=0; j<_n; ++j)
{
double randnum = (double(rand())/double(RAND_MAX));
if ( randnum < _distribution)
_C( i,j) = -1;
else if( randnum > (1.0-_distribution))
_C( i,j) = 1;
else
_C( i,j) = 0;
}
}
/// function to print the equations corresponding to the matrices of an equation system
template<class MatrixT>
void print_equations( const MatrixT& _B)
{
int m = gmm::mat_nrows( _B);
int n = gmm::mat_ncols( _B);
for( int i = 0; i < m; ++i)
{
for( int j = 0; j < n-1; ++j)
{
if( _B(i,j) != 0.0)
std::cout << _B(i,j) << "*x" << j;
else
std::cout << " 0 ";
if( j < n-2 ) std::cout << " + ";
}
std::cout << " = " << _B(i, n-1) << std::endl;
}
}
// Example main
int main(void)
{
std::cout << "---------- 1) setup an (m x n) sparse row matrix B (i.e. the B in the system ((Bx)^T)Bx)" << std::endl;
int m = 9;
int n = 5+1;
gmm::row_matrix< gmm::wsvector< double > > B;
random_sparse_row_matrix( B, m, n, 0.85);
std::cout << B << std::endl << std::endl;
std::cout << "---------- 2) extract the Ax=b equation system, A (n-1 x n-1)" << std::endl;
gmm::col_matrix< gmm::wsvector< double > > A;
std::vector< double > b;
extract_Axb( B, A, b);
std::cout << " A " << std::endl;
std::cout << A << " " << b << std::endl;
//gmm::inspect_matrix( B );
std::cout << std::endl;
std::cout << "---------- 3) define a set of linear constraints as an (c x n) row matrix C" << std::endl;
int c = 2;
gmm::row_matrix< gmm::wsvector< double > > C;
simple_constraint_row_matrix( C, c, n);
std::cout << C << std::endl;
std::cout << "corresponding to the following linear equations : " << std::endl;
print_equations( C );
std::cout << std::endl;
std::cout << "---------- 4) we now explicitly carry out the steps performed internally by the constrained solver and compare the two results at the end..." << std::endl;
// copy the matrices
gmm::col_matrix< gmm::wsvector< double > > Acpy( A );
// create a constrained solver
COMISO::ConstrainedSolver cs;
// vector of indices to round (this is the mixed-integer part)
std::vector< int > ids_to_round;
// lets say we want to round the third variable
ids_to_round.push_back(2);
// vector of independent variables to be eliminated (computed by the make_constraints_independent function)
std::vector< int > ids_to_elim;
std::cout << "---------- ---------- 4.1) make the constraints independent (gauss elimination on C)" << std::endl;
print_equations( C );
cs.make_constraints_independent( C, ids_to_round, ids_to_elim);
std::cout << " constraints after gauss elimination..." << std::endl;
std::cout << C << std::endl;
std::cout << " the variables to be eliminated are: " << std::endl;
std::cout << ids_to_elim << std::endl << std::endl;
gmm::row_matrix< gmm::wsvector< double > > Ccpy( C );
std::cout << "---------- ---------- 4.2) eliminate constraints from system matrix A" << std::endl;
// CSC matrix later initialized and used by solver
gmm::csc_matrix< double > Acsc;
// this re-indexing is also used by the solver, to know which variables are still there (!=-1) and which have been eliminated (=-1) it is setup by eliminate_constraints
std::vector< int > new_idx;
std::vector< double > x(b.size());
std::vector< double > b_cpy(b);
cs.eliminate_constraints( Ccpy, Acpy, x, b, ids_to_round, ids_to_elim, new_idx, Acsc);
std::cout << " A matrix after elimination of constraints..." << std::endl;
std::cout << Acsc << std::endl;
std::cout << "---------- ---------- 4.3) solve the system using the mixed-integer solver..." << std::endl;
// create solver
COMISO::MISolver miso;
// miso solve
miso.solve( Acsc, x, b, ids_to_round);
std::cout << " solution vector x is\n" << x << std::endl << std::endl;
std::cout << "---------- ---------- 4.4) now the solution must be re-indexed to the expected/original form/size...." << std::endl;
cs.restore_eliminated_vars( Ccpy, x, ids_to_elim, new_idx);
std::cout << " fullsize solution vector x is\n" << x << std::endl << std::endl;
std::cout << "---------- ---------- 5) the same result is obtained by one call to the constrained solver, which takes care of re-indexing etc. internally..." << std::endl;
// ids_to_round is altered by previous steps...
ids_to_round.clear();
ids_to_round.push_back(2);
x.resize(gmm::mat_nrows(A));
b.resize(gmm::mat_nrows(A));
cs.solve( C, A, x, b_cpy, ids_to_round, 0.0, false, true);
std::cout << " fullsize solution vector x is\n" << x << std::endl << std::endl;
return -1;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_cplex_soc WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_cplex_soc ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_cplex_soc PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_cplex_soc
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,124 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <CoMISo/NSolver/LeastSquaresProblem.hh>
#include <CoMISo/NSolver/LinearConstraint.hh>
#include <CoMISo/NSolver/NPDerivativeChecker.hh>
#include <CoMISo/NSolver/CPLEXSolver.hh>
#include <CoMISo/NSolver/IPOPTSolver.hh>
// solve least squares problem for x=1, y=2 and x-2y+z = 1
// with hard constraints x =-3, z>=3, z^2 >= x^2+y^2
// Example main
int main(void)
{
std::cout << "---------- 1) Problem description..." << std::endl;
std::cout << "Least squares terms: x=1, y=2 and x-2y+z = 1" << std::endl;
std::cout << "Constraints : x =-3, z>=3, z^2 >= x^2+y^2" << std::endl;
std::cout << "---------- 1) Get an instance of a LeastSquaresProblem..." << std::endl;
// number of unknowns
const int n = 3;
COMISO::LeastSquaresProblem lsqp(n);
// term0
COMISO::LinearConstraint::SVectorNC coeffs0(n);
coeffs0.coeffRef(0) = 1.0;
COMISO::LinearConstraint term0(coeffs0,-1.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term0);
// term1
COMISO::LinearConstraint::SVectorNC coeffs1(n);
coeffs1.coeffRef(1) = 1.0;
COMISO::LinearConstraint term1(coeffs1,-2.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term1);
// term2
COMISO::LinearConstraint::SVectorNC coeffs2(n);
coeffs2.coeffRef(0) = 1.0;
coeffs2.coeffRef(1) = -2.0;
coeffs2.coeffRef(2) = 1.0;
COMISO::LinearConstraint term2(coeffs2,-1.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term2);
std::cout << "---------- 2) set up constraints" << std::endl;
// set x = -3.0
COMISO::LinearConstraint lc;
lc.coeffs().coeffRef(0) = 1.0;
lc.b() = 3.0;
// set z>=3 (cone constraint requires that z>=0 !!!)
COMISO::BoundConstraint bc(2,3,3,COMISO::NConstraintInterface::NC_GREATER_EQUAL);
// set z^2 >= x^2+y^2
COMISO::ConeConstraint cc;
cc.resize(3);
cc.i() = 2;
cc.c() = 4.0;
cc.Q()(0,0) = 2.0;
cc.Q()(1,1) = 4.0;
cc.Q()(0,1) = 1.0;
cc.Q()(1,0) = 1.0;
// fill constraint vector
std::vector<COMISO::NConstraintInterface*> constraints;
constraints.push_back(&lc);
constraints.push_back(&bc);
constraints.push_back(&cc);
// check if CPLEX solver available in current configuration
#if( COMISO_CPLEX_AVAILABLE)
std::cout << "---------- 3) Solve with CPLEX solver... " << std::endl;
COMISO::CPLEXSolver cplx;
cplx.solve(&lsqp, constraints);
#endif
std::cout << "---------- 4) Print solution CPLEX..." << std::endl;
for( int i=0; i<n; ++i)
std::cerr << "x_" << i << " = " << lsqp.x()[i] << std::endl;
// check if IPOPT solver available in current configuration
#if( COMISO_IPOPT_AVAILABLE)
std::cout << "---------- 5) Solve with IPOPT solver... " << std::endl;
COMISO::IPOPTSolver ipopt;
ipopt.app().Options()->SetStringValue("derivative_test", "second-order");
ipopt.solve(&lsqp, constraints);
#endif
std::cout << "---------- 6) Print solution..." << std::endl;
for( int i=0; i<n; ++i)
std::cerr << "x_" << i << " = " << lsqp.x()[i] << std::endl;
return 0;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_eigenproblem WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_eigenproblem ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_eigenproblem PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_eigenproblem
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,107 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <iostream>
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if (COMISO_ARPACK_AVAILABLE && COMISO_SUITESPARSE_AVAILABLE && COMISO_EIGEN3_AVAILABLE)
//=============================================================================
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <CoMISo/EigenSolver/ArpackSolver.hh>
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
#include <Eigen/Dense>
//------------------------------------------------------------------------------------------------------
// Example main
int main(void)
{
// matrix types
#if EIGEN_VERSION_AT_LEAST(3,1,0)
typedef Eigen::SparseMatrix<double,Eigen::ColMajor> SMatrix;
#else
typedef Eigen::DynamicSparseMatrix<double,Eigen::ColMajor> SMatrix;
#endif
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> Matrix;
std::cout << "---------- 1) Setting up matrix..." << std::endl;
unsigned int n=5;
SMatrix A(n,n);
// 1D Laplacian
for(unsigned int i=0; i<n; ++i)
{
int count = 0;
if( i > 0)
{
A.coeffRef(i,i-1) = -1.0;
++count;
}
if(i<n-1)
{
A.coeffRef(i,i+1) = -1.0;
++count;
}
A.coeffRef(i,i) = count;
}
std::cout << "---------- 2) Solving for m smallest eigenvalues and eigenvectors..." << std::endl;
unsigned int m=3;
COMISO::ArpackSolver arsolv;
std::vector<double> evals;
Matrix evects;
arsolv.solve(A, evals, evects, m);
std::cout << "---------- 3) printing results..." << std::endl;
std::cerr << "********* eigenvalues: ";
for(unsigned int i=0; i<evals.size(); ++i)
std::cerr << evals[i] << ", ";
std::cerr << std::endl;
std::cerr <<"********* eigenvectors:" << std::endl;
std::cerr << evects << std::endl;
return 0;
}
//=============================================================================
#else
//=============================================================================
// Example main
int main(void)
{
std::cerr << "Info: required dependencies are missing, abort...\n";
return 0;
}
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_factored_solver WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_factored_solver ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_factored_solver PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_factored_solver
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,119 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <vector>
#include <CoMISo/Solver/ConstrainedSolver.hh>
#include <CoMISo/Solver/MISolver.hh>
#include <CoMISo/Solver/GMM_Tools.hh>
/// function to initialize a simple row matrix of equations
template<class MatrixT>
void init_fac( MatrixT& _B )
{
_B(0,0) = 0 ; _B(0,1) = 4 ; _B(0,2) = -2 ; _B(0,3) = 0 ; _B(0,4) = -1;
_B(1,0) = 0 ; _B(1,1) = 0 ; _B(1,2) = 0 ; _B(1,3) = 0 ; _B(1,4) = 0 ;
_B(2,0) = 5 ; _B(2,1) = 0 ; _B(2,2) = -3 ; _B(2,3) = 0 ; _B(2,4) = 0 ;
_B(3,0) = 0 ; _B(3,1) = 0 ; _B(3,2) = -2 ; _B(3,3) = 0 ; _B(3,4) = 0 ;
_B(4,0) = 0 ; _B(4,1) = -2; _B(4,2) = 0 ; _B(4,3) = 2 ; _B(4,4) = 0 ;
}
/// function to print the equations corresponding to the matrices of an equation system
template<class MatrixT>
void print_equations( const MatrixT& _B)
{
int m = gmm::mat_nrows( _B);
int n = gmm::mat_ncols( _B);
for( int i = 0; i < m; ++i)
{
for( int j = 0; j < n-1; ++j)
{
if( _B(i,j) != 0.0)
std::cout << _B(i,j) << "*x" << j;
else
std::cout << " 0 ";
if( j < n-2 ) std::cout << " + ";
}
std::cout << " = " << _B(i, n-1) << std::endl;
}
}
// Example main
int main(void)
{
std::cout << "---------- 1) Setup a number of equations (i.e. the B matrix of a factored system of linear equations B^tB)..." << std::endl;
int n = 4;
gmm::row_matrix< gmm::wsvector< double > > B(n+1,n+1);
std::vector< double > x(n);
init_fac( B );
// create an empty constraint matrix (will be used later)
gmm::row_matrix< gmm::wsvector< double > > constraints(0,n+1); //n+1 because of right hand side
// create an empty vector of variable indices to be rounded (will be used later)
std::vector< int > ids_to_round;
std::cout << B << std::endl << std::endl;
std::cout << "---------- 2) The original solution to this system is..." << std::endl;
COMISO::ConstrainedSolver cs;
// void solve( RMatrixT& _constraints, RMatrixT& _B, VectorT& _x, VectorIT& _idx_to_round, double _reg_factor = 0.0, bool _show_miso_settings = true, bool _show_timings = true );
//_show_miso_settings requires a QT context and hence must be false in this example
cs.solve( constraints, B, x, ids_to_round, 0.0, false, true);
// copy this solution for later
std::vector< double > org_x( x);
std::cout << x << std::endl;
std::cout << "---------- 3) Rounding: forcing the second variable to lie on an integer, changes the solution to..." << std::endl;
// reset system
init_fac( B );
ids_to_round.push_back(1);
cs.solve( constraints, B, x, ids_to_round, 0.0, false, true);
std::cout << x << std::endl;
std::cout << "---------- 4) Constraining: forcing the first variable to equal the second changes the solution to..." << std::endl;
// reset system
init_fac( B );
ids_to_round.clear();
ids_to_round.push_back(1);
// setup constraint x0*1+x1*0+x2*(-1)+x3*0=0
gmm::resize( constraints, 1, n+1);
constraints( 0, 0 ) = 1.0;
constraints( 0, 1 ) = -1.0;
std::cout << " the constraint equation looks like this:" << std::endl;
print_equations( constraints);
cs.solve( constraints, B, x, ids_to_round, 0.0, false, true);
std::cout << x << std::endl;
return -1;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_miqp WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_miqp ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_miqp PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_miqp
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,156 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <CoMISo/NSolver/NProblemInterface.hh>
#include <CoMISo/NSolver/NPDerivativeChecker.hh>
#include <CoMISo/NSolver/GUROBISolver.hh>
#include <CoMISo/NSolver/CPLEXSolver.hh>
#include <CoMISo/NSolver/LinearConstraint.hh>
#include <CoMISo/NSolver/VariableType.hh>
// generate an instance of a nonlinear problem by deriving from base class NProblemInterface
// implement all virtual functions in order to solve this problem by any of the solvers located
// in CoMISo/NSolver
class SmallNProblem : public COMISO::NProblemInterface
{
public:
// Sparse Matrix Type
// typedef Eigen::DynamicSparseMatrix<double,Eigen::ColMajor> SMatrixNP;
// specify a function which has several local minima
// f(x,y)=(x-2y+1)^2 + (x-5)^2
// number of unknown variables, here x and y = 2
virtual int n_unknowns ( )
{
return 2;
}
// initial value where the optimization should start from
virtual void initial_x ( double* _x )
{
_x[0] = 0.0;
_x[1] = 0.0;
}
// function evaluation at location _x
virtual double eval_f ( const double* _x )
{
double term = _x[0] - 2.0*_x[1] + 1.0;
double term2 = _x[0] - 5.0;
return term*term + term2*term2;
}
// gradient evaluation at location _x
virtual void eval_gradient( const double* _x, double* _g)
{
double term = _x[0] - 2.0*_x[1] + 1.0;
double term2 = _x[0] - 5.0;
_g[0] = 2.0*term + 2.0*term2;
_g[1] = -4.0*term;
}
// hessian matrix evaluation at location _x
virtual void eval_hessian ( const double* _x, SMatrixNP& _H)
{
_H.resize(n_unknowns(), n_unknowns());
_H.setZero();
_H.coeffRef(0,0) = 4.0;
_H.coeffRef(1,0) = -4.0;
_H.coeffRef(0,1) = -4.0;
_H.coeffRef(1,1) = 8.0;
}
// print result
virtual void store_result ( const double* _x )
{
std::cerr << "Energy: " << eval_f(_x) << std::endl;
std::cerr << "(x,y) = (" << _x[0] << "," << _x[1] << ")" << std::endl;
}
// advanced properties
virtual bool constant_hessian() { return true; }
};
//------------------------------------------------------------------------------------------------------
// Example main
int main(void)
{
std::cout << "---------- 1) Get an instance of a NProblem..." << std::endl;
SmallNProblem snp;
std::cout << "---------- 2) (optional for debugging) Check derivatives of problem..." << std::endl;
COMISO::NPDerivativeChecker npd;
npd.check_all(&snp);
std::cout << "---------- 3) setup list of integer variables..." << std::endl;
std::vector<COMISO::PairIndexVtype> discrete_variables;
discrete_variables.push_back( COMISO::PairIndexVtype(0,COMISO::Integer) );
std::cout << "---------- 4) setup constraints..." << std::endl;
std::vector<COMISO::NConstraintInterface*> constraints;
// setup constraint x+y <= 6.5
COMISO::LinearConstraint::SVectorNC coeffs(2);
coeffs.coeffRef(0) = 1.0;
coeffs.coeffRef(1) = 1.0;
COMISO::LinearConstraint lc(coeffs, -6.5, COMISO::LinearConstraint::NC_LESS_EQUAL);
constraints.push_back(&lc);
// check if IPOPT solver available in current configuration
#if( COMISO_GUROBI_AVAILABLE)
std::cout << "---------- 5) Get GUROBI solver... " << std::endl;
COMISO::GUROBISolver gsol;
std::cout << "---------- 4) Solve..." << std::endl;
gsol.solve(&snp, constraints, discrete_variables);
#endif
// check if TAO solver available in current configuration
#if( COMISO_CPLEX_AVAILABLE)
std::cout << "---------- 5) Solve with CPLEX solver... " << std::endl;
COMISO::CPLEXSolver csol;
std::cout << "---------- 4) Solve..." << std::endl;
csol.solve(&snp, constraints, discrete_variables);
#endif
return 0;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_nleast_squares WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_nleast_squares ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_nleast_squares PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_nleast_squares
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,85 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <CoMISo/NSolver/LeastSquaresProblem.hh>
#include <CoMISo/NSolver/LinearConstraint.hh>
#include <CoMISo/NSolver/NPDerivativeChecker.hh>
#include <CoMISo/NSolver/IPOPTSolver.hh>
// solve least squares problem for x=1, y=2 and x-2y = 1
// Example main
int main(void)
{
std::cout << "---------- 1) Get an instance of a LeastSquaresProblem..." << std::endl;
// number of unknowns
const int n = 2;
COMISO::LeastSquaresProblem lsqp(n);
// term0
COMISO::LinearConstraint::SVectorNC coeffs0(n);
coeffs0.coeffRef(0) = 1.0;
COMISO::LinearConstraint term0(coeffs0,-1.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term0);
// term1
COMISO::LinearConstraint::SVectorNC coeffs1(n);
coeffs1.coeffRef(1) = 1.0;
COMISO::LinearConstraint term1(coeffs1,-2.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term1);
// term2
COMISO::LinearConstraint::SVectorNC coeffs2(n);
coeffs2.coeffRef(0) = 1.0;
coeffs2.coeffRef(1) = -2.0;
COMISO::LinearConstraint term2(coeffs2,-1.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term2);
std::cout << "---------- 2) (optional for debugging) Check derivatives of problem..." << std::endl;
COMISO::NPDerivativeChecker npd;
npd.check_all(&lsqp);
// check if IPOPT solver available in current configuration
#if( COMISO_IPOPT_AVAILABLE)
std::cout << "---------- 3) Get IPOPT solver... " << std::endl;
COMISO::IPOPTSolver ipsol;
std::cout << "---------- 4) Solve..." << std::endl;
// there are no constraints -> provide an empty vector
std::vector<COMISO::NConstraintInterface*> constraints;
ipsol.solve(&lsqp, constraints);
#endif
std::cout << "---------- 5) Print solution..." << std::endl;
for( int i=0; i<n; ++i)
std::cerr << "x_" << i << " = " << lsqp.x()[i] << std::endl;
return 0;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_nsolver WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_nsolver ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_nsolver PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_nsolver
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,85 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <CoMISo/NSolver/LeastSquaresProblem.hh>
#include <CoMISo/NSolver/LinearConstraint.hh>
#include <CoMISo/NSolver/NPDerivativeChecker.hh>
#include <CoMISo/NSolver/IPOPTSolver.hh>
// solve least squares problem for x=1, y=2 and x-2y = 1
// Example main
int main(void)
{
std::cout << "---------- 1) Get an instance of a LeastSquaresProblem..." << std::endl;
// number of unknowns
const int n = 2;
COMISO::LeastSquaresProblem lsqp(n);
// term0
COMISO::LinearConstraint::SVectorNC coeffs0(n);
coeffs0.coeffRef(0) = 1.0;
COMISO::LinearConstraint term0(coeffs0,-1.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term0);
// term1
COMISO::LinearConstraint::SVectorNC coeffs1(n);
coeffs1.coeffRef(1) = 1.0;
COMISO::LinearConstraint term1(coeffs1,-2.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term1);
// term2
COMISO::LinearConstraint::SVectorNC coeffs2(n);
coeffs2.coeffRef(0) = 1.0;
coeffs2.coeffRef(1) = -2.0;
COMISO::LinearConstraint term2(coeffs2,-1.0,COMISO::NConstraintInterface::NC_EQUAL);
lsqp.add_term(&term2);
std::cout << "---------- 2) (optional for debugging) Check derivatives of problem..." << std::endl;
COMISO::NPDerivativeChecker npd;
npd.check_all(&lsqp);
// check if IPOPT solver available in current configuration
#if( COMISO_IPOPT_AVAILABLE)
std::cout << "---------- 3) Get IPOPT solver... " << std::endl;
COMISO::IPOPTSolver ipsol;
std::cout << "---------- 4) Solve..." << std::endl;
// there are no constraints -> provide an empty vector
std::vector<COMISO::NConstraintInterface*> constraints;
ipsol.solve(&lsqp, constraints);
#endif
std::cout << "---------- 5) Print solution..." << std::endl;
for( int i=0; i<n; ++i)
std::cerr << "x_" << i << " = " << lsqp.x()[i] << std::endl;
return 0;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_quadratic_solver WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_quadratic_solver ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_quadratic_solver PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_quadratic_solver
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,122 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <vector>
#include <CoMISo/Solver/ConstrainedSolver.hh>
#include <CoMISo/Solver/MISolver.hh>
#include <CoMISo/Solver/GMM_Tools.hh>
/// function to initialize a simple system of linear equations
template<class MatrixT>
void init_les( MatrixT& _A, std::vector< double >& _b)
{
_A(0,0) = 25 ; _A(0,1) = 0 ; _A(0,2) = -15; _A(0,3) = 0 ;
_A(1,0) = 0 ; _A(1,1) = 20; _A(1,2) = -8 ; _A(1,3) = -4;
_A(2,0) = -15 ; _A(2,1) = -8; _A(2,2) = 17 ; _A(2,3) = 0 ;
_A(3,0) = 0 ; _A(3,1) = -4; _A(3,2) = 0 ; _A(3,3) = 4 ;
_b[0] = 0; _b[1] = 4; _b[2] = -2; _b[3] = 0;
}
/// function to print the equations corresponding to the matrices of an equation system
template<class MatrixT>
void print_equations( const MatrixT& _B)
{
int m = gmm::mat_nrows( _B);
int n = gmm::mat_ncols( _B);
for( int i = 0; i < m; ++i)
{
for( int j = 0; j < n-1; ++j)
{
if( _B(i,j) != 0.0)
std::cout << _B(i,j) << "*x" << j;
else
std::cout << " 0 ";
if( j < n-2 ) std::cout << " + ";
}
std::cout << " = " << _B(i, n-1) << std::endl;
}
}
// Example main
int main(void)
{
std::cout << "---------- 1) Setup small (symmetric) test equation system Ax=b..." << std::endl;
int n = 4;
gmm::col_matrix< gmm::wsvector< double > > A(n,n);
std::vector< double > x(n);
std::vector< double > b(n);
init_les( A, b);
// create an empty constraint matrix (will be used later)
gmm::row_matrix< gmm::wsvector< double > > constraints(0,n+1); //n+1 because of right hand side
// create an empty vector of variable indices to be rounded (will be used later)
std::vector< int > ids_to_round;
std::cout << A << std::endl << b << std::endl;
std::cout << "---------- 2) The original solution to this system is..." << std::endl;
COMISO::ConstrainedSolver cs;
//void solve( RMatrixT& _constraints, CMatrixT& _A, VectorT& _x, VectorT& _rhs, VectorIT& _idx_to_round, double _reg_factor = 0.0, bool _show_miso_settings = true, bool _show_timings = true );
//_show_miso_settings requires a QT context and hence must be false in this example
cs.solve( constraints, A, x, b, ids_to_round, 0.0, false, true);
// copy this solution for later
std::vector< double > org_x( x);
std::cout << x << std::endl;
std::cout << "---------- 3) Rounding: forcing the second variable to lie on an integer, changes the solution to..." << std::endl;
// reset system
init_les( A, b);
ids_to_round.push_back(1);
cs.solve( constraints, A, x, b, ids_to_round, 0.0, false, true);
std::cout << x << std::endl;
std::cout << "---------- 4) Constraining: forcing the first variable to equal the second changes the solution to..." << std::endl;
// reset system
init_les( A, b);
ids_to_round.clear();
ids_to_round.push_back(1);
// setup constraint x0*1+x1*0+x2*(-1)+x3*0=0
gmm::resize( constraints, 1, n+1);
constraints( 0, 0 ) = 1.0;
constraints( 0, 1 ) = -1.0;
std::cout << " the constraint equation looks like this:" << std::endl;
print_equations( constraints);
cs.solve( constraints, A, x, b, ids_to_round, 0.0, false, true);
std::cout << x << std::endl;
return -1;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_quadratic_resolve WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_quadratic_resolve ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_quadratic_resolve PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_quadratic_resolve
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,146 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <vector>
#include <CoMISo/Solver/ConstrainedSolver.hh>
#include <CoMISo/Solver/MISolver.hh>
#include <CoMISo/Solver/GMM_Tools.hh>
/// function to initialize a simple system of linear equations
template<class MatrixT>
void init_les( MatrixT& _A, std::vector< double >& _b)
{
_A(0,0) = 25 ; _A(0,1) = 0 ; _A(0,2) = -15; _A(0,3) = 0 ;
_A(1,0) = 0 ; _A(1,1) = 20; _A(1,2) = -8 ; _A(1,3) = -4;
_A(2,0) = -15 ; _A(2,1) = -8; _A(2,2) = 17 ; _A(2,3) = 0 ;
_A(3,0) = 0 ; _A(3,1) = -4; _A(3,2) = 0 ; _A(3,3) = 4 ;
_b[0] = 0; _b[1] = 4; _b[2] = -2; _b[3] = 0;
}
/// function to print the equations corresponding to the matrices of an equation system
template<class MatrixT>
void print_equations( const MatrixT& _B)
{
int m = gmm::mat_nrows( _B);
int n = gmm::mat_ncols( _B);
for( int i = 0; i < m; ++i)
{
for( int j = 0; j < n-1; ++j)
{
if( _B(i,j) != 0.0)
std::cout << _B(i,j) << "*x" << j;
else
std::cout << " 0 ";
if( j < n-2 ) std::cout << " + ";
}
std::cout << " = " << -_B(i, n-1) << std::endl;
}
}
// Example main
int main(void)
{
std::cout << "---------- 1) Setup small (symmetric) test equation system Ax=b..." << std::endl;
int n = 4;
gmm::col_matrix< gmm::wsvector< double > > A(n,n);
std::vector< double > x(n);
std::vector< double > b(n);
std::vector<double> x_bak;
std::cout << "---------- 1) Set up problem..." << std::endl;
init_les( A, b);
// create an empty constraint matrix (will be used later)
gmm::row_matrix< gmm::wsvector< double > > constraints(0,n+1); //n+1 because of right hand side
// create an empty vector of variable indices to be rounded (will be used later)
std::vector< int > ids_to_round;
std::cout << A << std::endl << b << std::endl;
// setup constraints
gmm::resize( constraints, 3, n+1);
constraints( 0, 0 ) = 1.0;
constraints( 0, 1 ) = -1.0;
constraints( 0, n ) = 2.0;
constraints( 1, 3 ) = 1.0;
constraints( 1, n ) = -1.0;
// add one redundant constraint (this will be filtered out during Gaussian elimination)
constraints( 2, 0 ) = 1.0;
constraints( 2, 1 ) = -1.0;
constraints( 2, n ) = 2.0;
std::cout << " the constraint equations looks like this:" << std::endl;
print_equations( constraints);
std::cout << "---------- 2) Solve full ..." << std::endl;
COMISO::ConstrainedSolver cs;
cs.solve_const( constraints, A, x, b, ids_to_round, 0.0, false, true);
x_bak = x;
// first test: resolve with identical rhs's
std::vector<double> constraint_rhs(3);
std::vector<double> b_new = b;
constraint_rhs[0] = -2.0;
constraint_rhs[1] = 1.0;
constraint_rhs[2] = -2.0;
std::cout << "---------- 2) Solve same rhs pre-factorized ..." << std::endl;
cs.resolve(x, &constraint_rhs, &b_new);
std::cout << "orig result: " << x_bak << std::endl;
std::cout << "resolve result: " << x << std::endl;
// second test: resolve with changed rhs
constraint_rhs[0] = 4.0;
constraint_rhs[1] = -2.0;
constraint_rhs[2] = 4.0;
b_new[0] = 1.0;
b_new[1] = -2.0;
b_new[2] = 3.0;
b_new[3] = -5.0;
std::cout << "---------- 3) Solve different rhs pre-factorized ..." << std::endl;
cs.resolve(x, &constraint_rhs, &b_new);
// solve with new factorization
constraints( 0, n ) = -4.0;
constraints( 1, n ) = 2.0;
constraints( 2, n ) = -4.0;
std::cout << "---------- 4) Solve different rhs full ..." << std::endl;
cs.solve_const( constraints, A, x_bak, b_new, ids_to_round, 0.0, false, true);
std::cout << "orig result (with different rhs's): " << x_bak << std::endl;
std::cout << "resolve result (with different rhs's): " << x << std::endl;
return 0;
}

View File

@ -0,0 +1,15 @@
include (CoMISoExample)
if (WIN32)
acg_add_executable (small_sparseqr WIN32 ${sources} ${headers} )
else ()
acg_add_executable (small_sparseqr ${sources} ${headers} )
endif ()
# enable rpath linking
set_target_properties(small_sparseqr PROPERTIES INSTALL_RPATH_USE_LINK_PATH 1)
target_link_libraries (small_sparseqr
CoMISo
${COMISO_LINK_LIBRARIES}
)

View File

@ -0,0 +1,176 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include <vector>
#include <cstdlib>
#include <iostream>
//------------------------------------------------------------------------------------------------------
#if COMISO_SUITESPARSE_SPQR_AVAILABLE // additional spqr library required
//------------------------------------------------------------------------------------------------------
#include <CoMISo/Utils/StopWatch.hh>
#include <Eigen/Sparse>
#include <CoMISo/Solver/SparseQRSolver.hh>
#include <CoMISo/Solver/Eigen_Tools.hh>
//------------------------------------------------------------------------------------------------------
// Example main
int main(void)
{
std::cout << "---------- 0) Using Sparse QR for solving underdetermined equations and computing Null spaces " << std::endl;
typedef Eigen::SparseMatrix< double > SpMatrix;
typedef Eigen::MatrixXd DenMatrix;
typedef Eigen::Triplet< double > Triplet;
int dimr(4+1);
int dimc(4+2);
std::cout << "---------- 1) Creating matrix " << std::endl;
std::vector< Triplet > triplets;
for( int i = 0; i < dimc*dimr/2; ++i)
{
int x( rand()%(dimr-1));
int y( rand()%dimc);
double val( rand()%10);
//std::cerr << " setting (" << x << ", " << y << ") to " << val << std::endl;
triplets.push_back( Triplet( x, y, val));
}
SpMatrix A(dimr,dimc);
A.setFromTriplets(triplets.begin(), triplets.end());
std::cerr << DenMatrix(A) << std::endl;
int m = dimr;
int n = dimc;
if( m < n )
{
std::swap( m,n);
std::cerr << " ... m < n -> form transposed ..." << std::endl;
A = SpMatrix(A.transpose());
// test make also row -rank-deficinet
A.middleCols(n-1,1) = A.middleCols(0,1);
A.middleCols(0,1) = A.middleCols(n-2,1);
std::cerr << DenMatrix(A) << std::endl;
}
std::cerr << " ... m = " << m << "; n = " << n << std::endl;
std::cerr << std::endl;
std::cout << "---------- 2) Sparse QR " << std::endl;
COMISO::SparseQRSolver spqr;
SpMatrix Q,R;
std::vector< size_t > P;
int rank = spqr.factorize_system_eigen( A, Q, R, P);
int nullity(dimc-rank);
// setup permutation matrix
SpMatrix Pm( n, n);
if( !P.empty())
{
for( size_t i = 0; i < P.size(); ++i)
{
Pm.coeffRef( i, P[i]) = 1;
}
}
std::cout << "---------- 3) Result " << std::endl;
std::cerr << " Q " << std::endl << DenMatrix(Q) << std::endl;
std::cerr << " R " << std::endl << DenMatrix(R) << std::endl;
std::cerr << " P " << std::endl << P << std::endl;
std::cerr << " P matrix " << std::endl << DenMatrix(Pm) << std::endl;
std::cerr << " Rank " << rank << std::endl;
std::cerr << " Nullity " << nullity << std::endl;
// extract nullspace
SpMatrix NullSpace( Q.middleCols( std::max( 0, m-nullity), nullity));
std::cerr << " Nullspace " << std::endl << DenMatrix(NullSpace) << std::endl;
// non nullspace part of R
//// assuming superflous column in R is the last (if A is also row deficient)
//SpMatrix Rtmp(R.middleCols(0,std::min(n,n-(n-rank))).transpose());
//SpMatrix R1( R.transpose().middleCols(0, m-nullity));
SpMatrix Rtmp(R.transpose());
SpMatrix R1t( Rtmp.middleCols(0,m-nullity));
SpMatrix R1( R1t.transpose());
std::cerr << " Non-Nullspace R " << std::endl << DenMatrix(R1) << std::endl;
std::cout << "---------- 4) Verification " << std::endl;
SpMatrix reconstructedA(Q*R*Pm.transpose());
std::cerr << " Q orthogonal? \t " << ((fabs((Q.transpose()*Q).squaredNorm()-m) < 1e-8)?"yes":"no") << std::endl;
std::cerr << " A = QR? \t " << (((reconstructedA-A).squaredNorm() < 1e-8)? "yes":"no") << std::endl;
std::cerr << std::endl << std::endl;
std::cout << "---------- 5) Solving Ax=b (with x without nullspace component)" << std::endl;
// NOTE: A was transposed above to be m>n
SpMatrix b(n,1);
SpMatrix x(m,1);
for( int i = 0; i < n; ++i)
b.coeffRef(i,0) = rand()%10;
std::cerr << " ... System Ax = b .. \n";
std::cerr << " A " << std::endl << DenMatrix(A.transpose()) << " x " << std::endl << DenMatrix(x) << " b " << std::endl << DenMatrix(b) << std::endl;
std::cout << "---------- 5.1) test: solve using sparse QR solving .." << std::endl;
SpMatrix At(A.transpose());
spqr.solve_system_eigen( At, b, x);
std::cerr << " ... solution x .. " << std::endl;
std::cerr << DenMatrix(x) << std::endl;
std::cerr << " ... test: is a solution ? " << (((A.transpose()*x-b).squaredNorm()<1e-8)?"yes":"no") << std::endl;
std::cerr << " ... test: has nullspace component ? " << ((x.transpose()*NullSpace).squaredNorm()<1e-8?"yes":"no") << std::endl;
std::cerr << " ... Nullspace projections : " << (x.transpose()*NullSpace) << std::endl;
std::cout << "---------- 5.2) test: solve without nullspace .." << std::endl;
SpMatrix Atnull(At);
SpMatrix bnull(b);
SpMatrix xnull(m,1);
spqr.solve_system_eigen_min2norm( Atnull, bnull, xnull);
std::cerr << " ... solution x .. " << std::endl;
std::cerr << DenMatrix(xnull) << std::endl;
std::cerr << " ... test: is a solution ? " << (((A.transpose()*xnull-bnull).squaredNorm()<1e-8)?"yes":"no") << std::endl;
std::cerr << " ... test: has nullspace component ? " << ((xnull.transpose()*NullSpace).squaredNorm()<1e-8?"yes":"no") << std::endl;
std::cerr << " ... Nullspace projections : " << (xnull.transpose()*NullSpace) << std::endl;
return 0;
}
#else // COMISO_SUITESPARSE_SPQR_AVAILABLE
int main(void)
{
std::cerr << " SUITESPARSE_SPQR not available, please re-configure!\n";
return 0;
}
#endif // COMISO_SUITESPARSE_SPQR_AVAILABLE

View File

@ -0,0 +1,161 @@
//=============================================================================
//
// CLASS BoundConstraint - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
#include "BoundConstraint.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
BoundConstraint::
BoundConstraint(const unsigned int _var_idx, // index of variable for bound constraint
const double _bound, // bound: x(_var_idx) #_type, <,=,># _bound
const unsigned int _n, // number of unknowns in problem
const ConstraintType _type) // type of bound upper, lower or both (equal)
: NConstraintInterface(_type), idx_(_var_idx), bound_(_bound), n_(_n)
{
}
//-----------------------------------------------------------------------------
BoundConstraint::
~BoundConstraint()
{
}
//-----------------------------------------------------------------------------
int
BoundConstraint::
n_unknowns()
{
return n_;
}
//-----------------------------------------------------------------------------
double
BoundConstraint::
eval_constraint ( const double* _x )
{
return _x[idx_] - bound_;
}
//-----------------------------------------------------------------------------
void
BoundConstraint::
eval_gradient ( const double* _x, SVectorNC& _g )
{
_g.resize(n_); _g.coeffRef(idx_) = 1.0;
}
//-----------------------------------------------------------------------------
void
BoundConstraint::
eval_hessian ( const double* _x, SMatrixNC& _h )
{
_h.clear(); _h.resize(n_,n_);
}
//-----------------------------------------------------------------------------
bool
BoundConstraint::
is_linear() const
{
return true;
}
//-----------------------------------------------------------------------------
bool
BoundConstraint::
constant_gradient() const
{
return true;
}
//-----------------------------------------------------------------------------
bool
BoundConstraint::
constant_hessian() const
{
return true;
}
//-----------------------------------------------------------------------------
unsigned int&
BoundConstraint::
idx()
{
return idx_;
}
//-----------------------------------------------------------------------------
double&
BoundConstraint::
bound()
{
return bound_;
}
//-----------------------------------------------------------------------------
unsigned int&
BoundConstraint::
n()
{
return n_;
}
//-----------------------------------------------------------------------------
void
BoundConstraint::
resize(const unsigned int _n)
{
n_ = _n;
}
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,84 @@
//=============================================================================
//
// CLASS BoundConstraint
//
//=============================================================================
#ifndef COMISO_BOUNDCONSTRAINT_HH
#define COMISO_BOUNDCONSTRAINT_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "NConstraintInterface.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class BoundConstraint
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT BoundConstraint : public NConstraintInterface
{
public:
// inherited from NConstraintInterface
// typedef Eigen::SparseVector<double> SVectorNC;
// typedef SuperSparseMatrixT<double> SMatrixNC;
// // different types of constraints
// enum ConstraintType {NC_EQUAL, NC_LESS_EQUAL, NC_GREATER_EQUAL};
/// Default constructor
BoundConstraint(const unsigned int _var_idx = 0, // index of variable for bound constraint
const double _bound = 0.0, // bound: x(_var_idx) #_type, <,=,># _bound
const unsigned int _n = 0, // number of unknowns in problem
const ConstraintType _type = NC_LESS_EQUAL); // type of bound upper, lower or both (equal)
/// Destructor
virtual ~BoundConstraint();
virtual int n_unknowns ( );
virtual double eval_constraint ( const double* _x );
virtual void eval_gradient ( const double* _x, SVectorNC& _g );
virtual void eval_hessian ( const double* _x, SMatrixNC& _h );
virtual bool is_linear() const;
virtual bool constant_gradient() const;
virtual bool constant_hessian () const;
// set/get values
unsigned int& idx();
double& bound();
unsigned int& n();
void resize(const unsigned int _n);
private:
// variable idx
unsigned int idx_;
// variable bound
double bound_;
// number of unknowns
unsigned int n_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // ACG_BOUNDCONSTRAINT_HH defined
//=============================================================================

View File

@ -0,0 +1,140 @@
//=============================================================================
//
// CLASS COMISOSolver - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
//=============================================================================
#include <vector>
#include "COMISOSolver.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
// ********** SOLVE **************** //
void
COMISOSolver::
solve(NProblemInterface* _problem,
std::vector<NConstraintInterface*>& _constraints,
std::vector<PairUiV>& _discrete_constraints,
double _reg_factor,
bool _show_miso_settings,
bool _show_timings )
{
//----------------------------------------------
// 1. identify integer variables
//----------------------------------------------
// identify integer variables
std::vector<int> round_idxs;
for(unsigned int i=0; i<_discrete_constraints.size(); ++i)
switch(_discrete_constraints[i].second)
{
case Binary :
case Integer:
round_idxs.push_back(_discrete_constraints[i].first); break;
default : break;
}
//----------------------------------------------
// 2. setup constraints
//----------------------------------------------
int n = _problem->n_unknowns();
gmm::row_matrix< gmm::wsvector< double > > C(_constraints.size(), n+1);
int n_constraints = 0;
// get zero vector
std::vector<double> x(n, 0.0);
for(unsigned int i=0; i<_constraints.size(); ++i)
if(_constraints[i]->constraint_type() == NConstraintInterface::NC_EQUAL)
{
if(!_constraints[i]->is_linear())
std::cerr << "Warning: COMISOSolver received a problem with non-linear constraints!!!" << std::endl;
// get linear part
NConstraintInterface::SVectorNC gc;
_constraints[i]->eval_gradient(P(x), gc);
NConstraintInterface::SVectorNC::InnerIterator v_it(gc);
for(; v_it; ++v_it)
C(n_constraints, v_it.index()) = v_it.value();
// get constant part
C(n_constraints, n) = _constraints[i]->eval_constraint(P(x));
// move to next constraint
++n_constraints;
}
// resize matrix to final number of constraints
gmm::resize(C,n_constraints, n+1);
//----------------------------------------------
// 3. setup energy
//----------------------------------------------
if(!_problem->constant_hessian())
std::cerr << "Warning: COMISOSolver received a problem with non-constant hessian!!!" << std::endl;
// get hessian matrix
gmm::col_matrix< gmm::wsvector< double > > A(n,n);
NProblemInterface::SMatrixNP H;
_problem->eval_hessian(P(x), H);
for( int i=0; i<H.outerSize(); ++i)
for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
A(it.row(),it.col()) = it.value();
// get negative gradient
std::vector<double> rhs(_problem->n_unknowns());
_problem->eval_gradient(P(x), P(rhs));
for(unsigned int i=0; i<rhs.size(); ++i)
rhs[i] = -rhs[i];
// // add constant part
// objective += _problem->eval_f(P(x));
//----------------------------------------------
// 4. solve problem
//----------------------------------------------
cs_.solve(C,A,x,rhs,round_idxs,
_reg_factor, _show_miso_settings, _show_timings);
// void solve(
// RMatrixT& _constraints,
// CMatrixT& _A,
// VectorT& _x,
// VectorT& _rhs,
// VectorIT& _idx_to_round,
// double _reg_factor = 0.0,
// bool _show_miso_settings = true,
// bool _show_timings = true );
//----------------------------------------------
// 5. store result
//----------------------------------------------
_problem->store_result(P(x));
// std::cout << "COMISO Objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
}
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,85 @@
//=============================================================================
//
// CLASS COMISOSolver
//
//=============================================================================
#ifndef COMISO_COMISOSOLVER_HH
#define COMISO_COMISOSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <CoMISo/Solver/ConstrainedSolver.hh>
#include <vector>
#include "NProblemInterface.hh"
#include "NConstraintInterface.hh"
#include "VariableType.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NewtonSolver GUROBISolver.hh
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT COMISOSolver
{
public:
typedef std::pair<unsigned int, VariableType> PairUiV;
/// Default constructor
COMISOSolver() {}
/// Destructor
~COMISOSolver() {}
// ********** SOLVE **************** //
void solve(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
std::vector<PairUiV>& _discrete_constraints, // discrete constraint
double _reg_factor = 0.0, // reguluarization factor
bool _show_miso_settings = true, // show settings dialog
bool _show_timings = true ); // show timings
// get reference to ConstrainedSolver to manipulate parameters
ConstrainedSolver& solver() { return cs_;}
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
ConstrainedSolver cs_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // ACG_GUROBISOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,68 @@
//=============================================================================
//
// CLASS CPLEXSolver - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include "CPLEXSolver.hh"
#if COMISO_CPLEX_AVAILABLE
//=============================================================================
#include <stdexcept>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
CPLEXSolver::
CPLEXSolver()
{
}
//-----------------------------------------------------------------------------
//void
//CPLEXSolver::
//set_problem_output_path( const std::string &_problem_output_path)
//{
// problem_output_path_ = _problem_output_path;
//}
//
//
////-----------------------------------------------------------------------------
//
//
//void
//CPLEXSolver::
//set_problem_env_output_path( const std::string &_problem_env_output_path)
//{
// problem_env_output_path_ = _problem_env_output_path;
//}
//
//
////-----------------------------------------------------------------------------
//
//
//void
//CPLEXSolver::
//set_solution_input_path(const std::string &_solution_input_path)
//{
// solution_input_path_ = _solution_input_path;
//}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_CPLEX_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,117 @@
//=============================================================================
//
// CLASS CPLEXSolver
//
//=============================================================================
#ifndef COMISO_CPLEXSOLVER_HH
#define COMISO_CPLEXSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_CPLEX_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <vector>
#include <string>
#include "NProblemInterface.hh"
#include "NConstraintInterface.hh"
#include "VariableType.hh"
#include <ilcplex/ilocplex.h>
ILOSTLBEGIN
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NewtonSolver CPLEXSolver.hh
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT CPLEXSolver
{
public:
/// Default constructor
CPLEXSolver();
/// Destructor
~CPLEXSolver() { /*env_.end();*/}
// ********** SOLVE **************** //
// this function has to be inline due to static linking issues
inline bool solve(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
std::vector<PairIndexVtype>& _discrete_constraints, // discrete constraints
const double _time_limit = 60,
const bool _silent = false); // time limit in seconds
// same as above but without discrete constraints (for convenience)
inline bool solve(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
const double _time_limit = 60,
const bool _silent = false) // time limit in seconds
{ std::vector<PairIndexVtype> dc; return solve(_problem, _constraints, dc, _time_limit, _silent);}
// with handling of cone constrints
inline bool solve2(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
std::vector<PairIndexVtype>& _discrete_constraints, // discrete constraints
const double _time_limit = 60,
const bool _silent = false); // time limit in seconds
// void set_problem_output_path ( const std::string &_problem_output_path);
// void set_problem_env_output_path( const std::string &_problem_env_output_path);
// void set_solution_input_path ( const std::string &_solution_input_path);
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
// CPLEX environment
// IloEnv env_;
// filenames for exporting/importing gurobi solutions
// if string is empty nothing is imported or exported
// std::string problem_output_path_;
// std::string problem_env_output_path_;
// std::string solution_input_path_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_CPLEX_AVAILABLE
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_CPLEXSOLVER_C)
#define COMISO_CPLEXSOLVER_TEMPLATES
#include "CPLEXSolverT.cc"
#endif
//=============================================================================
#endif // ACG_CPLEXSOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,574 @@
//=============================================================================
//
// CLASS GCPLEXSolver - IMPLEMENTATION
//
//=============================================================================
#define COMISO_CPLEXSOLVER_C
//== INCLUDES =================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include "CPLEXSolver.hh"
#include "LinearConstraint.hh"
#include "BoundConstraint.hh"
#include "ConeConstraint.hh"
#if COMISO_CPLEX_AVAILABLE
//=============================================================================
#include <stdexcept>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
// ********** SOLVE **************** //
bool
CPLEXSolver::
solve2(NProblemInterface* _problem,
std::vector<NConstraintInterface*>& _constraints,
std::vector<PairIndexVtype>& _discrete_constraints,
const double _time_limit,
const bool _silent)
{
try
{
//----------------------------------------------
// 0. set up environment
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> get environment...\n";
IloEnv env_;
if(!_silent)
std::cerr << "cplex -> get model...\n";
IloModel model(env_);
// model.getEnv().set(GRB_DoubleParam_TimeLimit, _time_limit);
//----------------------------------------------
// 1. allocate variables
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> allocate variables...\n";
// determine variable types: 0->real, 1->integer, 2->bool
std::vector<char> vtypes(_problem->n_unknowns(),0);
for(unsigned int i=0; i<_discrete_constraints.size(); ++i)
if(_discrete_constraints[i].first < vtypes.size())
{
switch(_discrete_constraints[i].second)
{
case Integer: vtypes[_discrete_constraints[i].first] = 1; break;
case Binary : vtypes[_discrete_constraints[i].first] = 2; break;
default : break;
}
}
else
std::cerr << "ERROR: requested a discrete variable which is above the total number of variables"
<< _discrete_constraints[i].first << " vs " << vtypes.size() << std::endl;
// CPLEX variables
std::vector<IloNumVar> vars;
// first all
for( int i=0; i<_problem->n_unknowns(); ++i)
switch(vtypes[i])
{
case 0 : vars.push_back( IloNumVar(env_,-IloInfinity, IloInfinity, IloNumVar::Float) ); break;
case 1 : vars.push_back( IloNumVar(env_, -IloIntMax, IloIntMax, IloNumVar::Int) ); break;
case 2 : vars.push_back( IloNumVar(env_, 0, 1, IloNumVar::Bool) ); break;
}
// Integrate new variables
// model.update();
//----------------------------------------------
// 2. setup constraints
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> setup constraints...\n";
// get zero vector
std::vector<double> x(_problem->n_unknowns(), 0.0);
for(unsigned int i=0; i<_constraints.size(); ++i)
{
if(!_constraints[i]->is_linear())
std::cerr << "Warning: CPLEXSolver received a problem with non-linear constraints!!!" << std::endl;
IloExpr lin_expr(env_);
NConstraintInterface::SVectorNC gc;
_constraints[i]->eval_gradient(P(x), gc);
NConstraintInterface::SVectorNC::InnerIterator v_it(gc);
for(; v_it; ++v_it)
lin_expr += vars[v_it.index()]*v_it.value();
double b = _constraints[i]->eval_constraint(P(x));
switch(_constraints[i]->constraint_type())
{
case NConstraintInterface::NC_EQUAL : model.add(lin_expr + b == 0); break;
case NConstraintInterface::NC_LESS_EQUAL : model.add(lin_expr + b <= 0); break;
case NConstraintInterface::NC_GREATER_EQUAL : model.add(lin_expr + b >= 0); break;
}
}
// model.update();
//----------------------------------------------
// 3. setup energy
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> setup energy...\n";
if(!_problem->constant_hessian())
std::cerr << "Warning: CPLEXSolver received a problem with non-constant hessian!!!" << std::endl;
// GRBQuadExpr objective;
IloExpr objective(env_);
// add quadratic part
NProblemInterface::SMatrixNP H;
_problem->eval_hessian(P(x), H);
for( int i=0; i<H.outerSize(); ++i)
for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
objective += 0.5*it.value()*vars[it.row()]*vars[it.col()];
// add linear part
std::vector<double> g(_problem->n_unknowns());
_problem->eval_gradient(P(x), P(g));
for(unsigned int i=0; i<g.size(); ++i)
objective += g[i]*vars[i];
// add constant part
objective += _problem->eval_f(P(x));
model.add(IloMinimize(env_,objective));
// model.set(GRB_IntAttr_ModelSense, 1);
// model.setObjective(objective);
// model.update();
//----------------------------------------------
// 4. solve problem
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> generate model...\n";
IloCplex cplex(model);
cplex.setParam(IloCplex::TiLim, _time_limit);
{ // hack
// 0 [CPX_NODESEL_DFS] Depth-first search
// 1 [CPX_NODESEL_BESTBOUND] Best-bound search
// 2 [CPX_NODESEL_BESTEST] Best-estimate search
// 3 [CPX_NODESEL_BESTEST_ALT] Alternative best-estimate search
// cplex.setParam(IloCplex::NodeSel , 0);
}
if(!_silent)
std::cerr << "cplex -> solve...\n";
// silent mode?
if(_silent)
cplex.setOut(env_.getNullStream());
IloBool solution_found = cplex.solve();
// if (solution_input_path_.empty())
// {
// if (!problem_env_output_path_.empty())
// {
// std::cout << "Writing problem's environment into file \"" << problem_env_output_path_ << "\"." << std::endl;
// model.getEnv().writeParams(problem_env_output_path_);
// }
// if (!problem_output_path_.empty())
// {
// std::cout << "Writing problem into file \"" << problem_output_path_ << "\"." << std::endl;
// GurobiHelper::outputModelToMpsGz(model, problem_output_path_);
// }
//
// model.optimize();
// }
// else
// {
// std::cout << "Reading solution from file \"" << solution_input_path_ << "\"." << std::endl;
// }
//
//----------------------------------------------
// 5. store result
//----------------------------------------------
if(solution_found != IloFalse)
{
if(!_silent)
std::cerr << "cplex -> store result...\n";
// store computed result
for(unsigned int i=0; i<vars.size(); ++i)
x[i] = cplex.getValue(vars[i]);
_problem->store_result(P(x));
}
/*
if (solution_input_path_.empty())
{
// store computed result
for(unsigned int i=0; i<vars.size(); ++i)
x[i] = vars[i].get(GRB_DoubleAttr_X);
}
*/
// else
// {
// std::cout << "Loading stored solution from \"" << solution_input_path_ << "\"." << std::endl;
// // store loaded result
// const size_t oldSize = x.size();
// x.clear();
// GurobiHelper::readSolutionVectorFromSOL(x, solution_input_path_);
// if (oldSize != x.size()) {
// std::cerr << "oldSize != x.size() <=> " << oldSize << " != " << x.size() << std::endl;
// throw std::runtime_error("Loaded solution vector doesn't have expected dimension.");
// }
// }
//
// _problem->store_result(P(x));
//
// // ObjVal is only available if the optimize was called.
// if (solution_input_path_.empty())
// std::cout << "GUROBI Objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
return solution_found;
}
catch (IloException& e)
{
cerr << "Concert exception caught: " << e << endl;
return false;
}
catch (...)
{
cerr << "Unknown exception caught" << endl;
return false;
}
return false;
}
//-----------------------------------------------------------------------------
bool
CPLEXSolver::
solve(NProblemInterface* _problem,
std::vector<NConstraintInterface*>& _constraints,
std::vector<PairIndexVtype>& _discrete_constraints,
const double _time_limit,
const bool _silent)
{
try
{
//----------------------------------------------
// 0. set up environment
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> get environment...\n";
IloEnv env_;
if(!_silent)
std::cerr << "cplex -> get model...\n";
IloModel model(env_);
// model.getEnv().set(GRB_DoubleParam_TimeLimit, _time_limit);
//----------------------------------------------
// 1. allocate variables and initialize limits
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> allocate variables...\n";
// determine variable types: 0->real, 1->integer, 2->bool
std::vector<char> vtypes (_problem->n_unknowns(),0);
for(unsigned int i=0; i<_discrete_constraints.size(); ++i)
if(_discrete_constraints[i].first < vtypes.size())
{
switch(_discrete_constraints[i].second)
{
case Integer: vtypes [_discrete_constraints[i].first] = 1;
break;
case Binary : vtypes[_discrete_constraints[i].first] = 2;
break;
default : break;
}
}
else
std::cerr << "ERROR: requested a discrete variable which is above the total number of variables"
<< _discrete_constraints[i].first << " vs " << vtypes.size() << std::endl;
// CPLEX variables
std::vector<IloNumVar> vars; vars.reserve(_problem->n_unknowns());
// first all
for( int i=0; i<_problem->n_unknowns(); ++i)
switch(vtypes[i])
{
case 0 : vars.push_back( IloNumVar(env_,-IloInfinity, IloInfinity, IloNumVar::Float) ); break;
case 1 : vars.push_back( IloNumVar(env_, -IloIntMax, IloIntMax, IloNumVar::Int) ); break;
case 2 : vars.push_back( IloNumVar(env_, 0, 1, IloNumVar::Bool) ); break;
}
// Integrate new variables
// model.update();
//----------------------------------------------
// 2. setup constraints
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> setup constraints...\n";
// get zero vector
std::vector<double> x(_problem->n_unknowns(), 0.0);
// handle constraints depending on their tyep
for(unsigned int i=0; i<_constraints.size(); ++i)
{
// is linear constraint?
LinearConstraint* lin_ptr = dynamic_cast<LinearConstraint*>(_constraints[i]);
if(lin_ptr)
{
IloExpr lin_expr(env_);
NConstraintInterface::SVectorNC gc;
_constraints[i]->eval_gradient(P(x), gc);
NConstraintInterface::SVectorNC::InnerIterator v_it(gc);
for(; v_it; ++v_it)
lin_expr += vars[v_it.index()]*v_it.value();
double b = _constraints[i]->eval_constraint(P(x));
switch(_constraints[i]->constraint_type())
{
case NConstraintInterface::NC_EQUAL : model.add(lin_expr + b == 0); break;
case NConstraintInterface::NC_LESS_EQUAL : model.add(lin_expr + b <= 0); break;
case NConstraintInterface::NC_GREATER_EQUAL : model.add(lin_expr + b >= 0); break;
}
}
else
{
BoundConstraint* bnd_ptr = dynamic_cast<BoundConstraint*>(_constraints[i]);
if(bnd_ptr)
{
switch(bnd_ptr->constraint_type())
{
case NConstraintInterface::NC_EQUAL : vars[bnd_ptr->idx()].setBounds(bnd_ptr->bound(), bnd_ptr->bound()); break;
case NConstraintInterface::NC_LESS_EQUAL : vars[bnd_ptr->idx()].setUB(bnd_ptr->bound()); break;
case NConstraintInterface::NC_GREATER_EQUAL : vars[bnd_ptr->idx()].setLB(bnd_ptr->bound()); break;
}
}
else
{
ConeConstraint* cone_ptr = dynamic_cast<ConeConstraint*>(_constraints[i]);
if(cone_ptr)
{
IloExpr soc_lhs(env_);
IloExpr soc_rhs(env_);
soc_rhs= 0.5*cone_ptr->c()*vars[cone_ptr->i()]*vars[cone_ptr->i()];
NConstraintInterface::SMatrixNC::iterator q_it = cone_ptr->Q().begin();
for(; q_it != cone_ptr->Q().end(); ++q_it)
{
soc_lhs += 0.5*(*q_it)*vars[q_it.col()]*vars[q_it.row()];
}
model.add(soc_lhs <= soc_rhs);
}
else
std::cerr << "Warning: CPLEXSolver received a constraint of unknow type!!! -> skipping it" << std::endl;
}
}
}
// model.update();
//----------------------------------------------
// 3. setup energy
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> setup energy...\n";
if(!_problem->constant_hessian())
std::cerr << "Warning: CPLEXSolver received a problem with non-constant hessian!!!" << std::endl;
// GRBQuadExpr objective;
IloExpr objective(env_);
// add quadratic part
NProblemInterface::SMatrixNP H;
_problem->eval_hessian(P(x), H);
for( int i=0; i<H.outerSize(); ++i)
for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
objective += 0.5*it.value()*vars[it.row()]*vars[it.col()];
// add linear part
std::vector<double> g(_problem->n_unknowns());
_problem->eval_gradient(P(x), P(g));
for(unsigned int i=0; i<g.size(); ++i)
objective += g[i]*vars[i];
// add constant part
objective += _problem->eval_f(P(x));
model.add(IloMinimize(env_,objective));
// model.set(GRB_IntAttr_ModelSense, 1);
// model.setObjective(objective);
// model.update();
//----------------------------------------------
// 4. solve problem
//----------------------------------------------
if(!_silent)
std::cerr << "cplex -> generate model...\n";
IloCplex cplex(model);
cplex.setParam(IloCplex::TiLim, _time_limit);
{ // hack
// 0 [CPX_NODESEL_DFS] Depth-first search
// 1 [CPX_NODESEL_BESTBOUND] Best-bound search
// 2 [CPX_NODESEL_BESTEST] Best-estimate search
// 3 [CPX_NODESEL_BESTEST_ALT] Alternative best-estimate search
// cplex.setParam(IloCplex::NodeSel , 0);
}
if(!_silent)
std::cerr << "cplex -> solve...\n";
// silent mode?
if(_silent)
cplex.setOut(env_.getNullStream());
IloBool solution_found = cplex.solve();
// if (solution_input_path_.empty())
// {
// if (!problem_env_output_path_.empty())
// {
// std::cout << "Writing problem's environment into file \"" << problem_env_output_path_ << "\"." << std::endl;
// model.getEnv().writeParams(problem_env_output_path_);
// }
// if (!problem_output_path_.empty())
// {
// std::cout << "Writing problem into file \"" << problem_output_path_ << "\"." << std::endl;
// GurobiHelper::outputModelToMpsGz(model, problem_output_path_);
// }
//
// model.optimize();
// }
// else
// {
// std::cout << "Reading solution from file \"" << solution_input_path_ << "\"." << std::endl;
// }
//
//----------------------------------------------
// 5. store result
//----------------------------------------------
if(solution_found != IloFalse)
{
if(!_silent)
std::cerr << "cplex -> store result...\n";
// store computed result
for(unsigned int i=0; i<vars.size(); ++i)
x[i] = cplex.getValue(vars[i]);
_problem->store_result(P(x));
}
/*
if (solution_input_path_.empty())
{
// store computed result
for(unsigned int i=0; i<vars.size(); ++i)
x[i] = vars[i].get(GRB_DoubleAttr_X);
}
*/
// else
// {
// std::cout << "Loading stored solution from \"" << solution_input_path_ << "\"." << std::endl;
// // store loaded result
// const size_t oldSize = x.size();
// x.clear();
// GurobiHelper::readSolutionVectorFromSOL(x, solution_input_path_);
// if (oldSize != x.size()) {
// std::cerr << "oldSize != x.size() <=> " << oldSize << " != " << x.size() << std::endl;
// throw std::runtime_error("Loaded solution vector doesn't have expected dimension.");
// }
// }
//
// _problem->store_result(P(x));
//
// // ObjVal is only available if the optimize was called.
// if (solution_input_path_.empty())
// std::cout << "GUROBI Objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
return solution_found;
}
catch (IloException& e)
{
cerr << "Concert exception caught: " << e << endl;
return false;
}
catch (...)
{
cerr << "Unknown exception caught" << endl;
return false;
}
return false;
}
//-----------------------------------------------------------------------------
//void
//CPLEXSolver::
//set_problem_output_path( const std::string &_problem_output_path)
//{
// problem_output_path_ = _problem_output_path;
//}
//
//
////-----------------------------------------------------------------------------
//
//
//void
//CPLEXSolver::
//set_problem_env_output_path( const std::string &_problem_env_output_path)
//{
// problem_env_output_path_ = _problem_env_output_path;
//}
//
//
////-----------------------------------------------------------------------------
//
//
//void
//CPLEXSolver::
//set_solution_input_path(const std::string &_solution_input_path)
//{
// solution_input_path_ = _solution_input_path;
//}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_CPLEX_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,134 @@
//=============================================================================
//
// CLASS ConerConstraint
//
//=============================================================================
#ifndef COMISO_CONECONSTRAINT_CC
#define COMISO_CONECONSTRAINT_CC
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "NConstraintInterface.hh"
#include "ConeConstraint.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== Implementation =========================================================
/// Default constructor
ConeConstraint::ConeConstraint()
: NConstraintInterface(NConstraintInterface::NC_GREATER_EQUAL)
{
Q_.clear();
i_ = 1.0;
c_ = 1.0;
}
// cone constraint of the form -> 0.5*(c_ * x(i_)^2 - x^T Q_ x) >= 0
ConeConstraint::ConeConstraint(const double _c, const int _i, const SMatrixNC& _Q)
: NConstraintInterface(NConstraintInterface::NC_GREATER_EQUAL),
c_(_c), i_(_i), Q_(_Q)
{
}
/// Destructor
ConeConstraint::~ConeConstraint() {}
int ConeConstraint::n_unknowns()
{
return Q_.cols();
}
void ConeConstraint::resize(const unsigned int _n)
{
Q_.resize(_n,_n);
}
void ConeConstraint::clear()
{
Q_.clear();
}
const ConeConstraint::SMatrixNC& ConeConstraint::Q() const
{
return Q_;
}
ConeConstraint::SMatrixNC& ConeConstraint::Q()
{
return Q_;
}
const int& ConeConstraint::i() const
{
return i_;
}
int& ConeConstraint::i()
{
return i_;
}
const double& ConeConstraint::c() const
{
return c_;
}
double& ConeConstraint::c()
{
return c_;
}
double ConeConstraint::eval_constraint ( const double* _x )
{
// cone constraint of the form -> 0.5*(c_ * x(i_)^2 - x^T Q_ x) >= 0
double v = c_*_x[i_]*_x[i_];
SMatrixNC::iterator m_it = Q_.begin();
SMatrixNC::iterator m_end = Q_.end();
for(; m_it != m_end; ++m_it)
{
v -= (*m_it)*_x[m_it.row()]*_x[m_it.col()];
}
return 0.5*v;
}
void ConeConstraint::eval_gradient( const double* _x, SVectorNC& _g )
{
_g.setZero();
_g.resize(Q_.rows());
SMatrixNC::iterator m_it = Q_.begin();
SMatrixNC::iterator m_end = Q_.end();
for(; m_it != m_end; ++m_it)
{
_g.coeffRef(m_it.row()) -= (*m_it)*_x[m_it.col()];
}
_g.coeffRef(i_) += c_*_x[i_];
}
void ConeConstraint::eval_hessian ( const double* _x, SMatrixNC& _h )
{
_h = Q_;
_h.scale(-1.0);
_h(i_,i_) += c_;
}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // ACG_ConeConstraint_HH defined
//=============================================================================

View File

@ -0,0 +1,90 @@
//=============================================================================
//
// CLASS ConeConstraint
//
//=============================================================================
#ifndef COMISO_CONECONSTRAINT_HH
#define COMISO_CONECONSTRAINT_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "NConstraintInterface.hh"
#include <Eigen/StdVector>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
class COMISODLLEXPORT ConeConstraint : public NConstraintInterface
{
public:
// sparse vector type
typedef NConstraintInterface::SVectorNC SVectorNC;
typedef NConstraintInterface::SMatrixNC SMatrixNC;
/// Default constructor
ConeConstraint();
// cone constraint of the form -> 0.5*(c_ * x(i_)^2 - x^T Q_ x) >= 0
ConeConstraint(const double _c, const int _i, const SMatrixNC& _Q);
/// Destructor
virtual ~ConeConstraint();
virtual int n_unknowns();
// resize coefficient vector = #unknowns
void resize(const unsigned int _n);
// clear to zero constraint 0 =_type 0
void clear();
const double& c() const;
double& c();
const int& i() const;
int& i();
const SMatrixNC& Q() const;
SMatrixNC& Q();
virtual double eval_constraint ( const double* _x );
virtual void eval_gradient( const double* _x, SVectorNC& _g );
virtual void eval_hessian ( const double* _x, SMatrixNC& _h );
virtual bool is_linear() const { return false;}
virtual bool constant_gradient() const { return false;}
virtual bool constant_hessian () const { return true;}
private:
// cone constraint of the form -> 0.5*(c_ * x(i_)^2 - x^T Q_ x) >= 0
double c_;
int i_;
SMatrixNC Q_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
// support std vectors
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(COMISO::ConeConstraint);
//=============================================================================
#endif // ACG_CONECONSTRAINT_HH defined
//=============================================================================

View File

@ -0,0 +1,254 @@
//=============================================================================
//
// CLASS GUROBISolver - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_GUROBI_AVAILABLE
//=============================================================================
#include "GUROBISolver.hh"
#include <stdexcept>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
GUROBISolver::
GUROBISolver()
{
}
//-----------------------------------------------------------------------------
// ********** SOLVE **************** //
bool
GUROBISolver::
solve(NProblemInterface* _problem,
std::vector<NConstraintInterface*>& _constraints,
std::vector<PairIndexVtype>& _discrete_constraints,
const double _time_limit)
{
try
{
//----------------------------------------------
// 0. set up environment
//----------------------------------------------
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
model.getEnv().set(GRB_DoubleParam_TimeLimit, _time_limit);
//----------------------------------------------
// 1. allocate variables
//----------------------------------------------
// determine variable types: 0->real, 1->integer, 2->bool
std::vector<char> vtypes(_problem->n_unknowns(),0);
for(unsigned int i=0; i<_discrete_constraints.size(); ++i)
switch(_discrete_constraints[i].second)
{
case Integer: vtypes[_discrete_constraints[i].first] = 1; break;
case Binary : vtypes[_discrete_constraints[i].first] = 2; break;
default : break;
}
// GUROBI variables
std::vector<GRBVar> vars;
// first all
for( int i=0; i<_problem->n_unknowns(); ++i)
switch(vtypes[i])
{
case 0 : vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_CONTINUOUS) ); break;
case 1 : vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_INTEGER ) ); break;
case 2 : vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_BINARY ) ); break;
}
// Integrate new variables
model.update();
//----------------------------------------------
// 2. setup constraints
//----------------------------------------------
// get zero vector
std::vector<double> x(_problem->n_unknowns(), 0.0);
for(unsigned int i=0; i<_constraints.size(); ++i)
{
if(!_constraints[i]->is_linear())
std::cerr << "Warning: GUROBISolver received a problem with non-linear constraints!!!" << std::endl;
GRBLinExpr lin_expr;
NConstraintInterface::SVectorNC gc;
_constraints[i]->eval_gradient(P(x), gc);
NConstraintInterface::SVectorNC::InnerIterator v_it(gc);
for(; v_it; ++v_it)
// lin_expr += v_it.value()*vars[v_it.index()];
lin_expr = lin_expr + vars[v_it.index()]*v_it.value();
double b = _constraints[i]->eval_constraint(P(x));
switch(_constraints[i]->constraint_type())
{
case NConstraintInterface::NC_EQUAL : model.addConstr(lin_expr + b == 0); break;
case NConstraintInterface::NC_LESS_EQUAL : model.addConstr(lin_expr + b <= 0); break;
case NConstraintInterface::NC_GREATER_EQUAL : model.addConstr(lin_expr + b >= 0); break;
}
}
model.update();
//----------------------------------------------
// 3. setup energy
//----------------------------------------------
if(!_problem->constant_hessian())
std::cerr << "Warning: GUROBISolver received a problem with non-constant hessian!!!" << std::endl;
GRBQuadExpr objective;
// add quadratic part
NProblemInterface::SMatrixNP H;
_problem->eval_hessian(P(x), H);
for( int i=0; i<H.outerSize(); ++i)
for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
objective += 0.5*it.value()*vars[it.row()]*vars[it.col()];
// add linear part
std::vector<double> g(_problem->n_unknowns());
_problem->eval_gradient(P(x), P(g));
for(unsigned int i=0; i<g.size(); ++i)
objective += g[i]*vars[i];
// add constant part
objective += _problem->eval_f(P(x));
model.set(GRB_IntAttr_ModelSense, 1);
model.setObjective(objective);
model.update();
//----------------------------------------------
// 4. solve problem
//----------------------------------------------
if (solution_input_path_.empty())
{
if (!problem_env_output_path_.empty())
{
std::cout << "Writing problem's environment into file \"" << problem_env_output_path_ << "\"." << std::endl;
model.getEnv().writeParams(problem_env_output_path_);
}
if (!problem_output_path_.empty())
{
std::cout << "Writing problem into file \"" << problem_output_path_ << "\"." << std::endl;
GurobiHelper::outputModelToMpsGz(model, problem_output_path_);
}
model.optimize();
}
else
{
std::cout << "Reading solution from file \"" << solution_input_path_ << "\"." << std::endl;
}
//----------------------------------------------
// 5. store result
//----------------------------------------------
if (solution_input_path_.empty())
{
// store computed result
for(unsigned int i=0; i<vars.size(); ++i)
x[i] = vars[i].get(GRB_DoubleAttr_X);
}
else
{
std::cout << "Loading stored solution from \"" << solution_input_path_ << "\"." << std::endl;
// store loaded result
const size_t oldSize = x.size();
x.clear();
GurobiHelper::readSolutionVectorFromSOL(x, solution_input_path_);
if (oldSize != x.size()) {
std::cerr << "oldSize != x.size() <=> " << oldSize << " != " << x.size() << std::endl;
throw std::runtime_error("Loaded solution vector doesn't have expected dimension.");
}
}
_problem->store_result(P(x));
// ObjVal is only available if the optimize was called.
if (solution_input_path_.empty())
std::cout << "GUROBI Objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
return true;
}
catch(GRBException& e)
{
std::cout << "Error code = " << e.getErrorCode() << std::endl;
std::cout << e.getMessage() << std::endl;
return false;
}
catch(...)
{
std::cout << "Exception during optimization" << std::endl;
return false;
}
return false;
}
//-----------------------------------------------------------------------------
void
GUROBISolver::
set_problem_output_path( const std::string &_problem_output_path)
{
problem_output_path_ = _problem_output_path;
}
//-----------------------------------------------------------------------------
void
GUROBISolver::
set_problem_env_output_path( const std::string &_problem_env_output_path)
{
problem_env_output_path_ = _problem_env_output_path;
}
//-----------------------------------------------------------------------------
void
GUROBISolver::
set_solution_input_path(const std::string &_solution_input_path)
{
solution_input_path_ = _solution_input_path;
}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_GUROBI_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,92 @@
//=============================================================================
//
// CLASS GUROBISolver
//
//=============================================================================
#ifndef COMISO_GUROBISOLVER_HH
#define COMISO_GUROBISOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_GUROBI_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <vector>
#include <string>
#include "NProblemInterface.hh"
#include "NConstraintInterface.hh"
#include "VariableType.hh"
#include "GurobiHelper.hh"
#include <gurobi_c++.h>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NewtonSolver GUROBISolver.hh
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT GUROBISolver
{
public:
/// Default constructor
GUROBISolver();
/// Destructor
~GUROBISolver() {}
// ********** SOLVE **************** //
bool solve(NProblemInterface* _problem, // problem instance
std::vector<NConstraintInterface*>& _constraints, // linear constraints
std::vector<PairIndexVtype>& _discrete_constraints, // discrete constraints
const double _time_limit = 60 ); // time limit in seconds
void set_problem_output_path ( const std::string &_problem_output_path);
void set_problem_env_output_path( const std::string &_problem_env_output_path);
void set_solution_input_path ( const std::string &_solution_input_path);
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
// filenames for exporting/importing gurobi solutions
// if string is empty nothing is imported or exported
std::string problem_output_path_;
std::string problem_env_output_path_;
std::string solution_input_path_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_GUROBI_AVAILABLE
//=============================================================================
#endif // ACG_GUROBISOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,175 @@
/*
* GurobiHelper.cc
*
* Created on: Jan 4, 2012
* Author: ebke
*/
#include "GurobiHelper.hh"
#if (COMISO_GUROBI_AVAILABLE && COMISO_BOOST_AVAILABLE)
#include <QTemporaryFile>
#include <QFileInfo>
#include <boost/filesystem.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <cstdio>
#include <fstream>
#include <string>
#define OUTPUT_UNCOMPRESSED_WITH_CONSTANT_COMMENT 0
#define OUTPUT_CONSTANT_AS_CONT 1
namespace COMISO {
/**
* Helper class that ensures exception safe deletion
* of a temporary file.
*/
class TempFileGuard {
public:
TempFileGuard(const std::string &_filePath) : filePath_(_filePath) {
}
~TempFileGuard() {
if (boost::filesystem::exists(filePath_))
boost::filesystem::remove(filePath_);
}
const boost::filesystem::path &filePath() const { return filePath_; };
private:
boost::filesystem::path filePath_;
};
static void moveConstantTermIntoConstrainedVariable(GRBModel &model) {
const double constantTerm = model.getObjective().getLinExpr().getConstant();
//tmpModel.getObjective().addConstant(-constantTerm);
model.getObjective() -= constantTerm;
#if OUTPUT_CONSTANT_AS_CONT
model.addVar(constantTerm, constantTerm, 1, GRB_CONTINUOUS, "MIQ_synthetic_constant");
#else
model.addVar(1, 1, constantTerm, GRB_INTEGER, "MIQ_synthetic_constant");
#endif
}
static void copyFile(const char *from, const char *to) {
FILE *inF = fopen(from, "r");
FILE *outF = fopen(to, "w");
const int bufsize = 4096;
unsigned char buffer[bufsize];
do {
size_t readBytes = fread(buffer, 1, bufsize, inF);
fwrite(buffer, 1, readBytes, outF);
} while(!feof(inF));
fclose(inF);
fclose(outF);
}
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
void GurobiHelper::outputModelToMpsGz(GRBModel &model, const std::string &problem_output_path_) {
#if OUTPUT_UNCOMPRESSED_WITH_CONSTANT_COMMENT
boost::scoped_ptr<TempFileGuard> tempFileGuard;
{
QTemporaryFile tempFile("XXXXXX.mps");
tempFile.setAutoRemove(false);
tempFile.open();
// In order to minimize the likelihood of race conditions,
// we initialize tempFileGuard right here.
tempFileGuard.reset(new TempFileGuard(QFileInfo(tempFile).absoluteFilePath().toStdString()));
tempFile.close();
}
const std::string fileName = tempFileGuard->filePath().string();
model.write(fileName);
const double constantTerm = model.getObjective().getLinExpr().getConstant();
FILE *inF = fopen(fileName.c_str(), "r");
FILE *outF = fopen(problem_output_path_.c_str(), "w");
fprintf(outF, "* Constant Term: %.16e\n", constantTerm);
const int bufsize = 4096;
unsigned char buffer[bufsize];
int readBytes;
do {
readBytes = fread(buffer, 1, bufsize, inF);
fwrite(buffer, 1, readBytes, outF);
} while(!feof(inF));
fclose(inF);
fclose(outF);
#else
GRBModel tmpModel(model);
moveConstantTermIntoConstrainedVariable(tmpModel);
tmpModel.update();
tmpModel.write(problem_output_path_);
#endif
}
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
void GurobiHelper::importInitialSolutionIntoModel(GRBModel &model, const std::string &solution_path_) {
boost::scoped_ptr<TempFileGuard> tempFileGuard;
{
QTemporaryFile tempFile("XXXXXX.mst");
tempFile.setAutoRemove(false);
tempFile.open();
// In order to minimize the likelihood of race conditions,
// we initialize tempFileGuard right here.
tempFileGuard.reset(new TempFileGuard(QFileInfo(tempFile).absoluteFilePath().toStdString()));
tempFile.close();
}
const std::string fileName = tempFileGuard->filePath().string();
copyFile(solution_path_.c_str(), fileName.c_str());
//moveConstantTermIntoConstrainedVariable(model);
const double constantTerm = model.getObjective().getLinExpr().getConstant();
model.addVar(constantTerm, constantTerm, 0, GRB_CONTINUOUS, "MIQ_synthetic_constant");
model.update();
model.read(fileName);
model.update();
}
void GurobiHelper::readSolutionVectorFromSOL(std::vector<double> &out_solution_, const std::string &fileName_) {
std::ifstream solFile(fileName_.c_str());
//if (!solFile.good())
// throw std::runtime_error("Unable to open file \"" + fileName + "\".");
static const boost::regex commentRe("\\s*#", boost::regex_constants::perl);
static const boost::regex variableRe("\\s*(\\S+)\\s+([-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)", boost::regex_constants::perl);
std::string line;
while (solFile) {
std::getline(solFile, line);
if (boost::regex_search(line, commentRe, boost::match_continuous)) continue;
boost::smatch match;
if (boost::regex_search(line, match, variableRe, boost::match_continuous) && match[1] != "MIQ_synthetic_constant") {
out_solution_.push_back(boost::lexical_cast<double>(match[2]));
}
}
}
} /* namespace COMISO */
#endif

View File

@ -0,0 +1,51 @@
/*
* GurobiHelper.hh
*
* Created on: Jan 4, 2012
* Author: ebke
*/
#ifndef GUROBIHELPER_HH_
#define GUROBIHELPER_HH_
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if (COMISO_GUROBI_AVAILABLE && COMISO_BOOST_AVAILABLE)
//=============================================================================
#include <gurobi_c++.h>
#include <string>
#include <vector>
namespace COMISO {
class GurobiHelper {
public:
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
static void outputModelToMpsGz(GRBModel &model, const std::string &problem_output_path_);
/**
* WARNING: Never call outputModelToMpsGz and importInitialSolutionIntoModel
* on the same model. Both try to move the constant term into a variable and
* consequently, the second attempt to do so will fail.
*/
static void importInitialSolutionIntoModel(GRBModel &model, const std::string &solution_path_);
/**
* Reads the solution vector from a SOL file and appends it to
* out_solution_.
*/
static void readSolutionVectorFromSOL(std::vector<double> &out_solution_, const std::string &fileName_);
};
} /* namespace COMISO */
#endif /* COMISO_GUROBI_AVAILABLE */
#endif /* GUROBIHELPER_HH_ */

1153
src/external/CoMISo/NSolver/IPOPTSolver.cc vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,402 @@
//=============================================================================
//
// CLASS IPOPTSolver
//
//=============================================================================
#ifndef COMISO_IPOPTSOLVER_HH
#define COMISO_IPOPTSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_IPOPT_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <vector>
#include <cstddef>
#include <gmm/gmm.h>
#include "NProblemGmmInterface.hh"
#include "NProblemInterface.hh"
#include "NConstraintInterface.hh"
#include "BoundConstraint.hh"
#include <IpTNLP.hpp>
#include <IpIpoptApplication.hpp>
#include <IpSolveStatistics.hpp>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NewtonSolver NewtonSolver.hh <ACG/.../NewtonSolver.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT IPOPTSolver
{
public:
/// Default constructor -> set up IpOptApplication
IPOPTSolver();
/// Destructor
~IPOPTSolver() {}
// ********** SOLVE **************** //
// solve -> returns ipopt status code
//------------------------------------------------------
// enum ApplicationReturnStatus
// {
// Solve_Succeeded=0,
// Solved_To_Acceptable_Level=1,
// Infeasible_Problem_Detected=2,
// Search_Direction_Becomes_Too_Small=3,
// Diverging_Iterates=4,
// User_Requested_Stop=5,
// Feasible_Point_Found=6,
//
// Maximum_Iterations_Exceeded=-1,
// Restoration_Failed=-2,
// Error_In_Step_Computation=-3,
// Maximum_CpuTime_Exceeded=-4,
// Not_Enough_Degrees_Of_Freedom=-10,
// Invalid_Problem_Definition=-11,
// Invalid_Option=-12,
// Invalid_Number_Detected=-13,
//
// Unrecoverable_Exception=-100,
// NonIpopt_Exception_Thrown=-101,
// Insufficient_Memory=-102,
// Internal_Error=-199
// };
//------------------------------------------------------
int solve(NProblemInterface* _problem, const std::vector<NConstraintInterface*>& _constraints);
// same as above with additional lazy constraints that are only added iteratively to the problem if not satisfied
int solve(NProblemInterface* _problem,
const std::vector<NConstraintInterface*>& _constraints,
const std::vector<NConstraintInterface*>& _lazy_constraints,
const double _almost_infeasible = 0.5,
const int _max_passes = 5 );
// for convenience, if no constraints are given
int solve(NProblemInterface* _problem);
// deprecated interface for backwards compatibility
int solve(NProblemGmmInterface* _problem, std::vector<NConstraintInterface*>& _constraints);
// ********* CONFIGURATION ********************* //
// access the ipopt-application (for setting parameters etc.)
// example: app().Options()->SetIntegerValue("max_iter", 100);
Ipopt::IpoptApplication& app() {return (*app_); }
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
// smart pointer to IpoptApplication to set options etc.
Ipopt::SmartPtr<Ipopt::IpoptApplication> app_;
};
//== CLASS DEFINITION PROBLEM INSTANCE=========================================================
class NProblemIPOPT : public Ipopt::TNLP
{
public:
// Ipopt Types
typedef Ipopt::Number Number;
typedef Ipopt::Index Index;
typedef Ipopt::SolverReturn SolverReturn;
typedef Ipopt::IpoptData IpoptData;
typedef Ipopt::IpoptCalculatedQuantities IpoptCalculatedQuantities;
// sparse matrix and vector types
typedef NConstraintInterface::SVectorNC SVectorNC;
typedef NConstraintInterface::SMatrixNC SMatrixNC;
typedef NProblemInterface::SMatrixNP SMatrixNP;
/** default constructor */
NProblemIPOPT(NProblemInterface* _problem, const std::vector<NConstraintInterface*>& _constraints)
: problem_(_problem), store_solution_(false) { split_constraints(_constraints); analyze_special_properties(_problem, _constraints);}
/** default destructor */
virtual ~NProblemIPOPT() {};
/**@name Overloaded from TNLP */
//@{
/** Method to return some info about the nlp */
virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
Index& nnz_h_lag, IndexStyleEnum& index_style);
/** Method to return the bounds for my problem */
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u);
/** Method to return the starting point for the algorithm */
virtual bool get_starting_point(Index n, bool init_x, Number* x,
bool init_z, Number* z_L, Number* z_U,
Index m, bool init_lambda,
Number* lambda);
/** Method to return the objective value */
virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value);
/** Method to return the gradient of the objective */
virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f);
/** Method to return the constraint residuals */
virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g);
/** Method to return:
* 1) The structure of the jacobian (if "values" is NULL)
* 2) The values of the jacobian (if "values" is not NULL)
*/
virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow, Index *jCol,
Number* values);
/** Method to return:
* 1) The structure of the hessian of the lagrangian (if "values" is NULL)
* 2) The values of the hessian of the lagrangian (if "values" is not NULL)
*/
virtual bool eval_h(Index n, const Number* x, bool new_x,
Number obj_factor, Index m, const Number* lambda,
bool new_lambda, Index nele_hess, Index* iRow,
Index* jCol, Number* values);
//@}
/** @name Solution Methods */
//@{
/** This method is called when the algorithm is complete so the TNLP can store/write the solution */
virtual void finalize_solution(SolverReturn status,
Index n, const Number* x, const Number* z_L, const Number* z_U,
Index m, const Number* g, const Number* lambda,
Number obj_value,
const IpoptData* ip_data,
IpoptCalculatedQuantities* ip_cq);
//@}
// special properties of problem
bool hessian_constant() const;
bool jac_c_constant() const;
bool jac_d_constant() const;
bool& store_solution() {return store_solution_; }
std::vector<double>& solution() {return x_;}
private:
/**@name Methods to block default compiler methods.
* The compiler automatically generates the following three methods.
* Since the default compiler implementation is generally not what
* you want (for all but the most simple classes), we usually
* put the declarations of these methods in the private section
* and never implement them. This prevents the compiler from
* implementing an incorrect "default" behavior without us
* knowing. (See Scott Meyers book, "Effective C++")
*
*/
//@{
// MyNLP();
NProblemIPOPT(const NProblemIPOPT&);
NProblemIPOPT& operator=(const NProblemIPOPT&);
//@}
// split user-provided constraints into general-constraints and bound-constraints
void split_constraints(const std::vector<NConstraintInterface*>& _constraints);
// determine if hessian_constant, jac_c_constant or jac_d_constant
void analyze_special_properties(const NProblemInterface* _problem, const std::vector<NConstraintInterface*>& _constraints);
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
// pointer to problem instance
NProblemInterface* problem_;
// reference to constraints vector
std::vector<NConstraintInterface*> constraints_;
std::vector<BoundConstraint*> bound_constraints_;
bool hessian_constant_;
bool jac_c_constant_;
bool jac_d_constant_;
bool store_solution_;
std::vector<double> x_;
};
//== CLASS DEFINITION PROBLEM INSTANCE=========================================================
class NProblemGmmIPOPT : public Ipopt::TNLP
{
public:
// Ipopt Types
typedef Ipopt::Number Number;
typedef Ipopt::Index Index;
typedef Ipopt::SolverReturn SolverReturn;
typedef Ipopt::IpoptData IpoptData;
typedef Ipopt::IpoptCalculatedQuantities IpoptCalculatedQuantities;
// sparse matrix and vector types
typedef NConstraintInterface::SVectorNC SVectorNC;
typedef NConstraintInterface::SMatrixNC SMatrixNC;
typedef gmm::wsvector<double> SVectorNP;
typedef NProblemGmmInterface::SMatrixNP SMatrixNP;
typedef gmm::array1D_reference< double* > VectorPT;
typedef gmm::array1D_reference< const double* > VectorPTC;
typedef gmm::array1D_reference< Index* > VectorPTi;
typedef gmm::array1D_reference< const Index* > VectorPTCi;
typedef gmm::linalg_traits<SVectorNP>::const_iterator SVectorNP_citer;
typedef gmm::linalg_traits<SVectorNP>::iterator SVectorNP_iter;
/** default constructor */
NProblemGmmIPOPT(NProblemGmmInterface* _problem, std::vector<NConstraintInterface*>& _constraints)
: problem_(_problem), constraints_(_constraints), nnz_jac_g_(0), nnz_h_lag_(0)
{}
/** default destructor */
virtual ~NProblemGmmIPOPT() {};
/**@name Overloaded from TNLP */
//@{
/** Method to return some info about the nlp */
virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
Index& nnz_h_lag, IndexStyleEnum& index_style);
/** Method to return the bounds for my problem */
virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
Index m, Number* g_l, Number* g_u);
/** Method to return the starting point for the algorithm */
virtual bool get_starting_point(Index n, bool init_x, Number* x,
bool init_z, Number* z_L, Number* z_U,
Index m, bool init_lambda,
Number* lambda);
/** Method to return the objective value */
virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value);
/** Method to return the gradient of the objective */
virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f);
/** Method to return the constraint residuals */
virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g);
/** Method to return:
* 1) The structure of the jacobian (if "values" is NULL)
* 2) The values of the jacobian (if "values" is not NULL)
*/
virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
Index m, Index nele_jac, Index* iRow, Index *jCol,
Number* values);
/** Method to return:
* 1) The structure of the hessian of the lagrangian (if "values" is NULL)
* 2) The values of the hessian of the lagrangian (if "values" is not NULL)
*/
virtual bool eval_h(Index n, const Number* x, bool new_x,
Number obj_factor, Index m, const Number* lambda,
bool new_lambda, Index nele_hess, Index* iRow,
Index* jCol, Number* values);
//@}
/** @name Solution Methods */
//@{
/** This method is called when the algorithm is complete so the TNLP can store/write the solution */
virtual void finalize_solution(SolverReturn status,
Index n, const Number* x, const Number* z_L, const Number* z_U,
Index m, const Number* g, const Number* lambda,
Number obj_value,
const IpoptData* ip_data,
IpoptCalculatedQuantities* ip_cq);
//@}
private:
/**@name Methods to block default compiler methods.
* The compiler automatically generates the following three methods.
* Since the default compiler implementation is generally not what
* you want (for all but the most simple classes), we usually
* put the declarations of these methods in the private section
* and never implement them. This prevents the compiler from
* implementing an incorrect "default" behavior without us
* knowing. (See Scott Meyers book, "Effective C++")
*
*/
//@{
// MyNLP();
NProblemGmmIPOPT(const NProblemGmmIPOPT&);
NProblemGmmIPOPT& operator=(const NProblemGmmIPOPT&);
//@}
private:
// pointer to problem instance
NProblemGmmInterface* problem_;
// reference to constraints vector
std::vector<NConstraintInterface*>& constraints_;
int nnz_jac_g_;
int nnz_h_lag_;
// constant structure of jacobian_of_constraints and hessian_of_lagrangian
std::vector<Index> jac_g_iRow_;
std::vector<Index> jac_g_jCol_;
std::vector<Index> h_lag_iRow_;
std::vector<Index> h_lag_jCol_;
// Sparse Matrix of problem (don't initialize every time!!!)
SMatrixNP HP_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_IPOPT_AVAILABLE
//=============================================================================
#endif // ACG_IPOPTSOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,212 @@
//=============================================================================
//
// CLASS LeastSquaresProblem - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
#include "LeastSquaresProblem.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
//-----------------------------------------------------------------------------
void
LeastSquaresProblem::
add_term(NConstraintInterface* _term)
{
terms_.push_back(_term);
}
//-----------------------------------------------------------------------------
double
LeastSquaresProblem::
eval_term(const unsigned int _i, const double* _x)
{
if(_i >= terms_.size())
{
std::cerr << "ERROR: bad index in LeastSquaresProblem::eval_term" << std::endl;
return 0.0;
}
double vterm = terms_[_i]->eval_constraint(_x);
return vterm*vterm;
}
//-----------------------------------------------------------------------------
double
LeastSquaresProblem::
eval_term(const unsigned int _i)
{
if(!x_.empty())
return eval_term(_i, &(x_[0]));
else
{
std::cerr << "warning: called eval_term with zero unknowns..." << std::endl;
return 0.0;
}
}
//-----------------------------------------------------------------------------
int
LeastSquaresProblem::
n_unknowns ( )
{
return n_;
}
//-----------------------------------------------------------------------------
void
LeastSquaresProblem::
initial_x ( double* _x )
{
for( int i=0; i<this->n_unknowns(); ++i)
_x[i] = x_[i];
}
//-----------------------------------------------------------------------------
double
LeastSquaresProblem::
eval_f ( const double* _x )
{
double vtot(0.0);
for(unsigned int i=0; i<terms_.size(); ++i)
{
double vterm = terms_[i]->eval_constraint(_x);
vtot += vterm*vterm;
}
return vtot;
}
//-----------------------------------------------------------------------------
void
LeastSquaresProblem::
eval_gradient( const double* _x, double* _g)
{
// clear gradient
for( int i=0; i<this->n_unknowns(); ++i)
_g[i] = 0.0;
for(unsigned int i=0; i<terms_.size(); ++i)
{
// get local function value
double vterm = terms_[i]->eval_constraint(_x);
// get local gradient
NConstraintInterface::SVectorNC gterm;
terms_[i]->eval_gradient(_x, gterm);
// add terms to global gradient
NConstraintInterface::SVectorNC::InnerIterator v_it(gterm);
for( ; v_it; ++v_it)
{
_g[v_it.index()] += 2.0*vterm*v_it.value();
}
}
}
//-----------------------------------------------------------------------------
void
LeastSquaresProblem::
eval_hessian ( const double* _x, SMatrixNP& _H)
{
// clear old data
_H.resize(n_unknowns(), n_unknowns());
_H.setZero();
for(unsigned int i=0; i<terms_.size(); ++i)
{
// get local function value
double vterm = terms_[i]->eval_constraint(_x);
// get local gradient
NConstraintInterface::SVectorNC gterm;
terms_[i]->eval_gradient(_x, gterm);
// add terms to global gradient
NConstraintInterface::SVectorNC::InnerIterator v_it (gterm);
for( ; v_it; ++v_it)
{
NConstraintInterface::SVectorNC::InnerIterator v_it2(gterm);
for( ; v_it2; ++v_it2)
_H.coeffRef(v_it.index(), v_it2.index()) += 2.0*v_it.value()*v_it2.value();
}
NConstraintInterface::SMatrixNC Hterm;
terms_[i]->eval_hessian(_x, Hterm);
NConstraintInterface::SMatrixNC::iterator h_it = Hterm.begin();
NConstraintInterface::SMatrixNC::iterator h_end = Hterm.end();
for(; h_it != h_end; ++h_it)
_H.coeffRef(h_it.row(),h_it.col()) += 2.0*vterm*(*h_it);
}
}
//-----------------------------------------------------------------------------
void
LeastSquaresProblem::
store_result ( const double* _x )
{
for( int i=0; i<this->n_unknowns(); ++i)
x_[i] = _x[i];
}
//-----------------------------------------------------------------------------
bool
LeastSquaresProblem::
constant_hessian()
{
for(unsigned int i=0; i<terms_.size(); ++i)
{
if(!terms_[i]->is_linear())
return false;
}
return true;
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,84 @@
//=============================================================================
//
// CLASS LeastSquaresProblem
//
//=============================================================================
#ifndef COMISO_LeastSquaresProblem_HH
#define COMISO_LeastSquaresProblem_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/config.hh>
#include <CoMISo/Config/CoMISoDefines.hh>
#include <CoMISo/NSolver/NProblemInterface.hh>
#include <CoMISo/NSolver/NConstraintInterface.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class newClass newClass.hh
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT LeastSquaresProblem : public NProblemInterface
{
public:
/// Default constructor
LeastSquaresProblem(const int _n_unknowns) :n_(_n_unknowns), x_(_n_unknowns, 0.0) {}
/// Destructor
~LeastSquaresProblem() {}
void add_term(NConstraintInterface* _term);
double eval_term(const unsigned int _i, const double* _x);
double eval_term(const unsigned int _i);
// get reference to solution vector
const std::vector<double>& x() const {return x_;}
std::vector<double>& x() {return x_;}
// problem definition
virtual int n_unknowns ( );
virtual void initial_x ( double* _x );
virtual double eval_f ( const double* _x );
virtual void eval_gradient( const double* _x, double* _g);
virtual void eval_hessian ( const double* _x, SMatrixNP& _H);
virtual void store_result ( const double* _x );
// advanced properties
virtual bool constant_hessian();
private:
// #unknowns
int n_;
// current solution vector
std::vector<double> x_;
// pointer to terms
std::vector<NConstraintInterface*> terms_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_LeastSquaresProblem_HH defined
//=============================================================================

View File

@ -0,0 +1,103 @@
//=============================================================================
//
// CLASS LinearConstraint
//
//=============================================================================
#ifndef COMISO_LINEARCONSTRAINT_CC
#define COMISO_LINEARCONSTRAINT_CC
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "NConstraintInterface.hh"
#include "LinearConstraint.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== Implementation =========================================================
/// Default constructor
LinearConstraint::LinearConstraint(const ConstraintType _type) : NConstraintInterface(_type)
{}
// linear equation of the form -> coeffs_^T *x + b_=_type= 0
LinearConstraint::LinearConstraint(const SVectorNC& _coeffs, const double _b, const ConstraintType _type) : NConstraintInterface(_type)
{
coeffs_ = _coeffs;
b_ = _b;
}
/// Destructor
LinearConstraint::~LinearConstraint() {}
int LinearConstraint::n_unknowns()
{
return coeffs_.innerSize();
}
void LinearConstraint::resize(const unsigned int _n)
{
coeffs_.m_size = _n;
}
void LinearConstraint::clear()
{
coeffs_.setZero();
b_ = 0.0;
}
const LinearConstraint::SVectorNC& LinearConstraint::coeffs() const
{
return coeffs_;
}
LinearConstraint::SVectorNC& LinearConstraint::coeffs()
{
return coeffs_;
}
const double& LinearConstraint::b() const
{
return b_;
}
double& LinearConstraint::b()
{
return b_;
}
double LinearConstraint::eval_constraint ( const double* _x )
{
double v = b_;
SVectorNC::InnerIterator c_it(coeffs_);
for(; c_it; ++c_it)
v += c_it.value()*_x[c_it.index()];
return v;
}
void LinearConstraint::eval_gradient( const double* _x, SVectorNC& _g )
{
_g = coeffs_;
}
void LinearConstraint::eval_hessian ( const double* _x, SMatrixNC& _h )
{
_h.clear();
_h.resize(coeffs_.innerSize(), coeffs_.innerSize());
}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // ACG_LINEARCONSTRAINT_HH defined
//=============================================================================

View File

@ -0,0 +1,97 @@
//=============================================================================
//
// CLASS LinearConstraint
//
//=============================================================================
#ifndef COMISO_LINEARCONSTRAINT_HH
#define COMISO_LINEARCONSTRAINT_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "NConstraintInterface.hh"
#include <Eigen/StdVector>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemGmmInterface NProblemGmmInterface.hh <ACG/.../NPRoblemGmmInterface.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT LinearConstraint : public NConstraintInterface
{
public:
// sparse vector type
typedef NConstraintInterface::SVectorNC SVectorNC;
// different types of constraints
// enum ConstraintType {NC_EQUAL, NC_LESS_EQUAL, NC_GREATER_EQUAL};
/// Default constructor
LinearConstraint(const ConstraintType _type = NC_EQUAL);
// linear equation of the form -> coeffs_^T *x + b_=_type= 0
LinearConstraint(const SVectorNC& _coeffs, const double _b, const ConstraintType _type = NC_EQUAL);
/// Destructor
virtual ~LinearConstraint();
virtual int n_unknowns();
// resize coefficient vector = #unknowns
void resize(const unsigned int _n);
// clear to zero constraint 0 =_type 0
void clear();
const SVectorNC& coeffs() const;
SVectorNC& coeffs();
const double& b() const;
double& b();
virtual double eval_constraint ( const double* _x );
virtual void eval_gradient( const double* _x, SVectorNC& _g );
virtual void eval_hessian ( const double* _x, SMatrixNC& _h );
virtual bool is_linear() const { return true;}
virtual bool constant_gradient() const { return true;}
virtual bool constant_hessian () const { return true;}
// inherited from base
// virtual ConstraintType constraint_type ( ) { return type_; }
private:
// linear equation of the form -> coeffs_^T * x + b_
SVectorNC coeffs_;
double b_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
// support std vectors
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(COMISO::LinearConstraint);
//=============================================================================
#endif // ACG_LINEARCONSTRAINT_HH defined
//=============================================================================

View File

@ -0,0 +1,254 @@
//=============================================================================
//
// CLASS LinearConstraintHandlerElimination - IMPLEMENTATION TEMPLATES
//
//=============================================================================
//== INCLUDES =================================================================
#include "LinearConstraintHandlerElimination.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
void
LinearConstraintHandlerElimination::
initialize_identity(int _n)
{
n_ = _n;
n_red_ = _n;
m_ = 0;
b_.resize(n_);
gmm::resize(C_, n_, n_);
gmm::resize(Ct_, n_, n_);
gmm::clear(C_);
gmm::clear(Ct_);
for(int i=0; i<n_; ++i)
{
b_[i] = 0.0;
Ct_(i,i) = 1.0;
C_(i,i) = 1.0;
}
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
initialize( const std::vector<double>& _c)
{
if( _c.size() )
initialize( (double*) &(_c[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
initialize( double* _c)
{
// TODO
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
transform_x( const std::vector<double>& _x, std::vector<double>& _xC)
{
_xC.resize(n_red_);
if( _x.size() && _xC.size())
transform_x((double*)&(_x[0]), &(_xC[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
transform_x( double* _x, double* _xC)
{
// directly exploit orthogonality of QR-factorization
// _xC = Ct_*(_x-b_)
Vtemp_.resize(n_);
gmm::add(VectorPT(_x,n_), gmm::scaled(b_,-1.0), Vtemp_);
gmm::mult(Ct_,Vtemp_, VectorPT(_xC,n_red_));
// // set up least squares problem
// // Ct (_x - b_) = CtC _xC
//
// Vtemp_.resize(n_);
// Vtemp2_.resize(n_red_);
// gmm::add(VectorPT(_x,n_), gmm::scaled(b_,-1.0), Vtemp_);
// gmm::mult(Ct_,Vtemp_, Vtemp2_);
//
// // solve least squares problem
// if( n_red_)
// chol_CtC_.solve(_xC, (double*)(&(Vtemp2_[0])));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
inv_transform_x( const std::vector<double>& _xC, std::vector<double>& _x)
{
_x.resize(n_);
if( _x.size())
inv_transform_x( (double*)&(_xC[0]), &(_x[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
inv_transform_x( double* _xC, double* _x)
{
gmm::copy(b_, VectorPT(_x, n_));
gmm::mult_add(C_, VectorPT(_xC, n_red_), VectorPT(_x, n_));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
project_x( const std::vector<double>& _x, std::vector<double>& _xp)
{
_xp.resize(n_);
if( _x.size())
project_x((double*)&(_x[0]), &(_xp[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
project_x( double* _x, double* _xp)
{
if( n_ == n_red_) // special case of no constraints
{
// just copy
gmm::copy(VectorPT(_x, n_), VectorPT(_xp, n_));
}
else
{
Vtemp_.resize( n_red_);
transform_x (_x , &(Vtemp_[0]));
inv_transform_x( &(Vtemp_[0]), _xp );
}
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
project_dx( const std::vector<double>& _x, std::vector<double>& _xp)
{
_xp.resize(n_);
if( _x.size())
project_dx((double*)&(_x[0]), &(_xp[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
project_dx( double* _x, double* _xp)
{
if( n_ == n_red_) // special case of no constraints
{
// just copy
gmm::copy(VectorPT(_x, n_), VectorPT(_xp, n_));
}
else
{
// idea: C_ is an orthonormal basis of the kernel
// -> simply project out the non-constraint part
Vtemp_.resize( n_red_);
gmm::mult(Ct_, VectorPT(_x, n_), Vtemp_);
gmm::mult(C_, Vtemp_, VectorPT(_xp, n_));
// // check result
// std::cerr << "check result..." << std::endl;
// Vtemp_.resize(b_orig_.size());
// gmm::mult(A_orig_, VectorPT(_xp, n_), Vtemp_);
//// gmm::add(gmm::scaled(b_orig_, -1.0), Vtemp_);
// std::cerr << "check constraint update... " << gmm::vect_norm2(Vtemp_) << std::endl;
//
//// std::cerr << "check constraint update... " << COMISO_GMM::residuum_norm<RMatrix,std::vector<double> >(A_orig_,Vtemp_, b_orig_) << std::endl;
}
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
transform_gradient( const std::vector<double>& _g, std::vector<double>& _gC)
{
_gC.resize(n_red_);
if( _g.size() && _gC.size())
transform_gradient( (double*)&(_g[0]), &(_gC[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
transform_gradient( double* _g, double* _gC)
{
gmm::mult( Ct_, VectorPT(_g, n_), VectorPT(_gC, n_red_));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerElimination::
transform_hessian( const RMatrix& _H, RMatrix& _HC)
{
// resize and clear matrix
gmm::resize(_HC, n_red_, n_red_);
gmm::clear(_HC);
gmm::resize(Mtemp_, n_, n_red_);
gmm::mult(_H,C_, Mtemp_);
gmm::mult(Ct_, Mtemp_, _HC);
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,134 @@
//=============================================================================
//
// CLASS LinearConstraintHandlerElimination
//
//=============================================================================
#ifndef COMISO_LINEARCONSTRAINTHANDLERELIMINATION_HH
#define COMISO_LINEARCONSTRAINTHANDLERELIMINATION_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <iostream>
#include <gmm/gmm.h>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class LinearConstraintHandler LinearConstraintHandler.hh <ACG/.../LinearConstraintHandler.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT LinearConstraintHandlerElimination
{
public:
typedef gmm::col_matrix< gmm::wsvector< double> > CMatrix;
typedef gmm::row_matrix< gmm::wsvector< double> > RMatrix;
// use c-arrays as vectors for gmm
typedef gmm::array1D_reference<double*> VectorPT;
/// Constructor
LinearConstraintHandlerElimination() {initialize_identity(0);}
// initialize Constructor
template<class MatrixT, class VectorT>
LinearConstraintHandlerElimination( const MatrixT& _C, const VectorT& _c)
{initialize(_C, _c); }
/// Destructor
~LinearConstraintHandlerElimination() {}
// number of variables
int n() {return n_;}
// number of reduced variables (after elimination)
int n_reduced() {return n_red_;}
// number of linearly independent constraints (n-n_reduced)
int n_constraints() { return m_;}
// initialize new constraints
template<class MatrixT, class VectorT>
void initialize( const MatrixT& _C, const VectorT& _c);
// no constraints
void initialize_identity(int _n);
// initialize new constraints rhs only
void initialize( const std::vector<double>& _c);
void initialize( double* _c);
// transform x vector (least squares solution, fulfilling the constraints)
void transform_x( const std::vector<double>& _x, std::vector<double>& _xC);
void transform_x( double* _x, double* _xC);
// inverse transform x ( x_reduced -> x)
void inv_transform_x( const std::vector<double>& _xC, std::vector<double>& _x);
void inv_transform_x( double* _xC, double* _x);
// project x to closest one fullfilling the constraints: inv_transform_x(transform_x(x))
void project_x( const std::vector<double>& _x, std::vector<double>& _xp);
void project_x( double* _x, double* _xp);
// project dx to closest one that A(x0+dx) = b
void project_dx( const std::vector<double>& _x, std::vector<double>& _xp);
void project_dx( double* _x, double* _xp);
// transform gradient
void transform_gradient( const std::vector<double>& _g, std::vector<double>& _gC);
void transform_gradient( double* _g, double* _gC);
// transform hessian
void transform_hessian( const RMatrix& _H, RMatrix& _HC);
private:
// Constraints in basis transformation form x_orig = b_ + C_*x_reduced
// notice that C_ is a basis of the nullspace of the constraints
RMatrix C_;
RMatrix Ct_;
std::vector<double> b_;
// number of variables
int n_;
// number of constraints (linear independent)
int m_;
// number of reduced variables
int n_red_;
// temp matrix to transform hessian and temp vectors
RMatrix Mtemp_;
std::vector<double> Vtemp_;
// hack -> store initial linear system
RMatrix A_orig_;
std::vector<double> b_orig_;
};
//=============================================================================
} // namespace ACG
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_LINEARCONSTRAINTHANDLERELIMINATION_C)
#define COMISO_LINEARCONSTRAINTHANDLERELIMINATION_TEMPLATES
#include "LinearConstraintHandlerEliminationT.cc"
#endif
//=============================================================================
#endif // COMISO_LINEARCONSTRAINTHANDLERELIMINATION_HH defined
//=============================================================================

View File

@ -0,0 +1,112 @@
//=============================================================================
//
// CLASS LinearConstraintHandlerElimination - IMPLEMENTATION
//
//=============================================================================
#define COMISO_LINEARCONSTRAINTHANDLERELIMINATION_C
//== INCLUDES =================================================================
#include "LinearConstraintHandlerElimination.hh"
#include <CoMISo/Solver/SparseQRSolver.hh>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
template<class MatrixT, class VectorT>
void
LinearConstraintHandlerElimination::
initialize( const MatrixT& _C, const VectorT& _c)
{
// no constraints?
if( gmm::mat_nrows(_C) == 0)
{
initialize_identity( gmm::mat_ncols(_C));
}
else
{
// require SPQR SOLVER!!!
#if(COMISO_SUITESPARSE_SPQR_AVAILABLE)
// Construct constraints basis form via QR-factorization (see Nocedal 426...)
// Constraints in basis transformation form x_orig = b_ + C_*x_reduced
// notice that C_ is a basis of the nullspace of the constraints
// and _C*b_ = _c (means b_ is one solution of the constraints)
std::cerr << "Initialize Linear Constraint handler...\n";
COMISO::SparseQRSolver sqr;
// sqr.calc_system_gmm(_C);
CMatrix Q;
CMatrix R;
std::vector<int> P;
int rank = sqr.factorize_system_gmm(gmm::transposed(_C), Q, R, P);
// Q[0..m-1,rank..m-1] is basis of the nullspace -> C_, Ct_
int m = gmm::mat_nrows(Q);
gmm::resize(C_, m, m-rank);
gmm::clear (C_);
gmm::copy( gmm::sub_matrix(Q, gmm::sub_interval(0,m), gmm::sub_interval(rank,m-rank)), C_);
gmm::resize(Ct_, gmm::mat_ncols(C_), gmm::mat_nrows(C_));
gmm::copy( gmm::transposed(C_), Ct_);
// compute b_
b_.resize(gmm::mat_ncols(_C));
// hack (too expensive, directly exploit Q,R,P from above)
sqr.calc_system_gmm(_C);
sqr.solve(b_, _c);
n_ = gmm::mat_nrows(C_);
n_red_ = gmm::mat_ncols(C_);
m_ = n_ - n_red_;
// hack -> store initial system
if(0)
{
gmm::resize(A_orig_, gmm::mat_nrows(_C), gmm::mat_ncols(_C));
gmm::resize(b_orig_, _c.size());
gmm::copy(_C, A_orig_);
gmm::copy(_c, b_orig_);
}
// RMatrix CtC(n_red_, n_red_);
// gmm::mult(Ct_,C_, CtC);
// std::cerr << "CtC\n";
// std::cerr << CtC << std::endl;
/*
// set up least squares problem
gmm::resize(Mtemp_, gmm::mat_ncols(C_), gmm::mat_ncols(C_));
gmm::mult(Ct_, C_, Mtemp_);
chol_CtC_.calc_system_gmm(Mtemp_);
*/
// std::cerr << "Q: " << Q << std::endl;
// std::cerr << "R: " << R << std::endl;
// std::cerr << "P: " << P << std::endl;
// std::cerr << "C_:" << C_ << std::endl;
// std::cerr << "b_:" << b_ << std::endl;
//
// std::cerr << "#rows: " << gmm::mat_nrows(_C) << std::endl;
// std::cerr << "#nullspace: " << m << std::endl;
// std::cerr << "rank: " << rank << std::endl;
// std::cerr << "dim Q = " << gmm::mat_nrows(Q) << " x " << gmm::mat_ncols(Q) << std::endl;
// std::cerr << "dim R = " << gmm::mat_nrows(R) << " x " << gmm::mat_ncols(R) << std::endl;
#else
std::cerr << "ERROR: SQPR-Solver required by LinearConstraintHandlerElimination not available !!!" << std::endl;
#endif
}
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,131 @@
//=============================================================================
//
// CLASS LinearConstraintHandlerPenalty - IMPLEMENTATION TEMPLATES
//
//=============================================================================
//== INCLUDES =================================================================
#include "LinearConstraintHandlerPenalty.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
/// Constructor
LinearConstraintHandlerPenalty::LinearConstraintHandlerPenalty() : penalty_(10000) {}
//-----------------------------------------------------------------------------
/// Destructor
LinearConstraintHandlerPenalty::~LinearConstraintHandlerPenalty()
{}
//-----------------------------------------------------------------------------
// penalty weight
double& LinearConstraintHandlerPenalty::penalty()
{ return penalty_; }
//-----------------------------------------------------------------------------
// number of variables
int LinearConstraintHandlerPenalty::n()
{return n_;}
//-----------------------------------------------------------------------------
// number of linearly independent constraints (n-n_reduced)
int LinearConstraintHandlerPenalty::n_constraints()
{ return m_;}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerPenalty::
initialize( const std::vector<double>& _c)
{
if( _c.size() )
initialize( (double*) &(_c[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerPenalty::
initialize( double* _c)
{
for(unsigned int i=0; i<b_.size(); ++i)
b_[i] = _c[i];
penalty_grad_b_.resize(n_);
gmm::mult(gmm::transposed(C_), b_, penalty_grad_b_);
gmm::scale(penalty_grad_b_, -2.0*penalty_);
}
//-----------------------------------------------------------------------------
double
LinearConstraintHandlerPenalty::
add_penalty_f( double* _x, const double _f)
{
temp_.resize(b_.size());
gmm::mult(C_, VectorPT(_x, n_), temp_);
gmm::add(gmm::scaled(b_, -1.0), temp_);
double fp = ( penalty_* (gmm::vect_sp(temp_, temp_)) );
return _f + fp;
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerPenalty::
add_penalty_gradient( const std::vector<double>& _x, std::vector<double>& _g)
{
_g.resize(n_);
if( _x.size() && _g.size())
add_penalty_gradient( (double*)&(_x[0]), &(_g[0]));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerPenalty::
add_penalty_gradient( double* _x, double* _g)
{
gmm::add( penalty_grad_b_, VectorPT(_g, n_));
gmm::mult_add(penalty_H_, VectorPT(_x, n_), VectorPT(_g, n_));
}
//-----------------------------------------------------------------------------
void
LinearConstraintHandlerPenalty::
add_penalty_hessian( RMatrix& _H)
{
gmm::add(penalty_H_, _H);
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,115 @@
//=============================================================================
//
// CLASS LinearConstraintHandlerElimination
//
//=============================================================================
#ifndef COMISO_LINEARCONSTRAINTHANDLERPENALTY_HH
#define COMISO_LINEARCONSTRAINTHANDLERPENALTY_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <iostream>
#include <gmm/gmm.h>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class LinearConstraintHandler LinearConstraintHandler.hh <ACG/.../LinearConstraintHandler.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT LinearConstraintHandlerPenalty
{
public:
typedef gmm::col_matrix< gmm::wsvector< double> > CMatrix;
typedef gmm::row_matrix< gmm::wsvector< double> > RMatrix;
// use c-arrays as vectors for gmm
typedef gmm::array1D_reference<double*> VectorPT;
/// Constructor
LinearConstraintHandlerPenalty();
// initialize Constructor
template<class MatrixT, class VectorT>
LinearConstraintHandlerPenalty( const MatrixT& _C, const VectorT& _c);
/// Destructor
~LinearConstraintHandlerPenalty();
// penalty weight
double& penalty();
// number of variables
int n();
// number of linearly independent constraints (n-n_reduced)
int n_constraints();
// initialize new constraints
template<class MatrixT, class VectorT>
void initialize( const MatrixT& _C, const VectorT& _c);
// initialize new constraints rhs only
void initialize( const std::vector<double>& _c);
void initialize( double* _c);
// transform energy
double add_penalty_f( double* _x, const double _f);
// transform gradient
void add_penalty_gradient( const std::vector<double>& _x, std::vector<double>& _g);
void add_penalty_gradient( double* _x, double* _g);
// transform hessian
void add_penalty_hessian( RMatrix& _H);
private:
// penalty weight
double penalty_;
// Linear Constraints C_*x_ = b_
RMatrix C_;
std::vector<double> b_;
// precomputed penalty terms
RMatrix penalty_H_;
std::vector<double> penalty_grad_b_;
// temp vector
std::vector<double> temp_;
// number of variables
int n_;
// number of constraints (linear independent)
int m_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(ACG_LINEARCONSTRAINTHANDLERPENALTY_C)
#define ACG_LINEARCONSTRAINTHANDLERPENALTY_TEMPLATES
#include "LinearConstraintHandlerPenaltyT.cc"
#endif
//=============================================================================
#endif // ACG_LINEARCONSTRAINTHANDLERPENALTY_HH defined
//=============================================================================

View File

@ -0,0 +1,59 @@
//=============================================================================
//
// CLASS LinearConstraintHandlerPenalty - IMPLEMENTATION
//
//=============================================================================
#define COMISO_LINEARCONSTRAINTHANDLERPENALTY_C
//== INCLUDES =================================================================
#include "LinearConstraintHandlerPenalty.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
// initialize Constructor
template<class MatrixT, class VectorT>
LinearConstraintHandlerPenalty::LinearConstraintHandlerPenalty( const MatrixT& _C, const VectorT& _c) :
penalty_(10000)
{initialize(_C, _c); }
template<class MatrixT, class VectorT>
void
LinearConstraintHandlerPenalty::
initialize( const MatrixT& _C, const VectorT& _c)
{
gmm::resize(C_, gmm::mat_nrows(_C), gmm::mat_ncols(_C));
gmm::copy(_C,C_);
b_ = _c;
n_ = gmm::mat_ncols(_C);
m_ = b_.size();
// initialize penalty stuff
// penalty_H_ = 2*penalty*A^t A
// penalty_grad_b_ = -2*penalty*A^t b
gmm::resize(penalty_H_, n_, n_);
gmm::clear(penalty_H_);
RMatrix temp(n_,m_);
gmm::copy( gmm::transposed(C_), temp);
gmm::mult( temp,C_, penalty_H_);
gmm::scale(penalty_H_, 2.0*penalty_);
penalty_grad_b_.clear();
penalty_grad_b_.resize(n_);
gmm::mult(gmm::transposed(C_), b_, penalty_grad_b_);
gmm::scale(penalty_grad_b_, -2.0*penalty_);
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,113 @@
//=============================================================================
//
// CLASS NConstraintInterface
//
//=============================================================================
#ifndef COMISO_NCONSTRAINTINTERFACE_HH
#define COMISO_NCONSTRAINTINTERFACE_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_EIGEN3_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "SuperSparseMatrixT.hh"
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemGmmInterface NProblemGmmInterface.hh <ACG/.../NPRoblemGmmInterface.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT NConstraintInterface
{
public:
// define Sparse Datatypes
typedef Eigen::SparseVector<double> SVectorNC;
typedef SuperSparseMatrixT<double> SMatrixNC;
// different types of constraints
enum ConstraintType {NC_EQUAL, NC_LESS_EQUAL, NC_GREATER_EQUAL};
/// Default constructor
NConstraintInterface(const ConstraintType _type = NC_EQUAL, double _eps = 1e-6) : type_(_type) {}
/// Destructor
virtual ~NConstraintInterface() {}
virtual int n_unknowns ( ) = 0;
virtual double eval_constraint ( const double* _x ) = 0;
virtual void eval_gradient ( const double* _x, SVectorNC& _g ) = 0;
virtual void eval_hessian ( const double* _x, SMatrixNC& _h ) = 0;
virtual ConstraintType& constraint_type ( ) { return type_; }
virtual bool is_satisfied ( const double* _x, double _eps = 1e-6)
{
switch( type_)
{
case NC_EQUAL : return (fabs(eval_constraint(_x)) <= _eps); break;
case NC_LESS_EQUAL : return ( eval_constraint(_x) <= _eps); break;
case NC_GREATER_EQUAL: return ( eval_constraint(_x) >= -_eps); break;
}
return false;
}
// provide special properties
virtual bool is_linear() const { return false;}
virtual bool constant_gradient() const { return false;}
virtual bool constant_hessian () const { return false;}
virtual double gradient_update_factor( const double* _x, double _eps = 1e-6)
{
double val = eval_constraint(_x);
bool upper_bound_ok = ( val <= _eps);
bool lower_bound_ok = ( val >= -_eps);
if(upper_bound_ok)
{
if(lower_bound_ok || type_ == NC_LESS_EQUAL) return 0.0;
else return 1.0;
}
else
{
if(lower_bound_ok && type_ == NC_GREATER_EQUAL) return 0.0;
else return -1.0;
}
}
private:
// constraint type
ConstraintType type_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================
#endif // ACG_NCONSTRAINTINTERFACE_HH defined
//=============================================================================

View File

@ -0,0 +1,330 @@
//=============================================================================
//
// CLASS NConstraintInterfaceAD
//
//=============================================================================
#ifndef COMISO_NCONSTRAINTINTERFACEAD_HH
#define COMISO_NCONSTRAINTINTERFACEAD_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_ADOLC_AVAILABLE
#if COMISO_EIGEN3_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "SuperSparseMatrixT.hh"
#include <boost/shared_array.hpp>
#include <adolc/adolc.h>
#include <adolc/adouble.h>
#include <adolc/drivers/drivers.h>
#include <adolc/sparse/sparsedrivers.h>
#include <adolc/taping.h>
#include "NConstraintInterface.hh"
#include "NProblemInterfaceAD.hpp"
#include "TapeIDSingleton.hh"
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemInterfaceAD NProblemInterfaceAD.hpp
The problem interface using automatic differentiation.
*/
class COMISODLLEXPORT NConstraintInterfaceAD : public NConstraintInterface {
public:
// Define Sparse Datatypes
typedef NConstraintInterface::SVectorNC SVectorNC;
typedef NConstraintInterface::SMatrixNC SMatrixNC;
typedef NConstraintInterface::ConstraintType ConstraintType;
/// Default constructor
NConstraintInterfaceAD(NProblemInterfaceAD& _problem, int _n_unknowns,
const ConstraintType _type = NC_EQUAL, double _eps = 1e-6) :
NConstraintInterface(_type, _eps),
problem_(_problem),
n_unknowns_(_n_unknowns),
type_(_type),
function_evaluated_(false),
use_tape_(true),
constant_hessian_evaluated_(false),
tape_(static_cast<short int>(TapeIDSingleton::Instance()->requestId())) {
for(size_t i = 0; i < 11; ++i) tape_stats_[i] = 0;
}
/// Destructor
virtual ~NConstraintInterfaceAD() {
TapeIDSingleton::Instance()->releaseId(static_cast<size_t>(tape_));
}
/**
* \brief Only override this function
*/
virtual adouble evaluate(const adouble* _x) = 0;
public:
virtual int n_unknowns() {
return n_unknowns_;
}
virtual double eval_constraint(const double* _x) {
double y = 0.0;
if(!function_evaluated_ || !use_tape_) {
adouble y_d = 0.0;
boost::shared_array<adouble> x_d_ptr = problem_.x_d_ptr();
trace_on(tape_); // Start taping
// Fill data vector
for(int i = 0; i < n_unknowns_; ++i) {
x_d_ptr[i] <<= _x[i];
}
// Call virtual function to compute
// functional value
y_d = evaluate(x_d_ptr.get());
y_d >>= y;
trace_off();
#ifdef ADOLC_STATS
tapestats(tape_, tape_stats_);
std::cout << "Status values for tape " << tape_ << std::endl;
std::cout << "===============================================" << std::endl;
std::cout << "Number of independent variables:\t" << tape_stats_[0] << std::endl;
std::cout << "Number of dependent variables:\t\t" << tape_stats_[1] << std::endl;
std::cout << "Max. number of live active variables:\t" << tape_stats_[2] << std::endl;
std::cout << "Size of value stack:\t\t\t" << tape_stats_[3] << std::endl;
std::cout << "Buffer size:\t\t\t\t" << tape_stats_[4] << std::endl;
std::cout << "Total number of operations recorded:\t" << tape_stats_[5] << std::endl;
std::cout << "Other stats [6]:\t\t\t" << tape_stats_[6] << std::endl;
std::cout << "Other stats [7]:\t\t\t" << tape_stats_[7] << std::endl;
std::cout << "Other stats [8]:\t\t\t" << tape_stats_[8] << std::endl;
std::cout << "Other stats [9]:\t\t\t" << tape_stats_[9] << std::endl;
std::cout << "Other stats [10]:\t\t\t" << tape_stats_[10] << std::endl;
std::cout << "===============================================" << std::endl;
#endif
function_evaluated_ = true;
} else {
double ay[1] = {0.0};
int ec = function(tape_, 1, n_unknowns_, const_cast<double*>(_x), ay);
#ifdef ADOLC_RET_CODES
std::cout << "Info: function() returned code " << ec << std::endl;
#endif
y = ay[0];
}
return y;
}
virtual void eval_gradient(const double* _x, SVectorNC& _g) {
if(!function_evaluated_ || !use_tape_) {
// Evaluate original functional
eval_constraint(_x);
}
boost::shared_array<double> grad_p = problem_.grad_ptr();
_g.resize(n_unknowns_);
_g.setZero();
int ec = gradient(tape_, n_unknowns_, _x, grad_p.get());
if(ec < 0) {
// Retape function if return code indicates discontinuity
function_evaluated_ = false;
#ifdef ADOLC_RET_CODES
std::cout << __FUNCTION__ << " invokes retaping of function due to discontinuity! Return code: " << ec << std::endl;
#endif
eval_constraint(_x);
ec = gradient(tape_, n_unknowns_, _x, grad_p.get());
}
#ifdef ADOLC_RET_CODES
std::cout << "Info: gradient() returned code " << ec << std::endl;
#endif
for(int i = 0; i < n_unknowns_; ++i) {
_g.coeffRef(i) = grad_p[i];
}
}
virtual void eval_hessian(const double* _x, SMatrixNC& _H) {
_H.resize(n_unknowns_, n_unknowns_);
if(constant_hessian() && constant_hessian_evaluated_) {
_H = constant_hessian_;
return;
}
if(!function_evaluated_ || !use_tape_) {
// Evaluate original functional
eval_constraint(_x);
}
if(sparse_hessian()) {
int nz = 0;
int opt[2] = {0, 0};
unsigned int* r_ind = NULL;
unsigned int* c_ind = NULL;
double* val = NULL;
int ec = sparse_hess(tape_, n_unknowns_, 0, _x, &nz, &r_ind, &c_ind, &val, opt);
if(ec < 0) {
// Retape function if return code indicates discontinuity
function_evaluated_ = false;
#ifdef ADOLC_RET_CODES
std::cout << __FUNCTION__ << " invokes retaping of function due to discontinuity! Return code: " << ec << std::endl;
#endif
eval_constraint(_x);
ec = sparse_hess(tape_, n_unknowns_, 0, _x, &nz, &r_ind, &c_ind, &val, opt);
}
assert(*nz >= 0);
assert(r_ind != NULL);
assert(c_ind != NULL);
assert(val != NULL);
#ifdef ADOLC_RET_CODES
std::cout << "Info: sparse_hessian() returned code " << ec << std::endl;
#endif
for(int i = 0; i < nz; ++i) {
_H(r_ind[i], c_ind[i]) = val[i];
}
if(constant_hessian()) {
constant_hessian_ = _H;
constant_hessian_evaluated_ = true;
}
delete[] r_ind;
delete[] c_ind;
delete[] val;
} else {
double** h_ptr = problem_.dense_hessian_ptr();
int ec = hessian(tape_, n_unknowns_, const_cast<double*>(_x), h_ptr);
if(ec < 0) {
// Retape function if return code indicates discontinuity
function_evaluated_ = false;
#ifdef ADOLC_RET_CODES
std::cout << __FUNCTION__ << " invokes retaping of function due to discontinuity! Return code: " << ec << std::endl;
#endif
eval_constraint(_x);
ec = hessian(tape_, n_unknowns_, const_cast<double*>(_x), h_ptr);
}
#ifdef ADOLC_RET_CODES
std::cout << "Info: hessian() returned code " << ec << std::endl;
#endif
for(int i = 0; i < n_unknowns_; ++i) {
for(int j = 0; j <= i; ++j) {
_H(i, j) = h_ptr[i][j];
if(i != j) {
_H(j, i) = h_ptr[i][j];
}
}
}
if(constant_hessian()) {
constant_hessian_ = _H;
constant_hessian_evaluated_ = true;
}
}
}
/** \brief Use tape
* Set this to false if the energy functional
* is discontinuous (so that the operator tree
* has to be re-established at each evaluation)
*/
bool use_tape() const {
return use_tape_;
}
void use_tape(bool _b) {
use_tape_ = _b;
}
/**
* \brief Indicate whether the hessian is sparse.
* If so, the computations (as well as the memory
* consumption) can be performed more efficiently.
*/
virtual bool sparse_hessian() {
return false;
}
private:
// Reference to associated objective function
NProblemInterfaceAD& problem_;
// Number of unknowns
int n_unknowns_;
// Constraint type
ConstraintType type_;
size_t tape_stats_[11];
bool function_evaluated_;
bool use_tape_;
SMatrixNC constant_hessian_;
bool constant_hessian_evaluated_;
const short int tape_;
};
//=============================================================================
}// namespace COMISO
//=============================================================================
#endif // COMISO_ADOLC_AVAILABLE
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================
#endif // ACG_NCONSTRAINTINTERFACEAD_HH defined
//=============================================================================

View File

@ -0,0 +1,223 @@
//=============================================================================
//
// CLASS NPDERIVATIVECHECKER
//
//=============================================================================
#ifndef COMISO_NPDERIVATIVECHECKER_HH
#define COMISO_NPDERIVATIVECHECKER_HH
//== INCLUDES =================================================================
#include "NProblemGmmInterface.hh"
#include "NProblemInterface.hh"
#include <iostream>
#include <iomanip>
#include <limits>
#include <cmath>
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <CoMISo/Config/CoMISoDefines.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NPDerivativeChecker
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT NPDerivativeChecker
{
public:
struct Config
{
Config() : x_min(-1.0), x_max(1.0), n_iters(1), dx(1e-5), eps(1e-3), relativeEps(std::numeric_limits<double>::quiet_NaN())
{}
double x_min;
double x_max;
int n_iters;
double dx;
double eps;
double relativeEps;
};
/// Default constructor
NPDerivativeChecker() {}
/// Destructor
~NPDerivativeChecker() {}
template<class ProblemInterface>
bool check_all(ProblemInterface* _np, double _dx, double _eps)
{
conf_.dx = _dx;
conf_.eps = _eps;
return check_all(_np);
}
template<class ProblemInterface>
bool check_all(ProblemInterface* _np)
{
bool d1_ok = check_d1(_np);
bool d2_ok = check_d2(_np);
return ( d1_ok && d2_ok);
}
template<class ProblemInterface>
bool check_d1(ProblemInterface* _np)
{
int n_ok = 0;
int n_errors = 0;
int n = _np->n_unknowns();
std::vector<double> x(n), g(n);
for(int i=0; i<conf_.n_iters; ++i)
{
// get random x
get_random_x(x, conf_.x_min, conf_.x_max);
// gradient
_np->eval_gradient(P(x), P(g));
for(int j=0; j<n; ++j)
{
// double fd = finite_difference(_np, x, j);
x[j] += conf_.dx;
double f1 = _np->eval_f(P(x));
x[j] -= 2.0*conf_.dx;
double f0 = _np->eval_f(P(x));
x[j] += conf_.dx;
double fd = (f1-f0)/(2.0*conf_.dx);
if ((!std::isnan(conf_.relativeEps) && fabs(fd-g[j]) > fmax(fabs(g[j]), 1.0) * conf_.relativeEps) || fabs(fd-g[j]) > conf_.eps)
{
++ n_errors;
std::cerr << "Gradient error in component " << j << ": " << g[j]
<< " should be " << fd << " (" << fabs(fd-g[j]) << ")" << std::endl;
}
else ++ n_ok;
}
}
std::cerr << "############## Gradient Checker Summary #############\n";
std::cerr << "#ok : " << n_ok << std::endl;
std::cerr << "#error: " << n_errors << std::endl;
return (n_errors == 0);
}
template<class MatrixType>
inline double getCoeff(const MatrixType &m, int r, int c);
template<class ProblemInterface>
bool check_d2(ProblemInterface* _np)
{
int n_ok = 0;
int n_errors = 0;
int n = _np->n_unknowns();
std::vector<double> x(n);
typename ProblemInterface::SMatrixNP H(n,n);
for(int i=0; i<conf_.n_iters; ++i)
{
// get random x
get_random_x(x, conf_.x_min, conf_.x_max);
// gradient
_np->eval_hessian(P(x), H);
for(int j=0; j<n; ++j)
for(int k=0; k<n; ++k)
{
x[j] += conf_.dx;
x[k] += conf_.dx;
double f0 = _np->eval_f(P(x));
x[j] -= 2.0*conf_.dx;
double f1 = _np->eval_f(P(x));
x[j] += 2.0*conf_.dx;
x[k] -= 2.0*conf_.dx;
double f2 = _np->eval_f(P(x));
x[j] -= 2.0*conf_.dx;
double f3 = _np->eval_f(P(x));
double fd = (f0-f1-f2+f3)/(4.0*conf_.dx*conf_.dx);
if ((!std::isnan(conf_.relativeEps) && fabs(fd-H.coeff(j,k)) > fmax(fabs(getCoeff(H, j,k)), 1.0) * conf_.relativeEps) || fabs(fd-getCoeff(H, j,k)) > conf_.eps)
{
++ n_errors;
std::cerr << "Hessian error in component " << j << "," << k << ": " << getCoeff(H, j,k)
<< " should be (following FiniteDifferences) " << fd
<< " (absolute delta: " << fabs(fd-getCoeff(H, j,k))
<< ", relative delta:" << (fabs(fd-getCoeff(H, j,k))/fmax(fabs(getCoeff(H, j,k)), 1.0)) << ")" << std::endl;
}
else ++ n_ok;
}
}
std::cerr << "############## Hessian Checker Summary #############\n";
std::cerr << "#ok : " << n_ok << std::endl;
std::cerr << "#error: " << n_errors << std::endl;
return (n_errors == 0);
}
Config& config() { return conf_; }
protected:
void get_random_x(std::vector<double>& _x, double _xmin, double _xmax)
{
// get random values in [-1,1]
gmm::fill_random(_x);
double range = _xmax - _xmin;
for(unsigned int i=0; i<_x.size(); ++i)
_x[i] = (((_x[i]+1.0)/2.0)*range + _xmin);
}
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
Config conf_;
};
template<>
inline double NPDerivativeChecker::getCoeff(const NProblemInterface::SMatrixNP &m, int r, int c) {
return m.coeff(r, c);
}
template<>
inline double NPDerivativeChecker::getCoeff(const NProblemGmmInterface::SMatrixNP &m, int r, int c) {
return m(r, c);
}
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // ACG_NPDERIVATIVECHECKER defined
//=============================================================================

View File

@ -0,0 +1,167 @@
//=============================================================================
//
// CLASS NPLinearConstraints
//
//=============================================================================
//== INCLUDES =================================================================
#include "NPLinearConstraints.hh"
#include "NProblemGmmInterface.hh"
#include "LinearConstraintHandlerElimination.hh"
#include "LinearConstraintHandlerPenalty.hh"
//#include "LinearConstraintHandlerLagrange.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/// Default constructor having a pointer to the main problem
NPLinearConstraintsElimination::NPLinearConstraintsElimination( NProblemGmmInterface* _np) : base_(_np), cache_initialized_(false)
{
if( !base_) std::cerr << "Warning: initialized NPLinearConstraints with zero pointer...\n";
this->initialize_identity(base_->n_unknowns());
}
/// Destructor
NPLinearConstraintsElimination::~NPLinearConstraintsElimination() {}
// NSolverInterface
int NPLinearConstraintsElimination::n_unknowns ()
{ return this->n_reduced(); }
void NPLinearConstraintsElimination::initial_x ( double* _x )
{
// transform initial x from parent NP
x_.resize(this->n());
base_->initial_x(P(x_));
this->transform_x(P(x_), _x);
cache_initialized_ = false;
update_x(_x);
}
double NPLinearConstraintsElimination::eval_f( const double* _x )
{
update_x(_x);
return base_->eval_f(P(x_));
}
void NPLinearConstraintsElimination::eval_gradient( const double* _x, double* _g)
{
update_x(_x);
vtemp_.resize(this->n());
base_->eval_gradient( P(x_), P(vtemp_));
this->transform_gradient( P(vtemp_), _g);
}
void NPLinearConstraintsElimination::eval_hessian ( const double* _x, SMatrixNP& _H)
{
update_x(_x);
SMatrixNP H;
base_->eval_hessian(P(x_), H);
this->transform_hessian(H,_H);
}
void NPLinearConstraintsElimination::store_result ( const double* _x )
{
update_x(_x);
base_->store_result( P(x_));
}
void NPLinearConstraintsElimination::update_x(const double* _xr)
{
if(!cache_initialized_)
{
x_.resize(this->n());
xr_.resize(this->n_reduced());
if(!xr_.empty())
xr_[0] = _xr[0] + 1.0;
else
{
x_.resize(this->n());
this->inv_transform_x(xr_, x_);
cache_initialized_ = true;
}
}
for( int i=0; i<this->n_reduced(); ++i)
if( _xr[i] != xr_[i])
{
gmm::copy( VectorPT((double*)_xr, this->n_reduced()), this->xr_);
x_.resize(this->n());
this->inv_transform_x(xr_, x_);
cache_initialized_ = true;
//quit
return;
}
}
// convert vector into pointer
double* NPLinearConstraintsElimination::P(const std::vector<double>& _v)
{
if(_v.size())
return (double*) (&(_v[0]));
else
return 0;
}
//=============================================================================
/// Default constructor having a pointer to the main problem
NPLinearConstraintsPenalty::NPLinearConstraintsPenalty( NProblemGmmInterface* _np) : base_(_np)
{ if( !base_) std::cerr << "Warning: initialized NPLinearConstraints with zero pointer...\n"; }
/// Destructor
NPLinearConstraintsPenalty::~NPLinearConstraintsPenalty()
{}
// NSolverInterface
int NPLinearConstraintsPenalty::n_unknowns ()
{ return base_->n_unknowns(); }
void NPLinearConstraintsPenalty::initial_x ( double* _x )
{
base_->initial_x(_x);
}
double NPLinearConstraintsPenalty::eval_f( const double* _x )
{
return this->add_penalty_f((double*)_x, base_->eval_f(_x));
}
void NPLinearConstraintsPenalty::eval_gradient( const double* _x, double* _g)
{
base_->eval_gradient( _x, _g);
this->add_penalty_gradient((double*)_x, _g);
}
void NPLinearConstraintsPenalty::eval_hessian ( const double* _x, SMatrixNP& _H)
{
base_->eval_hessian(_x, _H);
this->add_penalty_hessian(_H);
}
void NPLinearConstraintsPenalty::store_result ( const double* _x )
{
base_->store_result( _x);
}
//=============================================================================
} // namespace ACG
//=============================================================================

View File

@ -0,0 +1,138 @@
//=============================================================================
//
// CLASS NPLinearConstraints
//
//=============================================================================
#ifndef COMISO_NPLINEARCONSTRAINTS_HH
#define COMISO_NPLINEARCONSTRAINTS_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <gmm/gmm.h>
#include "NProblemGmmInterface.hh"
#include "LinearConstraintHandlerElimination.hh"
#include "LinearConstraintHandlerPenalty.hh"
//#include "LinearConstraintHandlerLagrange.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NPLinearConstraints{ Elimination, Penalty, Lagrange}
providing different techniques to handle linear constraints within
non-linear optimization. All three techniques transfer the constraint
problem into an unconstrained one.
*/
// ConstraintHandler working with Elimination approach
class COMISODLLEXPORT NPLinearConstraintsElimination : public NProblemGmmInterface, public LinearConstraintHandlerElimination
{
public:
// use c-arrays as vectors for gmm
typedef gmm::array1D_reference<double*> VectorPT;
/// Default constructor having a pointer to the main problem
NPLinearConstraintsElimination( NProblemGmmInterface* _np);
/// Destructor
~NPLinearConstraintsElimination();
// initialize constraints
template<class MatrixT, class VectorT>
void initialize_constraints( const MatrixT& _C, const VectorT& _c);
// NSolverInterface
virtual int n_unknowns ();
virtual void initial_x ( double* _x );
virtual double eval_f( const double* _x );
virtual void eval_gradient( const double* _x, double* _g);
virtual void eval_hessian ( const double* _x, SMatrixNP& _H);
virtual void store_result ( const double* _x );
protected:
void update_x(const double* _xr);
// convert vector into pointer
double* P(const std::vector<double>& _v);
private:
NProblemGmmInterface* base_;
bool cache_initialized_;
std::vector<double> x_;
std::vector<double> xr_;
std::vector<double> vtemp_;
};
//=============================================================================
// ConstraintHandler working with Penalty
class COMISODLLEXPORT NPLinearConstraintsPenalty : public NProblemGmmInterface, public LinearConstraintHandlerPenalty
{
public:
// use c-arrays as vectors for gmm
typedef gmm::array1D_reference<double*> VectorPT;
/// Default constructor having a pointer to the main problem
NPLinearConstraintsPenalty( NProblemGmmInterface* _np);
/// Destructor
~NPLinearConstraintsPenalty();
// initialize constraints
template<class MatrixT, class VectorT>
void initialize_constraints( const MatrixT& _C, const VectorT& _c);
// NSolverInterface
virtual int n_unknowns ();
virtual void initial_x ( double* _x );
virtual double eval_f( const double* _x );
virtual void eval_gradient( const double* _x, double* _g);
virtual void eval_hessian ( const double* _x, SMatrixNP& _H);
virtual void store_result ( const double* _x );
private:
NProblemGmmInterface* base_;
};
//=============================================================================
} // namespace ACG
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_NSOLVERGMMINTERFACE_C)
#define ACG_NSOLVERGMMINTERFACE_TEMPLATES
#include "NPLinearConstraintsT.cc"
#endif
//=============================================================================
#endif // COMISO_NSOLVERGMMINTERFACE_HH defined
//=============================================================================

View File

@ -0,0 +1,49 @@
//=============================================================================
//
// CLASS NPLinearConstraints
//
//=============================================================================
#define COMISO_NSOLVERGMMINTERFACE_C
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <gmm/gmm.h>
#include "NProblemGmmInterface.hh"
#include "LinearConstraintHandlerElimination.hh"
#include "LinearConstraintHandlerPenalty.hh"
//#include "LinearConstraintHandlerLagrange.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
// initialize constraints
template<class MatrixT, class VectorT>
void NPLinearConstraintsElimination::initialize_constraints( const MatrixT& _C, const VectorT& _c)
{
initialize(_C, _c);
cache_initialized_ = false;
}
//=============================================================================
// initialize constraints
template<class MatrixT, class VectorT>
void NPLinearConstraintsPenalty::initialize_constraints( const MatrixT& _C, const VectorT& _c)
{
initialize(_C, _c);
}
//=============================================================================
} // namespace ACG
//=============================================================================

112
src/external/CoMISo/NSolver/NPTiming.cc vendored Normal file
View File

@ -0,0 +1,112 @@
//=============================================================================
//
// CLASS NPTiming
//
//=============================================================================
//== INCLUDES =================================================================
#include <iostream>
#include <iomanip>
#include "NPTiming.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/// Default constructor
NPTiming::NPTiming(NProblemGmmInterface* _base) : base_(_base) {start_timing();}
/// Destructor
NPTiming::~NPTiming() {}
int NPTiming::n_unknowns ()
{
return base_->n_unknowns();
}
void NPTiming::initial_x( double* _x )
{
base_->initial_x(_x);
}
double NPTiming::eval_f( const double* _x )
{
++n_eval_f_;
sw_.start();
double f = base_->eval_f(_x);
timing_eval_f_ += sw_.stop();
return f;
}
void NPTiming::eval_gradient( const double* _x, double* _g)
{
++n_eval_gradient_;
sw_.start();
base_->eval_gradient(_x, _g);
timing_eval_gradient_ += sw_.stop();
}
void NPTiming::eval_hessian ( const double* _x, SMatrixNP& _H)
{
++n_eval_hessian_;
sw_.start();
base_->eval_hessian(_x, _H);
timing_eval_hessian_ += sw_.stop();
}
void NPTiming::store_result ( const double* _x )
{
base_->store_result(_x);
print_statistics();
}
void NPTiming::start_timing()
{
swg_.start();
timing_eval_f_ = 0.0;
timing_eval_gradient_ = 0.0;
timing_eval_hessian_ = 0.0;
n_eval_f_ = 0;
n_eval_gradient_ = 0;
n_eval_hessian_ = 0;
}
void NPTiming::print_statistics()
{
double time_total = swg_.stop();
double time_np = timing_eval_f_ + timing_eval_gradient_ + timing_eval_hessian_;
std::cerr << "######## NP-Timings ########" << std::endl;
std::cerr << "total time : " << time_total/1000.0 << "s\n";
std::cerr << "total time NP : " << time_np/1000.0 << "s (" << time_np/time_total*100.0 << " %)\n";
std::cerr << std::fixed << std::setprecision(5)
<< "eval_f time : " << timing_eval_f_/1000.0
<< "s ( #evals: " << n_eval_f_ << " -> avg "
<< timing_eval_f_/(1000.0*double(n_eval_f_)) << "s )\n"
<< "eval_grad time: " << timing_eval_gradient_/1000.0
<< "s ( #evals: " << n_eval_gradient_ << " -> avg "
<< timing_eval_gradient_/(1000.0*double(n_eval_gradient_)) << "s )\n"
<< "eval_hess time: " << timing_eval_hessian_/1000.0
<< "s ( #evals: " << n_eval_hessian_ << " -> avg "
<< timing_eval_hessian_/(1000.0*double(n_eval_hessian_)) << "s )\n";
}
//=============================================================================
} // namespace COMISO
//=============================================================================

85
src/external/CoMISo/NSolver/NPTiming.hh vendored Normal file
View File

@ -0,0 +1,85 @@
//=============================================================================
//
// CLASS NPTiming
//
//=============================================================================
#ifndef COMISO_NPTIMING_HH
#define COMISO_NPTIMING_HH
//== INCLUDES =================================================================
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include "NProblemGmmInterface.hh"
#include <CoMISo/Config/CoMISoDefines.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemGmmInterface NProblemGmmInterface.hh <ACG/.../NProblemGmmInterface.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT NPTiming : public NProblemGmmInterface
{
public:
/// Default constructor
NPTiming(NProblemGmmInterface* _base);
/// Destructor
~NPTiming();
virtual int n_unknowns ();
virtual void initial_x( double* _x );
virtual double eval_f( const double* _x );
virtual void eval_gradient( const double* _x, double* _g);
virtual void eval_hessian ( const double* _x, SMatrixNP& _H);
virtual void store_result ( const double* _x );
void start_timing();
protected:
void print_statistics();
private:
NProblemGmmInterface* base_;
StopWatch swg_;
StopWatch sw_;
// timings
double timing_eval_f_;
double timing_eval_gradient_;
double timing_eval_hessian_;
// number of function executions
int n_eval_f_;
int n_eval_gradient_;
int n_eval_hessian_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_NPTIMING_HH defined
//=============================================================================

View File

@ -0,0 +1,64 @@
//=============================================================================
//
// CLASS NProblemGmmInterface
// **************** DEPRECATED -> Please use NProblemInterface ***************//
//=============================================================================
#ifndef COMISO_NPROBLEMGMMINTERFACE_HH
#define COMISO_NPROBLEMGMMINTERFACE_HH
//== INCLUDES =================================================================
#include <gmm/gmm.h>
#include <CoMISo/Config/CoMISoDefines.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemGmmInterface NProblemGmmInterface.hh <ACG/.../NPRoblemGmmInterface.hh>
Brief Description.
A more elaborate description follows.
*/
// *** This class is DEPRECATED -> Please use NProblemInterface ***//
class COMISODLLEXPORT NProblemGmmInterface
{
public:
// ToDo: appropriate MatrixType ???
typedef gmm::row_matrix< gmm::wsvector<double> > SMatrixNP;
/// Default constructor
NProblemGmmInterface()
{std::cerr << "Warning: NProblemGmmInterface is deprecated -> use NProblemInterface instead!!!" << std::endl;}
/// Destructor
~NProblemGmmInterface() {}
virtual int n_unknowns ( ) = 0;
virtual void initial_x ( double* _x ) = 0;
virtual double eval_f ( const double* _x ) = 0;
virtual void eval_gradient( const double* _x, double* _g) = 0;
virtual void eval_hessian ( const double* _x, SMatrixNP& _H) = 0;
virtual void store_result ( const double* _x ) = 0;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_NPROBLEMGMMINTERFACE_HH defined
//=============================================================================

View File

@ -0,0 +1,11 @@
#include "NProblemInterface.hh"
namespace COMISO {
NProblemInterface::NProblemInterface() {
}
NProblemInterface::~NProblemInterface() {
}
}

View File

@ -0,0 +1,82 @@
//=============================================================================
//
// CLASS NProblemGmmInterface
//
//=============================================================================
#ifndef COMISO_NPROBLEMINTERFACE_HH
#define COMISO_NPROBLEMINTERFACE_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_EIGEN3_AVAILABLE
//== INCLUDES =================================================================
#include <Eigen/Eigen>
#if !(EIGEN_VERSION_AT_LEAST(3,1,0))
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#endif
#include <Eigen/Sparse>
#include <CoMISo/Config/CoMISoDefines.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemGmmInterface NProblemGmmInterface.hh <ACG/.../NPRoblemGmmInterface.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT NProblemInterface
{
public:
// Sparse Matrix Type
#if EIGEN_VERSION_AT_LEAST(3,1,0)
typedef Eigen::SparseMatrix<double,Eigen::ColMajor> SMatrixNP;
#else
typedef Eigen::DynamicSparseMatrix<double,Eigen::ColMajor> SMatrixNP;
#endif
/// Default constructor
NProblemInterface();
/// Destructor
virtual ~NProblemInterface();
// problem definition
virtual int n_unknowns ( ) = 0;
virtual void initial_x ( double* _x ) = 0;
virtual double eval_f ( const double* _x ) = 0;
virtual void eval_gradient( const double* _x, double* _g) = 0;
virtual void eval_hessian ( const double* _x, SMatrixNP& _H) = 0;
virtual void store_result ( const double* _x ) = 0;
// advanced properties
virtual bool constant_gradient() const { return false; }
virtual bool constant_hessian() const { return false; }
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================
#endif // COMISO_NPROBLEMGMMINTERFACE_HH defined
//=============================================================================

View File

@ -0,0 +1,362 @@
/*
* NProblemInterfaceAD.hpp
*
* Created on: Nov 30, 2012
* Author: kremer
*/
#ifndef NPROBLEMINTERFACEAD_HPP_
#define NPROBLEMINTERFACEAD_HPP_
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_ADOLC_AVAILABLE
#if COMISO_EIGEN3_AVAILABLE
//== INCLUDES =================================================================
#include <vector>
#include <boost/shared_array.hpp>
#include <adolc/adolc.h>
#include <adolc/adouble.h>
#include <adolc/drivers/drivers.h>
#include <adolc/sparse/sparsedrivers.h>
#include <adolc/taping.h>
#include <Eigen/Eigen>
#if !(EIGEN_VERSION_AT_LEAST(3,1,0))
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#endif
#include <Eigen/Sparse>
#include <CoMISo/Config/CoMISoDefines.hh>
#include "TapeIDSingleton.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NProblemmInterfaceAD NProblemInterfaceAD.hpp <ACG/.../NProblemInterfaceAD.hh>
Brief Description.
Extend the problem interface with auto differentiation using ADOL-C
*/
class COMISODLLEXPORT NProblemInterfaceAD : public NProblemInterface
{
public:
// Sparse Matrix Type
#if EIGEN_VERSION_AT_LEAST(3,1,0)
typedef Eigen::SparseMatrix<double,Eigen::ColMajor> SMatrixNP;
#else
typedef Eigen::DynamicSparseMatrix<double,Eigen::ColMajor> SMatrixNP;
#endif
/// Default constructor
NProblemInterfaceAD(int _n_unknowns) :
n_unknowns_(_n_unknowns),
dense_hessian_(NULL),
function_evaluated_(false),
use_tape_(true),
tape_(static_cast<short int>(TapeIDSingleton::Instance()->requestId())) {
for(size_t i = 0; i < 11; ++i) tape_stats_[i] = 0;
}
/// Destructor
virtual ~NProblemInterfaceAD() {
if(dense_hessian_ != NULL) {
for(int i = 0; i < n_unknowns_; ++i) {
delete[] dense_hessian_[i];
}
delete[] dense_hessian_;
}
TapeIDSingleton::Instance()->releaseId(static_cast<size_t>(tape_));
}
// ================================================
// Override these three methods
// ================================================
virtual void initial_x(double* _x) = 0;
virtual adouble evaluate(const adouble* _x) = 0;
virtual void store_result(const double* _x) = 0;
// ================================================
// Optionally override these methods, too
// ================================================
/**
* \brief Indicate whether the hessian is sparse.
* If so, the computations (as well as the memory
* consumption) can be performed more efficiently.
*/
virtual bool sparse_hessian() {
return false;
}
// ================================================
virtual int n_unknowns() {
return n_unknowns_;
}
virtual double eval_f(const double* _x) {
double y = 0.0;
if(!function_evaluated_ || !use_tape_) {
adouble y_d = 0.0;
boost::shared_array<adouble> x_d = x_d_ptr();
trace_on(tape_); // Start taping
// Fill data vector
for(int i = 0; i < n_unknowns_; ++i) {
x_d[i] <<= _x[i];
}
// Call virtual function to compute
// functional value
y_d = evaluate(x_d.get());
y_d >>= y;
trace_off();
#ifdef ADOLC_STATS
tapestats(tape_, tape_stats_);
std::cout << "Status values for tape " << tape_ << std::endl;
std::cout << "===============================================" << std::endl;
std::cout << "Number of independent variables:\t" << tape_stats_[0] << std::endl;
std::cout << "Number of dependent variables:\t\t" << tape_stats_[1] << std::endl;
std::cout << "Max. number of live active variables:\t" << tape_stats_[2] << std::endl;
std::cout << "Size of value stack:\t\t\t" << tape_stats_[3] << std::endl;
std::cout << "Buffer size:\t\t\t\t" << tape_stats_[4] << std::endl;
std::cout << "Total number of operations recorded:\t" << tape_stats_[5] << std::endl;
std::cout << "Other stats [6]:\t\t\t" << tape_stats_[6] << std::endl;
std::cout << "Other stats [7]:\t\t\t" << tape_stats_[7] << std::endl;
std::cout << "Other stats [8]:\t\t\t" << tape_stats_[8] << std::endl;
std::cout << "Other stats [9]:\t\t\t" << tape_stats_[9] << std::endl;
std::cout << "Other stats [10]:\t\t\t" << tape_stats_[10] << std::endl;
std::cout << "===============================================" << std::endl;
#endif
function_evaluated_ = true;
} else {
double ay[1] = {0.0};
int ec = function(tape_, 1, n_unknowns_, const_cast<double*>(_x), ay);
#ifdef ADOLC_RET_CODES
std::cout << "Info: function() returned code " << ec << std::endl;
#endif
y = ay[0];
}
return y;
}
virtual void eval_gradient(const double* _x, double* _g) {
if(!function_evaluated_ || !use_tape_) {
// Evaluate original functional
eval_f(_x);
}
int ec = gradient(tape_, n_unknowns_, _x, _g);
if(ec < 0) {
// Retape function if return code indicates discontinuity
function_evaluated_ = false;
#ifdef ADOLC_RET_CODES
std::cout << __FUNCTION__ << " invokes retaping of function due to discontinuity! Return code: " << ec << std::endl;
#endif
eval_f(_x);
ec = gradient(tape_, n_unknowns_, _x, _g);
}
#ifdef ADOLC_RET_CODES
std::cout << "Info: gradient() returned code " << ec << std::endl;
#endif
}
virtual void eval_hessian(const double* _x, SMatrixNP& _H) {
_H.resize(n_unknowns_, n_unknowns_);
_H.setZero();
if(!function_evaluated_ || !use_tape_) {
// Evaluate original functional
eval_f(_x);
}
if(sparse_hessian()) {
int nz = 0;
int opt[2] = {0, 0};
unsigned int* r_ind_p = NULL;
unsigned int* c_ind_p = NULL;
double* val_p = NULL;
int ec = sparse_hess(tape_, n_unknowns_, 0, _x, &nz, &r_ind_p, &c_ind_p, &val_p, opt);
if(ec < 0) {
// Retape function if return code indicates discontinuity
function_evaluated_ = false;
#ifdef ADOLC_RET_CODES
std::cout << __FUNCTION__ << " invokes retaping of function due to discontinuity! Return code: " << ec << std::endl;
#endif
eval_f(_x);
ec = sparse_hess(tape_, n_unknowns_, 0, _x, &nz, &r_ind_p, &c_ind_p, &val_p, opt);
}
assert(*nz >= 0);
assert(r_ind_p != NULL);
assert(c_ind_p != NULL);
assert(val_p != NULL);
#ifdef ADOLC_RET_CODES
std::cout << "Info: sparse_hessian() returned code " << ec << std::endl;
#endif
for(int i = 0; i < nz; ++i) {
_H.coeffRef(r_ind_p[i], c_ind_p[i]) = val_p[i];
}
delete[] r_ind_p;
delete[] c_ind_p;
delete[] val_p;
} else {
// Dense hessian data
double** h_ptr = dense_hessian_ptr();
int ec = hessian(tape_, n_unknowns_, const_cast<double*>(_x), h_ptr);
if(ec < 0) {
// Retape function if return code indicates discontinuity
function_evaluated_ = false;
#ifdef ADOLC_RET_CODES
std::cout << __FUNCTION__ << " invokes retaping of function due to discontinuity! Return code: " << ec << std::endl;
#endif
eval_f(_x);
ec = hessian(tape_, n_unknowns_, const_cast<double*>(_x), h_ptr);
}
#ifdef ADOLC_RET_CODES
std::cout << "Info: hessian() returned code " << ec << std::endl;
#endif
for(int i = 0; i < n_unknowns_; ++i) {
for(int j = 0; j <= i; ++j) {
_H.coeffRef(i, j) = h_ptr[i][j];
if(i != j) {
_H.coeffRef(j, i) = h_ptr[i][j];
}
}
}
}
}
bool use_tape() const {
return use_tape_;
}
/** \brief Use tape
* Set this to false if the energy functional
* is discontinuous (so that the operator tree
* has to be re-established at each evaluation)
*/
void use_tape(bool _b) {
use_tape_ = _b;
}
/**
* \brief Get sample point vector's address
*
* The objective function class allocates the
* memory for this vector at construction.
* Get the pointer to this vector and inject it
* into the constraint classes in order to
* prevent them from allocating their own vectors
* (which can be inefficient in terms of memory
* consumption in case there are many constraints)
*/
boost::shared_array<adouble> x_d_ptr() {
if(x_d_.get() == NULL) {
x_d_.reset(new adouble[n_unknowns_]);
}
return x_d_;
}
boost::shared_array<double> grad_ptr() {
if(grad_.get() == NULL) {
grad_.reset(new double[n_unknowns_]);
}
return grad_;
}
double** dense_hessian_ptr() {
if(dense_hessian_ == NULL) {
dense_hessian_ = new double*[n_unknowns_];
for(int i = 0; i < n_unknowns_; ++i) {
dense_hessian_[i] = new double[i+1];
}
}
return dense_hessian_;
}
private:
int n_unknowns_;
// Shared data
boost::shared_array<adouble> x_d_;
// Gradient vector
boost::shared_array<double> grad_;
// Dense hessian
double** dense_hessian_;
size_t tape_stats_[11];
bool function_evaluated_;
bool use_tape_;
const short int tape_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_ADOLC_AVAILABLE
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================
#endif /* NPROBLEMINTERFACEAD_HPP_ */

View File

@ -0,0 +1,122 @@
//=============================================================================
//
// CLASS NewtonSolver - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
#include "NewtonSolver.hh"
#include <CoMISo/Solver/CholmodSolver.hh>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
// solve
int
NewtonSolver::
solve(NProblemGmmInterface* _problem)
{
#if COMISO_SUITESPARSE_AVAILABLE
// get problem size
int n = _problem->n_unknowns();
// hesse matrix
NProblemGmmInterface::SMatrixNP H;
// gradient
std::vector<double> x(n), x_new(n), dx(n), g(n);
// get initial x, initial grad and initial f
_problem->initial_x(P(x));
double f = _problem->eval_f(P(x));
double reg = 1e-3;
COMISO::CholmodSolver chol;
for(int i=0; i<max_iter_; ++i)
{
_problem->eval_gradient(P(x), P(g));
// check for convergence
if( gmm::vect_norm2(g) < convergence_eps_)
{
std::cerr << "Newton Solver converged after "
<< i << " iterations" << std::endl;
_problem->store_result(P(x));
return true;
}
// get current hessian
_problem->eval_hessian(P(x), H);
// regularize
double reg_comp = reg*gmm::mat_trace(H)/double(n);
for(int j=0; j<n; ++j)
H(j,j) += reg_comp;
// solve linear system
bool factorization_ok = false;
if(constant_hessian_structure_ && i != 0)
factorization_ok = chol.update_system_gmm(H);
else
factorization_ok = chol.calc_system_gmm(H);
bool improvement = false;
if(factorization_ok)
if(chol.solve( dx, g))
{
gmm::add(x, gmm::scaled(dx,-1.0),x_new);
double f_new = _problem->eval_f(P(x_new));
if( f_new < f)
{
// swap x and x_new (and f and f_new)
x_new.swap(x);
f = f_new;
improvement = true;
std::cerr << "energy improved to " << f << std::endl;
}
}
// adapt regularization
if(improvement)
{
if(reg > 1e-9)
reg *= 0.1;
}
else
{
if(reg < 1e4)
reg *= 10.0;
else
{
_problem->store_result(P(x));
std::cerr << "Newton solver reached max regularization but did not converge ... " << std::endl;
return false;
}
}
}
_problem->store_result(P(x));
std::cerr << "Newton Solver did not converge!!! after "
<< max_iter_ << " iterations." << std::endl;
return false;
#else
std::cerr << "Warning: NewtonSolver requires not-available CholmodSolver...\n";
return false;
#endif
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,80 @@
//=============================================================================
//
// CLASS NewtonSolver
//
//=============================================================================
#ifndef COMISO_NEWTONSOLVER_HH
#define COMISO_NEWTONSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <gmm/gmm.h>
#include "NProblemGmmInterface.hh"
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class NewtonSolver NewtonSolver.hh <ACG/.../NewtonSolver.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT NewtonSolver
{
public:
/// Default constructor
NewtonSolver() : max_iter_(20), convergence_eps_(1e-6), constant_hessian_structure_(false) {}
/// Destructor
~NewtonSolver() {}
// solve
int solve(NProblemGmmInterface* _problem);
// solve specifying parameters
int solve(NProblemGmmInterface* _problem, int _max_iter, double _eps)
{
max_iter_ = _max_iter;
convergence_eps_ = _eps;
return solve(_problem);
}
bool& constant_hessian_structure() { return constant_hessian_structure_; }
protected:
double* P(std::vector<double>& _v)
{
if( !_v.empty())
return ((double*)&_v[0]);
else
return 0;
}
private:
int max_iter_;
double convergence_eps_;
bool constant_hessian_structure_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // ACG_NEWTONSOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,27 @@
//=============================================================================
//
// CLASS SuperSparseMatrixT - IMPLEMENTATION
//
//=============================================================================
#define COMISO_SUPERSPARSEMATRIXT_C
//== INCLUDES =================================================================
#include "SuperSparseMatrixT.hh"
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,201 @@
//=============================================================================
//
// CLASS SuperSparseMatrixT
//
//=============================================================================
#ifndef COMISO_SUPERSPARSEMATRIXT_HH
#define COMISO_SUPERSPARSEMATRIXT_HH
//== INCLUDES =================================================================
#include <iostream>
#include <map>
#include <math.h>
#include <Eigen/Dense>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class SuperSparseMatrixT SuperSparseMatrixT.hh <COMISO/.../SuperSparseMatrixT.hh>
Brief Description.
A more elaborate description follows.
*/
template <class VType>
class SuperSparseMatrixT
{
public:
// value type
typedef VType VT;
typedef std::pair<unsigned int, unsigned int> PII;
// iterate over elements
class iterator
{
public:
// default constructor
iterator() {}
// copy constructor
iterator(const iterator& _it) { m_it_ = _it.m_it_; }
// map iterator constructor
iterator(const typename std::map<PII,VType>::iterator& _m_it) { m_it_ = _m_it; }
// get reference to data
VT& operator*() { return m_it_->second; }
// get row and col of value
unsigned int row() {return m_it_->first.first; }
unsigned int col() {return m_it_->first.second; }
// post-increment
iterator& operator++() { ++m_it_; return(*this);}
iterator operator++(int) { return iterator(++m_it_); }
bool operator== (const iterator& _it) { return (m_it_ == _it.m_it_);}
bool operator!= (const iterator& _it) { return (m_it_ != _it.m_it_);}
// get raw iterator of map
typename std::map<PII,VType>::iterator& map_iterator() {return m_it_;}
private:
typename std::map<PII,VType>::iterator m_it_;
};
/// Constructor
SuperSparseMatrixT(const int _n_rows = 0, const int _n_cols = 0)
: n_rows_(_n_rows), n_cols_(_n_cols)
{}
/// Destructor
~SuperSparseMatrixT() {}
// iterate over non-zeros
iterator begin() { return iterator(data_.begin()); }
iterator end() { return iterator(data_.end()); }
// erase element
void erase( iterator _it) { data_.erase(_it.map_iterator()); }
// element access
VT& operator()(const unsigned int _i, const unsigned int _j)
{ return data_[PII(_i,_j)]; }
// const element access
const VT& operator()(const unsigned int _i, const unsigned int _j) const
{ return data_[PII(_i,_j)]; }
// get number of stored elements
unsigned int nonZeros() { return data_.size(); }
// get dimensions
unsigned int rows() const { return n_rows_;}
unsigned int cols() const { return n_cols_;}
// resize matrix -> delete invalid elements
void resize(const unsigned int _n_rows, const unsigned int _n_cols)
{
n_rows_ = _n_rows;
n_cols_ = _n_cols;
// delete out of range elements
typename std::map<PII, VT>::iterator m_it = data_.begin();
for(; m_it != data_.end();)
{
if(m_it->first.first >=n_rows_ || m_it->first.second >= n_cols_)
data_.erase(m_it++);
else
++m_it;
}
}
// clear data
void clear()
{ data_.clear(); }
// removes all values whose absolut value is smaller than _eps
void prune(const VT _eps)
{
typename std::map<PII, VT>::iterator m_it = data_.begin();
for(; m_it != data_.end();)
{
if(fabs(m_it->second) < _eps)
data_.erase(m_it++);
else
++m_it;
}
}
// scale matrix by scalar
void scale(const VT _s)
{
typename std::map<PII, VT>::iterator m_it = data_.begin();
for(; m_it != data_.end(); ++m_it)
m_it->second *=_s;
}
void print()
{
iterator it = begin();
iterator ite = end();
std::cerr << "######## SuperSparseMatrix ########" << std::endl;
std::cerr << "dimension : " << rows() << " x " << cols() << std::endl;
std::cerr << "#non-zeros: " << nonZeros() << std::endl;
for(; it!=ite; ++it)
std::cerr << "(" << it.row() << "," << it.col() << ") -> " << *it << std::endl;
}
void print_eigenvalues()
{
Eigen::MatrixXd A = Eigen::MatrixXd::Zero(n_rows_, n_cols_);
iterator it = begin();
for(; it != end(); ++it)
A(it.row(),it.col()) = *it;
Eigen::EigenSolver<Eigen::MatrixXd> eigensolver(A);
if (eigensolver.info() != Eigen::Success) abort();
std::cout << "The eigenvalues of A are:\n" << eigensolver.eigenvalues() << std::endl;
// std::cout << "Here's a matrix whose columns are eigenvectors of A \n"
// << "corresponding to these eigenvalues:\n"
// << eigensolver.eigenvectors() << std::endl;
}
private:
// dimension of matrix
unsigned int n_rows_;
unsigned int n_cols_;
typename std::map<PII, VT> data_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_SUPERSPARSEMATRIXT_C)
#define COMISO_SUPERSPARSEMATRIXT_TEMPLATES
#include "SuperSparseMatrixT.cc"
#endif
//=============================================================================
#endif // COMISO_SUPERSPARSEMATRIXT_HH defined
//=============================================================================

999
src/external/CoMISo/NSolver/TAOSolver.cc vendored Normal file
View File

@ -0,0 +1,999 @@
//=============================================================================
//
// CLASS TAOSolver - IMPLEMENTATION
//
//=============================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_TAO_AVAILABLE
//== INCLUDES =================================================================
#include "TAOSolver.hh"
//#include <dlfcn.h>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
// static member initialization
bool TAOSolver::initialized_ = false;
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// interface of TAO was changed from version 1 to 2 !!!
#if (TAO_VERSION_MAJOR < 2)
int
TAOSolver::
solve( NProblemGmmInterface* _base)
{
// // initialize (only once)
// initialize();
// std::cerr << "tao 1\n";
// // MPI_Init(0,0);
// char *libm="libmpi.so";
// dlopen(libm,RTLD_GLOBAL);
if(!initialized_)
{
/* Initialize TAO,PETSc */
// non command line arguments necessary ...
std::cerr << "Initialize MPI/Petsc/TAO ";
static char help[] ="help\n";
int argc = 0;
char **argv;
// MPI_Init(&argc, &argv);
PetscInitialize( &argc, &argv,(char *)0,help );
TaoInitialize ( &argc, &argv,(char *)0,help );
initialized_ = true;
std::cerr << " done!!!\n";
}
/* used to check for functions returning nonzeros */
int info;
// check for single processor
int size;
MPI_Comm_size(MPI_COMM_WORLD,&size);
if (size >1) {
PetscPrintf(PETSC_COMM_SELF,"TAOSolver is intended for single processor use!\n");
SETERRQ(1,"Incorrect number of processors");
}
/* Create TAO solver and set desired solution method */
// TaoMethod method="tao_cg"; /* minimization method */
TaoMethod method="tao_ntr"; /* minimization method */
// TaoMethod method="tao_nm"; /* minimization method */
TAO_SOLVER tao; /* TAO_SOLVER solver context */
TAO_APPLICATION testapp; /* The PETSc application */
info = TaoCreate(PETSC_COMM_SELF,method,&tao); CHKERRQ(info);
info = TaoApplicationCreate(PETSC_COMM_SELF,&testapp); CHKERRQ(info);
// initalize vector
int n = _base->n_unknowns();
Vec x;
info = VecCreateSeq(PETSC_COMM_SELF, n, &x); CHKERRQ(info);
PetscScalar* X;
info = VecGetArray(x,&X); CHKERRQ(info);
_base->initial_x(X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
// initialize matrix
/* Create a matrix data structure to store the Hessian. This structure will be used by TAO */
Mat H;
// ToDo: get nonzero_pattern
// int nnz[1]; nnz[0] = 1;
// info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,nnz,&H); /* PETSc routine */
info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,0,&H); /* PETSc routine */
info = MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE); CHKERRQ(info); /* PETSc flag */
info = TaoAppSetHessianMat(testapp,H,H); CHKERRQ(info); /* A TAO routine */
// initialize solution vector
info = TaoAppSetInitialSolutionVec(testapp,x); CHKERRQ(info);
/* Provide TAO routines for function evaluation */
info = TaoAppSetObjectiveRoutine(testapp, objective, (void*) _base); CHKERRQ(info);
info = TaoAppSetGradientRoutine (testapp, gradient , (void*) _base); CHKERRQ(info);
info = TaoAppSetHessianRoutine (testapp, hessian , (void*) _base); CHKERRQ(info);
/* SOLVE THE APPLICATION */
info = TaoSolveApplication(testapp,tao); CHKERRQ(info);
/* Get information on termination */
TaoTerminateReason reason;
info = TaoGetTerminationReason(tao,&reason); CHKERRQ(info);
if (reason <= 0)
std::cerr << "Warning: TAO-Solver did not converge!!!\n";
else
std::cerr << "TAO-Solver converged!!!\n";
// To View TAO solver information use
info = TaoView(tao); CHKERRQ(info);
// if successfull get and store result
// if( reason)
{
info = TaoAppGetSolutionVec(testapp, &x);
info = VecGetArray(x,&X); CHKERRQ(info);
_base->store_result( X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
}
// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
// /* Free TAO data structures */
info = TaoDestroy(tao); CHKERRQ(info);
info = TaoAppDestroy(testapp); CHKERRQ(info);
return reason;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
solve( NProblemInterface* _base)
{
// // initialize (only once)
// initialize();
// std::cerr << "tao 1\n";
// // MPI_Init(0,0);
// char *libm="libmpi.so";
// dlopen(libm,RTLD_GLOBAL);
if(!initialized_)
{
/* Initialize TAO,PETSc */
// non command line arguments necessary ...
std::cerr << "Initialize MPI/Petsc/TAO ";
static char help[] ="help\n";
int argc = 0;
char **argv;
// MPI_Init(&argc, &argv);
PetscInitialize( &argc, &argv,(char *)0,help );
TaoInitialize ( &argc, &argv,(char *)0,help );
initialized_ = true;
std::cerr << " done!!!\n";
}
/* used to check for functions returning nonzeros */
int info;
// check for single processor
int size;
MPI_Comm_size(MPI_COMM_WORLD,&size);
if (size >1) {
PetscPrintf(PETSC_COMM_SELF,"TAOSolver is intended for single processor use!\n");
SETERRQ(1,"Incorrect number of processors");
}
/* Create TAO solver and set desired solution method */
// TaoMethod method="tao_cg"; /* minimization method */
TaoMethod method="tao_ntr"; /* minimization method */
// TaoMethod method="tao_nm"; /* minimization method */
TAO_SOLVER tao; /* TAO_SOLVER solver context */
TAO_APPLICATION testapp; /* The PETSc application */
info = TaoCreate(PETSC_COMM_SELF,method,&tao); CHKERRQ(info);
info = TaoApplicationCreate(PETSC_COMM_SELF,&testapp); CHKERRQ(info);
// initalize vector
int n = _base->n_unknowns();
Vec x;
info = VecCreateSeq(PETSC_COMM_SELF, n, &x); CHKERRQ(info);
PetscScalar* X;
info = VecGetArray(x,&X); CHKERRQ(info);
_base->initial_x(X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
// initialize matrix
/* Create a matrix data structure to store the Hessian. This structure will be used by TAO */
Mat H;
// ToDo: get nonzero_pattern
// int nnz[1]; nnz[0] = 1;
// info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,nnz,&H); /* PETSc routine */
info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,0,&H); /* PETSc routine */
info = MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE); CHKERRQ(info); /* PETSc flag */
info = TaoAppSetHessianMat(testapp,H,H); CHKERRQ(info); /* A TAO routine */
// initialize solution vector
info = TaoAppSetInitialSolutionVec(testapp,x); CHKERRQ(info);
/* Provide TAO routines for function evaluation */
info = TaoAppSetObjectiveRoutine(testapp, objective2, (void*) _base); CHKERRQ(info);
info = TaoAppSetGradientRoutine (testapp, gradient2 , (void*) _base); CHKERRQ(info);
info = TaoAppSetHessianRoutine (testapp, hessian2 , (void*) _base); CHKERRQ(info);
/* SOLVE THE APPLICATION */
info = TaoSolveApplication(testapp,tao); CHKERRQ(info);
/* Get information on termination */
TaoTerminateReason reason;
info = TaoGetTerminationReason(tao,&reason); CHKERRQ(info);
if (reason <= 0)
std::cerr << "Warning: TAO-Solver did not converge!!!\n";
else
std::cerr << "TAO-Solver converged!!!\n";
// To View TAO solver information use
info = TaoView(tao); CHKERRQ(info);
// if successfull get and store result
// if( reason)
{
info = TaoAppGetSolutionVec(testapp, &x);
info = VecGetArray(x,&X); CHKERRQ(info);
_base->store_result( X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
}
// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
// /* Free TAO data structures */
info = TaoDestroy(tao); CHKERRQ(info);
info = TaoAppDestroy(testapp); CHKERRQ(info);
return reason;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
objective( TAO_APPLICATION _app, Vec _x, double* _result, void* _base)
{
NProblemGmmInterface* base = (NProblemGmmInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
// evaluate function
(*_result) = base->eval_f(x);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
gradient(TAO_APPLICATION _app, Vec _x, Vec _g, void* _base)
{
NProblemGmmInterface* base = (NProblemGmmInterface*) _base;
PetscScalar *x, *g;
int info;
/* Get pointers to vector data */
info = VecGetArray(_x,&x); CHKERRQ(info);
info = VecGetArray(_g,&g); CHKERRQ(info);
// compute gradient
base->eval_gradient( x, g);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
info = VecRestoreArray(_g,&g); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
hessian(TAO_APPLICATION _app, Vec _x, Mat* _H, Mat* _H_pre, MatStructure* _H_struct, void* _base)
{
NProblemGmmInterface* base = (NProblemGmmInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
/* Initialize matrix entries to zero */
info = MatZeroEntries(*_H); CHKERRQ(info);
// iterate over non-zero elements
NProblemGmmInterface::SMatrixNP H;
base->eval_hessian( x, H);
for (unsigned int i = 0; i < gmm::mat_nrows(H); ++i)
{
typedef gmm::linalg_traits<NProblemGmmInterface::SMatrixNP>::const_sub_row_type
CRow;
CRow row = gmm::mat_const_row(H, i);
gmm::linalg_traits<CRow>::const_iterator it = gmm::vect_const_begin(row);
gmm::linalg_traits<CRow>::const_iterator ite = gmm::vect_const_end(row);
int m = 1;
int n = 1;
int idxm[1]; idxm[0] = i;
int idxn[1];
PetscScalar values[1];
for(; it != ite; ++it)
{
idxn[0] = it.index();
values[0] = *it;
info = MatSetValues(*_H, m, idxm, n, idxn, values, INSERT_VALUES);
}
}
/* Assemble the matrix */
info = MatAssemblyBegin(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
info = MatAssemblyEnd(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
*_H_struct = SAME_NONZERO_PATTERN;
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
objective2( TAO_APPLICATION _app, Vec _x, double* _result, void* _base)
{
NProblemInterface* base = (NProblemInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
// evaluate function
(*_result) = base->eval_f(x);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
gradient2(TAO_APPLICATION _app, Vec _x, Vec _g, void* _base)
{
NProblemInterface* base = (NProblemInterface*) _base;
PetscScalar *x, *g;
int info;
/* Get pointers to vector data */
info = VecGetArray(_x,&x); CHKERRQ(info);
info = VecGetArray(_g,&g); CHKERRQ(info);
// compute gradient
base->eval_gradient( x, g);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
info = VecRestoreArray(_g,&g); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
hessian2(TAO_APPLICATION _app, Vec _x, Mat* _H, Mat* _H_pre, MatStructure* _H_struct, void* _base)
{
NProblemInterface* base = (NProblemInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
/* Initialize matrix entries to zero */
info = MatZeroEntries(*_H); CHKERRQ(info);
// iterate over non-zero elements
NProblemInterface::SMatrixNP H;
base->eval_hessian( x, H);
for(int i=0; i<H.outerSize(); ++i)
{
int m = 1;
int n = 1;
int idxm[1]; idxm[0] = i;
int idxn[1];
PetscScalar values[1];
for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
{
idxm[0] = it.row();
idxn[0] = it.col();
values[0] = it.value();
info = MatSetValues(*_H, m, idxm, n, idxn, values, INSERT_VALUES);
}
}
/* Assemble the matrix */
info = MatAssemblyBegin(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
info = MatAssemblyEnd(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
*_H_struct = SAME_NONZERO_PATTERN;
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
void
TAOSolver::
initialize()
{
if(!initialized_)
{
/* Initialize TAO,PETSc */
// non command line arguments necessary ...
std::cerr << "Initialize MPI/Petsc/TAO ";
static char help[] ="help\n";
static int argc = 0;
static char **argv;
// MPI_Init(&argc, &argv);
PetscInitialize( &argc, &argv,(char *)0,help );
TaoInitialize ( &argc, &argv,(char *)0,help );
initialized_ = true;
std::cerr << " done!!!\n";
}
}
//-----------------------------------------------------------------------------
void
TAOSolver::
cleanup()
{
/* Finalize TAO */
TaoFinalize();
PetscFinalize();
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
#else // (TAO_VERSION_MAJOR < 2)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int
TAOSolver::
solve( NProblemGmmInterface* _base)
{
// // initialize (only once)
// initialize();
// std::cerr << "tao 1\n";
// // MPI_Init(0,0);
// char *libm="libmpi.so";
// dlopen(libm,RTLD_GLOBAL);
if(!initialized_)
{
/* Initialize TAO,PETSc */
// non command line arguments necessary ...
std::cerr << "Initialize MPI/Petsc/TAO ";
static char help[] ="help\n";
int argc = 0;
char **argv;
// MPI_Init(&argc, &argv);
PetscInitialize( &argc, &argv,(char *)0,help );
TaoInitialize ( &argc, &argv,(char *)0,help );
initialized_ = true;
std::cerr << " done!!!\n";
}
/* used to check for functions returning nonzeros */
int info;
// check for single processor
int size;
MPI_Comm_size(MPI_COMM_WORLD,&size);
if (size >1) {
PetscPrintf(PETSC_COMM_SELF,"TAOSolver is intended for single processor use!\n");
SETERRQ(PETSC_COMM_SELF,1,"Incorrect number of processors");
}
/* Create TAO solver with desired solution method */
TaoSolver tao; /* TaoSolver solver context */
TaoCreate(PETSC_COMM_SELF,&tao);
TaoSetType(tao,"tao_ntr");
/* Create TAO solver and set desired solution method */
// TaoMethod method="tao_cg"; /* minimization method */
// TaoMethod method="tao_ntr"; /* minimization method */
// TaoMethod method="tao_nm"; /* minimization method */
// TAO_SOLVER tao; /* TAO_SOLVER solver context */
// TAO_APPLICATION testapp; /* The PETSc application */
// info = TaoCreate(PETSC_COMM_SELF,method,&tao); CHKERRQ(info);
// info = TaoApplicationCreate(PETSC_COMM_SELF,&testapp); CHKERRQ(info);
// initalize vector
int n = _base->n_unknowns();
Vec x;
info = VecCreateSeq(PETSC_COMM_SELF, n, &x); CHKERRQ(info);
PetscScalar* X;
info = VecGetArray(x,&X); CHKERRQ(info);
_base->initial_x(X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
// initialize matrix
/* Create a matrix data structure to store the Hessian. This structure will be used by TAO */
Mat H;
// ToDo: get nonzero_pattern
// int nnz[1]; nnz[0] = 1;
// info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,nnz,&H); /* PETSc routine */
info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,0,&H); /* PETSc routine */
info = MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE); CHKERRQ(info); /* PETSc flag */
//info = TaoAppSetHessianMat(testapp,H,H); CHKERRQ(info); /* A TAO routine */
// initialize solution vector
// info = TaoAppSetInitialSolutionVec(testapp,x); CHKERRQ(info);
TaoSetInitialVector(tao,x);
/* Provide TAO routines for function evaluation */
TaoSetObjectiveRoutine(tao, objective, (void*) _base);
TaoSetGradientRoutine (tao, gradient , (void*) _base);
TaoSetHessianRoutine (tao, H, H, hessian , (void*) _base);
/* SOLVE */
TaoSolve(tao);
/* Get information on termination */
TaoSolverTerminationReason reason;
TaoGetTerminationReason(tao,&reason);
if (reason <= 0)
std::cerr << "Warning: TAO-Solver did not converge!!!\n";
else
std::cerr << "TAO-Solver converged!!!\n";
// To View TAO solver information use
info = TaoView(tao, PETSC_VIEWER_STDOUT_SELF); CHKERRQ(info);
// if successfull get and store result
// if( reason)
{
TaoGetSolutionVector(tao, &x);
info = VecGetArray(x,&X); CHKERRQ(info);
_base->store_result( X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
}
// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
// /* Free TAO data structures */
TaoDestroy(&tao);
/* Free PETSc data structures */
VecDestroy(&x);
MatDestroy(&H);
TaoFinalize();
return reason;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
solve( NProblemInterface* _base)
{
// // initialize (only once)
// initialize();
// std::cerr << "tao 1\n";
// // MPI_Init(0,0);
// char *libm="libmpi.so";
// dlopen(libm,RTLD_GLOBAL);
if(!initialized_)
{
/* Initialize TAO,PETSc */
// non command line arguments necessary ...
std::cerr << "Initialize MPI/Petsc/TAO ";
static char help[] ="help\n";
int argc = 0;
char **argv;
// MPI_Init(&argc, &argv);
PetscInitialize( &argc, &argv,(char *)0,help );
TaoInitialize ( &argc, &argv,(char *)0,help );
initialized_ = true;
std::cerr << " done!!!\n";
}
/* used to check for functions returning nonzeros */
int info;
// check for single processor
int size;
MPI_Comm_size(MPI_COMM_WORLD,&size);
if (size >1) {
PetscPrintf(PETSC_COMM_SELF,"TAOSolver is intended for single processor use!\n");
SETERRQ(PETSC_COMM_SELF,1,"Incorrect number of processors");
}
/* Create TAO solver with desired solution method */
TaoSolver tao; /* TaoSolver solver context */
TaoCreate(PETSC_COMM_SELF,&tao);
TaoSetType(tao,"tao_ntr");
/* Create TAO solver and set desired solution method */
// TaoMethod method="tao_cg"; /* minimization method */
// TaoMethod method="tao_ntr"; /* minimization method */
// TaoMethod method="tao_nm"; /* minimization method */
// TAO_SOLVER tao; /* TAO_SOLVER solver context */
// TAO_APPLICATION testapp; /* The PETSc application */
// info = TaoCreate(PETSC_COMM_SELF,method,&tao); CHKERRQ(info);
// info = TaoApplicationCreate(PETSC_COMM_SELF,&testapp); CHKERRQ(info);
// initalize vector
int n = _base->n_unknowns();
Vec x;
info = VecCreateSeq(PETSC_COMM_SELF, n, &x); CHKERRQ(info);
PetscScalar* X;
info = VecGetArray(x,&X); CHKERRQ(info);
_base->initial_x(X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
// initialize matrix
/* Create a matrix data structure to store the Hessian. This structure will be used by TAO */
Mat H;
// ToDo: get nonzero_pattern
// int nnz[1]; nnz[0] = 1;
// info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,nnz,&H); /* PETSc routine */
info = MatCreateSeqAIJ(PETSC_COMM_SELF,n,n,0,0,&H); /* PETSc routine */
info = MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE); CHKERRQ(info); /* PETSc flag */
//info = TaoAppSetHessianMat(testapp,H,H); CHKERRQ(info); /* A TAO routine */
// initialize solution vector
// info = TaoAppSetInitialSolutionVec(testapp,x); CHKERRQ(info);
TaoSetInitialVector(tao,x);
/* Provide TAO routines for function evaluation */
TaoSetObjectiveRoutine(tao, objective2, (void*) _base);
TaoSetGradientRoutine (tao, gradient2 , (void*) _base);
TaoSetHessianRoutine (tao, H, H, hessian2 , (void*) _base);
/* SOLVE */
TaoSolve(tao);
/* Get information on termination */
TaoSolverTerminationReason reason;
TaoGetTerminationReason(tao,&reason);
if (reason <= 0)
std::cerr << "Warning: TAO-Solver did not converge!!!\n";
else
std::cerr << "TAO-Solver converged!!!\n";
// To View TAO solver information use
info = TaoView(tao, PETSC_VIEWER_STDOUT_SELF); CHKERRQ(info);
// if successfull get and store result
// if( reason)
{
TaoGetSolutionVector(tao, &x);
info = VecGetArray(x,&X); CHKERRQ(info);
_base->store_result( X);
info = VecRestoreArray(x,&X); CHKERRQ(info);
}
// VecView(x, PETSC_VIEWER_STDOUT_WORLD);
// /* Free TAO data structures */
TaoDestroy(&tao);
/* Free PETSc data structures */
VecDestroy(&x);
MatDestroy(&H);
TaoFinalize();
return reason;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
objective( TaoSolver _tao, Vec _x, double* _result, void* _base)
{
NProblemGmmInterface* base = (NProblemGmmInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
// evaluate function
(*_result) = base->eval_f(x);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
gradient(TaoSolver _tao, Vec _x, Vec _g, void* _base)
{
NProblemGmmInterface* base = (NProblemGmmInterface*) _base;
PetscScalar *x, *g;
int info;
/* Get pointers to vector data */
info = VecGetArray(_x,&x); CHKERRQ(info);
info = VecGetArray(_g,&g); CHKERRQ(info);
// compute gradient
base->eval_gradient( x, g);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
info = VecRestoreArray(_g,&g); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
hessian(TaoSolver _tao, Vec _x, Mat* _H, Mat* _H_pre, MatStructure* _H_struct, void* _base)
{
NProblemGmmInterface* base = (NProblemGmmInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
/* Initialize matrix entries to zero */
info = MatZeroEntries(*_H); CHKERRQ(info);
// iterate over non-zero elements
NProblemGmmInterface::SMatrixNP H;
base->eval_hessian( x, H);
for (unsigned int i = 0; i < gmm::mat_nrows(H); ++i)
{
typedef gmm::linalg_traits<NProblemGmmInterface::SMatrixNP>::const_sub_row_type
CRow;
CRow row = gmm::mat_const_row(H, i);
gmm::linalg_traits<CRow>::const_iterator it = gmm::vect_const_begin(row);
gmm::linalg_traits<CRow>::const_iterator ite = gmm::vect_const_end(row);
int m = 1;
int n = 1;
int idxm[1]; idxm[0] = i;
int idxn[1];
PetscScalar values[1];
for(; it != ite; ++it)
{
idxn[0] = it.index();
values[0] = *it;
info = MatSetValues(*_H, m, idxm, n, idxn, values, INSERT_VALUES);
}
}
/* Assemble the matrix */
info = MatAssemblyBegin(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
info = MatAssemblyEnd(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
*_H_struct = SAME_NONZERO_PATTERN;
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
objective2( TaoSolver _tao, Vec _x, double* _result, void* _base)
{
NProblemInterface* base = (NProblemInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
// evaluate function
(*_result) = base->eval_f(x);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
gradient2(TaoSolver _tao, Vec _x, Vec _g, void* _base)
{
NProblemInterface* base = (NProblemInterface*) _base;
PetscScalar *x, *g;
int info;
/* Get pointers to vector data */
info = VecGetArray(_x,&x); CHKERRQ(info);
info = VecGetArray(_g,&g); CHKERRQ(info);
// compute gradient
base->eval_gradient( x, g);
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
info = VecRestoreArray(_g,&g); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
int
TAOSolver::
hessian2(TaoSolver _tao, Vec _x, Mat* _H, Mat* _H_pre, MatStructure* _H_struct, void* _base)
{
NProblemInterface* base = (NProblemInterface*) _base;
PetscScalar *x;
/* Get pointers to vector data */
int info = VecGetArray(_x,&x); CHKERRQ(info);
/* Initialize matrix entries to zero */
info = MatZeroEntries(*_H); CHKERRQ(info);
// iterate over non-zero elements
NProblemInterface::SMatrixNP H;
base->eval_hessian( x, H);
for(int i=0; i<H.outerSize(); ++i)
{
int m = 1;
int n = 1;
int idxm[1]; idxm[0] = i;
int idxn[1];
PetscScalar values[1];
for (NProblemInterface::SMatrixNP::InnerIterator it(H,i); it; ++it)
{
idxm[0] = it.row();
idxn[0] = it.col();
values[0] = it.value();
info = MatSetValues(*_H, m, idxm, n, idxn, values, INSERT_VALUES);
}
}
/* Assemble the matrix */
info = MatAssemblyBegin(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
info = MatAssemblyEnd(*_H,MAT_FINAL_ASSEMBLY); CHKERRQ(info);
*_H_struct = SAME_NONZERO_PATTERN;
/* Restore vectors */
info = VecRestoreArray(_x,&x); CHKERRQ(info);
return 0;
}
//-----------------------------------------------------------------------------
void
TAOSolver::
initialize()
{
if(!initialized_)
{
/* Initialize TAO,PETSc */
// non command line arguments necessary ...
std::cerr << "Initialize MPI/Petsc/TAO ";
static char help[] ="help\n";
static int argc = 0;
static char **argv;
// MPI_Init(&argc, &argv);
PetscInitialize( &argc, &argv,(char *)0,help );
TaoInitialize ( &argc, &argv,(char *)0,help );
initialized_ = true;
std::cerr << " done!!!\n";
}
}
//-----------------------------------------------------------------------------
void
TAOSolver::
cleanup()
{
/* Finalize TAO */
TaoFinalize();
PetscFinalize();
}
#endif
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_TAO_AVAILABLE

View File

@ -0,0 +1,98 @@
//=============================================================================
//
// CLASS TAOSolver
//
//=============================================================================
#ifndef COMISO_TAOSOLVER_HH
#define COMISO_TAOSOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_TAO_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "NProblemGmmInterface.hh"
#include "NProblemInterface.hh"
#include <mpi.h>
#include <tao.h>
#include <gmm/gmm.h>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class TAOSolver TAOSolver.hh <ACG/.../TAOSolver.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT TAOSolver
{
public:
/// Default constructor
TAOSolver() {}
/// Destructor
~TAOSolver() {}
// solve problem
static int solve( NProblemInterface* _base);
static int solve( NProblemGmmInterface* _base);
private:
static void initialize();
// ToDo: cleanup has to be started automatically
static void cleanup();
#if (TAO_VERSION_MAJOR < 2)
// declar TAO function prototypes
static int objective(TAO_APPLICATION,Vec,double*,void*);
static int gradient (TAO_APPLICATION,Vec,Vec ,void*);
static int hessian (TAO_APPLICATION,Vec,Mat*,Mat*,MatStructure*,void*);
static int objective2(TAO_APPLICATION,Vec,double*,void*);
static int gradient2 (TAO_APPLICATION,Vec,Vec ,void*);
static int hessian2 (TAO_APPLICATION,Vec,Mat*,Mat*,MatStructure*,void*);
#else
static PetscErrorCode objective(TaoSolver,Vec,double*,void*);
static PetscErrorCode gradient (TaoSolver,Vec,Vec ,void*);
static PetscErrorCode hessian (TaoSolver,Vec,Mat*,Mat*,MatStructure*,void*);
static PetscErrorCode objective2(TaoSolver,Vec,double*,void*);
static PetscErrorCode gradient2 (TaoSolver,Vec,Vec ,void*);
static PetscErrorCode hessian2 (TaoSolver,Vec,Mat*,Mat*,MatStructure*,void*);
#endif
private:
// initialized?
static bool initialized_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_TAO_AVAILABLE
//=============================================================================
#endif // ACG_TAOSOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,10 @@
/*
* TapeIDSingleton.cc
*
* Created on: Jan 4, 2013
* Author: kremer
*/
#include "TapeIDSingleton.hh"
TapeIDSingleton* TapeIDSingleton::reference_ = NULL;

View File

@ -0,0 +1,57 @@
/*
* TapeIDSingleton.hpp
*
* Created on: Jan 4, 2013
* Author: kremer
*/
#ifndef TAPEIDSINGLETON_HPP_
#define TAPEIDSINGLETON_HPP_
#include <vector>
#include <cassert>
#include <cstring>
class TapeIDSingleton {
public:
static TapeIDSingleton* Instance() {
if(reference_ == NULL) {
reference_ = new TapeIDSingleton();
}
return reference_;
}
size_t requestId() {
// Test if previously requested id is available again
const size_t n = ids_.size();
for(size_t i = 0; i < n; ++i) {
if(!ids_[i]) {
ids_[i] = true;
return i;
}
}
// Request new id at the end of array
size_t id = ids_.size();
ids_.push_back(true);
return id;
}
void releaseId(const size_t _i) {
assert(_i < ids_.size());
ids_[_i] = false;
}
private:
TapeIDSingleton() {}
TapeIDSingleton(const TapeIDSingleton&) {}
~TapeIDSingleton() {}
static TapeIDSingleton* reference_;
std::vector<bool> ids_;
};
#endif /* TAPEIDSINGLETON_HPP_ */

View File

@ -0,0 +1,86 @@
//=============================================================================
//
// CLASS BaseTaoGmmInterface
//
//=============================================================================
#ifndef COMISO_TESTINTERFACE_HH
#define COMISO_TESTINTERFACE_HH
//== INCLUDES =================================================================
#include "NProblemGmmInterface.hh"
#include <gmm/gmm.h>
#include <CoMISo/Config/CoMISoDefines.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class BaseTaoGmmInterface BaseTaoGmmInterface.hh <ACG/.../BaseTaoGmmInterface.hh>
Brief Description.
A more elaborate description follows.
*/
class COMISODLLEXPORT TestInterface : public NProblemGmmInterface
{
public:
/// Default constructor
TestInterface() {}
/// Destructor
~TestInterface() {}
// minimize (x-2.4)^2
virtual int n_unknowns ( )
{
return 1;
}
virtual void initial_x ( double* _x )
{
_x[0] = 100;
}
virtual double eval_f ( const double* _x )
{
return (_x[0]-2.4)*(_x[0]-2.4);
}
virtual void eval_gradient( const double* _x, double* _g)
{
_g[0] = 2.0*(_x[0]-2.4);
}
virtual void eval_hessian( const double* _x, SMatrixNP& _H)
{
gmm::resize(_H,1,1);
_H(0,0) = 2.0;
}
virtual void store_result ( const double* _x )
{
std::cerr << "result: " << _x[0] << std::endl;
}
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_TESTINTERFACE_HH defined
//=============================================================================

View File

@ -0,0 +1,34 @@
//=============================================================================
//
// ENUM VariableType
//
//=============================================================================
#ifndef COMISO_VARIABLETYPE_HH
#define COMISO_VARIABLETYPE_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
enum VariableType { Real, Integer, Binary};
typedef std::pair<unsigned int, VariableType> PairIndexVtype;
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_VARIABLETYPE_HH defined
//=============================================================================

View File

@ -0,0 +1,156 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS MISolverDialog - IMPLEMENTATION
//
//=============================================================================
//== INCLUDES =================================================================
#include <CoMISo/Config/config.hh>
//== BUILD-TIME DEPENDENCIES =================================================================
#if(COMISO_QT4_AVAILABLE)
//============================================================================================
#include "MISolverDialogUI.hh"
#include <QtGui>
//== NAMESPACES ===============================================================
namespace COMISO {
//== IMPLEMENTATION ==========================================================
//-----------------------------------------------------------------------------
void
MISolverDialog::
get_parameters()
{
// QDoubleSpinBox *localErrorDSB;
// QSpinBox *localItersSB;
// QDoubleSpinBox *cgErrorDSB;
// QSpinBox *cgItersSB;
// QDoubleSpinBox *taucsErrorDSB;
// QCheckBox *finalTaucsCB;
// QCheckBox *initialTaucsCB;
// QSpinBox *infoSB;
// QCheckBox *directRoundingCB;
initialFullCB ->setChecked( misolver_.get_inital_full());
iterFullCB ->setChecked( misolver_.get_iter_full());
finalFullCB ->setChecked( misolver_.get_final_full());
directRoundingCB ->setChecked( misolver_.get_direct_rounding());
noRoundingCB ->setChecked( misolver_.get_no_rounding());
multipleRoundingCB->setChecked( misolver_.get_multiple_rounding());
gurobiRoundingCB ->setChecked( misolver_.get_gurobi_rounding());
cplexRoundingCB ->setChecked( misolver_.get_cplex_rounding());
localItersSB ->setValue( misolver_.get_local_iters());
localErrorDSB->setValue( log(misolver_.get_local_error())/log(10.0f));
cgItersSB ->setValue( misolver_.get_cg_iters());
cgErrorDSB->setValue( log(misolver_.get_cg_error())/log(10.0f));
gurobiMaxTimeDSB->setValue(misolver_.get_gurobi_max_time());
multipleRoundingDSB->setValue( misolver_.get_multiple_rounding_threshold());
infoSB->setValue( misolver_.get_noise());
solverStatsCheckBox->setChecked( misolver_.get_stats( ));
use_reordering_cb->setChecked( misolver_.use_constraint_reordering() );
}
//-----------------------------------------------------------------------------
void
MISolverDialog::
set_parameters()
{
misolver_.set_inital_full ( initialFullCB ->isChecked() );
misolver_.set_iter_full ( iterFullCB ->isChecked() );
misolver_.set_final_full ( finalFullCB ->isChecked() );
misolver_.set_direct_rounding( directRoundingCB->isChecked());
misolver_.set_no_rounding( noRoundingCB->isChecked());
misolver_.set_multiple_rounding( multipleRoundingCB->isChecked());
misolver_.set_gurobi_rounding( gurobiRoundingCB->isChecked());
misolver_.set_cplex_rounding ( cplexRoundingCB->isChecked());
misolver_.set_local_iters( localItersSB ->value());
misolver_.set_local_error( pow(10, localErrorDSB->value()));
misolver_.set_cg_iters( cgItersSB ->value());
misolver_.set_cg_error( pow(10, cgErrorDSB->value()));
misolver_.set_gurobi_max_time(gurobiMaxTimeDSB->value());
misolver_.set_multiple_rounding_threshold( multipleRoundingDSB->value());
misolver_.set_noise( infoSB->value());
misolver_.set_stats( solverStatsCheckBox->isChecked());
misolver_.use_constraint_reordering() = use_reordering_cb->isChecked();
}
//-----------------------------------------------------------------------------
void
MISolverDialog::
slotOkButton()
{
set_parameters();
close();
}
//-----------------------------------------------------------------------------
void
MISolverDialog::
slotCancelButton()
{
close();
}
//=============================================================================
} // namespace COMISO
//== BUILD-TIME DEPENDENCIES ==================================================
#endif
//=============================================================================

View File

@ -0,0 +1,113 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS MiSolverDialog
//
//=============================================================================
#ifndef COMISO_MISOLVERDIALOG_HH
#define COMISO_MISOLVERDIALOG_HH
#include <CoMISo/Config/config.hh>
//== BUILD-TIME DEPENDENCIES =================================================================
#if(COMISO_QT4_AVAILABLE)
//============================================================================================
//== INCLUDES =================================================================
#include "ui_QtMISolverDialogBaseUI.hh"
// ACGMake users have to include
// #include "QtMISolverDialogBase.hh"
#include <Solver/MISolver.hh>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO
{
//== CLASS DEFINITION =========================================================
/** \class MISolverDialog MISolverDialog.hh <COMISO/.../MISolverDialog.hh>
Brief Description.
A more elaborate description follows.
*/
class MISolverDialog
: public QDialog, public Ui::QtMISolverDialogBaseUI
{
Q_OBJECT
public:
/// Default constructor
MISolverDialog( MISolver& _misolver,
QWidget* _parent = 0 ):
QDialog( _parent ),
Ui::QtMISolverDialogBaseUI(),
misolver_( _misolver )
{
setupUi( this );
get_parameters();
connect( okPB, SIGNAL( clicked() ), this, SLOT( slotOkButton() ) );
connect( cancelPB, SIGNAL( clicked() ), this, SLOT( slotCancelButton() ) );
}
/// Destructor
~MISolverDialog() {}
void get_parameters();
void set_parameters();
public slots:
virtual void slotOkButton();
virtual void slotCancelButton();
private:
MISolver& misolver_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#endif // COMISO_MISOLVERDIALOG_HH defined
//=============================================================================
#endif

View File

@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QtMISolverDialogBaseUI</class>
<widget class="QDialog" name="QtMISolverDialogBaseUI">
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>385</width>
<height>273</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="8" column="1">
<widget class="QCheckBox" name="cplexRoundingCB">
<property name="text">
<string>use cplex</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Max Error (1e-x)</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Iterations</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Local</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="localErrorDSB">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-1000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000.000000000000000</double>
</property>
<property name="value">
<double>6.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="localItersSB">
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>10000</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>CG</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="cgErrorDSB">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>-1000000000.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000.000000000000000</double>
</property>
<property name="value">
<double>6.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="cgItersSB">
<property name="maximum">
<number>1000000000</number>
</property>
<property name="value">
<number>20</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Full</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="initialFullCB">
<property name="text">
<string>initial</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="iterFullCB">
<property name="text">
<string>iter not converged</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="finalFullCB">
<property name="text">
<string>final</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Rounding</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="directRoundingCB">
<property name="text">
<string>direct</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="noRoundingCB">
<property name="text">
<string>no</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="multipleRoundingCB">
<property name="text">
<string>multiple</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="multipleRoundingDSB">
<property name="decimals">
<number>2</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>0.500000000000000</double>
</property>
<property name="value">
<double>0.500000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Info Level</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QSpinBox" name="infoSB"/>
</item>
<item>
<widget class="QCheckBox" name="solverStatsCheckBox">
<property name="text">
<string>Output solver statistics</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Constraints</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="use_reordering_cb">
<property name="text">
<string>reordering</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>GUROBI</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="gurobiRoundingCB">
<property name="text">
<string>use gurobi</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QDoubleSpinBox" name="gurobiMaxTimeDSB">
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>60.000000000000000</double>
</property>
</widget>
</item>
<item row="7" column="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>s</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="okPB">
<property name="text">
<string>Ok</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelPB">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>14</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

63
src/external/CoMISo/README.txt vendored Normal file
View File

@ -0,0 +1,63 @@
CoMISo Version 1.0 rc1
www.rwth-graphics.de
zimmer@informatik.rwth-aachen.de
bommes@informatik.rwth-aachen.de
Update! Version 1.1
-------------------
For the CoMISo to work only Eigen3 and GMM++ are needed.
What is
-------
This is a short readme file to get you started with the Constrained Mixed-Integer Solver (CoMISo). It shortly overviews the system prerequisites and explains how to build the package. See the examples and the HarmonicExample OpenFlipper plugin for usage examples and ideas.
Requirements
------------
Here is an example of what packages were needed to compile CoMISo on a freshly installed Ubuntu 9.04 system
# sudo apt-get install g++
# sudo apt-get install cmake
# sudo apt-get install libgmm-dev
# sudo apt-get install libboost-dev
# sudo apt-get install libblas-dev
# sudo apt-get install libsuitesparse-dev
(some other needed libraries such as lapack, are installed as dependencies of the above)
For Windows and Macintosh systems the corresponding packages need to be downloaded and installed.
The cmake build system should enable building the CoMISo library under Windows and Macintosh systems, please let me know if this is (not) the case!
OpenFlipper requirements:
-------------------------
To build OpenFlipper you additionally need to install all the Qt4 packages libqt4-{dev-dbg, dev, network, gui, opengl, opengl-dev, script, scripttools, ...} and also
# sudo apt-get install libglew1.5-dev
# sudo apt-get install glutg3-dev
Building (Stand alone)
----------------------
Assuming CoMISo was unpacked to the directory SOME_DIRECTORY/CoMISo (where SOME_DIRECTORY should be /PATH_TO_OPENFLIPPER/libs/CoMISo for integration with the OpenFlipper framework) the package is built by creating a build directory, using cmake to create the Makefiles and using make to actually build:
# cd /SOME_DIRECTORY/CoMISo/
# mkdir build
# cd build
# cmake ..
(assuming all needed packages are installed and cmake threw no errors...)
# make
The binaries (examples) and the shared library are found under
/SOME_DIRECTORY/CoMISO/build/Build/bin/
and
/SOME_DIRECTORY/CoMISO/build/Build/lib/CoMISo/
Building (For use with OpenFlipper)
-----------------------------------
Simply extract/checkout the CoMISo directory to the /PATH_TO_OPENFLIPPER/libs/ directory. The library will be automatically built and you will find the shared library libCoMISo.so under the OpenFlipper build directory.
To use the solver in your Plugin add CoMISo to the CMakeLists.txt of the plugin and you are set, see Plugin-HarmonicExample for an example.
Using
-----
To use the solver library in your applications have a look at the /SOME_DIRECTORY/CoMISo/Examples/ and the sample OpenFlipper plugin (Plugin-HarmonicExample) downloadable from the CoMISo project homepage.
Feedback
--------
We appreciate your feedback! Bugs, comments, questions or patches send them to zimmer@informatik.rwth-aachen.de or bommes@informatik.rwth-aachen.de !

View File

@ -0,0 +1,262 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_SUITESPARSE_AVAILABLE
//=============================================================================
#include "CholmodSolver.hh"
namespace COMISO {
CholmodSolver::CholmodSolver()
{
mp_cholmodCommon = new cholmod_common;
cholmod_start( mp_cholmodCommon );
mp_L = 0;
show_timings_ = false;
mp_cholmodCommon->nmethods = 1;
// use AMD ordering
mp_cholmodCommon->method[0].ordering = CHOLMOD_AMD ;
// use METIS ordering
// mp_cholmodCommon->method[0].ordering = CHOLMOD_METIS ;
// try all methods
// mp_cholmodCommon->nmethods = 9;
}
//-----------------------------------------------------------------------------
CholmodSolver::~CholmodSolver()
{
if( mp_L )
{
cholmod_free_factor( &mp_L, mp_cholmodCommon );
}
cholmod_finish( mp_cholmodCommon );
delete mp_cholmodCommon;
mp_cholmodCommon = NULL;
}
//-----------------------------------------------------------------------------
bool CholmodSolver::calc_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values)
{
if(show_timings_) sw_.start();
colptr_ = _colptr;
rowind_ = _rowind;
values_ = _values;
int n = colptr_.size()-1;
cholmod_sparse matA;
matA.nrow = n;
matA.ncol = n;
matA.nzmax = _values.size();
matA.p = &colptr_[0];
matA.i = &rowind_[0];
matA.x = &values_[0];
matA.nz = 0;
matA.z = 0;
// matA.stype = -1;
matA.stype = 1;
matA.itype = CHOLMOD_INT;
matA.xtype = CHOLMOD_REAL;
matA.dtype = CHOLMOD_DOUBLE;
matA.sorted = 1;
matA.packed = 1;
// clean up
if( mp_L )
{
cholmod_free_factor( &mp_L, mp_cholmodCommon );
mp_L = 0;
}
if(show_timings_)
{
std::cerr << " Cholmod Timing cleanup: " << sw_.stop()/1000.0 << "s\n";
sw_.start();
}
if( !(mp_L = cholmod_analyze( &matA, mp_cholmodCommon )) )
{
std::cout << "cholmod_analyze failed" << std::endl;
return false;
}
// // show selected ordering method
// std::cerr << "best ordering was: " << mp_cholmodCommon->selected << std::endl;
// std::cerr << "current ordering was: " << mp_cholmodCommon->current << std::endl;
if(show_timings_)
{
std::cerr << " Cholmod Timing analyze: " << sw_.stop()/1000.0 << "s\n";
sw_.start();
}
if( !cholmod_factorize( &matA, mp_L, mp_cholmodCommon ) )
{
std::cout << "cholmod_factorize failed" << std::endl;
return false;
}
if(show_timings_)
{
std::cerr << " Cholmod Timing factorize: " << sw_.stop()/1000.0 << "s\n";
sw_.start();
}
return true;
}
//-----------------------------------------------------------------------------
bool CholmodSolver::update_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values )
{
if( !mp_L )
return false;
colptr_ = _colptr;
rowind_ = _rowind;
values_ = _values;
int n = colptr_.size()-1;
cholmod_sparse matA;
matA.nrow = n;
matA.ncol = n;
matA.nzmax = _values.size();
matA.p = &colptr_[0];
matA.i = &rowind_[0];
matA.x = &values_[0];
matA.nz = 0;
matA.z = 0;
// matA.stype = -1;
matA.stype = 1;
matA.itype = CHOLMOD_INT;
matA.xtype = CHOLMOD_REAL;
matA.dtype = CHOLMOD_DOUBLE;
matA.sorted = 1;
matA.packed = 1;
if( !cholmod_factorize( &matA, mp_L, mp_cholmodCommon ) )
{
std::cout << "cholmod_factorize failed" << std::endl;
return false;
}
return true;
}
//-----------------------------------------------------------------------------
bool CholmodSolver::solve( double * _x, double * _b)
{
const unsigned int n = colptr_.size() - 1;
cholmod_dense *x, b;
b.nrow = n;
b.ncol = 1;
b.nzmax = n;
b.d = b.nrow;
b.x = _b;
b.z = 0;
b.xtype = CHOLMOD_REAL;
b.dtype = CHOLMOD_DOUBLE;
if( !(x = cholmod_solve( CHOLMOD_A, mp_L, &b, mp_cholmodCommon )) )
{
std::cout << "cholmod_solve failed" << std::endl;
return false;
}
for( unsigned int i = 0; i < n; ++i )
_x[i] = ((double*)x->x)[i];
cholmod_free_dense( &x, mp_cholmodCommon );
return true;
}
//-----------------------------------------------------------------------------
int CholmodSolver::dimension()
{
return std::max(int(0), (int)(colptr_.size()-1));
}
//-----------------------------------------------------------------------------
bool CholmodSolver::
solve ( std::vector<double>& _x0, std::vector<double>& _b)
{
return solve( &(_x0[0]), &(_b[0]));
}
//-----------------------------------------------------------------------------
bool& CholmodSolver::
show_timings()
{
return show_timings_;
}
}
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,124 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS CholmodSolver
//
//=============================================================================
#ifndef COMISO_CHOLMOD_SOLVER_HH
#define COMISO_CHOLMOD_SOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_SUITESPARSE_AVAILABLE
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <iostream>
#include <vector>
#include "cholmod.h"
// typedef struct cholmod_common_struct cholmod_common;
// typedef struct cholmod_factor_struct cholmod_factor;
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
class COMISODLLEXPORT CholmodSolver
{
public:
// _size is maximal size this instance can handle (smaller problems are possible!!!)
CholmodSolver();
~CholmodSolver();
bool calc_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values );
template< class GMM_MatrixT>
bool calc_system_gmm( const GMM_MatrixT& _mat);
template< class Eigen_MatrixT>
bool calc_system_eigen( const Eigen_MatrixT& _mat);
bool update_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values );
template< class GMM_MatrixT>
bool update_system_gmm( const GMM_MatrixT& _mat);
template< class Eigen_MatrixT>
bool update_system_eigen( const Eigen_MatrixT& _mat);
bool solve ( double * _x0, double * _b);
bool solve ( std::vector<double>& _x0, std::vector<double>& _b);
bool& show_timings();
int dimension();
private:
cholmod_common * mp_cholmodCommon;
cholmod_factor * mp_L;
std::vector<double> values_;
std::vector<int> colptr_;
std::vector<int> rowind_;
bool show_timings_;
StopWatch sw_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_CHOLMOD_SOLVER_TEMPLATES_C)
#define COMISO_CHOLMOD_SOLVER_TEMPLATES
#include "CholmodSolverT.cc"
#endif
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================
#endif // COMISO_CHOLMOD_SOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,131 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_SUITESPARSE_AVAILABLE
//=============================================================================
#define COMISO_CHOLMOD_SOLVER_TEMPLATES_C
#include <CoMISo/Solver/GMM_Tools.hh>
#include <CoMISo/Solver/Eigen_Tools.hh>
#include <CoMISo/Solver/CholmodSolver.hh>
namespace COMISO {
template< class GMM_MatrixT>
bool CholmodSolver::calc_system_gmm( const GMM_MatrixT& _mat)
{
// std::vector<int> colptr;
// std::vector<int> rowind;
// std::vector<double> values;
if(show_timings_) sw_.start();
COMISO_GMM::get_ccs_symmetric_data( _mat,
'u',
values_,
rowind_,
colptr_ );
if(show_timings_)
{
std::cerr << "Cholmod Timing GMM convert: " << sw_.stop()/1000.0 << "s\n";
std::cerr << "#nnz: " << values_.size() << std::endl;
}
return calc_system( colptr_, rowind_, values_);
}
//-----------------------------------------------------------------------------
template< class GMM_MatrixT>
bool CholmodSolver::update_system_gmm( const GMM_MatrixT& _mat)
{
// std::vector<int> colptr;
// std::vector<int> rowind;
// std::vector<double> values;
COMISO_GMM::get_ccs_symmetric_data( _mat,
'u',
values_,
rowind_,
colptr_ );
return update_system( colptr_, rowind_, values_);
}
//-----------------------------------------------------------------------------
template< class Eigen_MatrixT>
bool CholmodSolver::calc_system_eigen( const Eigen_MatrixT& _mat)
{
if(show_timings_) sw_.start();
#if COMISO_EIGEN3_AVAILABLE
COMISO_EIGEN::get_ccs_symmetric_data( _mat,
'u',
values_,
rowind_,
colptr_ );
#endif
if(show_timings_)
{
std::cerr << "Cholmod Timing EIGEN convert: " << sw_.stop()/1000.0 << "s\n";
std::cerr << "#nnz: " << values_.size() << std::endl;
}
return calc_system( colptr_, rowind_, values_);
}
//-----------------------------------------------------------------------------
template< class Eigen_MatrixT>
bool CholmodSolver::update_system_eigen( const Eigen_MatrixT& _mat)
{
#if COMISO_EIGEN3_AVAILABLE
COMISO_EIGEN::get_ccs_symmetric_data( _mat,
'u',
values_,
rowind_,
colptr_ );
#endif
return update_system( colptr_, rowind_, values_);
}
}
//=============================================================================
#endif // COMISO_SUITESPARSE_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,118 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include "ConstrainedSolver.hh"
#include <gmm/gmm.h>
namespace COMISO {
//-----------------------------------------------------------------------------
int
ConstrainedSolver::
find_gcd(std::vector<int>& _v_gcd, int& _n_ints)
{
bool found_gcd = false;
bool done = false;
bool all_same = true;
int i_gcd = -1;
int prev_val = -1;
// check integer coefficient pairwise
while( !done)
{
// assume gcd of all pairs is the same
all_same = true;
for( int k=0; k<_n_ints-1 && !done; ++k)
{
// use abs(.) to get same sign needed for all_same
_v_gcd[k] = abs(gcd(_v_gcd[k],_v_gcd[k+1]));
if( k>0 && prev_val != _v_gcd[k])
all_same = false;
prev_val = _v_gcd[k];
// if a 2 was found, all other entries have to be divisible by 2
if(_v_gcd[k] == 2)
{
bool all_ok=true;
for( int l=0; l<_n_ints; ++l)
if( abs(_v_gcd[l]%2) != 0)
{
all_ok = false;
break;
}
done = true;
if( all_ok )
{
found_gcd = true;
i_gcd = 2;
}
else
{
found_gcd = false;
}
}
}
// already done (by successfull "2"-test)?
if(!done)
{
// all gcds the same?
// we just need to check one final gcd between first 2 elements
if( all_same && _n_ints >1)
{
_v_gcd[0] = abs(gcd(_v_gcd[0],_v_gcd[1]));
// we are done
_n_ints = 1;
}
// only one value left, either +-1 or gcd
if( _n_ints == 1)
{
done = true;
if( (_v_gcd[0])*(_v_gcd[0]) == 1)
{
found_gcd = false;
//std::cerr << __FUNCTION__ << " Info: No gcd found!" << std::endl;
}
else
{
i_gcd = _v_gcd[0];
found_gcd = true;
//std::cerr << __FUNCTION__ << " Info: Found gcd = " << i_gcd << std::endl;
}
}
}
// we now have n_ints-1 gcds to check next iteration
--_n_ints;
}
return i_gcd;
}
//-----------------------------------------------------------------------------
}

View File

@ -0,0 +1,463 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS ConstrainedSolver
//
//=============================================================================
#ifndef COMISO_CONSTRAINEDSOLVER_HH
#define COMISO_CONSTRAINEDSOLVER_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include "GMM_Tools.hh"
#include "MISolver.hh"
#include <vector>
//== FORWARDDECLARATIONS ======================================================
//== DEFINES ==================================================================
#define ROUND(x) ((x)<0?int((x)-0.5):int((x)+0.5))
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class ConstrainedSolver ConstrainedSolver.hh <ACG/.../ConstrainedSolver.hh>
Takes a linear (symmetric) system of equations and a set of linear constraints and solves it.
*/
class COMISODLLEXPORT ConstrainedSolver
{
public:
typedef gmm::csc_matrix<double> CSCMatrix;
typedef gmm::row_matrix< gmm::wsvector< double > > RowMatrix;
/// default Constructor
/** _do_gcd specifies if a greatest common devisor correction should be used when no (+-)1-coefficient is found*/
ConstrainedSolver( bool _do_gcd = true): do_gcd_(_do_gcd)
{ epsilon_ = 1e-8; noisy_ = 1; }
/// Destructor
~ConstrainedSolver() { }
/** @name Contrained solvers
* Functions to solve constrained linear systems of the form Ax=b (stemming from quadratic energies).
* The constraints can be linear constraints of the form \f$ x_1*c_1+ \cdots +x_n*c_n=c \f$ as well as integer constraints \f$x_i\in \mathbf{Z}\f$.
* The system is then solved with these constraints in mind. For solving the system the Mixed-Integer Solver \a MISolver is used.
*/
/*@{*/
/// Quadratic matrix constrained solver
/**
* Takes a system of the form Ax=b, a constraint matrix C and a set of variables _to_round to be rounded to integers. \f$ A\in \mathbf{R}^{n\times n}\f$
* @param _constraints row matrix with rows of the form \f$ [ c_1, c_2, \cdots, c_n, c_{n+1} ] \f$ corresponding to the linear equation \f$ c_1*x_1+\cdots+c_n*x_n + c_{n+1}=0 \f$.
* @param _A nxn-dimensional column matrix of the system
* @param _x n-dimensional variable vector
* @param _rhs n-dimensional right hand side.
* @param _idx_to_round indices i of variables x_i that shall be rounded
* @param _reg_factor regularization factor. Helps unstable, low rank system to become solvable. Adds \f$ \_reg\_factor*mean(trace(_A))*Id \f$ to A.
* @param _show_miso_settings should the (QT) dialog of the Mixed-Integer solver pop up?
* @param _show_timings shall some timings be printed?
*/
template<class RMatrixT, class CMatrixT, class VectorT, class VectorIT >
void solve(
RMatrixT& _constraints,
CMatrixT& _A,
VectorT& _x,
VectorT& _rhs,
VectorIT& _idx_to_round,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// const version of above function
template<class RMatrixT, class CMatrixT, class VectorT, class VectorIT >
void solve_const(
const RMatrixT& _constraints,
const CMatrixT& _A,
VectorT& _x,
const VectorT& _rhs,
const VectorIT& _idx_to_round,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// efficent re-solve with modified _constraint_rhs and/or _rhs (if not modified use 0 pointer)
// by keeping previous _constraints and _A fixed
// _constraint_rhs and _rhs are constant, i.e. not changed
template<class VectorT >
void resolve(
VectorT& _x,
VectorT* _constraint_rhs = 0,
VectorT* _rhs = 0,
bool _show_timings = true );
/// Non-Quadratic matrix constrained solver
/**
* Same as above, but performs the elimination of the constraints directly on the B matrix of \f$ x^\top B^\top Bx \f$, where B has m rows (equations) and (n+1) columns \f$ [ x_1, x_2, \cdots, x_n, -rhs ] \f$.
* \note This function might be more efficient in some cases, but generally the solver for the quadratic matrix above is a safer bet. Needs further testing.
* \note Internally the \f$ A=B^\top B \f$ matrix is formed.
* @param _constraints row matrix with rows of the form \f$ [ c_1, c_2, \cdots, c_n, c_{n+1} ] \f$ corresponding to the linear equation \f$ c_1*x_1+\cdots+c_n*x_n + c_{n+1}=0 \f$.
* @param _B mx(n+1)-dimensional column matrix of the system
* @param _x n-dimensional variable vector
* @param _idx_to_round indices i of variables x_i that shall be rounded
* @param _reg_factor regularization factor. Helps unstable, low rank system to become solvable.
* @param _show_miso_settings should the (QT) dialog of the Mixed-Integer solver pop up?
* @param _show_timings shall some timings be printed?
*/
template<class RMatrixT, class VectorT, class VectorIT >
void solve(
RMatrixT& _constraints,
RMatrixT& _B,
VectorT& _x,
VectorIT& _idx_to_round,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// const version of above function
template<class RMatrixT, class VectorT, class VectorIT >
void solve_const(
const RMatrixT& _constraints,
const RMatrixT& _B,
VectorT& _x,
const VectorIT& _idx_to_round,
double _reg_factor = 0.0,
bool _show_miso_settings = true,
bool _show_timings = true );
// efficent re-solve with modified _rhs by keeping previous _constraints and _A fixed
// ATTENTION: only the rhs resulting from B^TB can be changed!!! otherwise use solve
template<class RMatrixT, class VectorT >
void resolve(
const RMatrixT& _B,
VectorT& _x,
VectorT* _constraint_rhs = 0,
bool _show_timings = true );
/*@}*/
/** @name Eliminate constraints
* Functions to eliminate (or integrate) linear constraints from an equation system. These functions are used internally by the \a solve functions.
*/
/*@{*/
/// Make constraints independent
/**
* This function performs a Gauss elimination on the constraint matrix making the constraints easier to eliminate.
* \note A certain amount of independence of the constraints is assumed.
* \note contradicting constraints will be ignored.
* \warning care must be taken when non-trivial constraints occur where some of the variables contain integer-variables (to be rounded) as the optimal result might not always occur.
* @param _constraints row matrix with constraints
* @param _idx_to_round indices of variables to be rounded (these must be considered.)
* @param _c_elim the "returned" vector of variable indices and the order in which the can be eliminated.
*/
template<class RMatrixT, class VectorIT >
void make_constraints_independent(
RMatrixT& _constraints,
VectorIT& _idx_to_round,
std::vector<int>& _c_elim );
template<class RMatrixT, class VectorIT >
void make_constraints_independent_reordering(
RMatrixT& _constraints,
VectorIT& _idx_to_round,
std::vector<int>& _c_elim );
/// Eliminate constraints on a factored matrix B
/**
* \note Constraints are assumed to have been made independent by \a make_constraints_independent.
* @param _constraints row matrix with constraints (n+1 columns)
* @param _B system row matrix mx(n+1)
* @param _idx_to_round indices to be rounded
* @param _c_elim the indices of the variables to be eliminated.
* @param _new_idx the created re-indexing map. new_idx[i] = -1 means x_i eliminated, new_idx[i] = j means x_i is now at index j.
* @param _Bcol resulting (smaller) column matrix to be used for future computations. (e.g. convert to CSC and solve)
*/
template<class SVector1T, class SVector2T, class VectorIT, class SVector3T>
void eliminate_constraints(
gmm::row_matrix<SVector1T>& _constraints,
gmm::row_matrix<SVector2T>& _B,
VectorIT& _idx_to_round,
std::vector<int>& _c_elim,
std::vector<int>& _new_idx,
gmm::col_matrix<SVector3T>& _Bcol);
/// Eliminate constraints on a quadratic matrix A
/**
* \note Constraints are assumed to have been made independent by \a make_constraints_independent.
* \note _x must have correct size (same as _rhs)
* @param _constraints row matrix with constraints (n+1 columns)
* @param _A system row matrix nxn)
* @param _x variable vector
* @param _rhs right hand side
* @param _idx_to_round indices to be rounded
* @param _c_elim the indices of the variables to be eliminated.
* @param _new_idx the created re-indexing map. new_idx[i] = -1 means x_i eliminated, new_idx[i] = j means x_i is now at index j.
* @param _Acsc resulting (smaller) column (csc) matrix to be used for future computations.
*/
template<class SVector1T, class SVector2T, class VectorIT, class CSCMatrixT>
void eliminate_constraints(
gmm::row_matrix<SVector1T>& _constraints,
gmm::col_matrix<SVector2T>& _A,
std::vector<double>& _x,
std::vector<double>& _rhs,
VectorIT& _idx_to_round,
std::vector<int>& _c_elim,
std::vector<int>& _new_idx,
CSCMatrixT& _Acsc);
/// Restore a solution vector to the un-eliminated size
/**
* @param _constraints row matrix with constraints (n+1 columns)
* @param _x solution vector to reduced/eliminated system (result will also be written here)
* @param _c_elim vector of eliminated indices
* @param _new_idx re-indexing vector
*/
template<class RMatrixT, class VectorT >
void restore_eliminated_vars( RMatrixT& _constraints,
VectorT& _x,
std::vector<int>& _c_elim,
std::vector<int>& _new_idx);
/*@}*/
/// Set numerical epsilon for valid constraint coefficient
void set_epsilon( double _epsilon) { epsilon_ = _epsilon; }
/// Set noise-level (how much std output is given) 0 basically none, 1 important stuff (warning/timing, is default), 2+ not so important
void set_noisy( int _noisy) { noisy_ = _noisy;}
// Get/Set whether the constraint reordering is used (default true)
bool& use_constraint_reordering() { return miso_.use_constraint_reordering(); }
/** @name Verify the result.
* Functions to verify the result of the constrained solver. Are the constraints met, are the correct variables correctly rounded ...
*/
/*@{*/
template<class RMatrixT, class CMatrixT, class VectorT>
double verify_constrained_system(
const RMatrixT& _conditions,
const CMatrixT& _A,
const VectorT& _x,
const VectorT& _rhs,
double _eps = 1e-9);
template<class RMatrixT, class CMatrixT, class VectorT, class VectorIT>
double verify_constrained_system_round(
const RMatrixT& _conditions,
const CMatrixT& _A,
const VectorT& _x,
const VectorT& _rhs,
const VectorIT& _idx_to_round,
double _eps = 1e-9);
template<class RMatrixT, class VectorT, class VectorIT>
void verify_mi_factored( const RMatrixT& _conditions,
const RMatrixT& _B,
const VectorT& _x,
const VectorIT& _idx_to_round );
/*@}*/
/// Access the MISolver (e.g. to change settings)
COMISO::MISolver& misolver() { return miso_;}
private:
template<class RowT, class MatrixT>
void add_row( int _row_i,
double _coeff,
RowT _row,
MatrixT& _mat );
template<class RowT, class RMatrixT, class CMatrixT>
void add_row_simultaneously( int _row_i,
double _coeff,
RowT _row,
RMatrixT& _rmat,
CMatrixT& _cmat );
template<class CMatrixT, class VectorT, class VectorIT>
double setup_and_solve_system( CMatrixT& _B,
VectorT& _x,
VectorIT& _idx_to_round,
double _reg_factor,
bool _show_miso_settings);
// warning: order of replacement not the same as in _columns (internal sort)
template<class CMatrixT>
void eliminate_columns( CMatrixT& _M,
const std::vector< int >& _columns);
inline int gcd( int _a, int _b)
{
while( _b != 0)
{
int t(_b);
_b = _a%_b;
_a = t;
}
return _a;
}
int find_gcd(std::vector<int>& _v_gcd, int& _n_ints);
// TODO if no gcd correction was possible, at least use a variable divisible by 2 as new elim_j (to avoid in-exactness e.g. 1/3)
template<class RMatrixT>
bool update_constraint_gcd( RMatrixT& _constraints,
int _row_i,
int& _elim_j,
std::vector<int>& _v_gcd,
int& _n_ints);
private:
/// Copy constructor (not used)
ConstrainedSolver(const ConstrainedSolver& _rhs);
/// Assignment operator (not used)
ConstrainedSolver& operator=(const ConstrainedSolver& _rhs);
// MISO solver
COMISO::MISolver miso_;
double epsilon_;
int noisy_;
bool do_gcd_;
// --------------- Update by Marcel to enable efficient re-solve with changed rhs ----------------------
// Store for symbolic elimination information for rhs
class rhsUpdateTable {
public:
void append(int _i, double _f, int _j, bool _flag)
{
// std::cerr << "append " << _i << ", " << _j << ", " << _f << ", " << int(_flag) << std::endl;
table_.push_back(rhsUpdateTableEntry(_i, _j, _f, _flag));
}
void add_elim_id(int _i) { elim_var_ids_.push_back(_i); }
void clear() { table_.clear(); elim_var_ids_.clear(); }
// apply stored transformations to _rhs
void apply(std::vector<double>& _constraint_rhs, std::vector<double>& _rhs)
{
std::vector<rhsUpdateTableEntry>::const_iterator t_it, t_end;
t_end = table_.end();
int cur_j = -1;
double cur_rhs = 0.0;
for(t_it = table_.begin(); t_it != t_end; ++t_it)
{
if(t_it->rhs_flag)
_rhs[t_it->i] += t_it->f*_constraint_rhs[t_it->j];
else
{
if(t_it->j != cur_j) { cur_j = t_it->j; cur_rhs = _rhs[cur_j]; }
_rhs[t_it->i] += t_it->f * cur_rhs;
}
}
}
// remove eliminated elements from _rhs
void eliminate(std::vector<double>& _rhs)
{
std::vector<int> evar( elim_var_ids_ );
std::sort( evar.begin(), evar.end() );
evar.push_back( std::numeric_limits<int>::max() );
int cur_evar_idx=0;
unsigned int nc = _rhs.size();
for( unsigned int i=0; i<nc; ++i )
{
unsigned int next_i = evar[cur_evar_idx];
if ( i != next_i ) _rhs[i-cur_evar_idx] = _rhs[i];
else ++cur_evar_idx;
}
_rhs.resize( nc - cur_evar_idx );
}
// store transformed constraint matrix and index map to allow for later re-substitution
template<class RMatrixT>
void store(const RMatrixT& _constraints, const std::vector<int>& _c_elim, const std::vector<int>& _new_idx)
{
constraints_p_.resize( gmm::mat_nrows(_constraints), gmm::mat_ncols(_constraints));
gmm::copy(_constraints, constraints_p_);
c_elim_ = _c_elim;
new_idx_ = _new_idx;
}
private:
class rhsUpdateTableEntry {
public:
rhsUpdateTableEntry(int _i, int _j, double _f, bool _rhs_flag) : i(_i), j(_j), f(_f), rhs_flag(_rhs_flag) {}
int i;
int j;
double f;
bool rhs_flag;
};
std::vector<rhsUpdateTableEntry> table_;
std::vector<int> elim_var_ids_;
public:
std::vector<int> c_elim_;
std::vector<int> new_idx_;
RowMatrix constraints_p_;
// cache current rhs_ and constraint_rhs_ and linear transformation of constraint_rhs_ D_
RowMatrix D_;
std::vector<double> cur_rhs_;
// constraint_rhs after Gaussian elimination update D*constraint_rhs_orig_
std::vector<double> cur_constraint_rhs_;
} rhs_update_table_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_CONSTRAINEDSOLVER_C)
#define COMISO_CONSTRAINEDSOLVER_TEMPLATES
#include "ConstrainedSolverT.cc"
#endif
//=============================================================================
#endif // COMISO_CONSTRAINEDSOLVER_HH defined
//=============================================================================

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include "EigenLDLTSolver.hh"
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#if (COMISO_EIGEN3_AVAILABLE)
//== INCLUDES =================================================================
namespace COMISO {
EigenLDLTSolver::EigenLDLTSolver() : n_(0)
{
}
//-----------------------------------------------------------------------------
EigenLDLTSolver::~EigenLDLTSolver()
{
}
//-----------------------------------------------------------------------------
bool EigenLDLTSolver::calc_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values)
{
std::cerr << "Info: EigenLDLTSolver::calc_system( const std::vector<int> ...) not implemented yet..." << std::endl;
return false;
}
//-----------------------------------------------------------------------------
bool EigenLDLTSolver::update_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values )
{
std::cerr << "Info: EigenLDLTSolver::update_system( const std::vector<int> ...) not implemented yet..." << std::endl;
return false;
}
//-----------------------------------------------------------------------------
bool EigenLDLTSolver::solve( double * _x, double * _b)
{
// map arrays to Eigen-Vectors
Eigen::Map<Eigen::VectorXd> x(_x,n_);
Eigen::Map<Eigen::VectorXd> b(_b,n_);
// solve for another right hand side:
x = ldlt_.solve(b);
return (ldlt_.info()==Eigen::Success);
}
//-----------------------------------------------------------------------------
int EigenLDLTSolver::dimension()
{
return n_;
}
//-----------------------------------------------------------------------------
bool EigenLDLTSolver::
solve ( std::vector<double>& _x0, std::vector<double>& _b)
{
return solve( &(_x0[0]), &(_b[0]));
}
//-----------------------------------------------------------------------------
bool& EigenLDLTSolver::
show_timings()
{
return show_timings_;
}
}
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,121 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS CholmodSolver
//
//=============================================================================
#ifndef COMISO_EIGEN_LDLT_SOLVER_HH
#define COMISO_EIGEN_LDLT_SOLVER_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if (COMISO_EIGEN3_AVAILABLE)
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <CoMISo/Utils/StopWatch.hh>
#include <iostream>
#include <vector>
#include <Eigen/Eigen>
#include <Eigen/Sparse>
#include <Eigen/SparseCholesky>
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
class COMISODLLEXPORT EigenLDLTSolver
{
public:
// _size is maximal size this instance can handle (smaller problems are possible!!!)
EigenLDLTSolver();
~EigenLDLTSolver();
bool calc_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values );
template< class GMM_MatrixT>
bool calc_system_gmm( const GMM_MatrixT& _mat);
template< class Eigen_MatrixT>
bool calc_system_eigen( const Eigen_MatrixT& _mat);
bool update_system( const std::vector<int>& _colptr,
const std::vector<int>& _rowind,
const std::vector<double>& _values );
template< class GMM_MatrixT>
bool update_system_gmm( const GMM_MatrixT& _mat);
template< class Eigen_MatrixT>
bool update_system_eigen( const Eigen_MatrixT& _mat);
bool solve ( double * _x0, double * _b);
bool solve ( std::vector<double>& _x0, std::vector<double>& _b);
bool& show_timings();
int dimension();
private:
// dimension n_
unsigned int n_;
Eigen::SimplicialLDLT<Eigen::SparseMatrix<double> > ldlt_;
bool show_timings_;
StopWatch sw_;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_EIGEN_LDLT_SOLVER_TEMPLATES_C)
#define COMISO_EIGEN_LDLT_SOLVER_TEMPLATES
#include "EigenLDLTSolverT.cc"
#endif
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================
#endif // COMISO_EIGEN_LDLT_SOLVER_HH defined
//=============================================================================

View File

@ -0,0 +1,119 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if (COMISO_EIGEN3_AVAILABLE)
//== INCLUDES =================================================================
#define COMISO_EIGEN_LDLT_SOLVER_TEMPLATES_C
#include <CoMISo/Solver/GMM_Tools.hh>
#include <CoMISo/Solver/Eigen_Tools.hh>
#include <CoMISo/Solver/EigenLDLTSolver.hh>
namespace COMISO {
template< class GMM_MatrixT>
bool EigenLDLTSolver::calc_system_gmm( const GMM_MatrixT& _mat)
{
if(show_timings_) sw_.start();
Eigen::SparseMatrix<double> E;
COMISO_EIGEN::gmm_to_eigen(_mat, E);
if(show_timings_)
{
std::cerr << "EigenLDLT Timing GMM convert: " << sw_.stop()/1000.0 << "s\n";
std::cerr << "#nnz: " << E.nonZeros() << std::endl;
}
return calc_system_eigen( E);
}
//-----------------------------------------------------------------------------
template< class GMM_MatrixT>
bool EigenLDLTSolver::update_system_gmm( const GMM_MatrixT& _mat)
{
if(show_timings_) sw_.start();
Eigen::SparseMatrix<double> E;
COMISO_EIGEN::gmm_to_eigen(_mat, E);
if(show_timings_)
{
std::cerr << "EigenLDLT Timing GMM convert: " << sw_.stop()/1000.0 << "s\n";
std::cerr << "#nnz: " << E.nonZeros() << std::endl;
}
return update_system_eigen( E);
}
//-----------------------------------------------------------------------------
template< class Eigen_MatrixT>
bool EigenLDLTSolver::calc_system_eigen( const Eigen_MatrixT& _mat)
{
n_ = _mat.rows();
if(show_timings_) sw_.start();
ldlt_.compute(_mat);
if(show_timings_)
{
std::cerr << "EigenLDLT Timing EIGEN compute: " << sw_.stop()/1000.0 << "s\n";
}
return (ldlt_.info()==Eigen::Success);
}
//-----------------------------------------------------------------------------
template< class Eigen_MatrixT>
bool EigenLDLTSolver::update_system_eigen( const Eigen_MatrixT& _mat)
{
if(show_timings_) sw_.start();
ldlt_.factorize(_mat);
if(show_timings_)
{
std::cerr << "EigenLDLT Timing EIGEN factorize: " << sw_.stop()/1000.0 << "s\n";
}
return (ldlt_.info()==Eigen::Success );
}
}
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,684 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS Eigen_Tools - IMPLEMENTATION
//
//=============================================================================
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_EIGEN3_AVAILABLE
#define COMISO_Eigen_TOOLS_C
//== INCLUDES =================================================================
#include "Eigen_Tools.hh"
#include <queue>
#include <CoMISo/Utils/StopWatch.hh>
#include <CoMISo/Utils/VSToolsT.hh>
#include <gmm/gmm.h>
//== NAMESPACES ===============================================================
namespace COMISO_EIGEN
{
//== IMPLEMENTATION ==========================================================
//-----------------------------------------------------------------------------
template<class MatrixT, class REALT, class INTT>
void get_ccs_symmetric_data( const MatrixT& _mat,
const char _uplo,
std::vector<REALT>& _values,
std::vector<INTT>& _rowind,
std::vector<INTT>& _colptr )
{
// Assumes col major
int m = _mat.innerSize();
int n = _mat.outerSize();
_values.resize( 0 );
_rowind.resize( 0 );
_colptr.resize( 0 );
INTT iv( 0 );
typedef typename MatrixT::InnerIterator It;
switch ( _uplo )
{
case 'l':
case 'L':
// for all columns
for ( int i=0; i<n; ++i )
{
_colptr.push_back( iv );
// row it
It it(_mat, i);
for( ; it; ++it)
{
if( it.index() >= i )
{
_values.push_back( it.value());
_rowind.push_back( it.index());
++iv;
}
}
}
_colptr.push_back( iv );
break;
case 'u':
case 'U':
// for all columns
for ( int i=0; i<n; ++i )
{
_colptr.push_back( iv );
// row it
It it(_mat, i);
for( ; it; ++it)
{
if( it.index() <= i )
{
_values.push_back( it.value());
_rowind.push_back( it.index());
++iv;
}
}
}
_colptr.push_back( iv );
break;
case 'c':
case 'C':
// for all columns
for ( int i=0; i<n; ++i )
{
_colptr.push_back( iv );
// row it
It it(_mat, i);
for( ; it; ++it)
{
_values.push_back( it.value());
_rowind.push_back( it.index());
++iv;
}
}
_colptr.push_back( iv );
break;
default:
std::cerr << "ERROR: parameter uplo must bei either 'U' or 'L' or 'C'!!!\n";
break;
}
}
//-----------------------------------------------------------------------------
// inspect the matrix: dimension, symmetry, zero_rows, zero_cols, nnz, max, min, max_abs, min_abs, NAN, INF
template<class MatrixT>
void inspect_matrix( const MatrixT& _A)
{
std::cerr << "################### INSPECT MATRIX ##################\n";
std::cerr << "#outer size : " << _A.outerSize() << std::endl;
std::cerr << "#inner size : " << _A.innerSize() << std::endl;
std::cerr << "#rows : " << _A.rows() << std::endl;
std::cerr << "#cols : " << _A.cols() << std::endl;
std::cerr << "#nonzeros : " << _A.nonZeros() << std::endl;
std::cerr << "#nonzeros/row: " << (double(_A.nonZeros())/double(_A.rows())) << std::endl;
std::cerr << "symmetric : " << is_symmetric( _A) << std::endl;
MatrixT trans( _A.transpose());
int zero_rows = 0;
int zero_cols = 0;
for(int i=0; i<_A.outerSize(); ++i)
{
typename MatrixT::InnerIterator it(_A, i);
if( !it) ++zero_rows;
}
for(int i=0; i<trans.outerSize(); ++i)
{
typename MatrixT::InnerIterator it(trans, i);
if( !it) ++zero_cols;
}
std::cerr << "zero rows : " << zero_rows << std::endl;
std::cerr << "zero cols : " << zero_cols << std::endl;
typedef typename MatrixT::Scalar Scalar;
Scalar vmin = std::numeric_limits<Scalar>::max();
Scalar vmax = std::numeric_limits<Scalar>::min();
Scalar vmin_abs = std::numeric_limits<Scalar>::max();
Scalar vmax_abs = 0;
int n_nan = 0;
int n_inf = 0;
// inspect elements
for(int i=0; i<_A.outerSize(); ++i)
{
typename MatrixT::InnerIterator it( _A, i);
for(; it ; ++it)
{
if( it.value() < vmin ) vmin = it.value();
if( it.value() > vmax ) vmax = it.value();
if( fabs(it.value()) < vmin_abs) vmin_abs = fabs(it.value());
if( fabs(it.value()) > vmax_abs) vmax_abs = fabs(it.value());
if( std::isnan(it.value())) ++n_nan;
if( std::isinf(it.value())) ++n_inf;
}
}
std::cerr << "min val : " << vmin << std::endl;
std::cerr << "max val : " << vmax << std::endl;
std::cerr << "min |val| : " << vmin_abs << std::endl;
std::cerr << "max |val| : " << vmax_abs << std::endl;
std::cerr << "#nan : " << n_nan << std::endl;
std::cerr << "#inf : " << n_inf << std::endl;
std::cerr << "min eval : " << "..." << std::endl;
std::cerr << "max eval : " << "..." << std::endl;
std::cerr << "min|eval| : " << "..." << std::endl;
std::cerr << "max|eval| : " << "..." << std::endl;
}
//-----------------------------------------------------------------------------
// symmetric ?
template<class MatrixT>
bool is_symmetric( const MatrixT& _A)
{
typedef typename MatrixT::InnerIterator It;
typedef typename MatrixT::Scalar Scalar;
int nouter( _A.outerSize());
int ninner( _A.innerSize());
if( nouter != ninner )
return false;
bool symmetric(true);
for( int c = 0; c < nouter; ++c)
{
for( It it(_A,c); it; ++it)
{
int r(it.index());
Scalar val(it.value());
// find diagonal partner element
bool found(false);
for( It dit(_A,r); dit; ++dit)
{
if( dit.index() < c )
{}
else if( dit.index() == c)
{
if( dit.value() == val)
found = true;
break;
}
else
{
break;
}
}
if( !found)
{
symmetric = false;
break;
}
}
}
return symmetric;
}
//-----------------------------------------------------------------------------
template< class Eigen_MatrixT, class IntT >
void permute( const Eigen_MatrixT& _QR, const std::vector< IntT>& _Pvec, Eigen_MatrixT& _A)
{
#ifdef COMISO_EIGEN3_AVAILABLE
typedef typename Eigen_MatrixT::Scalar Scalar;
int m = _QR.innerSize();
int n = _QR.outerSize();
if( _Pvec.size() == 0)
{
_A = _QR;
return;
}
if( _Pvec.size() != (size_t)_QR.cols() && _Pvec.size() != 0)
{
std::cerr << __FUNCTION__ << " wrong size of permutation vector, should have #cols length (or zero)" << std::endl;
}
// build sparse permutation matrix
typedef Eigen::Triplet< Scalar > Triplet;
std::vector< Triplet > triplets;
triplets.reserve(_QR.nonZeros());
_A = Eigen_MatrixT( m, n);
typedef typename Eigen_MatrixT::InnerIterator It;
for( int c = 0; c < n; ++c) // cols
{
for( It it(_QR,c); it; ++it) // rows
{
int r(it.index());
Scalar val(it.value());
int newcol( _Pvec[c]);
triplets.push_back( Triplet( r, newcol, val));
}
}
_A.setFromTriplets( triplets.begin(), triplets.end());
#endif
}
//-----------------------------------------------------------------------------
#if COMISO_SUITESPARSE_AVAILABLE
/// Eigen to Cholmod_sparse interface
template<class MatrixT>
void cholmod_to_eigen( const cholmod_sparse& _AC, MatrixT& _A)
{
#ifdef COMISO_EIGEN3_AVAILABLE
// initialize dimensions
typedef typename MatrixT::Scalar Scalar;
typedef Eigen::Triplet< Scalar > Triplet;
size_t nzmax( _AC.nzmax);
std::cerr << __FUNCTION__ << " row " << _AC.nrow << " col " << _AC.ncol << " stype " << _AC.stype << std::endl;
_A = MatrixT(_AC.nrow, _AC.ncol);
std::vector< Triplet > triplets;
triplets.reserve(nzmax);
if(!_AC.packed)
{
std::cerr << "Warning: " << __FUNCTION__ << " does not support unpacked matrices yet!!!" << std::endl;
return;
}
// Pointer to data
double* X((double*)_AC.x);
// complete matrix stored
if(_AC.stype == 0)
{
// which integer type?
if(_AC.itype == CHOLMOD_LONG)
{
UF_long* P((UF_long*)_AC.p);
UF_long* I((UF_long*)_AC.i);
for(UF_long i=0; i<(UF_long)_AC.ncol; ++i)
for(UF_long j= P[i]; j< P[i+1]; ++j)
//_A( I[j], i) += X[j]; // += really needed?
triplets.push_back( Triplet( I[j], i, X[j]));
}
else
{
int* P((int*)_AC.p);
int* I((int*)_AC.i);
for(int i=0; i<(int)_AC.ncol; ++i)
for(int j= P[i]; j< P[i+1]; ++j)
triplets.push_back( Triplet( I[j], i, X[j]));
//_A( I[j], i) += X[j];
}
}
else // only upper or lower diagonal stored
{
// which integer type?
if(_AC.itype == CHOLMOD_LONG)
{
UF_long* P((UF_long*)_AC.p);
UF_long* I((UF_long*)_AC.i);
for(UF_long i=0; i<(UF_long)_AC.ncol; ++i)
for(UF_long j=P[i]; j<P[i+1]; ++j)
{
//_A(I[j], i) += X[j];
triplets.push_back( Triplet( I[j], i, X[j]));
// add up symmetric part
if( I[j] != i)
triplets.push_back( Triplet( i, I[j], X[j]));
//_A(i,I[j]) += X[j];
}
}
else
{
int* P((int*)_AC.p);
int* I((int*)_AC.i);
for(int i=0; i<(int)_AC.ncol; ++i)
for(int j=P[i]; j<P[i+1]; ++j)
{
//_A(I[j], i) += X[j];
triplets.push_back( Triplet( I[j], i, X[j]));
// add up symmetric part
if( I[j] != i)
// _A(i,I[j]) += X[j];
triplets.push_back( Triplet( i, I[j], X[j]));
}
}
}
_A.setFromTriplets( triplets.begin(), triplets.end());
#endif
}
/// GMM to Cholmod_sparse interface
template<class MatrixT>
void eigen_to_cholmod( const MatrixT& _A, cholmod_sparse* &_AC, cholmod_common* _common, int _sparsity_type, bool _long_int)
{
/* _sparsity_type
* 0: matrix is "unsymmetric": use both upper and lower triangular parts
* (the matrix may actually be symmetric in pattern and value, but
* both parts are explicitly stored and used). May be square or
* rectangular.
* >0: matrix is square and symmetric, use upper triangular part.
* Entries in the lower triangular part are ignored.
* <0: matrix is square and symmetric, use lower triangular part.
* Entries in the upper triangular part are ignored. */
int m = _A.innerSize();
int n = _A.outerSize();
// get upper or lower
char uplo = 'c';
if(_sparsity_type < 0) uplo = 'l';
if(_sparsity_type > 0) uplo = 'u';
if( _long_int) // long int version
{
std::vector<double> values;
std::vector<UF_long> rowind;
std::vector<UF_long> colptr;
// get data of gmm matrix
COMISO_EIGEN::get_ccs_symmetric_data( _A, uplo, values, rowind, colptr);
// allocate cholmod matrix
_AC = cholmod_l_allocate_sparse(m,n,values.size(),true,true,_sparsity_type,CHOLMOD_REAL, _common);
// copy data to cholmod matrix
for(UF_long i=0; i<(UF_long)values.size(); ++i)
{
((double*) (_AC->x))[i] = values[i];
((UF_long*)(_AC->i))[i] = rowind[i];
}
for(UF_long i=0; i<(UF_long)colptr.size(); ++i)
((UF_long*)(_AC->p))[i] = colptr[i];
}
else // int version
{
std::vector<double> values;
std::vector<int> rowind;
std::vector<int> colptr;
// get data of gmm matrix
COMISO_EIGEN::get_ccs_symmetric_data( _A, uplo, values, rowind, colptr);
// allocate cholmod matrix
_AC = cholmod_allocate_sparse(m,n,values.size(),true,true,_sparsity_type,CHOLMOD_REAL, _common);
// copy data to cholmod matrix
for(unsigned int i=0; i<values.size(); ++i)
{
((double*)(_AC->x))[i] = values[i];
((int*) (_AC->i))[i] = rowind[i];
}
for(unsigned int i=0; i<colptr.size(); ++i)
((int*)(_AC->p))[i] = colptr[i];
}
}
#endif
/*
/// Eigen to Cholmod_dense interface
template<class MatrixT>
void cholmod_to_eigen_dense( const cholmod_dense& _AC, MatrixT& _A)
{
// initialize dimensions
typedef typename MatrixT::Scalar Scalar;
typedef Eigen::Triplet< Scalar > Triplet;
size_t nzmax( _AC.nzmax);
_A = MatrixT(_AC.nrow, _AC.ncol);
std::vector< Triplet > triplets;
triplets.reserve(nzmax);
if(!_AC.packed)
{
std::cerr << "Warning: " << __FUNCTION__ << " does not support unpacked matrices yet!!!" << std::endl;
return;
}
// Pointer to data
double* X((double*)_AC.x);
// complete matrix stored
if(_AC.stype == 0)
{
// which integer type?
if(_AC.itype == CHOLMOD_LONG)
{
UF_long* P((UF_long*)_AC.p);
UF_long* I((UF_long*)_AC.i);
for(UF_long i=0; i<(UF_long)_AC.ncol; ++i)
for(UF_long j= P[i]; j< P[i+1]; ++j)
//_A( I[j], i) += X[j]; // += really needed?
triplets.push_back( Triplet( I[j], i, X[j]));
}
else
{
int* P((int*)_AC.p);
int* I((int*)_AC.i);
for(int i=0; i<(int)_AC.ncol; ++i)
for(int j= P[i]; j< P[i+1]; ++j)
triplets.push_back( Triplet( I[j], i, X[j]));
//_A( I[j], i) += X[j];
}
}
else // only upper or lower diagonal stored
{
// which integer type?
if(_AC.itype == CHOLMOD_LONG)
{
UF_long* P((UF_long*)_AC.p);
UF_long* I((UF_long*)_AC.i);
for(UF_long i=0; i<(UF_long)_AC.ncol; ++i)
for(UF_long j=P[i]; j<P[i+1]; ++j)
{
//_A(I[j], i) += X[j];
triplets.push_back( Triplet( I[j], i, X[j]));
// add up symmetric part
if( I[j] != i)
triplets.push_back( Triplet( i, I[j], X[j]));
//_A(i,I[j]) += X[j];
}
}
else
{
int* P((int*)_AC.p);
int* I((int*)_AC.i);
for(int i=0; i<(int)_AC.ncol; ++i)
for(int j=P[i]; j<P[i+1]; ++j)
{
//_A(I[j], i) += X[j];
triplets.push_back( Triplet( I[j], i, X[j]));
// add up symmetric part
if( I[j] != i)
// _A(i,I[j]) += X[j];
triplets.push_back( Triplet( i, I[j], X[j]));
}
}
}
_A.setFromTriplets( triplets.begin(), triplets.end());
}
/// GMM to Cholmod_sparse interface
template<class MatrixT>
void eigen_to_cholmod_dense( const MatrixT& _A, cholmod_dense* &_AC, cholmod_common* _common, bool _long_int)
{
int m = _A.innerSize();
int n = _A.outerSize();
// allocate cholmod matrix
_AC = cholmod_l_allocate_sparse(m,n,values.size(),true,true,_sparsity_type,CHOLMOD_REAL, _common);
_AC = cholmod_l_allocate_dense (m,n,n, xtype, cc)
if( _long_int) // long int version
{
std::vector<double> values;
std::vector<UF_long> rowind;
std::vector<UF_long> colptr;
// get data of gmm matrix
COMISO_EIGEN::get_ccs_symmetric_data( _A, uplo, values, rowind, colptr);
// allocate cholmod matrix
_AC = cholmod_l_allocate_sparse(m,n,values.size(),true,true,_sparsity_type,CHOLMOD_REAL, _common);
// copy data to cholmod matrix
for(UF_long i=0; i<(UF_long)values.size(); ++i)
{
((double*) (_AC->x))[i] = values[i];
((UF_long*)(_AC->i))[i] = rowind[i];
}
for(UF_long i=0; i<(UF_long)colptr.size(); ++i)
((UF_long*)(_AC->p))[i] = colptr[i];
}
else // int version
{
std::vector<double> values;
std::vector<int> rowind;
std::vector<int> colptr;
// get data of gmm matrix
COMISO_EIGEN::get_ccs_symmetric_data( _A, uplo, values, rowind, colptr);
// allocate cholmod matrix
_AC = cholmod_allocate_sparse(m,n,values.size(),true,true,_sparsity_type,CHOLMOD_REAL, _common);
// copy data to cholmod matrix
for(unsigned int i=0; i<values.size(); ++i)
{
((double*)(_AC->x))[i] = values[i];
((int*) (_AC->i))[i] = rowind[i];
}
for(unsigned int i=0; i<colptr.size(); ++i)
((int*)(_AC->p))[i] = colptr[i];
}
}*/
// convert a gmm col-sparse matrix into an eigen sparse matrix
template<class GMM_MatrixT, class EIGEN_MatrixT>
void gmm_to_eigen( const GMM_MatrixT& _G, EIGEN_MatrixT& _E)
{
#ifdef COMISO_EIGEN3_AVAILABLE
typedef typename EIGEN_MatrixT::Scalar Scalar;
typedef typename gmm::linalg_traits<GMM_MatrixT>::const_sub_col_type ColT;
typedef typename gmm::linalg_traits<ColT>::const_iterator CIter;
// build matrix triplets
typedef Eigen::Triplet< Scalar > Triplet;
std::vector< Triplet > triplets;
triplets.reserve(gmm::nnz(_G));
for(unsigned int i=0; i<gmm::mat_ncols(_G); ++i)
{
ColT col = mat_const_col( _G, i );
CIter it = gmm::vect_const_begin( col );
CIter ite = gmm::vect_const_end( col );
for ( ; it!=ite; ++it )
triplets.push_back( Triplet( it.index(), i, *it));
}
// generate eigen matrix
_E = EIGEN_MatrixT( gmm::mat_nrows(_G), gmm::mat_ncols(_G));
_E.setFromTriplets( triplets.begin(), triplets.end());
#endif
}
//=============================================================================
} // namespace COMISO
//=============================================================================
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================

View File

@ -0,0 +1,129 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#ifndef COMISO_Eigen_TOOLS_HH
#define COMISO_Eigen_TOOLS_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
#if COMISO_EIGEN3_AVAILABLE
//== INCLUDES =================================================================
#include <iostream>
#include <vector>
#include <algorithm>
#include <limits>
#include <cmath>
#include <Eigen/Dense>
#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET
#include <Eigen/Sparse>
#if COMISO_SUITESPARSE_AVAILABLE
#include <cholmod.h>
#endif
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO_EIGEN
{
/** \class EigenTools Eigen_Tools.hh
A collection of helper functions for manipulating (Eigen) matrices.
*/
//== FUNCTION DEFINITION ======================================================
/// Get matrix data (CSC matrix format) from matrix
/** Used by Cholmod wrapper
* @param _mat matrix
* @param _c uplo parameter (l, L, u, U, c, C)
* @param _values values vector
* @param _rowind row indices
* @param _colptr column pointer */
template<class MatrixT, class REALT, class INTT>
void get_ccs_symmetric_data( const MatrixT& _mat,
const char _c,
std::vector<REALT>& _values,
std::vector<INTT>& _rowind,
std::vector<INTT>& _colptr );
/// Inspect the matrix (print)
/** Prints useful matrix informations such as, dimension, symmetry, zero_rows, zero_cols, nnz, max, min, max_abs, min_abs, NAN, INF
* @param _A matrix */
template<class MatrixT>
void inspect_matrix( const MatrixT& _A);
/** checks for symmetry
* @param _A matrix
* @return symmetric? (bool)*/
template<class MatrixT>
bool is_symmetric( const MatrixT& _A);
template< class Eigen_MatrixT, class IntT >
void permute( const Eigen_MatrixT& _QR, const std::vector< IntT>& _Pvec, Eigen_MatrixT& _A);
#if COMISO_SUITESPARSE_AVAILABLE
/// Eigen to Cholmod_sparse interface
template<class MatrixT>
void cholmod_to_eigen( const cholmod_sparse& _AC, MatrixT& _A);
template<class MatrixT>
void eigen_to_cholmod( const MatrixT& _A,
cholmod_sparse* &_AC,
cholmod_common* _common,
int _sparsity_type = 0,
bool _long_int = false);
#endif
// convert a gmm column-sparse matrix into an eigen sparse matrix
template<class GMM_MatrixT, class EIGEN_MatrixT>
void gmm_to_eigen( const GMM_MatrixT& _G, EIGEN_MatrixT& _E);
//=============================================================================
} // namespace COMISO_Eigen
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_Eigen_TOOLS_C)
#define COMISO_Eigen_TOOLS_TEMPLATES
#include "Eigen_Tools.cc"
#endif
//=============================================================================
#endif // COMISO_EIGEN3_AVAILABLE
//=============================================================================//=============================================================================
#endif // Eigen_TOOLS_HH defined
//=============================================================================

1262
src/external/CoMISo/Solver/GMM_Tools.cc vendored Normal file

File diff suppressed because it is too large Load Diff

275
src/external/CoMISo/Solver/GMM_Tools.hh vendored Normal file
View File

@ -0,0 +1,275 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#ifndef COMISO_GMM_TOOLS_HH
#define COMISO_GMM_TOOLS_HH
//== COMPILE-TIME PACKAGE REQUIREMENTS ========================================
#include <CoMISo/Config/config.hh>
//== INCLUDES =================================================================
#include <iostream>
#include <vector>
#include <algorithm>
#include <gmm/gmm.h>
#if COMISO_SUITESPARSE_AVAILABLE
#include <cholmod.h>
#endif
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO_GMM
{
/** \class GMMTools GMM_Tools.hh
A collection of helper functions for manipulating (gmm) matrices.
*/
//== FUNCTION DEFINITION ======================================================
/** @name Variable elimination
* These functions are used to eliminate (one or more) variables x_i from an equation system Ax=b. Elimination meaning that x_i has been assigned a value x_i = c and is considered a constant, this changes entries of the matrix which depend on i and finally "eliminates" the ith row and column and updates the rhs. */
/*@{*/
/// Eliminate multiple variables from a CSC matrix.
/**
* \note eliminate_csc_vars2 is probably more efficient
* @param _evar indices of variables to be eliminated
* @param _eval values c_i of x_i to be eliminated, x_i = c_i
* @param _A CSC Matrix of the equation system
* @param _x variable vector of equation system
* @param _rhs right-hand side vector of equation system */
template<class ScalarT, class VectorT, class RealT, class IntegerT>
void eliminate_csc_vars(
const std::vector<IntegerT>& _evar,
const std::vector<ScalarT>& _eval,
typename gmm::csc_matrix<RealT>& _A,
VectorT& _x,
VectorT& _rhs );
/// Eliminate variables from a CSC matric.
template<class ScalarT, class VectorT, class RealT, class IntegerT>
void eliminate_csc_vars2(
const std::vector<IntegerT>& _evar,
const std::vector<ScalarT>& _eval,
typename gmm::csc_matrix<RealT>& _A,
VectorT& _x,
VectorT& _rhs );
/// Eliminate only one variable x_i = c (CSC matrices)
/** Specialization to eliminating one varaible
* @param _j index of variable to be eliminated
* @param _value_j value c of x_i to be eliminated, x_i = c
* @param _A CSC Matrix of the equation system
* @param _x variable vector of equation system
* @param _rhs right-hand side vector of equation system */
template<class ScalarT, class VectorT, class RealT>
void eliminate_var(
const unsigned int _j,
const ScalarT _value_j,
typename gmm::csc_matrix<RealT>& _A,
VectorT& _x,
VectorT& _rhs );
/// eliminate multiple variables from a (NON CSC) linear system by fixin x[j] = _value_j
/**
* @param _evar indices of variables to be eliminated
* @param _eval values c_i of x_i to be eliminated, x_i = c_i
* @param _A (non-CSC) Matrix of the equation system
* @param _x variable vector of equation system
* @param _rhs right-hand side vector of equation system */
template<class IntegerT, class ScalarT, class VectorT, class MatrixT>
void eliminate_vars(
const std::vector<IntegerT>& _evar,
const std::vector<ScalarT>& _eval,
MatrixT& _A,
VectorT& _x,
VectorT& _rhs );
/// Eliminate only one variable x_i = c (non-CSC matrices)
/** Specialization to eliminating one varaible
* @param _j index of variable to be eliminated
* @param _value_j value c of x_i to be eliminated, x_i = c
* @param _A (non-CSC) Matrix of the equation system
* @param _x variable vector of equation system
* @param _rhs right-hand side vector of equation system */
template<class ScalarT, class VectorT, class SVT>
void eliminate_var(
const unsigned int _j,
const ScalarT _value_j,
gmm::col_matrix<SVT>& _A,
VectorT& _x,
VectorT& _rhs );
/// update indices of eliminated variables
/**
* @param _evar indices of variables that were eliminated
* @param _idx index map to be changed.
* @param _dummy value to which eliminated entries of _idx are set. */
template<class IntegerT, class IntegerT2>
void eliminate_vars_idx(
const std::vector<IntegerT >& _evar,
std::vector<IntegerT2>& _idx,
IntegerT2 _dummy = -1,
IntegerT2 _range = -1);
/// update index of eliminated variable
/** Specialization to update only one eliminated variable
* @param _evar index of variable that was eliminated
* @param _idx index map to be changed.
* @param _dummy value to which eliminated entry of _idx is set. */
template<class IntegerT, class IntegerT2>
void eliminate_var_idx(
const IntegerT _evar,
std::vector<IntegerT2>& _idx,
IntegerT2 _dummy = -1 );
/// do in-place elimination in CSC format by setting row and column to zero and
/// diagonal entry to zero
/**
* @param _j index of variable to be eliminated
* @param _value_j value c of x_i to be eliminated, x_i = c
* @param _A (non-CSC) Matrix of the equation system
* @param _x variable vector of equation system
* @param _rhs right-hand side vector of equation system */
template<class ScalarT, class VectorT, class RealT>
void fix_var_csc_symmetric( const unsigned int _j,
const ScalarT _value_j,
typename gmm::csc_matrix<RealT>& _A,
VectorT& _x,
VectorT& _rhs );
/*@}*/
/// Get matrix data (CSC matrix format) from matrix
/** Used by Cholmod wrapper
* @param _mat matrix
* @param _c uplo parameter (l, L, u, U, c, C)
* @param _values values vector
* @param _rowind row indices
* @param _colptr column pointer */
template<class MatrixT, class REALT, class INTT>
void get_ccs_symmetric_data( const MatrixT& _mat,
const char _c,
std::vector<REALT>& _values,
std::vector<INTT>& _rowind,
std::vector<INTT>& _colptr );
/// Regularize matrix
/** Makes matrices with rank(_mat)<n solvable.
* Add factor*avg(trace(_mat))*Identity to _mat.
* @param _mat Matrix to regularize
* @param _v factor in factor*avg(trace(_mat))*Identity */
template<class MatrixT>
void regularize_hack( MatrixT& _mat, double _v = 1e-6 );
/// Local Gauss Seidel update of lin. equation system.
/**
* Add factor*avg(trace(_mat))*Identity to _mat.
* @param _A Matrix of linear system
* @param _x variable vector of linear system
* @param _rhs right hand side of linear system
* @param _max_iter maximum number of iterations
* @param _tolerance error tolerance threshold
* @return number of iterations performed */
template<class MatrixT, class VectorT>
int gauss_seidel_local(
MatrixT& _A,
VectorT& _x,
VectorT& _rhs,
std::vector<unsigned int> _idxs,
int _max_iter = 10000,
double _tolerance = 1e-6 );
/// Residuum norm of linear system
/** residuum = Ax-b
* @param _A Matrix
* @param _x Variables
* @param _rhs right hand side
* @return norm Ax-rhs */
template<class MatrixT, class VectorT>
double residuum_norm( MatrixT& _A, VectorT& _x, VectorT& _rhs );
/// Convert factored LSE to quadratic representation
/** Conversion is done by computing _F^t _F where the last column is the _rhs
* @param _F Factored Matrix (input)
* @param _Q Quadratic Matrix (output)
* @param _rhs right hand side (output) */
template<class MatrixT, class MatrixT2, class VectorT>
void factored_to_quadratic( MatrixT& _F, MatrixT2& _Q, VectorT& _rhs);
/// Inspect the matrix (print)
/** Prints useful matrix informations such as, dimension, symmetry, zero_rows, zero_cols, nnz, max, min, max_abs, min_abs, NAN, INF
* @param _A matrix */
template<class MatrixT>
void inspect_matrix( const MatrixT& _A);
/// Print the matrix as dense matrix
template<class MatrixT>
void print_dense( const MatrixT& _A);
#if COMISO_SUITESPARSE_AVAILABLE
/// GMM to Cholmod_sparse interface
template<class MatrixT>
void cholmod_to_gmm( const cholmod_sparse& _AC, MatrixT& _A);
template<class MatrixT>
void gmm_to_cholmod( const MatrixT& _A,
cholmod_sparse* &_AC,
cholmod_common* _common,
int _sparsity_type = 0,
bool _long_int = false);
#endif
//=============================================================================
} // namespace COMISO_GMM
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_GMM_TOOLS_C)
#define COMISO_GMM_TOOLS_TEMPLATES
#include "GMM_Tools.cc"
#endif
//=============================================================================
#endif // GMM_GMM_TOOLS_HH defined
//=============================================================================

View File

@ -0,0 +1,253 @@
//=============================================================================
//
// CLASS IterativeSolverT - IMPLEMENTATION
//
//=============================================================================
#define COMISO_ITERATIVESOLVERT_C
//== INCLUDES =================================================================
#include "IterativeSolverT.hh"
//== NAMESPACES ===============================================================
namespace COMISO{
//== IMPLEMENTATION ==========================================================
template <class RealT>
bool
IterativeSolverT<RealT>::
gauss_seidel_local( typename gmm::csc_matrix<Real>& _A,
std::vector<Real>& _x,
std::vector<Real>& _rhs,
std::vector<unsigned int>& _idxs,
int& _max_iter,
Real& _tolerance )
{
if( _max_iter == 0) return false;
typedef typename gmm::linalg_traits< gmm::csc_matrix<Real> >::const_sub_col_type ColT;
typedef typename gmm::linalg_traits<ColT>::const_iterator CIter;
// clear old data
i_temp.clear();
q.clear();
for ( unsigned int i=0; i<_idxs.size(); ++i )
q.push_back( _idxs[i] );
int it_count = 0;
while ( !q.empty() && it_count < _max_iter )
{
++it_count;
unsigned int cur_i = q.front();
q.pop_front();
i_temp.clear();
ColT col = mat_const_col( _A, cur_i );
CIter it = gmm::vect_const_begin( col );
CIter ite = gmm::vect_const_end( col );
double res_i = -_rhs[cur_i];
double x_i_new = _rhs[cur_i];
double diag = 1.0;
for ( ; it!=ite; ++it )
{
res_i += ( *it ) * _x[it.index()];
x_i_new -= ( *it ) * _x[it.index()];
if( it.index() != cur_i)
i_temp.push_back( it.index() );
else
diag = *it;
}
// take inverse of diag
diag = 1.0/diag;
// compare relative residuum normalized by diagonal entry
if ( fabs(res_i*diag) > _tolerance )
{
_x[cur_i] += x_i_new*diag;
for ( unsigned int j=0; j<i_temp.size(); ++j )
q.push_back( i_temp[j] );
}
}
// converged?
return q.empty();
}
//-----------------------------------------------------------------------------
template <class RealT>
bool
IterativeSolverT<RealT>::
gauss_seidel_local2( typename gmm::csc_matrix<Real>& _A,
std::vector<Real>& _x,
std::vector<Real>& _rhs,
std::vector<unsigned int>& _idxs,
int& _max_iter,
Real& _tolerance )
{
typedef typename gmm::linalg_traits< gmm::csc_matrix<Real> >::const_sub_col_type ColT;
typedef typename gmm::linalg_traits<ColT>::const_iterator CIter;
double t2 = _tolerance*_tolerance;
// clear old data
i_temp.clear();
s.clear();
for ( unsigned int i=0; i<_idxs.size(); ++i )
s.insert( _idxs[i] );
int it_count = 0;
bool finished = false;
while ( !finished && it_count < _max_iter )
{
finished = true;
std::set<int>::iterator s_it = s.begin();
for(; s_it != s.end(); ++s_it)
{
++it_count;
unsigned int cur_i = *s_it;
i_temp.clear();
ColT col = mat_const_col( _A, cur_i );
CIter it = gmm::vect_const_begin( col );
CIter ite = gmm::vect_const_end( col );
double res_i = -_rhs[cur_i];
double x_i_new = _rhs[cur_i];
double diag = 1.0;
for ( ; it!=ite; ++it )
{
res_i += ( *it ) * _x[it.index()];
x_i_new -= ( *it ) * _x[it.index()];
if( it.index() != cur_i)
i_temp.push_back( it.index() );
else
diag = *it;
}
// compare relative residuum normalized by diagonal entry
if ( res_i*res_i/diag > t2 )
{
_x[cur_i] += x_i_new/_A( cur_i, cur_i );
for ( unsigned int j=0; j<i_temp.size(); ++j )
{
finished = false;
s.insert( i_temp[j] );
}
}
}
}
// converged?
return finished;
}
//-----------------------------------------------------------------------------
template <class RealT>
bool
IterativeSolverT<RealT>::
conjugate_gradient( typename gmm::csc_matrix<Real>& _A,
std::vector<Real>& _x,
std::vector<Real>& _rhs,
int& _max_iter,
Real& _tolerance )
{
Real rho, rho_1(0), a;
// initialize vectors
p_.resize(_x.size());
q_.resize(_x.size());
r_.resize(_x.size());
d_.resize(_x.size());
gmm::copy( _x, p_);
// initialize diagonal (for relative norm)
for(unsigned int i=0; i<_x.size(); ++i)
d_[i] = 1.0/_A(i,i);
// start with iteration 0
int cur_iter(0);
gmm::mult(_A, gmm::scaled(_x, Real(-1)), _rhs, r_);
rho = gmm::vect_sp( r_, r_);
gmm::copy(r_, p_);
bool not_converged = true;
Real res_norm(0);
// while not converged
while( (not_converged = ( (res_norm=vect_norm_rel(r_, d_)) > _tolerance)) &&
cur_iter < _max_iter)
{
// std::cerr << "iter " << cur_iter << " res " << res_norm << std::endl;
if (cur_iter != 0)
{
rho = gmm::vect_sp( r_, r_);
gmm::add(r_, gmm::scaled(p_, rho / rho_1), p_);
}
gmm::mult(_A, p_, q_);
a = rho / gmm::vect_sp( q_, p_);
gmm::add(gmm::scaled(p_, a), _x);
gmm::add(gmm::scaled(q_, -a), r_);
rho_1 = rho;
++cur_iter;
}
_max_iter = cur_iter;
_tolerance = res_norm;
return (!not_converged);
}
//-----------------------------------------------------------------------------
template <class RealT>
typename IterativeSolverT<RealT>::Real
IterativeSolverT<RealT>::
vect_norm_rel(const std::vector<Real>& _v, const std::vector<Real>& _diag) const
{
Real res = 0.0;
for(unsigned int i=0; i<_v.size(); ++i)
{
res = std::max(fabs(_v[i]*_diag[i]), res);
// Real cur = fabs(_v[i]*_diag[i]);
// if(cur > res)
// res = cur;
}
return res;
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace COMISO
//=============================================================================

View File

@ -0,0 +1,104 @@
//=============================================================================
//
// CLASS IterativeSolverT
//
//=============================================================================
#ifndef COMISO_ITERATIVESOLVERT_HH
#define COMISO_ITERATIVESOLVERT_HH
//== INCLUDES =================================================================
#include <gmm/gmm.h>
#include <deque>
#include <queue>
#include <set>
//== FORWARDDECLARATIONS ======================================================
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class IterativeSolverT IterativeSolverT.hh <COMISO/.../IterativeSolverT.hh>
Brief Description.
A more elaborate description follows.
*/
template <class RealT>
class IterativeSolverT
{
public:
typedef RealT Real;
/// Constructor
IterativeSolverT() {}
/// Destructor
~IterativeSolverT() {}
// local gauss_seidel
bool gauss_seidel_local( typename gmm::csc_matrix<Real>& _A,
std::vector<Real>& _x,
std::vector<Real>& _rhs,
std::vector<unsigned int>& _idxs,
int& _max_iter,
Real& _tolerance );
// local gauss_seidel
bool gauss_seidel_local2( typename gmm::csc_matrix<Real>& _A,
std::vector<Real>& _x,
std::vector<Real>& _rhs,
std::vector<unsigned int>& _idxs,
int& _max_iter,
Real& _tolerance );
// conjugate gradient
bool conjugate_gradient( typename gmm::csc_matrix<Real>& _A,
std::vector<Real>& _x,
std::vector<Real>& _rhs,
int& _max_iter,
Real& _tolerance );
private:
// compute relative norm
Real vect_norm_rel(const std::vector<Real>& _v, const std::vector<Real>& _diag) const;
private:
// helper for conjugate gradient
std::vector<Real> p_;
std::vector<Real> q_;
std::vector<Real> r_;
std::vector<Real> d_;
// helper for local gauss seidel
std::vector<unsigned int> i_temp;
std::deque<unsigned int> q;
std::set<int> s;
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_ITERATIVESOLVERT_C)
#define COMISO_ITERATIVESOLVERT_TEMPLATES
#include "IterativeSolverT.cc"
#endif
//=============================================================================
#endif // COMISO_ITERATIVESOLVERT_HH defined
//=============================================================================

738
src/external/CoMISo/Solver/MISolver.cc vendored Normal file
View File

@ -0,0 +1,738 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
#include <CoMISo/Config/config.hh>
#include "MISolver.hh"
#if(COMISO_QT4_AVAILABLE)
#include <CoMISo/QtWidgets/MISolverDialogUI.hh>
#endif
#if COMISO_GUROBI_AVAILABLE
#include <gurobi_c++.h>
#endif
#include <CoMISo/Utils/StopWatch.hh>
#include <gmm/gmm.h>
#include <float.h>
// hack for testing only
#include "SparseQRSolver.hh"
#include "UMFPACKSolver.hh"
#include "EigenLDLTSolver.hh"
#define ROUND(x) ((x)<0?int((x)-0.5):int((x)+0.5))
namespace COMISO {
// Constructor
MISolver::MISolver()
{
// default parameters
initial_full_solution_ = true;
iter_full_solution_ = true;
final_full_solution_ = true;
direct_rounding_ = false;
no_rounding_ = false;
multiple_rounding_ = true;
gurobi_rounding_ = false;
cplex_rounding_ = false;
max_local_iters_ = 100000;
max_local_error_ = 1e-3;
max_cg_iters_ = 50;
max_cg_error_ = 1e-3;
multiple_rounding_threshold_ = 0.5;
gurobi_max_time_ = 60;
noisy_ = 0;
stats_ = true;
use_constraint_reordering_ = true;
}
//-----------------------------------------------------------------------------
void
MISolver::solve_no_rounding(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs )
{
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve(_x, _rhs);
}
//-----------------------------------------------------------------------------
void
MISolver::resolve(
Vecd& _x,
Vecd& _rhs )
{
direct_solver_.solve(_x, _rhs);
}
//-----------------------------------------------------------------------------
void
MISolver::solve_direct_rounding(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round)
{
Veci to_round(_to_round);
// copy to round vector and make it unique
std::sort(to_round.begin(), to_round.end());
Veci::iterator last_unique;
last_unique = std::unique(to_round.begin(), to_round.end());
int r = last_unique - to_round.begin();
to_round.resize( r);
// initalize old indices
Veci old_idx(_rhs.size());
for(unsigned int i=0; i<old_idx.size(); ++i)
old_idx[i] = i;
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve(_x, _rhs);
// check solver performance (only for testing!!!)
{
StopWatch sw;
// hack
const bool enable_performance_test = false;
// performance comparison code
#if(COMISO_SUITESPARSE_SPQR_AVAILABLE)
if(enable_performance_test)
{
sw.start();
COMISO::SparseQRSolver spqr;
spqr.calc_system_gmm(_A);
std::cerr << "SparseQR factor took: " << sw.stop()/1000.0 << "s\n";
Vecd x2(_x);
sw.start();
spqr.solve(x2,_rhs);
std::cerr << "SparseQR solve took: " << sw.stop()/1000.0 << "s\n";
Vecd res(_x);
gmm::add(_x,gmm::scaled(x2,-1.0),res);
std::cerr << "DIFFERENCE IN RESULT: " << gmm::vect_norm2(res) << std::endl;
}
#endif
// performance comparison code
#if(COMISO_SUITESPARSE_AVAILABLE)
if(enable_performance_test)
{
sw.start();
COMISO::UMFPACKSolver umf;
umf.calc_system_gmm(_A);
std::cerr << "UMFPack factor took: " << sw.stop()/1000.0 << "s\n";
Vecd x3(_x);
sw.start();
umf.solve(x3,_rhs);
std::cerr << "UMFPack solve took: " << sw.stop()/1000.0 << "s\n";
Vecd res2(_x);
gmm::add(_x,gmm::scaled(x3,-1.0),res2);
std::cerr << "UMFPACK DIFFERENCE IN RESULT: " << gmm::vect_norm2(res2) << std::endl;
}
// performance comparison code
if(enable_performance_test)
{
sw.start();
COMISO::CholmodSolver chol;
chol.calc_system_gmm(_A);
std::cerr << "Choldmod factor took: " << sw.stop()/1000.0 << "s\n";
Vecd x4(_x);
sw.start();
chol.solve(x4,_rhs);
std::cerr << "Choldmod solve took: " << sw.stop()/1000.0 << "s\n";
Vecd res(_x);
gmm::add(_x,gmm::scaled(x4,-1.0),res);
std::cerr << "DIFFERENCE IN RESULT: " << gmm::vect_norm2(res) << std::endl;
}
#endif
#if(COMISO_EIGEN3_AVAILABLE)
// performance comparison code
if(enable_performance_test)
{
sw.start();
COMISO::EigenLDLTSolver ldlt;
ldlt.calc_system_gmm(_A);
std::cerr << "Eigen LDLT factor took: " << sw.stop()/1000.0 << "s\n";
Vecd x5(_x);
sw.start();
ldlt.solve(x5,_rhs);
std::cerr << "Eigen LDLT solve took: " << sw.stop()/1000.0 << "s\n";
Vecd res(_x);
gmm::add(_x,gmm::scaled(x5,-1.0),res);
std::cerr << "DIFFERENCE IN RESULT: " << gmm::vect_norm2(res) << std::endl;
}
#endif
}
// round and eliminate variables
Vecui elim_i;
Vecd elim_v;
for( unsigned int i=0; i < to_round.size(); ++i)
{
_x[to_round[i]] = ROUND(_x[to_round[i]]);
elim_i.push_back(to_round[i]);
elim_v.push_back(_x[to_round[i]]);
// update old idx
old_idx[to_round[i]] = -1;
}
Veci::iterator new_end = std::remove( old_idx.begin(), old_idx.end(), -1);
old_idx.resize( new_end-old_idx.begin());
// eliminate vars from linear system
Vecd xr(_x);
COMISO_GMM::eliminate_csc_vars2( elim_i, elim_v, _A, xr, _rhs);
// std::cerr << "size A: " << gmm::mat_nrows(_A) << " " << gmm::mat_ncols(_A)
// << std::endl;
// std::cerr << "size x : " << xr.size() << std::endl;
// std::cerr << "size rhs: " << _rhs.size() << std::endl;
// final full solution
if( gmm::mat_ncols( _A) > 0)
{
// direct_solver_.update_system_gmm(_A);
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve( xr, _rhs);
}
// store solution values to result vector
for(unsigned int i=0; i<old_idx.size(); ++i)
{
_x[ old_idx[i] ] = xr[i];
}
}
//-----------------------------------------------------------------------------
void
MISolver::solve_iterative(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round,
bool _fixed_order )
{
// StopWatch
COMISO::StopWatch sw;
double time_search_next_integer = 0;
// some statistics
n_local_ = 0;
n_cg_ = 0;
n_full_ = 0;
// reset cholmod step flag
cholmod_step_done_ = false;
Veci to_round(_to_round);
// if the order is not fixed, uniquify the indices
if( !_fixed_order)
{
// copy to round vector and make it unique
std::sort(to_round.begin(), to_round.end());
Veci::iterator last_unique;
last_unique = std::unique(to_round.begin(), to_round.end());
int r = last_unique - to_round.begin();
to_round.resize( r);
}
// initalize old indices
Veci old_idx(_rhs.size());
for(unsigned int i=0; i<old_idx.size(); ++i)
old_idx[i] = i;
if( initial_full_solution_)
{
if( noisy_ > 2) std::cerr << "initial full solution" << std::endl;
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve(_x, _rhs);
cholmod_step_done_ = true;
++n_full_;
}
// neighbors for local optimization
Vecui neigh_i;
// Vector for reduced solution
Vecd xr(_x);
// loop until solution computed
for(unsigned int i=0; i<to_round.size(); ++i)
{
if( noisy_ > 0)
{
std::cerr << "Integer DOF's left: " << to_round.size()-(i+1) << " ";
if( noisy_ > 1)
std::cerr << "residuum_norm: " << COMISO_GMM::residuum_norm( _A, xr, _rhs) << std::endl;
}
// index to eliminate
unsigned int i_best = 0;
// position in round vector
unsigned int tr_best = 0;
if( _fixed_order ) // if order is fixed, simply get next index from to_round
{
i_best = to_round[i];
}
else // else search for best rounding candidate
{
sw.start();
// find index yielding smallest rounding error
double r_best = FLT_MAX;
for(unsigned int j=0; j<to_round.size(); ++j)
{
if( to_round[j] != -1)
{
int cur_idx = to_round[j];
double rnd_error = fabs( ROUND(xr[cur_idx]) - xr[cur_idx]);
if( rnd_error < r_best)
{
i_best = cur_idx;
r_best = rnd_error;
tr_best = j;
}
}
}
time_search_next_integer += sw.stop();
}
// store rounded value
double rnd_x = ROUND(xr[i_best]);
_x[ old_idx[i_best] ] = rnd_x;
// compute neighbors
neigh_i.clear();
Col col = gmm::mat_const_col(_A, i_best);
ColIter it = gmm::vect_const_begin( col);
ColIter ite = gmm::vect_const_end ( col);
for(; it!=ite; ++it)
if(it.index() != i_best)
neigh_i.push_back(it.index());
// eliminate var
COMISO_GMM::fix_var_csc_symmetric(i_best, rnd_x, _A, xr, _rhs);
to_round[tr_best] = -1;
// 3-stage update of solution w.r.t. roundings
// local GS / CG / SparseCholesky
update_solution( _A, xr, _rhs, neigh_i);
}
// final full solution?
if( final_full_solution_)
{
if( noisy_ > 2) std::cerr << "final full solution" << std::endl;
if( gmm::mat_ncols( _A) > 0)
{
if(cholmod_step_done_)
direct_solver_.update_system_gmm(_A);
else
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve( xr, _rhs);
++n_full_;
}
}
// store solution values to result vector
for(unsigned int i=0; i<old_idx.size(); ++i)
{
_x[ old_idx[i] ] = xr[i];
}
// output statistics
if( stats_)
{
std::cerr << "\t" << __FUNCTION__ << " *** Statistics of MiSo Solver ***\n";
std::cerr << "\t\t Number of CG iterations = " << n_cg_ << std::endl;
std::cerr << "\t\t Number of LOCAL iterations = " << n_local_ << std::endl;
std::cerr << "\t\t Number of FULL iterations = " << n_full_ << std::endl;
std::cerr << "\t\t Number of ROUNDING = " << _to_round.size() << std::endl;
std::cerr << "\t\t time searching next integer = " << time_search_next_integer / 1000.0 <<"s\n";
std::cerr << std::endl;
}
}
//-----------------------------------------------------------------------------
void
MISolver::update_solution(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Vecui& _neigh_i )
{
// set to not converged
bool converged = false;
// compute new solution
if(max_local_iters_ > 0)
{
if( noisy_ > 2)std::cerr << "use local iteration ";
int n_its = max_local_iters_;
double tolerance = max_local_error_;
converged = siter_.gauss_seidel_local(_A, _x, _rhs, _neigh_i, n_its, tolerance);
++n_local_;
}
// conjugate gradient
if( !converged && max_cg_iters_ > 0)
{
if( noisy_ > 2) std::cerr << ", cg ";
int max_cg_iters = max_cg_iters_;
double tolerance = max_cg_error_;
converged = siter_.conjugate_gradient(_A, _x,_rhs, max_cg_iters, tolerance);
if( noisy_ > 3)
std::cerr << "( converged " << converged << " "
<< " iters " << max_cg_iters << " "
<< " res_norm " << tolerance << std::endl;
++n_cg_;
}
if(!converged && iter_full_solution_)
{
if( noisy_ > 2)std::cerr << ", full ";
if( gmm::mat_ncols( _A) > 0)
{
if(cholmod_step_done_)
direct_solver_.update_system_gmm(_A);
else
{
direct_solver_.calc_system_gmm(_A);
cholmod_step_done_ = true;
}
direct_solver_.solve(_x,_rhs);
++n_full_;
}
}
if( noisy_ > 2)std::cerr << std::endl;
}
//-----------------------------------------------------------------------------
void
MISolver::solve_multiple_rounding(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round )
{
// StopWatch
COMISO::StopWatch sw;
double time_search_next_integer = 0;
// some statistics
n_local_ = 0;
n_cg_ = 0;
n_full_ = 0;
// reset cholmod step flag
cholmod_step_done_ = false;
Veci to_round(_to_round);
// copy to round vector and make it unique
std::sort(to_round.begin(), to_round.end());
Veci::iterator last_unique;
last_unique = std::unique(to_round.begin(), to_round.end());
int r = last_unique - to_round.begin();
to_round.resize( r);
// initalize old indices
Veci old_idx(_rhs.size());
for(unsigned int i=0; i<old_idx.size(); ++i)
old_idx[i] = i;
if( initial_full_solution_)
{
if( noisy_ > 2) std::cerr << "initial full solution" << std::endl;
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve(_x, _rhs);
cholmod_step_done_ = true;
++n_full_;
}
// neighbors for local optimization
Vecui neigh_i;
// Vector for reduced solution
Vecd xr(_x);
// loop until solution computed
for(unsigned int i=0; i<to_round.size(); ++i)
{
if( noisy_ > 0)
{
std::cerr << "Integer DOF's left: " << to_round.size()-(i+1) << " ";
if( noisy_ > 1)
std::cerr << "residuum_norm: " << COMISO_GMM::residuum_norm( _A, xr, _rhs) << std::endl;
}
// position in round vector
std::vector<int> tr_best;
sw.start();
RoundingSet rset;
rset.set_threshold(multiple_rounding_threshold_);
// find index yielding smallest rounding error
for(unsigned int j=0; j<to_round.size(); ++j)
{
if( to_round[j] != -1)
{
int cur_idx = to_round[j];
double rnd_error = fabs( ROUND(xr[cur_idx]) - xr[cur_idx]);
rset.add(j, rnd_error);
}
}
rset.get_ids( tr_best);
time_search_next_integer += sw.stop();
// nothing more to do?
if( tr_best.empty() )
break;
if( noisy_ > 5)
std::cerr << "round " << tr_best.size() << " variables simultaneously\n";
// clear neigh for local update
neigh_i.clear();
for(unsigned int j = 0; j<tr_best.size(); ++j)
{
int i_cur = to_round[tr_best[j]];
// store rounded value
double rnd_x = ROUND(xr[i_cur]);
_x[ old_idx[i_cur] ] = rnd_x;
// compute neighbors
Col col = gmm::mat_const_col(_A, i_cur);
ColIter it = gmm::vect_const_begin( col);
ColIter ite = gmm::vect_const_end ( col);
for(; it!=ite; ++it)
if(it.index() != (unsigned int)i_cur)
neigh_i.push_back(it.index());
// eliminate var
COMISO_GMM::fix_var_csc_symmetric( i_cur, rnd_x, _A, xr, _rhs);
to_round[tr_best[j]] = -1;
}
// 3-stage update of solution w.r.t. roundings
// local GS / CG / SparseCholesky
update_solution( _A, xr, _rhs, neigh_i);
}
// final full solution?
if( final_full_solution_)
{
if( noisy_ > 2) std::cerr << "final full solution" << std::endl;
if( gmm::mat_ncols( _A) > 0)
{
if(cholmod_step_done_)
direct_solver_.update_system_gmm(_A);
else
direct_solver_.calc_system_gmm(_A);
direct_solver_.solve( xr, _rhs);
++n_full_;
}
}
// store solution values to result vector
for(unsigned int i=0; i<old_idx.size(); ++i)
{
_x[ old_idx[i] ] = xr[i];
}
// output statistics
if( stats_)
{
std::cerr << "\t" << __FUNCTION__ << " *** Statistics of MiSo Solver ***\n";
std::cerr << "\t\t Number of CG iterations = " << n_cg_ << std::endl;
std::cerr << "\t\t Number of LOCAL iterations = " << n_local_ << std::endl;
std::cerr << "\t\t Number of FULL iterations = " << n_full_ << std::endl;
std::cerr << "\t\t Number of ROUNDING = " << _to_round.size() << std::endl;
std::cerr << "\t\t time searching next integer = " << time_search_next_integer / 1000.0 <<"s\n";
std::cerr << std::endl;
}
}
//-----------------------------------------------------------------------------
void
MISolver::solve_gurobi(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round)
{
#if COMISO_GUROBI_AVAILABLE
// get round-indices in set
std::set<int> to_round;
for(unsigned int i=0; i<_to_round.size();++i)
to_round.insert(_to_round[i]);
try {
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
// set time limite
model.getEnv().set(GRB_DoubleParam_TimeLimit, gurobi_max_time_);
unsigned int n = _rhs.size();
// 1. allocate variables
std::vector<GRBVar> vars;
for( unsigned int i=0; i<n; ++i)
if( to_round.count(i))
vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_INTEGER));
else
vars.push_back( model.addVar(-GRB_INFINITY, GRB_INFINITY, 0.0, GRB_CONTINUOUS));
// Integrate new variables
model.update();
// 2. setup_energy
// build objective function from linear system E = x^tAx - 2x^t*rhs
GRBQuadExpr objective;
for(unsigned int i=0; i<_A.nc; ++i)
for(unsigned int j=_A.jc[i]; j<_A.jc[i+1]; ++j)
{
objective += _A.pr[j]*vars[_A.ir[j]]*vars[i];
}
for(unsigned int i=0; i<n; ++i)
objective -= 2*_rhs[i]*vars[i];
// _A.jc[c+1]
// _A.pr[write]
// _A.ir[write]
// _A.nc
// _A.nr
// minimize
model.set(GRB_IntAttr_ModelSense, 1);
model.setObjective(objective);
// 4. solve
model.optimize();
// 5. store result
_x.resize(n);
for(unsigned int i=0; i<n; ++i)
_x[i] = vars[i].get(GRB_DoubleAttr_X);
std::cout << "GUROBI objective: " << model.get(GRB_DoubleAttr_ObjVal) << std::endl;
}
catch(GRBException& e)
{
std::cout << "Error code = " << e.getErrorCode() << std::endl;
std::cout << e.getMessage() << std::endl;
}
catch(...)
{
std::cout << "Exception during optimization" << std::endl;
}
#else
std::cerr << "GUROBI solver is not available, please install it..." << std::endl;
#endif
}
//----------------------------------------------------------------------------
void
MISolver::
show_options_dialog()
{
#if(COMISO_QT4_AVAILABLE)
MISolverDialog* pd = new MISolverDialog(*this);
pd->exec();
#else
std::cerr << "Warning: Qt not available to show solver dialog!!!" << std::endl;
#endif
}
// end namespace COMISO
}// ----------------------

404
src/external/CoMISo/Solver/MISolver.hh vendored Normal file
View File

@ -0,0 +1,404 @@
/*===========================================================================*\
* *
* CoMISo *
* Copyright (C) 2008-2009 by Computer Graphics Group, RWTH Aachen *
* www.rwth-graphics.de *
* *
*---------------------------------------------------------------------------*
* This file is part of CoMISo. *
* *
* CoMISo is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* CoMISo is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with CoMISo. If not, see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS MISolver
//
//=============================================================================
#ifndef COMISO_MISOLVER_HH
#define COMISO_MISOLVER_HH
//== INCLUDES =================================================================
#include <CoMISo/Config/CoMISoDefines.hh>
#include <CoMISo/Config/config.hh>
#if COMISO_SUITESPARSE_AVAILABLE
#include "CholmodSolver.hh"
#elif COMISO_EIGEN3_AVAILABLE
#include "EigenLDLTSolver.hh"
#else
#print "Warning: MISolver requires Suitesparse or Eigen3 support"
#endif
#include "GMM_Tools.hh"
#include "IterativeSolverT.hh"
#include <vector>
#define ROUND_MI(x) ((x)<0?int((x)-0.5):int((x)+0.5))
//== FORWARDDECLARATIONS ======================================================
namespace COMISO {
class MISolverDialog;
}
//== NAMESPACES ===============================================================
namespace COMISO {
//== CLASS DEFINITION =========================================================
/** \class MISolver MISolver.hh
Mixed-Integer Solver.
Approximates the solution of a (mixed-)integer problem
by iteratively computing a continuous(real) minimizer x followed by a
rounding of the one variable x_i which is subsequently eliminated from the
system, and the system is solved again ...
*/
class COMISODLLEXPORT MISolver
{
public:
// typedefs
typedef gmm::csc_matrix< double > CSCMatrix;
typedef std::vector< double > Vecd;
typedef std::vector< int > Veci;
typedef std::vector< unsigned int > Vecui;
// gmm Column and ColumnIterator of CSC matrix
typedef gmm::linalg_traits< CSCMatrix >::const_sub_col_type Col;
typedef gmm::linalg_traits< Col >::const_iterator ColIter;
/// default Constructor
MISolver();
/// Destructor
~MISolver() {}
/// Compute greedy approximation to a mixed integer problem.
/** @param _A symmetric positive semi-definite CSC matrix (Will be \b destroyed!)
* @param _x vector holding solution at the end
* @param _rhs right hand side of system Ax=rhs (Will be \b destroyed!)
* @param _to_round vector with variable indices to round to integers
* @param _fixed_order specifies if _to_round indices shall be rounded in the
* given order (\b true) or be greedily selected (\b false)
* */
inline void solve(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round,
bool _fixed_order = false );
void resolve(
Vecd& _x,
Vecd& _rhs );
/// Compute greedy approximation to a mixed integer problem.
/** @param _B mx(n+1) matrix with (still non-squared) equations of the energy,
* including the right hand side (Will be \b destroyed!)
* @param _x vector holding solution at the end
* @param _to_round vector with variable indices to round to integers
* @param _fixed_order specifies if _to_round indices shall be rounded in the
* given order (\b true) or be greedily selected (\b false)
* */
template<class CMatrixT>
void solve(
CMatrixT& _B,
Vecd& _x,
Veci& _to_round,
bool _fixed_order = false );
/// show Qt-Options-Dialog for setting algorithm parameters
/** Requires a Qt Application running and COMISO_GUI to be defined */
void show_options_dialog();
/** @name Get/Set functions for algorithm parameters
* Besides being used by the Qt-Dialog these can also be called explicitly
* to set parameters of the algorithm. */
/*@{*/
/// Shall an initial full solution be computed?
void set_inital_full( bool _b) { initial_full_solution_=_b;}
/// Will an initial full solution be computed?
bool get_inital_full() { return initial_full_solution_;}
/// Shall an full solution be computed if iterative methods did not converged?
void set_iter_full( bool _b) { iter_full_solution_=_b;}
/// Will an full solution be computed if iterative methods did not converged?
bool get_iter_full() { return iter_full_solution_;}
/// Shall a final full solution be computed?
void set_final_full( bool _b) { final_full_solution_=_b;}
/// Will a final full solution be computed?
bool get_final_full() { return final_full_solution_;}
/// Shall direct (or greedy) rounding be used?
void set_direct_rounding( bool _b) { direct_rounding_=_b;}
/// Will direct rounding be used?
bool get_direct_rounding() { return direct_rounding_;}
/// Shall no rounding be performed?
void set_no_rounding( bool _b) { no_rounding_=_b;}
/// Will no rounding be performed?
bool get_no_rounding() { return no_rounding_;}
/// Shall multiple rounding be performed?
void set_multiple_rounding( bool _b) { multiple_rounding_=_b;}
/// Will multiple rounding be performed?
bool get_multiple_rounding() { return multiple_rounding_;}
/// Shall gurobi solver be used?
void set_gurobi_rounding( bool _b) { gurobi_rounding_=_b;}
/// Will gurobi rounding be performed?
bool get_gurobi_rounding() { return gurobi_rounding_;}
/// Shall cplex solver be used?
void set_cplex_rounding( bool _b) { cplex_rounding_=_b;}
/// Will cplex rounding be performed?
bool get_cplex_rounding() { return cplex_rounding_;}
/// Set number of maximum Gauss-Seidel iterations
void set_local_iters( unsigned int _i) { max_local_iters_ = _i;}
/// Get number of maximum Gauss-Seidel iterations
unsigned int get_local_iters() { return max_local_iters_;}
/// Set error threshold for Gauss-Seidel solver
void set_local_error( double _d) { max_local_error_ = _d;}
/// Get error threshold for Gauss-Seidel solver
double get_local_error() { return max_local_error_;}
/// Set number of maximum Conjugate Gradient iterations
void set_cg_iters( unsigned int _i) { max_cg_iters_ = _i;}
/// Get number of maximum Conjugate Gradient iterations
unsigned int get_cg_iters() { return max_cg_iters_;}
/// Set error threshold for Conjugate Gradient
void set_cg_error( double _d) { max_cg_error_ = _d;}
/// Get error threshold for Conjugate Gradient
double get_cg_error() { return max_cg_error_;}
/// Set multiple rounding threshold (upper bound of rounding performed in each iteration)
void set_multiple_rounding_threshold( double _d) { multiple_rounding_threshold_ = _d;}
/// Get multiple rounding threshold (upper bound of rounding performed in each iteration)
double get_multiple_rounding_threshold() { return multiple_rounding_threshold_;}
/// Set noise level of algorithm. 0 - quiet, 1 - more noise, 2 - even more, 100 - all noise
void set_noise( unsigned int _i) { noisy_ = _i;}
/// Get noise level of algorithm
unsigned int get_noise() { return noisy_;}
/// Set time limit for gurobi solver (in seconds)
void set_gurobi_max_time( double _d) { gurobi_max_time_ = _d;}
/// Get time limit for gurobi solver (in seconds)
double get_gurobi_max_time() { return gurobi_max_time_;}
/// Set output statistics of solver
void set_stats( bool _stats) { stats_ = _stats; }
/// Get output statistics of solver
bool get_stats( ) { return stats_; }
/*@}*/
/// Set/Get use_constraint_reordering for constraint solver (default = true)
bool& use_constraint_reordering() { return use_constraint_reordering_;}
private:
// find set of variables for simultaneous rounding
class RoundingSet
{
public:
typedef std::pair<double,int> PairDI;
RoundingSet() : threshold_(0.5), cur_sum_(0.0) {}
void clear() { rset_.clear(); cur_sum_ = 0.0;}
bool add( int _id, double _rd_val)
{
// empty set? -> always add one element
if( rset_.empty() || cur_sum_+_rd_val <= threshold_)
{
rset_.insert( PairDI(_rd_val,_id) );
cur_sum_ += _rd_val;
return true;
}
else
{
// move to last element
std::set<PairDI>::iterator s_it = rset_.end();
--s_it;
if( s_it->first > _rd_val)
{
cur_sum_ -= s_it->first;
rset_.erase(s_it);
rset_.insert( PairDI(_rd_val,_id) );
cur_sum_ += _rd_val;
return true;
}
}
return false;
}
void set_threshold( double _thres) { threshold_ = _thres; }
void get_ids( std::vector<int>& _ids )
{
_ids.clear();
_ids.reserve( rset_.size());
std::set<PairDI>::iterator s_it = rset_.begin();
for(; s_it != rset_.end(); ++s_it)
_ids.push_back( s_it->second);
}
private:
double threshold_;
double cur_sum_;
std::set<PairDI> rset_;
std::set<PairDI> test_;
};
private:
void solve_no_rounding(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs );
void solve_direct_rounding(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round);
void solve_multiple_rounding(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round );
void solve_iterative(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round,
bool _fixed_order );
void solve_gurobi(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round );
inline void solve_cplex(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Veci& _to_round );
void update_solution(
CSCMatrix& _A,
Vecd& _x,
Vecd& _rhs,
Vecui& _neigh_i );
private:
/// Copy constructor (not used)
MISolver(const MISolver& _rhs);
/// Assignment operator (not used)
MISolver& operator=(const MISolver& _rhs);
// parameters used by the MiSo
bool initial_full_solution_;
bool iter_full_solution_;
bool final_full_solution_;
bool direct_rounding_;
bool no_rounding_;
bool multiple_rounding_;
bool gurobi_rounding_;
bool cplex_rounding_;
double multiple_rounding_threshold_;
unsigned int max_local_iters_;
double max_local_error_;
unsigned int max_cg_iters_;
double max_cg_error_;
double max_full_error_;
unsigned int noisy_;
bool stats_;
// time limit for gurobi solver (in seconds)
double gurobi_max_time_;
// flag
bool cholmod_step_done_;
// declar direct solver depending on availability
#if COMISO_SUITESPARSE_AVAILABLE
COMISO::CholmodSolver direct_solver_;
#elif COMISO_EIGEN3_AVAILABLE
COMISO::EigenLDLTSolver direct_solver_;
#else
#print "Warning: MISolver requires Suitesparse or Eigen3 support"
#endif
IterativeSolverT<double> siter_;
// statistics
unsigned int n_local_;
unsigned int n_cg_;
unsigned int n_full_;
bool use_constraint_reordering_;
#if(COMISO_QT4_AVAILABLE)
friend class COMISO::MISolverDialog;
#endif
};
//=============================================================================
} // namespace COMISO
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_MISOLVER_C)
#define COMISO_MISOLVER_TEMPLATES
#include "MISolverT.cc"
#endif
//=============================================================================
#endif // COMISO_MISOLVER_HH defined
//=============================================================================

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