diff --git a/src/external/CoMISo/CHANGELOG b/src/external/CoMISo/CHANGELOG new file mode 100644 index 000000000..1b46e752e --- /dev/null +++ b/src/external/CoMISo/CHANGELOG @@ -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/ diff --git a/src/external/CoMISo/CMakeLists.txt b/src/external/CoMISo/CMakeLists.txt new file mode 100644 index 000000000..131d6bb78 --- /dev/null +++ b/src/external/CoMISo/CMakeLists.txt @@ -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() diff --git a/src/external/CoMISo/COPYING b/src/external/CoMISo/COPYING new file mode 100644 index 000000000..10926e87f --- /dev/null +++ b/src/external/CoMISo/COPYING @@ -0,0 +1,675 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. + diff --git a/src/external/CoMISo/CoMISo.cmake b/src/external/CoMISo/CoMISo.cmake new file mode 100644 index 000000000..a981bf386 --- /dev/null +++ b/src/external/CoMISo/CoMISo.cmake @@ -0,0 +1,2 @@ +# add our macro directory to cmake search path +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) diff --git a/src/external/CoMISo/Config/CoMISoDefines.hh b/src/external/CoMISo/Config/CoMISoDefines.hh new file mode 100644 index 000000000..492008b86 --- /dev/null +++ b/src/external/CoMISo/Config/CoMISoDefines.hh @@ -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 . * + * * +\*===========================================================================*/ + +#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 + + diff --git a/src/external/CoMISo/Config/config.hh.in b/src/external/CoMISo/Config/config.hh.in new file mode 100644 index 000000000..fc1d67bf3 --- /dev/null +++ b/src/external/CoMISo/Config/config.hh.in @@ -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@ + + diff --git a/src/external/CoMISo/EigenSolver/ArpackSolver.cc b/src/external/CoMISo/EigenSolver/ArpackSolver.cc new file mode 100644 index 000000000..981ab2ffb --- /dev/null +++ b/src/external/CoMISo/EigenSolver/ArpackSolver.cc @@ -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 +void +ArpackSolver:: +solve(const MatrixT& _A, + std::vector& _eigenvalues, + MatrixT2& _eigenvectors, + const int _n_eigvalues, + const char* _which_eigs ) +{ + Matrix A(_A); +// ARSymStdEig eig_prob(A.matrix().cols(), _n_eigvalues, &A, &Matrix::mult_Mv, (char*)_which_eigs, +// 0, 0.0, 2000); + + ARSymStdEig 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 +void +ArpackSolver:: +solve_inverse(const MatrixT& _A, + std::vector& _eigenvalues, + MatrixT2& _eigenvectors, + const int _n_eigvalues, + const char* _which_eigs) +{ + Matrix A(_A,true); + ARSymStdEig 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 +void +ArpackSolver:: +check_result(const MatrixT& _A, std::vector& _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 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 +//============================================================================= diff --git a/src/external/CoMISo/EigenSolver/ArpackSolver.hh b/src/external/CoMISo/EigenSolver/ArpackSolver.hh new file mode 100644 index 000000000..067916a60 --- /dev/null +++ b/src/external/CoMISo/EigenSolver/ArpackSolver.hh @@ -0,0 +1,98 @@ +//============================================================================= +// +// CLASS ArpackSolver +// +//============================================================================= + + +#ifndef COMISO_ARPACKSOLVER_HH +#define COMISO_ARPACKSOLVER_HH + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if (COMISO_ARPACK_AVAILABLE && COMISO_SUITESPARSE_AVAILABLE && COMISO_EIGEN3_AVAILABLE) + +//== INCLUDES ================================================================= +#include + +#include +#include "EigenArpackMatrixT.hh" + +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + + +/** \class ArpackSolver ArpackSolver.hh + + Brief Description. + + A more elaborate description follows. +*/ + + +class COMISODLLEXPORT ArpackSolver +{ +public: + + // sparse matrix type + typedef EigenArpackMatrixT > 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 + void solve(const MatrixT& _A, + std::vector& _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 + void solve_inverse(const MatrixT& _A, + std::vector& _eigenvalues, + MatrixT2& _eigenvectors, + const int _n_eigvalues = 1, + const char* _which_eigs = "LM"); + + + // check resulting eigenvalues/eigenvectors + template + void check_result(const MatrixT& _A, std::vector& _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 +//============================================================================= + diff --git a/src/external/CoMISo/EigenSolver/EigenArpackMatrixT.cc b/src/external/CoMISo/EigenSolver/EigenArpackMatrixT.cc new file mode 100644 index 000000000..540497817 --- /dev/null +++ b/src/external/CoMISo/EigenSolver/EigenArpackMatrixT.cc @@ -0,0 +1,35 @@ +//============================================================================= +// +// CLASS EigenArpackMatrixT - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_EIGENARPACKMATRIXT_C + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_SUITESPARSE_AVAILABLE +//============================================================================= + + +//== INCLUDES ================================================================= + +#include "EigenArpackMatrixT.hh" + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + + +//----------------------------------------------------------------------------- + + + +//============================================================================= +} // namespace ACG +//============================================================================= +#endif // COMISO_SUITESPARSE_AVAILABLE +//============================================================================= diff --git a/src/external/CoMISo/EigenSolver/EigenArpackMatrixT.hh b/src/external/CoMISo/EigenSolver/EigenArpackMatrixT.hh new file mode 100644 index 000000000..d7a112103 --- /dev/null +++ b/src/external/CoMISo/EigenSolver/EigenArpackMatrixT.hh @@ -0,0 +1,126 @@ +//============================================================================= +// +// CLASS EigenArpackMatrixT +// +//============================================================================= + + +#ifndef COMISO_EIGENARPACKMATRIXT_HH +#define COMISO_EIGENARPACKMATRIXT_HH + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if (COMISO_SUITESPARSE_AVAILABLE && COMISO_EIGEN3_AVAILABLE) +//============================================================================= + + +//== INCLUDES ================================================================= + +#include +#include + +#if EIGEN_VERSION_AT_LEAST(3,1,0) + #include +#else + #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET + #include +#endif +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + +/** \class EigenArpackMatrixT EigenArpackMatrixT.hh + + Brief Description. + + A more elaborate description follows. +*/ + +template +class EigenArpackMatrixT +{ +public: + + typedef MatrixT Matrix; + typedef RealT Real; + + /// Constructor + template + 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 > v(_v,mat_.rows()); // uses v as a ArrayXf object + Eigen::Map > 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 > v(_v,mat_.rows()); // uses v as a ArrayXf object + Eigen::Map > 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 > sllt_; +#else + Eigen::SparseLLT, 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 +//============================================================================= + diff --git a/src/external/CoMISo/Examples/factored_solver/CMakeLists.txt b/src/external/CoMISo/Examples/factored_solver/CMakeLists.txt new file mode 100644 index 000000000..da380df66 --- /dev/null +++ b/src/external/CoMISo/Examples/factored_solver/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/factored_solver/main.cc b/src/external/CoMISo/Examples/factored_solver/main.cc new file mode 100644 index 000000000..9248aac6f --- /dev/null +++ b/src/external/CoMISo/Examples/factored_solver/main.cc @@ -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 . * + * * +\*===========================================================================*/ + + + +#include +#include +#include +#include +#include +#include + +/// 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 +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 +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 +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 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; +} + diff --git a/src/external/CoMISo/Examples/quadratic_solver/CMakeLists.txt b/src/external/CoMISo/Examples/quadratic_solver/CMakeLists.txt new file mode 100644 index 000000000..a76e75913 --- /dev/null +++ b/src/external/CoMISo/Examples/quadratic_solver/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/quadratic_solver/main.cc b/src/external/CoMISo/Examples/quadratic_solver/main.cc new file mode 100644 index 000000000..74675be6d --- /dev/null +++ b/src/external/CoMISo/Examples/quadratic_solver/main.cc @@ -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 . * + * * +\*===========================================================================*/ + +#include +#include +#include +#include +#include +#include + +/// 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 +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 +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 +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 +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; +} + diff --git a/src/external/CoMISo/Examples/small_cplex_soc/CMakeLists.txt b/src/external/CoMISo/Examples/small_cplex_soc/CMakeLists.txt new file mode 100644 index 000000000..b76596e7e --- /dev/null +++ b/src/external/CoMISo/Examples/small_cplex_soc/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/small_cplex_soc/main.cc b/src/external/CoMISo/Examples/small_cplex_soc/main.cc new file mode 100644 index 000000000..53625f53e --- /dev/null +++ b/src/external/CoMISo/Examples/small_cplex_soc/main.cc @@ -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 . * + * * +\*===========================================================================*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +// 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 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; iSetStringValue("derivative_test", "second-order"); + ipopt.solve(&lsqp, constraints); +#endif + + std::cout << "---------- 6) Print solution..." << std::endl; + for( int i=0; i 0) + { + A.coeffRef(i,i-1) = -1.0; + ++count; + } + if(i 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. * + * * +\*===========================================================================*/ + + +#include +#include +#include +#include +#include +#include + + +/// function to initialize a simple row matrix of equations +template +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 +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; +} + diff --git a/src/external/CoMISo/Examples/small_miqp/CMakeLists.txt b/src/external/CoMISo/Examples/small_miqp/CMakeLists.txt new file mode 100644 index 000000000..f4040ef8e --- /dev/null +++ b/src/external/CoMISo/Examples/small_miqp/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/small_miqp/main.cc b/src/external/CoMISo/Examples/small_miqp/main.cc new file mode 100644 index 000000000..54a07e7cf --- /dev/null +++ b/src/external/CoMISo/Examples/small_miqp/main.cc @@ -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 . * + * * +\*===========================================================================*/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +// 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 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 discrete_variables; + discrete_variables.push_back( COMISO::PairIndexVtype(0,COMISO::Integer) ); + + std::cout << "---------- 4) setup constraints..." << std::endl; + std::vector 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; +} + diff --git a/src/external/CoMISo/Examples/small_nleast_squares/CMakeLists.txt b/src/external/CoMISo/Examples/small_nleast_squares/CMakeLists.txt new file mode 100644 index 000000000..438cdb292 --- /dev/null +++ b/src/external/CoMISo/Examples/small_nleast_squares/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/small_nleast_squares/main.cc b/src/external/CoMISo/Examples/small_nleast_squares/main.cc new file mode 100644 index 000000000..4aba84765 --- /dev/null +++ b/src/external/CoMISo/Examples/small_nleast_squares/main.cc @@ -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 . * + * * +\*===========================================================================*/ + +#include + +#include +#include +#include +#include +#include +#include + + +// 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 constraints; + ipsol.solve(&lsqp, constraints); +#endif + + std::cout << "---------- 5) Print solution..." << std::endl; + for( int i=0; i provide an empty vector + std::vector constraints; + ipsol.solve(&lsqp, constraints); +#endif + + std::cout << "---------- 5) Print solution..." << std::endl; + for( int i=0; i > 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; +} + diff --git a/src/external/CoMISo/Examples/small_quadratic_resolve_example/CMakeLists.txt b/src/external/CoMISo/Examples/small_quadratic_resolve_example/CMakeLists.txt new file mode 100644 index 000000000..982942ddc --- /dev/null +++ b/src/external/CoMISo/Examples/small_quadratic_resolve_example/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/small_quadratic_resolve_example/main.cc b/src/external/CoMISo/Examples/small_quadratic_resolve_example/main.cc new file mode 100644 index 000000000..d0425a104 --- /dev/null +++ b/src/external/CoMISo/Examples/small_quadratic_resolve_example/main.cc @@ -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 . * + * * +\*===========================================================================*/ + + + +#include +#include +#include +#include +#include +#include + + +/// function to initialize a simple system of linear equations +template +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 +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 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 constraint_rhs(3); + std::vector 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; +} + diff --git a/src/external/CoMISo/Examples/small_sparseqr/CMakeLists.txt b/src/external/CoMISo/Examples/small_sparseqr/CMakeLists.txt new file mode 100644 index 000000000..1bc292aef --- /dev/null +++ b/src/external/CoMISo/Examples/small_sparseqr/CMakeLists.txt @@ -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} +) diff --git a/src/external/CoMISo/Examples/small_sparseqr/main.cc b/src/external/CoMISo/Examples/small_sparseqr/main.cc new file mode 100644 index 000000000..e0087abe3 --- /dev/null +++ b/src/external/CoMISo/Examples/small_sparseqr/main.cc @@ -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 . * + * * +\*===========================================================================*/ + +#include +#include +#include +#include + +//------------------------------------------------------------------------------------------------------ +#if COMISO_SUITESPARSE_SPQR_AVAILABLE // additional spqr library required +//------------------------------------------------------------------------------------------------------ + +#include +#include +#include +#include + + +//------------------------------------------------------------------------------------------------------ + +// 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 + diff --git a/src/external/CoMISo/NSolver/BoundConstraint.cc b/src/external/CoMISo/NSolver/BoundConstraint.cc new file mode 100644 index 000000000..c0b541a8b --- /dev/null +++ b/src/external/CoMISo/NSolver/BoundConstraint.cc @@ -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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/BoundConstraint.hh b/src/external/CoMISo/NSolver/BoundConstraint.hh new file mode 100644 index 000000000..c419ef141 --- /dev/null +++ b/src/external/CoMISo/NSolver/BoundConstraint.hh @@ -0,0 +1,84 @@ +//============================================================================= +// +// CLASS BoundConstraint +// +//============================================================================= + + +#ifndef COMISO_BOUNDCONSTRAINT_HH +#define COMISO_BOUNDCONSTRAINT_HH + + +//== INCLUDES ================================================================= + +#include +#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 SVectorNC; +// typedef SuperSparseMatrixT 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/COMISOSolver.cc b/src/external/CoMISo/NSolver/COMISOSolver.cc new file mode 100644 index 000000000..ff01449a5 --- /dev/null +++ b/src/external/CoMISo/NSolver/COMISOSolver.cc @@ -0,0 +1,140 @@ +//============================================================================= +// +// CLASS COMISOSolver - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +//============================================================================= + +#include +#include "COMISOSolver.hh" + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + +// ********** SOLVE **************** // +void +COMISOSolver:: +solve(NProblemInterface* _problem, + std::vector& _constraints, + std::vector& _discrete_constraints, + double _reg_factor, + bool _show_miso_settings, + bool _show_timings ) +{ + + //---------------------------------------------- + // 1. identify integer variables + //---------------------------------------------- + + // identify integer variables + std::vector 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 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 rhs(_problem->n_unknowns()); + _problem->eval_gradient(P(x), P(rhs)); + for(unsigned int i=0; ieval_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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/COMISOSolver.hh b/src/external/CoMISo/NSolver/COMISOSolver.hh new file mode 100644 index 000000000..f13de482b --- /dev/null +++ b/src/external/CoMISo/NSolver/COMISOSolver.hh @@ -0,0 +1,85 @@ +//============================================================================= +// +// CLASS COMISOSolver +// +//============================================================================= + + +#ifndef COMISO_COMISOSOLVER_HH +#define COMISO_COMISOSOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include + +//== INCLUDES ================================================================= + +#include +#include +#include +#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 PairUiV; + + /// Default constructor + COMISOSolver() {} + + /// Destructor + ~COMISOSolver() {} + + // ********** SOLVE **************** // + void solve(NProblemInterface* _problem, // problem instance + std::vector& _constraints, // linear constraints + std::vector& _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& _v) + { + if( !_v.empty()) + return ((double*)&_v[0]); + else + return 0; + } + +private: + ConstrainedSolver cs_; +}; + + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#endif // ACG_GUROBISOLVER_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/CPLEXSolver.cc b/src/external/CoMISo/NSolver/CPLEXSolver.cc new file mode 100644 index 000000000..3f51f7b08 --- /dev/null +++ b/src/external/CoMISo/NSolver/CPLEXSolver.cc @@ -0,0 +1,68 @@ +//============================================================================= +// +// CLASS CPLEXSolver - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include "CPLEXSolver.hh" +#if COMISO_CPLEX_AVAILABLE +//============================================================================= + + +#include + +//== 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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/CPLEXSolver.hh b/src/external/CoMISo/NSolver/CPLEXSolver.hh new file mode 100644 index 000000000..9967c4def --- /dev/null +++ b/src/external/CoMISo/NSolver/CPLEXSolver.hh @@ -0,0 +1,117 @@ +//============================================================================= +// +// CLASS CPLEXSolver +// +//============================================================================= + + +#ifndef COMISO_CPLEXSOLVER_HH +#define COMISO_CPLEXSOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_CPLEX_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include +#include +#include "NProblemInterface.hh" +#include "NConstraintInterface.hh" +#include "VariableType.hh" + +#include +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& _constraints, // linear constraints + std::vector& _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& _constraints, // linear constraints + const double _time_limit = 60, + const bool _silent = false) // time limit in seconds + { std::vector dc; return solve(_problem, _constraints, dc, _time_limit, _silent);} + + // with handling of cone constrints + inline bool solve2(NProblemInterface* _problem, // problem instance + std::vector& _constraints, // linear constraints + std::vector& _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& _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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/CPLEXSolverT.cc b/src/external/CoMISo/NSolver/CPLEXSolverT.cc new file mode 100644 index 000000000..adabe08e4 --- /dev/null +++ b/src/external/CoMISo/NSolver/CPLEXSolverT.cc @@ -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 + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + + +// ********** SOLVE **************** // +bool +CPLEXSolver:: +solve2(NProblemInterface* _problem, + std::vector& _constraints, + std::vector& _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 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 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 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 g(_problem->n_unknowns()); + _problem->eval_gradient(P(x), P(g)); + for(unsigned int i=0; ieval_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; istore_result(P(x)); + } + +/* + if (solution_input_path_.empty()) + { + // store computed result + for(unsigned int i=0; i " << 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& _constraints, + std::vector& _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 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 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 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(_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(_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(_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 g(_problem->n_unknowns()); + _problem->eval_gradient(P(x), P(g)); + for(unsigned int i=0; ieval_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; istore_result(P(x)); + } + +/* + if (solution_input_path_.empty()) + { + // store computed result + for(unsigned int i=0; i " << 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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/ConeConstraint.cc b/src/external/CoMISo/NSolver/ConeConstraint.cc new file mode 100644 index 000000000..25b7fecc2 --- /dev/null +++ b/src/external/CoMISo/NSolver/ConeConstraint.cc @@ -0,0 +1,134 @@ +//============================================================================= +// +// CLASS ConerConstraint +// +//============================================================================= + + +#ifndef COMISO_CONECONSTRAINT_CC +#define COMISO_CONECONSTRAINT_CC + + +//== INCLUDES ================================================================= + +#include +#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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/ConeConstraint.hh b/src/external/CoMISo/NSolver/ConeConstraint.hh new file mode 100644 index 000000000..3f556d310 --- /dev/null +++ b/src/external/CoMISo/NSolver/ConeConstraint.hh @@ -0,0 +1,90 @@ +//============================================================================= +// +// CLASS ConeConstraint +// +//============================================================================= + + +#ifndef COMISO_CONECONSTRAINT_HH +#define COMISO_CONECONSTRAINT_HH + + +//== INCLUDES ================================================================= + +#include +#include "NConstraintInterface.hh" +#include + + +//== 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/GUROBISolver.cc b/src/external/CoMISo/NSolver/GUROBISolver.cc new file mode 100644 index 000000000..313b44193 --- /dev/null +++ b/src/external/CoMISo/NSolver/GUROBISolver.cc @@ -0,0 +1,254 @@ +//============================================================================= +// +// CLASS GUROBISolver - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_GUROBI_AVAILABLE +//============================================================================= + + +#include "GUROBISolver.hh" + +#include + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + + +GUROBISolver:: +GUROBISolver() +{ +} + +//----------------------------------------------------------------------------- + +// ********** SOLVE **************** // +bool +GUROBISolver:: +solve(NProblemInterface* _problem, + std::vector& _constraints, + std::vector& _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 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 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 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 g(_problem->n_unknowns()); + _problem->eval_gradient(P(x), P(g)); + for(unsigned int i=0; ieval_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 " << 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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/GUROBISolver.hh b/src/external/CoMISo/NSolver/GUROBISolver.hh new file mode 100644 index 000000000..caf2c7a26 --- /dev/null +++ b/src/external/CoMISo/NSolver/GUROBISolver.hh @@ -0,0 +1,92 @@ +//============================================================================= +// +// CLASS GUROBISolver +// +//============================================================================= + + +#ifndef COMISO_GUROBISOLVER_HH +#define COMISO_GUROBISOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_GUROBI_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include +#include +#include "NProblemInterface.hh" +#include "NConstraintInterface.hh" +#include "VariableType.hh" +#include "GurobiHelper.hh" + +#include + +//== 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& _constraints, // linear constraints + std::vector& _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& _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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/GurobiHelper.cc b/src/external/CoMISo/NSolver/GurobiHelper.cc new file mode 100644 index 000000000..0bfa41134 --- /dev/null +++ b/src/external/CoMISo/NSolver/GurobiHelper.cc @@ -0,0 +1,175 @@ +/* + * GurobiHelper.cc + * + * Created on: Jan 4, 2012 + * Author: ebke + */ + +#include "GurobiHelper.hh" + +#if (COMISO_GUROBI_AVAILABLE && COMISO_BOOST_AVAILABLE) + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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; + { + 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; + { + 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 &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(match[2])); + } + } +} + +} /* namespace COMISO */ + +#endif diff --git a/src/external/CoMISo/NSolver/GurobiHelper.hh b/src/external/CoMISo/NSolver/GurobiHelper.hh new file mode 100644 index 000000000..58d872b8b --- /dev/null +++ b/src/external/CoMISo/NSolver/GurobiHelper.hh @@ -0,0 +1,51 @@ +/* + * GurobiHelper.hh + * + * Created on: Jan 4, 2012 + * Author: ebke + */ + + +#ifndef GUROBIHELPER_HH_ +#define GUROBIHELPER_HH_ + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if (COMISO_GUROBI_AVAILABLE && COMISO_BOOST_AVAILABLE) +//============================================================================= + +#include +#include +#include + +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 &out_solution_, const std::string &fileName_); +}; + +} /* namespace COMISO */ +#endif /* COMISO_GUROBI_AVAILABLE */ +#endif /* GUROBIHELPER_HH_ */ + + diff --git a/src/external/CoMISo/NSolver/IPOPTSolver.cc b/src/external/CoMISo/NSolver/IPOPTSolver.cc new file mode 100644 index 000000000..8fd273dea --- /dev/null +++ b/src/external/CoMISo/NSolver/IPOPTSolver.cc @@ -0,0 +1,1153 @@ +//============================================================================= +// +// CLASS IPOPTSolver - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_IPOPT_AVAILABLE +//============================================================================= + + +#include "IPOPTSolver.hh" + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + +// Constructor +IPOPTSolver:: +IPOPTSolver() +{ + // Create an instance of the IpoptApplication + app_ = IpoptApplicationFactory(); + + // Switch to HSL if available in Comiso + #if COMISO_HSL_AVAILABLE + app_->Options()->SetStringValue("linear_solver", "ma57"); + #endif + + // Restrict memory to be able to run larger problems on windows + // with the default mumps solver + #ifdef WIN32 + app_->Options()->SetIntegerValue("mumps_mem_percent", 5); + #endif + + // set default parameters + app_->Options()->SetIntegerValue("max_iter", 100); + // app->Options()->SetStringValue("derivative_test", "second-order"); + // app->Options()->SetIntegerValue("print_level", 0); + // app->Options()->SetStringValue("expect_infeasible_problem", "yes"); + +} + + +//----------------------------------------------------------------------------- + + + +int +IPOPTSolver:: +solve(NProblemInterface* _problem, const std::vector& _constraints) +{ + //---------------------------------------------------------------------------- + // 1. Create an instance of IPOPT NLP + //---------------------------------------------------------------------------- + Ipopt::SmartPtr np = new NProblemIPOPT(_problem, _constraints); + NProblemIPOPT* np2 = dynamic_cast (Ipopt::GetRawPtr(np)); + + //---------------------------------------------------------------------------- + // 2. exploit special characteristics of problem + //---------------------------------------------------------------------------- + + std::cerr << "exploit detected special properties: "; + if(np2->hessian_constant()) + { + std::cerr << "*constant hessian* "; + app().Options()->SetStringValue("hessian_constant", "yes"); + } + + if(np2->jac_c_constant()) + { + std::cerr << "*constant jacobian of equality constraints* "; + app().Options()->SetStringValue("jac_c_constant", "yes"); + } + + if(np2->jac_d_constant()) + { + std::cerr << "*constant jacobian of in-equality constraints*"; + app().Options()->SetStringValue("jac_d_constant", "yes"); + } + std::cerr << std::endl; + + //---------------------------------------------------------------------------- + // 3. solve problem + //---------------------------------------------------------------------------- + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = app_->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + printf("\n\n*** Error IPOPT during initialization!\n"); + } + + status = app_->OptimizeTNLP( np); + + //---------------------------------------------------------------------------- + // 4. output statistics + //---------------------------------------------------------------------------- + if (status == Ipopt::Solve_Succeeded || status == Ipopt::Solved_To_Acceptable_Level) + { + // Retrieve some statistics about the solve + Ipopt::Index iter_count = app_->Statistics()->IterationCount(); + printf("\n\n*** IPOPT: The problem solved in %d iterations!\n", iter_count); + + Ipopt::Number final_obj = app_->Statistics()->FinalObjective(); + printf("\n\n*** IPOPT: The final value of the objective function is %e.\n", final_obj); + } + + return status; +} + + +//----------------------------------------------------------------------------- + + + +int +IPOPTSolver:: +solve(NProblemInterface* _problem, + const std::vector& _constraints, + const std::vector& _lazy_constraints, + const double _almost_infeasible, + const int _max_passes ) +{ + //---------------------------------------------------------------------------- + // 0. Initialize IPOPT Applicaiton + //---------------------------------------------------------------------------- + + StopWatch sw; sw.start(); + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = app_->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + printf("\n\n*** Error IPOPT during initialization!\n"); + } + + bool feasible_point_found = false; + int cur_pass = 0; + double acceptable_tolerance = 0.01; // hack: read out from ipopt!!! + // copy default constraints + std::vector constraints = _constraints; + std::vector lazy_added(_lazy_constraints.size(),false); + + // cache statistics of all iterations + std::vector n_inf; + std::vector n_almost_inf; + + while(!feasible_point_found && cur_pass <(_max_passes-1)) + { + ++cur_pass; + //---------------------------------------------------------------------------- + // 1. Create an instance of current IPOPT NLP + //---------------------------------------------------------------------------- + Ipopt::SmartPtr np = new NProblemIPOPT(_problem, constraints); + NProblemIPOPT* np2 = dynamic_cast (Ipopt::GetRawPtr(np)); + // enable caching of solution + np2->store_solution() = true; + + //---------------------------------------------------------------------------- + // 2. exploit special characteristics of problem + //---------------------------------------------------------------------------- + + std::cerr << "detected special properties which will be exploit: "; + if(np2->hessian_constant()) + { + std::cerr << "*constant hessian* "; + app().Options()->SetStringValue("hessian_constant", "yes"); + } + + if(np2->jac_c_constant()) + { + std::cerr << "*constant jacobian of equality constraints* "; + app().Options()->SetStringValue("jac_c_constant", "yes"); + } + + if(np2->jac_d_constant()) + { + std::cerr << "*constant jacobian of in-equality constraints*"; + app().Options()->SetStringValue("jac_d_constant", "yes"); + } + std::cerr << std::endl; + + //---------------------------------------------------------------------------- + // 3. solve problem + //---------------------------------------------------------------------------- + status = app_->OptimizeTNLP( np); + + // check lazy constraints + n_inf.push_back(0); + n_almost_inf.push_back(0); + feasible_point_found = true; + for(unsigned int i=0; i<_lazy_constraints.size(); ++i) + if(!lazy_added[i]) + { + NConstraintInterface* lc = _lazy_constraints[i]; + + double v = lc->eval_constraint(&(np2->solution()[0])); + + bool inf = false; + bool almost_inf = false; + + if(lc->constraint_type() == NConstraintInterface::NC_EQUAL) + { + v = std::abs(v); + if(v>acceptable_tolerance) + inf = true; + else + if(v>_almost_infeasible) + almost_inf = true; + } + else + if(lc->constraint_type() == NConstraintInterface::NC_GREATER_EQUAL) + { + if(v<-acceptable_tolerance) + inf = true; + else + if(v<_almost_infeasible) + almost_inf = true; + } + else + if(lc->constraint_type() == NConstraintInterface::NC_LESS_EQUAL) + { + if(v>acceptable_tolerance) + inf = true; + else + if(v>-_almost_infeasible) + almost_inf = true; + } + + // infeasible? + if(inf) + { + constraints.push_back(lc); + lazy_added[i] = true; + feasible_point_found = false; + ++n_inf.back(); + } + + // almost violated or violated? -> add to constraints + if(almost_inf) + { + constraints.push_back(lc); + lazy_added[i] = true; + ++n_almost_inf.back(); + } + } + } + + // no termination after max number of passes? + if(!feasible_point_found) + { + ++cur_pass; + + std::cerr << "*************** could not find feasible point after " << _max_passes-1 << " -> solving with all lazy constraints..." << std::endl; + for(unsigned int i=0; i<_lazy_constraints.size(); ++i) + if(!lazy_added[i]) + constraints.push_back(_lazy_constraints[i]); + + //---------------------------------------------------------------------------- + // 1. Create an instance of current IPOPT NLP + //---------------------------------------------------------------------------- + Ipopt::SmartPtr np = new NProblemIPOPT(_problem, constraints); + NProblemIPOPT* np2 = dynamic_cast (Ipopt::GetRawPtr(np)); + // enable caching of solution + np2->store_solution() = true; + + //---------------------------------------------------------------------------- + // 2. exploit special characteristics of problem + //---------------------------------------------------------------------------- + + std::cerr << "exploit detected special properties: "; + if(np2->hessian_constant()) + { + std::cerr << "*constant hessian* "; + app().Options()->SetStringValue("hessian_constant", "yes"); + } + + if(np2->jac_c_constant()) + { + std::cerr << "*constant jacobian of equality constraints* "; + app().Options()->SetStringValue("jac_c_constant", "yes"); + } + + if(np2->jac_d_constant()) + { + std::cerr << "*constant jacobian of in-equality constraints*"; + app().Options()->SetStringValue("jac_d_constant", "yes"); + } + std::cerr << std::endl; + + //---------------------------------------------------------------------------- + // 3. solve problem + //---------------------------------------------------------------------------- + status = app_->OptimizeTNLP( np); + } + + const double overall_time = sw.stop()/1000.0; + + //---------------------------------------------------------------------------- + // 4. output statistics + //---------------------------------------------------------------------------- + if (status == Ipopt::Solve_Succeeded || status == Ipopt::Solved_To_Acceptable_Level) + { + // Retrieve some statistics about the solve + Ipopt::Index iter_count = app_->Statistics()->IterationCount(); + printf("\n\n*** IPOPT: The problem solved in %d iterations!\n", iter_count); + + Ipopt::Number final_obj = app_->Statistics()->FinalObjective(); + printf("\n\n*** IPOPT: The final value of the objective function is %e.\n", final_obj); + } + + std::cerr <<"############# IPOPT with lazy constraints statistics ###############" << std::endl; + std::cerr << "overall time: " << overall_time << "s" << std::endl; + std::cerr << "#passes : " << cur_pass << "( of " << _max_passes << ")" << std::endl; + for(unsigned int i=0; i constraints; + return this->solve(_problem, constraints); +} + + +//----------------------------------------------------------------------------- + + +int +IPOPTSolver:: +solve(NProblemGmmInterface* _problem, std::vector& _constraints) +{ + std::cerr << "****** Warning: NProblemGmmInterface is deprecated!!! -> use NProblemInterface *******\n"; + + //---------------------------------------------------------------------------- + // 1. Create an instance of IPOPT NLP + //---------------------------------------------------------------------------- + Ipopt::SmartPtr np = new NProblemGmmIPOPT(_problem, _constraints); + + //---------------------------------------------------------------------------- + // 2. solve problem + //---------------------------------------------------------------------------- + + // Initialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = app_->Initialize(); + if (status != Ipopt::Solve_Succeeded) + { + printf("\n\n*** Error IPOPT during initialization!\n"); + } + + //---------------------------------------------------------------------------- + // 3. solve problem + //---------------------------------------------------------------------------- + status = app_->OptimizeTNLP(np); + + //---------------------------------------------------------------------------- + // 4. output statistics + //---------------------------------------------------------------------------- + if (status == Ipopt::Solve_Succeeded || status == Ipopt::Solved_To_Acceptable_Level) + { + // Retrieve some statistics about the solve + Ipopt::Index iter_count = app_->Statistics()->IterationCount(); + printf("\n\n*** IPOPT: The problem solved in %d iterations!\n", iter_count); + + Ipopt::Number final_obj = app_->Statistics()->FinalObjective(); + printf("\n\n*** IPOPT: The final value of the objective function is %e.\n", final_obj); + } + + return status; +} + + +//== IMPLEMENTATION PROBLEM INSTANCE========================================================== + + +void +NProblemIPOPT:: +split_constraints(const std::vector& _constraints) +{ + // split user-provided constraints into general-constraints and bound-constraints + constraints_ .clear(); constraints_.reserve(_constraints.size()); + bound_constraints_.clear(); bound_constraints_.reserve(_constraints.size()); + + for(unsigned int i=0; i<_constraints.size(); ++i) + { + BoundConstraint* bnd_ptr = dynamic_cast(_constraints[i]); + + if(bnd_ptr) + bound_constraints_.push_back(bnd_ptr); + else + constraints_.push_back(_constraints[i]); + } +} + + +//----------------------------------------------------------------------------- + + +void +NProblemIPOPT:: +analyze_special_properties(const NProblemInterface* _problem, const std::vector& _constraints) +{ + hessian_constant_ = true; + jac_c_constant_ = true; + jac_d_constant_ = true; + + if(!_problem->constant_hessian()) + hessian_constant_ = false; + + for(unsigned int i=0; i<_constraints.size(); ++i) + { + if(!_constraints[i]->constant_hessian()) + hessian_constant_ = false; + + if(!_constraints[i]->constant_gradient()) + { + if(_constraints[i]->constraint_type() == NConstraintInterface::NC_EQUAL) + jac_c_constant_ = false; + else + jac_d_constant_ = false; + } + + // nothing else to check? + if(!hessian_constant_ && !jac_c_constant_ && !jac_d_constant_) + break; + } + + //hessian of Lagrangian is only constant, if all hessians of the constraints are zero (due to lambda multipliers) + if(!jac_c_constant_ || !jac_d_constant_) + hessian_constant_ = false; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g, + Index& nnz_h_lag, IndexStyleEnum& index_style) +{ + // number of variables + n = problem_->n_unknowns(); + + // number of constraints + m = constraints_.size(); + + // get non-zeros of hessian of lagrangian and jacobi of constraints + nnz_jac_g = 0; + nnz_h_lag = 0; + + // get nonzero structure + std::vector x(n); + problem_->initial_x(P(x)); + + // nonzeros in the jacobian of C_ and the hessian of the lagrangian + SMatrixNP HP; + SVectorNC g; + SMatrixNC H; + problem_->eval_hessian(P(x), HP); + + // get nonzero structure of hessian of problem + for(int i=0; i= it.col()) + ++nnz_h_lag; + + // get nonzero structure of constraints + for( int i=0; ieval_gradient(P(x),g); + + nnz_jac_g += g.nonZeros(); + + // count lower triangular elements + constraints_[i]->eval_hessian (P(x),H); + + SMatrixNC::iterator m_it = H.begin(); + for(; m_it != H.end(); ++m_it) + if( m_it.row() >= m_it.col()) + ++nnz_h_lag; + } + + // We use the standard fortran index style for row/col entries + index_style = C_STYLE; + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::get_bounds_info(Index n, Number* x_l, Number* x_u, + Index m, Number* g_l, Number* g_u) +{ + // check dimensions + if( n != (Index)problem_->n_unknowns()) + std::cerr << "Warning: IPOPT #unknowns != n " << n << problem_->n_unknowns() << std::endl; + if( m != (Index)constraints_.size()) + std::cerr << "Warning: IPOPT #constraints != m " << m << constraints_.size() << std::endl; + + + // first clear all variable bounds + for( int i=0; iidx()) < n) + { + switch(bound_constraints_[i]->constraint_type()) + { + case NConstraintInterface::NC_LESS_EQUAL: + { + x_u[bound_constraints_[i]->idx()] = bound_constraints_[i]->bound(); + }break; + + case NConstraintInterface::NC_GREATER_EQUAL: + { + x_l[bound_constraints_[i]->idx()] = bound_constraints_[i]->bound(); + }break; + + case NConstraintInterface::NC_EQUAL: + { + x_l[bound_constraints_[i]->idx()] = bound_constraints_[i]->bound(); + x_u[bound_constraints_[i]->idx()] = bound_constraints_[i]->bound(); + }break; + } + } + else + std::cerr << "Warning: invalid bound constraint in IPOPTSolver!!!" << std::endl; + } + + // set bounds for constraints + for( int i=0; iconstraint_type()) + { + case NConstraintInterface::NC_EQUAL : g_u[i] = 0.0 ; g_l[i] = 0.0 ; break; + case NConstraintInterface::NC_LESS_EQUAL : g_u[i] = 0.0 ; g_l[i] = -1.0e19; break; + case NConstraintInterface::NC_GREATER_EQUAL : g_u[i] = 1.0e19; g_l[i] = 0.0 ; break; + default : g_u[i] = 1.0e19; g_l[i] = -1.0e19; break; + } + } + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::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) +{ + // get initial value of problem instance + problem_->initial_x(x); + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::eval_f(Index n, const Number* x, bool new_x, Number& obj_value) +{ + // return the value of the objective function + obj_value = problem_->eval_f(x); + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) +{ + problem_->eval_gradient(x, grad_f); + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) +{ + // evaluate all constraint functions + for( int i=0; ieval_constraint(x); + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::eval_jac_g(Index n, const Number* x, bool new_x, + Index m, Index nele_jac, Index* iRow, Index *jCol, + Number* values) +{ + if (values == NULL) + { + // get x for evaluation (arbitrary position should be ok) + std::vector x_rnd(problem_->n_unknowns(), 0.0); + + int gi = 0; + SVectorNC g; + for( int i=0; ieval_gradient(&(x_rnd[0]), g); + SVectorNC::InnerIterator v_it(g); + for( ; v_it; ++v_it) + { + iRow[gi] = i; + jCol[gi] = v_it.index(); + ++gi; + } + } + } + else + { + // return the values of the jacobian of the constraints + + // return the structure of the jacobian of the constraints + // global index + int gi = 0; + SVectorNC g; + + for( int i=0; ieval_gradient(x, g); + + SVectorNC::InnerIterator v_it(g); + + for( ; v_it; ++v_it) + { + values[gi] = v_it.value(); + ++gi; + } + } + + if( gi != nele_jac) + std::cerr << "Warning: number of non-zeros in Jacobian of C is incorrect: " + << gi << " vs " << nele_jac << std::endl; + } + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemIPOPT::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) +{ + if (values == NULL) + { + // return structure + + // get x for evaluation (arbitrary position should be ok) + std::vector x_rnd(problem_->n_unknowns(), 0.0); + + // global index + int gi = 0; + // get hessian of problem + SMatrixNP HP; + problem_->eval_hessian(&(x_rnd[0]), HP); + + for(int i=0; i= it.col()) + { + // it.value(); + iRow[gi] = it.row(); + jCol[gi] = it.col(); + ++gi; + } + } + + // Hessians of Constraints + for(unsigned int j=0; jeval_hessian(&(x_rnd[0]), H); + + SMatrixNC::iterator m_it = H.begin(); + SMatrixNC::iterator m_end = H.end(); + + for(; m_it != m_end; ++m_it) + { + // store lower triangular part only + if( m_it.row() >= m_it.col()) + { + iRow[gi] = m_it.row(); + jCol[gi] = m_it.col(); + ++gi; + } + } + } + + // error check + if( gi != nele_hess) + std::cerr << "Warning: number of non-zeros in Hessian of Lagrangian is incorrect while indexing: " + << gi << " vs " << nele_hess << std::endl; + } + else + { + // return values. + + // global index + int gi = 0; + // get hessian of problem + SMatrixNP HP; + problem_->eval_hessian(x, HP); + + for(int i=0; i= it.col()) + { + values[gi] = obj_factor*it.value(); + ++gi; + } + } + + // Hessians of Constraints + for(unsigned int j=0; jeval_hessian(x, H); + + SMatrixNC::iterator m_it = H.begin(); + SMatrixNC::iterator m_end = H.end(); + + for(; m_it != m_end; ++m_it) + { + // store lower triangular part only + if( m_it.row() >= m_it.col()) + { + values[gi] = lambda[j]*(*m_it); + ++gi; + } + } + } + + // error check + if( gi != nele_hess) + std::cerr << "Warning: number of non-zeros in Hessian of Lagrangian is incorrect2: " + << gi << " vs " << nele_hess << std::endl; + } + return true; +} + + +//----------------------------------------------------------------------------- + + +void NProblemIPOPT::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) +{ + // problem knows what to do + problem_->store_result(x); + + if(store_solution_) + { + x_.resize(n); + for( Index i=0; in_unknowns(); + + // number of constraints + m = constraints_.size(); + + // get nonzero structure + std::vector x(n); + problem_->initial_x(&(x[0])); + // ToDo: perturb x + + // nonzeros in the jacobian of C_ and the hessian of the lagrangian + SMatrixNP HP; + SVectorNC g; + SMatrixNC H; + problem_->eval_hessian(&(x[0]), HP); + nnz_jac_g = 0; + nnz_h_lag = 0; + + // clear old data + jac_g_iRow_.clear(); + jac_g_jCol_.clear(); + h_lag_iRow_.clear(); + h_lag_jCol_.clear(); + + // get non-zero structure of initial hessian + // iterate over rows + for( int i=0; i= (int)v_it.index()) + { + h_lag_iRow_.push_back(i); + h_lag_jCol_.push_back(v_it.index()); + ++nnz_h_lag; + } + } + } + + + // get nonzero structure of constraints + for( int i=0; ieval_gradient(&(x[0]),g); + constraints_[i]->eval_hessian (&(x[0]),H); + + // iterate over sparse vector + SVectorNC::InnerIterator v_it(g); + for(; v_it; ++v_it) + { + jac_g_iRow_.push_back(i); + jac_g_jCol_.push_back(v_it.index()); + ++nnz_jac_g; + } + + // iterate over superSparseMatrix + SMatrixNC::iterator m_it = H.begin(); + SMatrixNC::iterator m_end = H.end(); + for(; m_it != m_end; ++m_it) + if( m_it.row() >= m_it.col()) + { + h_lag_iRow_.push_back(m_it.row()); + h_lag_jCol_.push_back(m_it.col()); + ++nnz_h_lag; + } + } + + // store for error checking... + nnz_jac_g_ = nnz_jac_g; + nnz_h_lag_ = nnz_h_lag; + + // We use the standard fortran index style for row/col entries + index_style = C_STYLE; + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::get_bounds_info(Index n, Number* x_l, Number* x_u, + Index m, Number* g_l, Number* g_u) +{ + // first clear all variable bounds + for( int i=0; iconstraint_type()) + { + case NConstraintInterface::NC_EQUAL : g_u[i] = 0.0 ; g_l[i] = 0.0 ; break; + case NConstraintInterface::NC_LESS_EQUAL : g_u[i] = 0.0 ; g_l[i] = -1.0e19; break; + case NConstraintInterface::NC_GREATER_EQUAL : g_u[i] = 1.0e19; g_l[i] = 0.0 ; break; + default : g_u[i] = 1.0e19; g_l[i] = -1.0e19; break; + } + } + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::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) +{ + // get initial value of problem instance + problem_->initial_x(x); + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::eval_f(Index n, const Number* x, bool new_x, Number& obj_value) +{ + // return the value of the objective function + obj_value = problem_->eval_f(x); + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f) +{ + problem_->eval_gradient(x, grad_f); + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) +{ + // evaluate all constraint functions + for( int i=0; ieval_constraint(x); + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::eval_jac_g(Index n, const Number* x, bool new_x, + Index m, Index nele_jac, Index* iRow, Index *jCol, + Number* values) +{ + if (values == NULL) + { + // return the (cached) structure of the jacobian of the constraints + gmm::copy(jac_g_iRow_, VectorPTi(iRow, jac_g_iRow_.size())); + gmm::copy(jac_g_jCol_, VectorPTi(jCol, jac_g_jCol_.size())); + } + else + { + // return the values of the jacobian of the constraints + + // return the structure of the jacobian of the constraints + // global index + int gi = 0; + SVectorNC g; + + for( int i=0; ieval_gradient(x, g); + + SVectorNC::InnerIterator v_it(g); + + for( ; v_it; ++v_it) + { + if(gi < nele_jac) + values[gi] = v_it.value(); + ++gi; + } + } + + if( gi != nele_jac) + std::cerr << "Warning: number of non-zeros in Jacobian of C is incorrect: " + << gi << " vs " << nele_jac << std::endl; + } + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool NProblemGmmIPOPT::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) +{ + if (values == NULL) + { + // return the (cached) structure of the hessian + gmm::copy(h_lag_iRow_, VectorPTi(iRow, h_lag_iRow_.size())); + gmm::copy(h_lag_jCol_, VectorPTi(jCol, h_lag_jCol_.size())); + } + else + { + // return values. + + // global index + int gi = 0; + + // get hessian of problem + problem_->eval_hessian(x, HP_); + + for( int i=0; i= (int)v_it.index()) + { + if( gi < nele_hess) + values[gi] = obj_factor*(*v_it); + ++gi; + } + } + } + + // Hessians of Constraints + for(unsigned int j=0; jeval_hessian(x, H); + + SMatrixNC::iterator m_it = H.begin(); + SMatrixNC::iterator m_end = H.end(); + + for(; m_it != m_end; ++m_it) + { + // store lower triangular part only + if( m_it.row() >= m_it.col()) + { + if( gi < nele_hess) + values[gi] = lambda[j]*(*m_it); + ++gi; + } + } + } + + // error check + if( gi != nele_hess) + std::cerr << "Warning: number of non-zeros in Hessian of Lagrangian is incorrect: " + << gi << " vs " << nele_hess << std::endl; + } + return true; +} + + +//----------------------------------------------------------------------------- + + +void NProblemGmmIPOPT::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) +{ + // problem knows what to do + problem_->store_result(x); +} + + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#endif // COMISO_IPOPT_AVAILABLE +//============================================================================= diff --git a/src/external/CoMISo/NSolver/IPOPTSolver.hh b/src/external/CoMISo/NSolver/IPOPTSolver.hh new file mode 100644 index 000000000..a536c5494 --- /dev/null +++ b/src/external/CoMISo/NSolver/IPOPTSolver.hh @@ -0,0 +1,402 @@ +//============================================================================= +// +// CLASS IPOPTSolver +// +//============================================================================= + + +#ifndef COMISO_IPOPTSOLVER_HH +#define COMISO_IPOPTSOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_IPOPT_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include +#include "NProblemGmmInterface.hh" +#include "NProblemInterface.hh" +#include "NConstraintInterface.hh" +#include "BoundConstraint.hh" +#include +#include +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NewtonSolver 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& _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& _constraints, + const std::vector& _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& _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& _v) + { + if( !_v.empty()) + return ((double*)&_v[0]); + else + return 0; + } + +private: + + // smart pointer to IpoptApplication to set options etc. + Ipopt::SmartPtr 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& _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& 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& _constraints); + + // determine if hessian_constant, jac_c_constant or jac_d_constant + void analyze_special_properties(const NProblemInterface* _problem, const std::vector& _constraints); + + +protected: + double* P(std::vector& _v) + { + if( !_v.empty()) + return ((double*)&_v[0]); + else + return 0; + } + +private: + + // pointer to problem instance + NProblemInterface* problem_; + // reference to constraints vector + std::vector constraints_; + std::vector bound_constraints_; + + bool hessian_constant_; + bool jac_c_constant_; + bool jac_d_constant_; + + bool store_solution_; + std::vector 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 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::const_iterator SVectorNP_citer; + typedef gmm::linalg_traits::iterator SVectorNP_iter; + + /** default constructor */ + NProblemGmmIPOPT(NProblemGmmInterface* _problem, std::vector& _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& constraints_; + + int nnz_jac_g_; + int nnz_h_lag_; + + // constant structure of jacobian_of_constraints and hessian_of_lagrangian + std::vector jac_g_iRow_; + std::vector jac_g_jCol_; + std::vector h_lag_iRow_; + std::vector 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/LeastSquaresProblem.cc b/src/external/CoMISo/NSolver/LeastSquaresProblem.cc new file mode 100644 index 000000000..029607453 --- /dev/null +++ b/src/external/CoMISo/NSolver/LeastSquaresProblem.cc @@ -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; in_unknowns(); ++i) + _x[i] = x_[i]; +} + + +//----------------------------------------------------------------------------- + + +double +LeastSquaresProblem:: +eval_f ( const double* _x ) +{ + double vtot(0.0); + + for(unsigned int i=0; ieval_constraint(_x); + vtot += vterm*vterm; + } + + return vtot; +} + + +//----------------------------------------------------------------------------- + + +void +LeastSquaresProblem:: +eval_gradient( const double* _x, double* _g) +{ + // clear gradient + for( int i=0; in_unknowns(); ++i) + _g[i] = 0.0; + + for(unsigned int i=0; ieval_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; ieval_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; in_unknowns(); ++i) + x_[i] = _x[i]; +} + + +//----------------------------------------------------------------------------- + +bool +LeastSquaresProblem:: +constant_hessian() +{ + for(unsigned int i=0; iis_linear()) + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- + + + +//============================================================================= +} // namespace COMISO +//============================================================================= diff --git a/src/external/CoMISo/NSolver/LeastSquaresProblem.hh b/src/external/CoMISo/NSolver/LeastSquaresProblem.hh new file mode 100644 index 000000000..f9110ed66 --- /dev/null +++ b/src/external/CoMISo/NSolver/LeastSquaresProblem.hh @@ -0,0 +1,84 @@ +//============================================================================= +// +// CLASS LeastSquaresProblem +// +//============================================================================= + + +#ifndef COMISO_LeastSquaresProblem_HH +#define COMISO_LeastSquaresProblem_HH + + +//== INCLUDES ================================================================= +#include +#include +#include +#include + + +//== 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& x() const {return x_;} + std::vector& 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 x_; + + // pointer to terms + std::vector terms_; +}; + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#endif // COMISO_LeastSquaresProblem_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/LinearConstraint.cc b/src/external/CoMISo/NSolver/LinearConstraint.cc new file mode 100644 index 000000000..5dff69c2c --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraint.cc @@ -0,0 +1,103 @@ +//============================================================================= +// +// CLASS LinearConstraint +// +//============================================================================= + + +#ifndef COMISO_LINEARCONSTRAINT_CC +#define COMISO_LINEARCONSTRAINT_CC + + +//== INCLUDES ================================================================= + +#include +#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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/LinearConstraint.hh b/src/external/CoMISo/NSolver/LinearConstraint.hh new file mode 100644 index 000000000..792ab1bdd --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraint.hh @@ -0,0 +1,97 @@ +//============================================================================= +// +// CLASS LinearConstraint +// +//============================================================================= + + +#ifndef COMISO_LINEARCONSTRAINT_HH +#define COMISO_LINEARCONSTRAINT_HH + + +//== INCLUDES ================================================================= + +#include +#include "NConstraintInterface.hh" +#include + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NProblemGmmInterface 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/LinearConstraintHandlerElimination.cc b/src/external/CoMISo/NSolver/LinearConstraintHandlerElimination.cc new file mode 100644 index 000000000..05941036f --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraintHandlerElimination.cc @@ -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& _c) +{ + if( _c.size() ) + initialize( (double*) &(_c[0])); +} + + +//----------------------------------------------------------------------------- + + +void +LinearConstraintHandlerElimination:: +initialize( double* _c) +{ + // TODO +} + +//----------------------------------------------------------------------------- + +void +LinearConstraintHandlerElimination:: +transform_x( const std::vector& _x, std::vector& _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& _xC, std::vector& _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& _x, std::vector& _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& _x, std::vector& _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 >(A_orig_,Vtemp_, b_orig_) << std::endl; + } +} + + +//----------------------------------------------------------------------------- + + +void +LinearConstraintHandlerElimination:: +transform_gradient( const std::vector& _g, std::vector& _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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/LinearConstraintHandlerElimination.hh b/src/external/CoMISo/NSolver/LinearConstraintHandlerElimination.hh new file mode 100644 index 000000000..22c8a7c80 --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraintHandlerElimination.hh @@ -0,0 +1,134 @@ +//============================================================================= +// +// CLASS LinearConstraintHandlerElimination +// +//============================================================================= + + +#ifndef COMISO_LINEARCONSTRAINTHANDLERELIMINATION_HH +#define COMISO_LINEARCONSTRAINTHANDLERELIMINATION_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + + +/** \class LinearConstraintHandler 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 VectorPT; + + /// Constructor + LinearConstraintHandlerElimination() {initialize_identity(0);} + + // initialize Constructor + template + 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 + 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& _c); + void initialize( double* _c); + + // transform x vector (least squares solution, fulfilling the constraints) + void transform_x( const std::vector& _x, std::vector& _xC); + void transform_x( double* _x, double* _xC); + + // inverse transform x ( x_reduced -> x) + void inv_transform_x( const std::vector& _xC, std::vector& _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& _x, std::vector& _xp); + void project_x( double* _x, double* _xp); + + // project dx to closest one that A(x0+dx) = b + void project_dx( const std::vector& _x, std::vector& _xp); + void project_dx( double* _x, double* _xp); + + // transform gradient + void transform_gradient( const std::vector& _g, std::vector& _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 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 Vtemp_; + + // hack -> store initial linear system + RMatrix A_orig_; + std::vector 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/LinearConstraintHandlerEliminationT.cc b/src/external/CoMISo/NSolver/LinearConstraintHandlerEliminationT.cc new file mode 100644 index 000000000..c247e0f19 --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraintHandlerEliminationT.cc @@ -0,0 +1,112 @@ +//============================================================================= +// +// CLASS LinearConstraintHandlerElimination - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_LINEARCONSTRAINTHANDLERELIMINATION_C + +//== INCLUDES ================================================================= + +#include "LinearConstraintHandlerElimination.hh" + +#include + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + +template +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 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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/LinearConstraintHandlerPenalty.cc b/src/external/CoMISo/NSolver/LinearConstraintHandlerPenalty.cc new file mode 100644 index 000000000..89f523d51 --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraintHandlerPenalty.cc @@ -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& _c) +{ + if( _c.size() ) + initialize( (double*) &(_c[0])); +} + + +//----------------------------------------------------------------------------- + + +void +LinearConstraintHandlerPenalty:: +initialize( double* _c) +{ + for(unsigned int i=0; i& _x, std::vector& _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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/LinearConstraintHandlerPenalty.hh b/src/external/CoMISo/NSolver/LinearConstraintHandlerPenalty.hh new file mode 100644 index 000000000..3b0b9d147 --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraintHandlerPenalty.hh @@ -0,0 +1,115 @@ +//============================================================================= +// +// CLASS LinearConstraintHandlerElimination +// +//============================================================================= + + +#ifndef COMISO_LINEARCONSTRAINTHANDLERPENALTY_HH +#define COMISO_LINEARCONSTRAINTHANDLERPENALTY_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + + +/** \class LinearConstraintHandler 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 VectorPT; + + /// Constructor + LinearConstraintHandlerPenalty(); + + // initialize Constructor + template + 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 + void initialize( const MatrixT& _C, const VectorT& _c); + + // initialize new constraints rhs only + void initialize( const std::vector& _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& _x, std::vector& _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 b_; + + // precomputed penalty terms + RMatrix penalty_H_; + std::vector penalty_grad_b_; + + // temp vector + std::vector 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/LinearConstraintHandlerPenaltyT.cc b/src/external/CoMISo/NSolver/LinearConstraintHandlerPenaltyT.cc new file mode 100644 index 000000000..56a809872 --- /dev/null +++ b/src/external/CoMISo/NSolver/LinearConstraintHandlerPenaltyT.cc @@ -0,0 +1,59 @@ +//============================================================================= +// +// CLASS LinearConstraintHandlerPenalty - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_LINEARCONSTRAINTHANDLERPENALTY_C + +//== INCLUDES ================================================================= + +#include "LinearConstraintHandlerPenalty.hh" + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + +// initialize Constructor +template +LinearConstraintHandlerPenalty::LinearConstraintHandlerPenalty( const MatrixT& _C, const VectorT& _c) : + penalty_(10000) +{initialize(_C, _c); } + +template +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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/NConstraintInterface.hh b/src/external/CoMISo/NSolver/NConstraintInterface.hh new file mode 100644 index 000000000..1ec796582 --- /dev/null +++ b/src/external/CoMISo/NSolver/NConstraintInterface.hh @@ -0,0 +1,113 @@ +//============================================================================= +// +// CLASS NConstraintInterface +// +//============================================================================= + + +#ifndef COMISO_NCONSTRAINTINTERFACE_HH +#define COMISO_NCONSTRAINTINTERFACE_HH + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_EIGEN3_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include "SuperSparseMatrixT.hh" + + +#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET +#include + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NProblemGmmInterface NProblemGmmInterface.hh + + Brief Description. + + A more elaborate description follows. +*/ +class COMISODLLEXPORT NConstraintInterface +{ +public: + + // define Sparse Datatypes + typedef Eigen::SparseVector SVectorNC; + typedef SuperSparseMatrixT 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NConstraintInterfaceAD.hpp b/src/external/CoMISo/NSolver/NConstraintInterfaceAD.hpp new file mode 100644 index 000000000..6e15a9c26 --- /dev/null +++ b/src/external/CoMISo/NSolver/NConstraintInterfaceAD.hpp @@ -0,0 +1,330 @@ +//============================================================================= +// +// CLASS NConstraintInterfaceAD +// +//============================================================================= + +#ifndef COMISO_NCONSTRAINTINTERFACEAD_HH +#define COMISO_NCONSTRAINTINTERFACEAD_HH + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_ADOLC_AVAILABLE +#if COMISO_EIGEN3_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include "SuperSparseMatrixT.hh" + +#include + +#include +#include +#include +#include +#include + +#include "NConstraintInterface.hh" +#include "NProblemInterfaceAD.hpp" + +#include "TapeIDSingleton.hh" + +#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET +#include + +//== 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(TapeIDSingleton::Instance()->requestId())) { + + for(size_t i = 0; i < 11; ++i) tape_stats_[i] = 0; + } + + /// Destructor + virtual ~NConstraintInterfaceAD() { + TapeIDSingleton::Instance()->releaseId(static_cast(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 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(_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 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(_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(_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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NPDerivativeChecker.hh b/src/external/CoMISo/NSolver/NPDerivativeChecker.hh new file mode 100644 index 000000000..727d1108b --- /dev/null +++ b/src/external/CoMISo/NSolver/NPDerivativeChecker.hh @@ -0,0 +1,223 @@ +//============================================================================= +// +// CLASS NPDERIVATIVECHECKER +// +//============================================================================= + + +#ifndef COMISO_NPDERIVATIVECHECKER_HH +#define COMISO_NPDERIVATIVECHECKER_HH + + +//== INCLUDES ================================================================= + +#include "NProblemGmmInterface.hh" +#include "NProblemInterface.hh" + +#include +#include +#include +#include + +#include +#include + +#include + +//== 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::quiet_NaN()) + {} + + double x_min; + double x_max; + int n_iters; + double dx; + double eps; + double relativeEps; + }; + + /// Default constructor + NPDerivativeChecker() {} + + /// Destructor + ~NPDerivativeChecker() {} + + template + bool check_all(ProblemInterface* _np, double _dx, double _eps) + { + conf_.dx = _dx; + conf_.eps = _eps; + return check_all(_np); + } + + template + bool check_all(ProblemInterface* _np) + { + bool d1_ok = check_d1(_np); + bool d2_ok = check_d2(_np); + + return ( d1_ok && d2_ok); + } + + template + bool check_d1(ProblemInterface* _np) + { + int n_ok = 0; + int n_errors = 0; + + + int n = _np->n_unknowns(); + std::vector x(n), g(n); + + for(int i=0; ieval_gradient(P(x), P(g)); + + for(int j=0; jeval_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 + inline double getCoeff(const MatrixType &m, int r, int c); + + template + bool check_d2(ProblemInterface* _np) + { + int n_ok = 0; + int n_errors = 0; + + int n = _np->n_unknowns(); + std::vector x(n); + typename ProblemInterface::SMatrixNP H(n,n); + + for(int i=0; ieval_hessian(P(x), H); + + for(int j=0; jeval_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& _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& _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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NPLinearConstraints.cc b/src/external/CoMISo/NSolver/NPLinearConstraints.cc new file mode 100644 index 000000000..abb3faf65 --- /dev/null +++ b/src/external/CoMISo/NSolver/NPLinearConstraints.cc @@ -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; in_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& _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 +//============================================================================= + + diff --git a/src/external/CoMISo/NSolver/NPLinearConstraints.hh b/src/external/CoMISo/NSolver/NPLinearConstraints.hh new file mode 100644 index 000000000..78ea2685c --- /dev/null +++ b/src/external/CoMISo/NSolver/NPLinearConstraints.hh @@ -0,0 +1,138 @@ +//============================================================================= +// +// CLASS NPLinearConstraints +// +//============================================================================= + + +#ifndef COMISO_NPLINEARCONSTRAINTS_HH +#define COMISO_NPLINEARCONSTRAINTS_HH + + +//== INCLUDES ================================================================= + +#include +#include +#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 VectorPT; + + /// Default constructor having a pointer to the main problem + NPLinearConstraintsElimination( NProblemGmmInterface* _np); + + /// Destructor + ~NPLinearConstraintsElimination(); + + // initialize constraints + template + 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& _v); + +private: + NProblemGmmInterface* base_; + + bool cache_initialized_; + + std::vector x_; + std::vector xr_; + std::vector vtemp_; +}; + + +//============================================================================= + + +// ConstraintHandler working with Penalty +class COMISODLLEXPORT NPLinearConstraintsPenalty : public NProblemGmmInterface, public LinearConstraintHandlerPenalty +{ +public: + + // use c-arrays as vectors for gmm + typedef gmm::array1D_reference VectorPT; + + /// Default constructor having a pointer to the main problem + NPLinearConstraintsPenalty( NProblemGmmInterface* _np); + + /// Destructor + ~NPLinearConstraintsPenalty(); + + // initialize constraints + template + 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NPLinearConstraintsT.cc b/src/external/CoMISo/NSolver/NPLinearConstraintsT.cc new file mode 100644 index 000000000..4c9b787ba --- /dev/null +++ b/src/external/CoMISo/NSolver/NPLinearConstraintsT.cc @@ -0,0 +1,49 @@ +//============================================================================= +// +// CLASS NPLinearConstraints +// +//============================================================================= + +#define COMISO_NSOLVERGMMINTERFACE_C + +//== INCLUDES ================================================================= + +#include +#include +#include "NProblemGmmInterface.hh" +#include "LinearConstraintHandlerElimination.hh" +#include "LinearConstraintHandlerPenalty.hh" +//#include "LinearConstraintHandlerLagrange.hh" + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + +// initialize constraints +template +void NPLinearConstraintsElimination::initialize_constraints( const MatrixT& _C, const VectorT& _c) +{ + initialize(_C, _c); + cache_initialized_ = false; +} + +//============================================================================= + +// initialize constraints +template +void NPLinearConstraintsPenalty::initialize_constraints( const MatrixT& _C, const VectorT& _c) +{ + initialize(_C, _c); +} + + +//============================================================================= +} // namespace ACG +//============================================================================= + + diff --git a/src/external/CoMISo/NSolver/NPTiming.cc b/src/external/CoMISo/NSolver/NPTiming.cc new file mode 100644 index 000000000..94e4c89ee --- /dev/null +++ b/src/external/CoMISo/NSolver/NPTiming.cc @@ -0,0 +1,112 @@ +//============================================================================= +// +// CLASS NPTiming +// +//============================================================================= + + +//== INCLUDES ================================================================= + +#include +#include + +#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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NPTiming.hh b/src/external/CoMISo/NSolver/NPTiming.hh new file mode 100644 index 000000000..5b65984ac --- /dev/null +++ b/src/external/CoMISo/NSolver/NPTiming.hh @@ -0,0 +1,85 @@ +//============================================================================= +// +// CLASS NPTiming +// +//============================================================================= + + +#ifndef COMISO_NPTIMING_HH +#define COMISO_NPTIMING_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include "NProblemGmmInterface.hh" +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NProblemGmmInterface 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NProblemGmmInterface.hh b/src/external/CoMISo/NSolver/NProblemGmmInterface.hh new file mode 100644 index 000000000..da1c93331 --- /dev/null +++ b/src/external/CoMISo/NSolver/NProblemGmmInterface.hh @@ -0,0 +1,64 @@ +//============================================================================= +// +// CLASS NProblemGmmInterface +// **************** DEPRECATED -> Please use NProblemInterface ***************// +//============================================================================= + + +#ifndef COMISO_NPROBLEMGMMINTERFACE_HH +#define COMISO_NPROBLEMGMMINTERFACE_HH + + +//== INCLUDES ================================================================= + +#include + +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NProblemGmmInterface 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 > 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NProblemInterface.cc b/src/external/CoMISo/NSolver/NProblemInterface.cc new file mode 100644 index 000000000..1b754025a --- /dev/null +++ b/src/external/CoMISo/NSolver/NProblemInterface.cc @@ -0,0 +1,11 @@ +#include "NProblemInterface.hh" + +namespace COMISO { + +NProblemInterface::NProblemInterface() { +} + +NProblemInterface::~NProblemInterface() { +} + +} diff --git a/src/external/CoMISo/NSolver/NProblemInterface.hh b/src/external/CoMISo/NSolver/NProblemInterface.hh new file mode 100644 index 000000000..260b9511d --- /dev/null +++ b/src/external/CoMISo/NSolver/NProblemInterface.hh @@ -0,0 +1,82 @@ +//============================================================================= +// +// CLASS NProblemGmmInterface +// +//============================================================================= + + +#ifndef COMISO_NPROBLEMINTERFACE_HH +#define COMISO_NPROBLEMINTERFACE_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_EIGEN3_AVAILABLE + +//== INCLUDES ================================================================= + + +#include +#if !(EIGEN_VERSION_AT_LEAST(3,1,0)) + #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET +#endif +#include + +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NProblemGmmInterface 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 SMatrixNP; + #else + typedef Eigen::DynamicSparseMatrix 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/NProblemInterfaceAD.hpp b/src/external/CoMISo/NSolver/NProblemInterfaceAD.hpp new file mode 100644 index 000000000..d442bb771 --- /dev/null +++ b/src/external/CoMISo/NSolver/NProblemInterfaceAD.hpp @@ -0,0 +1,362 @@ +/* + * NProblemInterfaceAD.hpp + * + * Created on: Nov 30, 2012 + * Author: kremer + */ + +#ifndef NPROBLEMINTERFACEAD_HPP_ +#define NPROBLEMINTERFACEAD_HPP_ + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_ADOLC_AVAILABLE +#if COMISO_EIGEN3_AVAILABLE + +//== INCLUDES ================================================================= + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#if !(EIGEN_VERSION_AT_LEAST(3,1,0)) +#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET +#endif +#include + +#include + +#include "TapeIDSingleton.hh" + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + +/** \class NProblemmInterfaceAD NProblemInterfaceAD.hpp + + 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 SMatrixNP; +#else + typedef Eigen::DynamicSparseMatrix SMatrixNP; +#endif + + /// Default constructor + NProblemInterfaceAD(int _n_unknowns) : + n_unknowns_(_n_unknowns), + dense_hessian_(NULL), + function_evaluated_(false), + use_tape_(true), + tape_(static_cast(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(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 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(_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(_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(_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 x_d_ptr() { + if(x_d_.get() == NULL) { + x_d_.reset(new adouble[n_unknowns_]); + } + return x_d_; + } + + boost::shared_array 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 x_d_; + + // Gradient vector + boost::shared_array 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_ */ diff --git a/src/external/CoMISo/NSolver/NewtonSolver.cc b/src/external/CoMISo/NSolver/NewtonSolver.cc new file mode 100644 index 000000000..b031a230e --- /dev/null +++ b/src/external/CoMISo/NSolver/NewtonSolver.cc @@ -0,0 +1,122 @@ +//============================================================================= +// +// CLASS NewtonSolver - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +#include "NewtonSolver.hh" +#include + +//== 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 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; ieval_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; jeval_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 +//============================================================================= diff --git a/src/external/CoMISo/NSolver/NewtonSolver.hh b/src/external/CoMISo/NSolver/NewtonSolver.hh new file mode 100644 index 000000000..68cee5ef0 --- /dev/null +++ b/src/external/CoMISo/NSolver/NewtonSolver.hh @@ -0,0 +1,80 @@ +//============================================================================= +// +// CLASS NewtonSolver +// +//============================================================================= + + +#ifndef COMISO_NEWTONSOLVER_HH +#define COMISO_NEWTONSOLVER_HH + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include + +//== INCLUDES ================================================================= + +#include +#include +#include "NProblemGmmInterface.hh" + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class NewtonSolver 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& _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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/SuperSparseMatrixT.cc b/src/external/CoMISo/NSolver/SuperSparseMatrixT.cc new file mode 100644 index 000000000..8e399133c --- /dev/null +++ b/src/external/CoMISo/NSolver/SuperSparseMatrixT.cc @@ -0,0 +1,27 @@ +//============================================================================= +// +// CLASS SuperSparseMatrixT - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_SUPERSPARSEMATRIXT_C + +//== INCLUDES ================================================================= + +#include "SuperSparseMatrixT.hh" + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + + +//----------------------------------------------------------------------------- + + + +//============================================================================= +} // namespace COMISO +//============================================================================= diff --git a/src/external/CoMISo/NSolver/SuperSparseMatrixT.hh b/src/external/CoMISo/NSolver/SuperSparseMatrixT.hh new file mode 100644 index 000000000..1fa969278 --- /dev/null +++ b/src/external/CoMISo/NSolver/SuperSparseMatrixT.hh @@ -0,0 +1,201 @@ +//============================================================================= +// +// CLASS SuperSparseMatrixT +// +//============================================================================= + + +#ifndef COMISO_SUPERSPARSEMATRIXT_HH +#define COMISO_SUPERSPARSEMATRIXT_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + + +/** \class SuperSparseMatrixT SuperSparseMatrixT.hh + + Brief Description. + + A more elaborate description follows. +*/ + +template +class SuperSparseMatrixT +{ +public: + + // value type + typedef VType VT; + typedef std::pair 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::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::iterator& map_iterator() {return m_it_;} + + private: + typename std::map::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::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::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::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 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 data_; +}; + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_SUPERSPARSEMATRIXT_C) +#define COMISO_SUPERSPARSEMATRIXT_TEMPLATES +#include "SuperSparseMatrixT.cc" +#endif +//============================================================================= +#endif // COMISO_SUPERSPARSEMATRIXT_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/TAOSolver.cc b/src/external/CoMISo/NSolver/TAOSolver.cc new file mode 100644 index 000000000..7cf6bd76e --- /dev/null +++ b/src/external/CoMISo/NSolver/TAOSolver.cc @@ -0,0 +1,999 @@ +//============================================================================= +// +// CLASS TAOSolver - IMPLEMENTATION +// +//============================================================================= + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_TAO_AVAILABLE + + +//== INCLUDES ================================================================= + +#include "TAOSolver.hh" + +//#include + +//== 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::const_sub_row_type + CRow; + CRow row = gmm::mat_const_row(H, i); + + gmm::linalg_traits::const_iterator it = gmm::vect_const_begin(row); + gmm::linalg_traits::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; i1) { + 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::const_sub_row_type + CRow; + CRow row = gmm::mat_const_row(H, i); + + gmm::linalg_traits::const_iterator it = gmm::vect_const_begin(row); + gmm::linalg_traits::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 +#if COMISO_TAO_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include "NProblemGmmInterface.hh" +#include "NProblemInterface.hh" + +#include +#include +#include + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class TAOSolver 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/TapeIDSingleton.cc b/src/external/CoMISo/NSolver/TapeIDSingleton.cc new file mode 100644 index 000000000..24b498e55 --- /dev/null +++ b/src/external/CoMISo/NSolver/TapeIDSingleton.cc @@ -0,0 +1,10 @@ +/* + * TapeIDSingleton.cc + * + * Created on: Jan 4, 2013 + * Author: kremer + */ + +#include "TapeIDSingleton.hh" + +TapeIDSingleton* TapeIDSingleton::reference_ = NULL; diff --git a/src/external/CoMISo/NSolver/TapeIDSingleton.hh b/src/external/CoMISo/NSolver/TapeIDSingleton.hh new file mode 100644 index 000000000..41af0f193 --- /dev/null +++ b/src/external/CoMISo/NSolver/TapeIDSingleton.hh @@ -0,0 +1,57 @@ +/* + * TapeIDSingleton.hpp + * + * Created on: Jan 4, 2013 + * Author: kremer + */ + +#ifndef TAPEIDSINGLETON_HPP_ +#define TAPEIDSINGLETON_HPP_ + +#include +#include +#include + +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 ids_; +}; + +#endif /* TAPEIDSINGLETON_HPP_ */ diff --git a/src/external/CoMISo/NSolver/TestInterface.hh b/src/external/CoMISo/NSolver/TestInterface.hh new file mode 100644 index 000000000..993c8a0ae --- /dev/null +++ b/src/external/CoMISo/NSolver/TestInterface.hh @@ -0,0 +1,86 @@ +//============================================================================= +// +// CLASS BaseTaoGmmInterface +// +//============================================================================= + + +#ifndef COMISO_TESTINTERFACE_HH +#define COMISO_TESTINTERFACE_HH + + +//== INCLUDES ================================================================= + +#include "NProblemGmmInterface.hh" +#include + +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class BaseTaoGmmInterface 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 +//============================================================================= + diff --git a/src/external/CoMISo/NSolver/VariableType.hh b/src/external/CoMISo/NSolver/VariableType.hh new file mode 100644 index 000000000..c818ce555 --- /dev/null +++ b/src/external/CoMISo/NSolver/VariableType.hh @@ -0,0 +1,34 @@ +//============================================================================= +// +// ENUM VariableType +// +//============================================================================= + + +#ifndef COMISO_VARIABLETYPE_HH +#define COMISO_VARIABLETYPE_HH + + +//== INCLUDES ================================================================= + +#include + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + +enum VariableType { Real, Integer, Binary}; + +typedef std::pair PairIndexVtype; + +//============================================================================= +} // namespace COMISO +//============================================================================= +#endif // COMISO_VARIABLETYPE_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/QtWidgets/MISolverDialogUI.cc b/src/external/CoMISo/QtWidgets/MISolverDialogUI.cc new file mode 100644 index 000000000..d081c2155 --- /dev/null +++ b/src/external/CoMISo/QtWidgets/MISolverDialogUI.cc @@ -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 . * + * * +\*===========================================================================*/ + + + +//============================================================================= +// +// CLASS MISolverDialog - IMPLEMENTATION +// +//============================================================================= + +//== INCLUDES ================================================================= + +#include + +//== BUILD-TIME DEPENDENCIES ================================================================= +#if(COMISO_QT4_AVAILABLE) +//============================================================================================ + + +#include "MISolverDialogUI.hh" + +#include + +//== 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 +//============================================================================= diff --git a/src/external/CoMISo/QtWidgets/MISolverDialogUI.hh b/src/external/CoMISo/QtWidgets/MISolverDialogUI.hh new file mode 100644 index 000000000..1073c504a --- /dev/null +++ b/src/external/CoMISo/QtWidgets/MISolverDialogUI.hh @@ -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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS MiSolverDialog +// +//============================================================================= + + +#ifndef COMISO_MISOLVERDIALOG_HH +#define COMISO_MISOLVERDIALOG_HH + + +#include + +//== BUILD-TIME DEPENDENCIES ================================================================= +#if(COMISO_QT4_AVAILABLE) +//============================================================================================ + +//== INCLUDES ================================================================= + +#include "ui_QtMISolverDialogBaseUI.hh" + +// ACGMake users have to include +// #include "QtMISolverDialogBase.hh" + + +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO +{ + +//== CLASS DEFINITION ========================================================= + + + +/** \class MISolverDialog 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 diff --git a/src/external/CoMISo/QtWidgets/QtMISolverDialogBaseUI.ui b/src/external/CoMISo/QtWidgets/QtMISolverDialogBaseUI.ui new file mode 100644 index 000000000..cdce080ab --- /dev/null +++ b/src/external/CoMISo/QtWidgets/QtMISolverDialogBaseUI.ui @@ -0,0 +1,331 @@ + + + QtMISolverDialogBaseUI + + + Qt::ApplicationModal + + + + 0 + 0 + 385 + 273 + + + + Dialog + + + + + + + + use cplex + + + + + + + Max Error (1e-x) + + + + + + + Iterations + + + + + + + + 0 + 0 + + + + Local + + + + + + + 2 + + + -1000000000.000000000000000 + + + 1000000000.000000000000000 + + + 6.000000000000000 + + + + + + + 1000000000 + + + 10000 + + + + + + + + 0 + 0 + + + + CG + + + + + + + 2 + + + -1000000000.000000000000000 + + + 1000000000.000000000000000 + + + 6.000000000000000 + + + + + + + 1000000000 + + + 20 + + + + + + + + 0 + 0 + + + + Full + + + + + + + + + initial + + + true + + + + + + + iter not converged + + + true + + + + + + + final + + + true + + + false + + + + + + + + + Rounding + + + + + + + + + direct + + + + + + + no + + + + + + + multiple + + + + + + + 2 + + + 0.000000000000000 + + + 0.500000000000000 + + + 0.500000000000000 + + + + + + + + + + 0 + 0 + + + + Info Level + + + + + + + + + + + + Output solver statistics + + + + + + + + + Constraints + + + + + + + reordering + + + true + + + + + + + GUROBI + + + + + + + use gurobi + + + + + + + 999999999.000000000000000 + + + 60.000000000000000 + + + + + + + s + + + + + + + + + + + Ok + + + + + + + Cancel + + + + + + + + + Qt::Vertical + + + + 20 + 14 + + + + + + + + + diff --git a/src/external/CoMISo/README.txt b/src/external/CoMISo/README.txt new file mode 100644 index 000000000..f3764b308 --- /dev/null +++ b/src/external/CoMISo/README.txt @@ -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 ! diff --git a/src/external/CoMISo/Solver/CholmodSolver.cc b/src/external/CoMISo/Solver/CholmodSolver.cc new file mode 100644 index 000000000..764878928 --- /dev/null +++ b/src/external/CoMISo/Solver/CholmodSolver.cc @@ -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 . * + * * +\*===========================================================================*/ + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#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& _colptr, + const std::vector& _rowind, + const std::vector& _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& _colptr, + const std::vector& _rowind, + const std::vector& _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& _x0, std::vector& _b) +{ + return solve( &(_x0[0]), &(_b[0])); +} + +//----------------------------------------------------------------------------- + +bool& CholmodSolver:: +show_timings() +{ + return show_timings_; +} + + +} + +//============================================================================= +#endif // COMISO_SUITESPARSE_AVAILABLE +//============================================================================= diff --git a/src/external/CoMISo/Solver/CholmodSolver.hh b/src/external/CoMISo/Solver/CholmodSolver.hh new file mode 100644 index 000000000..691941e8c --- /dev/null +++ b/src/external/CoMISo/Solver/CholmodSolver.hh @@ -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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS CholmodSolver +// +//============================================================================= + +#ifndef COMISO_CHOLMOD_SOLVER_HH +#define COMISO_CHOLMOD_SOLVER_HH + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_SUITESPARSE_AVAILABLE + +//== INCLUDES ================================================================= + + +#include +#include + +#include +#include + +#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& _colptr, + const std::vector& _rowind, + const std::vector& _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& _colptr, + const std::vector& _rowind, + const std::vector& _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& _x0, std::vector& _b); + + bool& show_timings(); + + int dimension(); + +private: + + cholmod_common * mp_cholmodCommon; + + cholmod_factor * mp_L; + + std::vector values_; + std::vector colptr_; + std::vector 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 +//============================================================================= diff --git a/src/external/CoMISo/Solver/CholmodSolverT.cc b/src/external/CoMISo/Solver/CholmodSolverT.cc new file mode 100644 index 000000000..9c187cbc8 --- /dev/null +++ b/src/external/CoMISo/Solver/CholmodSolverT.cc @@ -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 . * + * * +\*===========================================================================*/ + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_SUITESPARSE_AVAILABLE +//============================================================================= + + +#define COMISO_CHOLMOD_SOLVER_TEMPLATES_C + +#include +#include +#include + + +namespace COMISO { + + +template< class GMM_MatrixT> +bool CholmodSolver::calc_system_gmm( const GMM_MatrixT& _mat) +{ +// std::vector colptr; +// std::vector rowind; +// std::vector 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 colptr; +// std::vector rowind; +// std::vector 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 +//============================================================================= diff --git a/src/external/CoMISo/Solver/ConstrainedSolver.cc b/src/external/CoMISo/Solver/ConstrainedSolver.cc new file mode 100644 index 000000000..58b8f751d --- /dev/null +++ b/src/external/CoMISo/Solver/ConstrainedSolver.cc @@ -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 . * + * * +\*===========================================================================*/ + + +#include "ConstrainedSolver.hh" + +#include + +namespace COMISO { + +//----------------------------------------------------------------------------- + +int +ConstrainedSolver:: +find_gcd(std::vector& _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; +} + +//----------------------------------------------------------------------------- + +} + diff --git a/src/external/CoMISo/Solver/ConstrainedSolver.hh b/src/external/CoMISo/Solver/ConstrainedSolver.hh new file mode 100644 index 000000000..f3fd90472 --- /dev/null +++ b/src/external/CoMISo/Solver/ConstrainedSolver.hh @@ -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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS ConstrainedSolver +// +//============================================================================= + + +#ifndef COMISO_CONSTRAINEDSOLVER_HH +#define COMISO_CONSTRAINEDSOLVER_HH + + +//== INCLUDES ================================================================= +#include + +#include "GMM_Tools.hh" +#include "MISolver.hh" +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== DEFINES ================================================================== +#define ROUND(x) ((x)<0?int((x)-0.5):int((x)+0.5)) +//== NAMESPACES =============================================================== + +namespace COMISO { +//== CLASS DEFINITION ========================================================= + +/** \class ConstrainedSolver 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 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 + 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 + 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 + 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 + 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 + 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 + 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 + void make_constraints_independent( + RMatrixT& _constraints, + VectorIT& _idx_to_round, + std::vector& _c_elim ); + + template + void make_constraints_independent_reordering( + RMatrixT& _constraints, + VectorIT& _idx_to_round, + std::vector& _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 + void eliminate_constraints( + gmm::row_matrix& _constraints, + gmm::row_matrix& _B, + VectorIT& _idx_to_round, + std::vector& _c_elim, + std::vector& _new_idx, + gmm::col_matrix& _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 + void eliminate_constraints( + gmm::row_matrix& _constraints, + gmm::col_matrix& _A, + std::vector& _x, + std::vector& _rhs, + VectorIT& _idx_to_round, + std::vector& _c_elim, + std::vector& _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 + void restore_eliminated_vars( RMatrixT& _constraints, + VectorT& _x, + std::vector& _c_elim, + std::vector& _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 + double verify_constrained_system( + const RMatrixT& _conditions, + const CMatrixT& _A, + const VectorT& _x, + const VectorT& _rhs, + double _eps = 1e-9); + + template + 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 + 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 + void add_row( int _row_i, + double _coeff, + RowT _row, + MatrixT& _mat ); + + template + void add_row_simultaneously( int _row_i, + double _coeff, + RowT _row, + RMatrixT& _rmat, + CMatrixT& _cmat ); + + + template + 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 + 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& _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 + bool update_constraint_gcd( RMatrixT& _constraints, + int _row_i, + int& _elim_j, + std::vector& _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& _constraint_rhs, std::vector& _rhs) + { + std::vector::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& _rhs) + { + std::vector evar( elim_var_ids_ ); + std::sort( evar.begin(), evar.end() ); + evar.push_back( std::numeric_limits::max() ); + + int cur_evar_idx=0; + unsigned int nc = _rhs.size(); + for( unsigned int i=0; i + void store(const RMatrixT& _constraints, const std::vector& _c_elim, const std::vector& _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 table_; + std::vector elim_var_ids_; + + public: + std::vector c_elim_; + std::vector new_idx_; + RowMatrix constraints_p_; + + // cache current rhs_ and constraint_rhs_ and linear transformation of constraint_rhs_ D_ + RowMatrix D_; + std::vector cur_rhs_; + // constraint_rhs after Gaussian elimination update D*constraint_rhs_orig_ + std::vector 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 +//============================================================================= + diff --git a/src/external/CoMISo/Solver/ConstrainedSolverT.cc b/src/external/CoMISo/Solver/ConstrainedSolverT.cc new file mode 100644 index 000000000..78c69ae0f --- /dev/null +++ b/src/external/CoMISo/Solver/ConstrainedSolverT.cc @@ -0,0 +1,1468 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS MISolver - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_CONSTRAINEDSOLVER_C +//== INCLUDES ================================================================= + +#include "ConstrainedSolver.hh" +#include +#include "GMM_Tools.hh" +#include +#include +#include + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + +template +void +ConstrainedSolver:: +solve_const( const RMatrixT& _constraints, + const CMatrixT& _A, + VectorT& _x, + const VectorT& _rhs, + const VectorIT& _idx_to_round, + double _reg_factor, + bool _show_miso_settings, + bool _show_timings ) +{ + // copy matrices + RMatrixT constraints( gmm::mat_nrows(_constraints), gmm::mat_ncols(_constraints)); + gmm::copy(_constraints, constraints); + + CMatrixT A( gmm::mat_nrows(_A), gmm::mat_ncols(_A)); + gmm::copy(_A, A); + + // ... and vectors + VectorT rhs(_rhs); + VectorIT idx_to_round(_idx_to_round); + + // call non-const function + solve(constraints, + A, + _x, + rhs, + idx_to_round, + _reg_factor, + _show_miso_settings, + _show_timings); +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +solve_const( const RMatrixT& _constraints, + const RMatrixT& _B, + VectorT& _x, + const VectorIT& _idx_to_round, + double _reg_factor, + bool _show_miso_settings, + bool _show_timings ) +{ + // copy matrices + RMatrixT constraints( gmm::mat_nrows(_constraints), gmm::mat_ncols(_constraints)); + gmm::copy(_constraints, constraints); + + RMatrixT B( gmm::mat_nrows(_B), gmm::mat_ncols(_B)); + gmm::copy(_B, B); + + // ... and vectors + VectorIT idx_to_round(_idx_to_round); + + // call non-const function + solve(constraints, + B, + _x, + idx_to_round, + _reg_factor, + _show_miso_settings, + _show_timings); +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +solve( + RMatrixT& _constraints, + RMatrixT& _B, + VectorT& _x, + VectorIT& _idx_to_round, + double _reg_factor, + bool _show_miso_settings, + bool _show_timings ) +{ + // convert into quadratic system + VectorT rhs; + gmm::col_matrix< gmm::rsvector< double > > A; + COMISO_GMM::factored_to_quadratic(_B, A, rhs); + + // solve + solve( _constraints, A, _x, rhs, + _idx_to_round, _reg_factor, + _show_miso_settings, + _show_timings); + +// int nrows = gmm::mat_nrows(_B); +// int ncols = gmm::mat_ncols(_B); +// int ncons = gmm::mat_nrows(_constraints); + +// if( _show_timings) std::cerr << __FUNCTION__ << "\n Initial dimension: " << nrows << " x " << ncols << ", number of constraints: " << ncons << std::endl; + +// // StopWatch for Timings +// COMISO::StopWatch sw, sw2; sw.start(); sw2.start(); + +// // c_elim[i] = index of variable which is eliminated in condition i +// // or -1 if condition is invalid +// std::vector c_elim( ncons); + +// // apply sparse gauss elimination to make subsequent _constraints independent +// make_constraints_independent( _constraints, _idx_to_round, c_elim); +// double time_gauss = sw.stop()/1000.0; sw.start(); + +// // eliminate conditions and return column matrix Bcol +// gmm::col_matrix< gmm::rsvector< double > > Bcol( nrows, ncols); + +// // reindexing vector +// std::vector new_idx; + +// eliminate_constraints( _constraints, _B, _idx_to_round, c_elim, new_idx, Bcol); +// double time_eliminate = sw.stop()/1000.0; + +// if( _show_timings) std::cerr << "Eliminated dimension: " << gmm::mat_nrows(Bcol) << " x " << gmm::mat_ncols(Bcol) << std::endl; + +// // setup and solve system +// double time_setup = setup_and_solve_system( Bcol, _x, _idx_to_round, _reg_factor, _show_miso_settings); +// sw.start(); + +// // double time_setup_solve = sw.stop()/1000.0; sw.start(); + +// // restore eliminated vars to fulfill the given conditions +// restore_eliminated_vars( _constraints, _x, c_elim, new_idx); + +// double time_resubstitute = sw.stop()/1000.0; sw.start(); + +// // double time_total = sw2.stop()/1000.0; + +// if( _show_timings) std::cerr << "Timings: \n\t" << +// "Gauss Elimination " << time_gauss << " s\n\t" << +// "System Elimination " << time_eliminate << " s\n\t" << +// "Setup " << time_setup << " s\n\t" << +// // "Setup + Mi-Solver " << time_setup_solve << " s\n\t" << +// "Resubstitution " << time_resubstitute << " s\n\t" << std::endl << std::endl; +// //"Total " << time_total << std::endl; +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +solve( + RMatrixT& _constraints, + CMatrixT& _A, + VectorT& _x, + VectorT& _rhs, + VectorIT& _idx_to_round, + double _reg_factor, + bool _show_miso_settings, + bool _show_timings ) +{ + // show options dialog + if( _show_miso_settings) + miso_.show_options_dialog(); + + + int nrows = gmm::mat_nrows(_A); + int ncols = gmm::mat_ncols(_A); + int ncons = gmm::mat_nrows(_constraints); + + if( _show_timings) std::cerr << __FUNCTION__ << "\n Initital dimension: " << nrows << " x " << ncols + << ", number of constraints: " << ncons << " use reordering: " << use_constraint_reordering() << std::endl; + + // StopWatch for Timings + COMISO::StopWatch sw, sw2; sw.start(); sw2.start(); + + // c_elim[i] = index of variable which is eliminated in condition i + // or -1 if condition is invalid + std::vector c_elim( ncons); + + // apply sparse gauss elimination to make subsequent _conditions independent + if(use_constraint_reordering()) + make_constraints_independent_reordering( _constraints, _idx_to_round, c_elim); + else + make_constraints_independent( _constraints, _idx_to_round, c_elim); + + double time_gauss = sw.stop()/1000.0; sw.start(); + + // re-indexing vector + std::vector new_idx; + + gmm::csc_matrix< double > Acsc; + eliminate_constraints( _constraints, _A, _x, _rhs, _idx_to_round, c_elim, new_idx, Acsc); + double time_eliminate = sw.stop()/1000.0; + + if( _show_timings) + { + std::cerr << "Eliminated dimension: " << Acsc.nr << " x " << Acsc.nc << std::endl; + std::cerr << "#nonzeros: " << gmm::nnz(Acsc) << std::endl; + } + + sw.start(); + miso_.solve( Acsc, _x, _rhs, _idx_to_round); + double time_miso = sw.stop()/1000.0; sw.start(); + + rhs_update_table_.store(_constraints, c_elim, new_idx); + // restore eliminated vars to fulfill the given conditions + restore_eliminated_vars( _constraints, _x, c_elim, new_idx); + + double time_resubstitute = sw.stop()/1000.0; sw.start(); + double time_total = time_gauss + time_eliminate + time_miso + time_resubstitute; + if( _show_timings) std::cerr << "Timings: \n\t" << + "\tGauss Elimination " << time_gauss << " s\n\t" << + "\tSystem Elimination " << time_eliminate << " s\n\t" << + "\tMi-Solver " << time_miso << " s\n\t" << + "\tResubstitution " << time_resubstitute << " s\n\t" << + "\tTotal " << time_total << std::endl << std::endl; +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +resolve( + const RMatrixT& _B, + VectorT& _x, + VectorT* _constraint_rhs, + bool _show_timings ) +{ + // extract rhs from quadratic system + VectorT rhs; + // gmm::col_matrix< gmm::rsvector< double > > A; + // COMISO_GMM::factored_to_quadratic(_B, A, rhs); + //TODO only compute rhs, not complete A for efficiency + + unsigned int m = gmm::mat_nrows(_B); + unsigned int n = gmm::mat_ncols(_B); + + typedef typename gmm::linalg_traits::const_sub_row_type CRowT; + typedef typename gmm::linalg_traits::sub_row_type RowT; + typedef typename gmm::linalg_traits::const_iterator RIter; + typedef typename gmm::linalg_traits::value_type VecValT; + + gmm::resize(rhs, n-1); + gmm::clear(rhs); + for(unsigned int i = 0; i < m; ++i) + { + // get current condition row + CRowT row = gmm::mat_const_row( _B, i); + RIter row_it = gmm::vect_const_begin( row); + RIter row_end = gmm::vect_const_end( row); + + if(row_end == row_it) continue; + --row_end; + if(row_end.index() != n-1) continue; + VecValT n_i = *row_end; + while(row_end != row_it) + { + --row_end; + rhs[row_end.index()] -= (*row_end) * n_i; + } + } + + // solve + resolve(_x, _constraint_rhs, &rhs, + _show_timings); +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +resolve( + VectorT& _x, + VectorT* _constraint_rhs, + VectorT* _rhs , + bool _show_timings ) +{ + // StopWatch for Timings + COMISO::StopWatch sw; + + sw.start(); + // apply stored updates and eliminations to exchanged rhs + if(_constraint_rhs) + { + // apply linear transformation of Gaussian elimination + rhs_update_table_.cur_constraint_rhs_.resize(gmm::mat_nrows(rhs_update_table_.D_)); + gmm::mult(rhs_update_table_.D_, *_constraint_rhs, rhs_update_table_.cur_constraint_rhs_); + + // update rhs of stored constraints + unsigned int nc = gmm::mat_ncols(rhs_update_table_.constraints_p_); + for(unsigned int i=0; i rhs_red = rhs_update_table_.cur_rhs_; + + rhs_update_table_.apply(rhs_update_table_.cur_constraint_rhs_, rhs_red); + rhs_update_table_.eliminate(rhs_red); + + // std::cerr << "############### Resolve info ##############" << std::endl; + // std::cerr << rhs_update_table_.D_ << std::endl; + // std::cerr << rhs_update_table_.cur_rhs_ << std::endl; + // std::cerr << rhs_update_table_.cur_constraint_rhs_ << std::endl; + // std::cerr << rhs_update_table_.table_.size() << std::endl; + // std::cerr << "rhs_red: " << rhs_red << std::endl; + + miso_.resolve(_x, rhs_red); + + double time_miso = sw.stop()/1000.0; sw.start(); + + // restore eliminated vars to fulfill the given conditions + restore_eliminated_vars( rhs_update_table_.constraints_p_, _x, rhs_update_table_.c_elim_, rhs_update_table_.new_idx_); + + double time_resubstitute = sw.stop()/1000.0; sw.start(); + double time_total = time_miso + time_resubstitute; + if( _show_timings) std::cerr << "Timings: \n\t" << + "\tMi-Solver " << time_miso << " s\n\t" << + "\tResubstitution " << time_resubstitute << " s\n\t" << + "\tTotal " << time_total << std::endl << std::endl; +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +make_constraints_independent( + RMatrixT& _constraints, + VectorIT& _idx_to_round, + std::vector& _c_elim) +{ + // setup linear transformation for rhs, start with identity + unsigned int nr = gmm::mat_nrows(_constraints); + gmm::resize(rhs_update_table_.D_, nr, nr); + gmm::clear(rhs_update_table_.D_); + for(unsigned int i=0; i roundmap( n_vars, false); + for(unsigned int i=0; i<_idx_to_round.size(); ++i) + roundmap[_idx_to_round[i]] = true; + + // copy constraints into column matrix (for faster update via iterators) + typedef gmm::wsvector CVector; + typedef gmm::col_matrix< CVector > CMatrix; + CMatrix constraints_c; + gmm::resize(constraints_c, gmm::mat_nrows(_constraints), gmm::mat_ncols(_constraints)); + gmm::copy(_constraints, constraints_c); + + // for all conditions + for(unsigned int i=0; i::const_sub_row_type CRowT; + typedef typename gmm::linalg_traits::sub_row_type RowT; + typedef typename gmm::linalg_traits::const_iterator RIter; + + // get current condition row + CRowT row = gmm::mat_const_row( _constraints, i); + RIter row_it = gmm::vect_const_begin( row); + RIter row_end = gmm::vect_const_end( row); + double elim_val = FLT_MAX; + double max_elim_val = -FLT_MAX; + + // new: gcd + std::vector v_gcd; + v_gcd.resize(gmm::nnz(row),-1); + int n_ints(0); + bool gcd_update_valid(true); + + for(; row_it != row_end; ++row_it) + { + int cur_j = row_it.index(); + // do not use the constant part + if( cur_j != n_vars - 1 ) + { + // found real valued var? -> finished (UPDATE: no not any more, find biggest real value to avoid x/1e-13) + if( !roundmap[ cur_j ]) + { + if( fabs(*row_it) > max_elim_val) + { + elim_j = cur_j; + max_elim_val = fabs(*row_it); + } + //break; + } + else + { + double cur_row_val(fabs(*row_it)); + // gcd + // if the coefficient of an integer variable is not an integer, then + // the variable most problably will not be (expect if all coeffs are the same, e.g. 0.5) + if( (double(int(cur_row_val))- cur_row_val) != 0.0) + { +// std::cerr << __FUNCTION__ << " Warning: coefficient of integer variable is NOT integer: " +// << cur_row_val << std::endl; + gcd_update_valid = false; + } + + v_gcd[n_ints] = cur_row_val; + ++n_ints; + + // store integer closest to 1, must be greater than epsilon_ + if( fabs(cur_row_val-1.0) < elim_val && cur_row_val > epsilon_) + { + elim_int_j = cur_j; + elim_val = fabs(cur_row_val-1.0); + } + } + } + } + + // first try to eliminate a valid (>epsilon_) real valued variable (safer) + if( max_elim_val > epsilon_) + {} + else // use the best found integer + elim_j = elim_int_j; + + // if no integer or real valued variable greater than epsilon_ existed, then + // elim_j is now -1 and this row is not considered as a valid constraint + + + + + // store result + _c_elim[i] = elim_j; + // error check result + if( elim_j == -1) + { + // redundant or incompatible? + if( noisy_ > 0) + if( fabs(gmm::mat_const_row(_constraints, i)[n_vars-1]) > epsilon_ ) + std::cerr << "Warning: incompatible condition: " + << fabs(gmm::mat_const_row(_constraints, i)[n_vars-1]) << std::endl; + // else + // std::cerr << "Warning: redundant condition:\n"; + } + else + if(roundmap[elim_j] && elim_val > 1e-6) + { + if( do_gcd_ && gcd_update_valid) + { + // perform gcd update + bool gcd_ok = update_constraint_gcd( _constraints, i, elim_j, v_gcd, n_ints); + if( !gcd_ok) + if( noisy_ > 0) + std::cerr << __FUNCTION__ << " Warning: GCD update failed! " << gmm::mat_const_row(_constraints, i) << std::endl; + } + else + { + if( noisy_ > 0) + { + if( !do_gcd_) + std::cerr << __FUNCTION__ << " Warning: NO +-1 coefficient found, integer rounding cannot be guaranteed. Try using the GCD option! " << gmm::mat_const_row(_constraints, i) << std::endl; + else + std::cerr << __FUNCTION__ << " Warning: GCD of non-integer cannot be computed! " << gmm::mat_const_row(_constraints, i) << std::endl; + + } + } + } + + + // is this condition dependent? + if( elim_j != -1 ) + { + // get elim variable value + double elim_val_cur = _constraints(i, elim_j); + + // copy col + CVector col = constraints_c.col(elim_j); + + // iterate over column + typename gmm::linalg_traits::const_iterator c_it = gmm::vect_const_begin(col); + typename gmm::linalg_traits::const_iterator c_end = gmm::vect_const_end(col); + + for(; c_it != c_end; ++c_it) + if( c_it.index() > i) + { + // sw.start(); + double val = -(*c_it)/elim_val_cur; + + add_row_simultaneously( c_it.index(), val, gmm::mat_row(_constraints, i), _constraints, constraints_c); + // make sure the eliminated entry is 0 on all other rows and not 1e-17 + _constraints( c_it.index(), elim_j) = 0; + constraints_c(c_it.index(), elim_j) = 0; + + // update linear transition of rhs + gmm::add(gmm::scaled(gmm::mat_row(rhs_update_table_.D_, i), val), + gmm::mat_row(rhs_update_table_.D_, c_it.index())); + } + } + } +} + + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +make_constraints_independent_reordering( + RMatrixT& _constraints, + VectorIT& _idx_to_round, + std::vector& _c_elim) +{ + // setup linear transformation for rhs, start with identity + unsigned int nr = gmm::mat_nrows(_constraints); + gmm::resize(rhs_update_table_.D_, nr, nr); + gmm::clear(rhs_update_table_.D_); + for(unsigned int i=0; i roundmap( n_vars, false); + for(unsigned int i=0; i<_idx_to_round.size(); ++i) + roundmap[_idx_to_round[i]] = true; + + // copy constraints into column matrix (for faster update via iterators) + typedef gmm::wsvector CVector; + typedef gmm::col_matrix< CVector > CMatrix; + CMatrix constraints_c; + gmm::resize(constraints_c, gmm::mat_nrows(_constraints), gmm::mat_ncols(_constraints)); + gmm::copy(_constraints, constraints_c); + + // init priority queue + MutablePriorityQueueT queue; + queue.clear( nr ); + for(unsigned int i=0; i row_visited(nr, false); + std::vector row_ordering; row_ordering.reserve(nr); + + + // for all conditions + // for(unsigned int i=0; i::const_sub_row_type CRowT; + typedef typename gmm::linalg_traits::sub_row_type RowT; + typedef typename gmm::linalg_traits::const_iterator RIter; + + // get current condition row + CRowT row = gmm::mat_const_row( _constraints, i); + RIter row_it = gmm::vect_const_begin( row); + RIter row_end = gmm::vect_const_end( row); + double elim_val = FLT_MAX; + double max_elim_val = -FLT_MAX; + + // new: gcd + std::vector v_gcd; + v_gcd.resize(gmm::nnz(row),-1); + int n_ints(0); + bool gcd_update_valid(true); + + for(; row_it != row_end; ++row_it) + { + int cur_j = row_it.index(); + // do not use the constant part + if( cur_j != n_vars - 1 ) + { + // found real valued var? -> finished (UPDATE: no not any more, find biggest real value to avoid x/1e-13) + if( !roundmap[ cur_j ]) + { + if( fabs(*row_it) > max_elim_val) + { + elim_j = cur_j; + max_elim_val = fabs(*row_it); + } + //break; + } + else + { + double cur_row_val(fabs(*row_it)); + // gcd + // if the coefficient of an integer variable is not an integer, then + // the variable most problably will not be (expect if all coeffs are the same, e.g. 0.5) + if( (double(int(cur_row_val))- cur_row_val) != 0.0) + { +// std::cerr << __FUNCTION__ << " Warning: coefficient of integer variable is NOT integer: " +// << cur_row_val << std::endl; + gcd_update_valid = false; + } + + v_gcd[n_ints] = cur_row_val; + ++n_ints; + + // store integer closest to 1, must be greater than epsilon_ + if( fabs(cur_row_val-1.0) < elim_val && cur_row_val > epsilon_) + { + elim_int_j = cur_j; + elim_val = fabs(cur_row_val-1.0); + } + } + } + } + + // first try to eliminate a valid (>epsilon_) real valued variable (safer) + if( max_elim_val > epsilon_) + {} + else // use the best found integer + elim_j = elim_int_j; + + // if no integer or real valued variable greater than epsilon_ existed, then + // elim_j is now -1 and this row is not considered as a valid constraint + + + + + // store result + _c_elim[i] = elim_j; + // error check result + if( elim_j == -1) + { + // redundant or incompatible? + if( noisy_ > 0) + if( fabs(gmm::mat_const_row(_constraints, i)[n_vars-1]) > epsilon_ ) + std::cerr << "Warning: incompatible condition: " + << fabs(gmm::mat_const_row(_constraints, i)[n_vars-1]) << std::endl; + // else + // std::cerr << "Warning: redundant condition:\n"; + } + else + if(roundmap[elim_j] && elim_val > 1e-6) + { + if( do_gcd_ && gcd_update_valid) + { + // perform gcd update + bool gcd_ok = update_constraint_gcd( _constraints, i, elim_j, v_gcd, n_ints); + if( !gcd_ok) + if( noisy_ > 0) + std::cerr << __FUNCTION__ << " Warning: GCD update failed! " << gmm::mat_const_row(_constraints, i) << std::endl; + } + else + { + if( noisy_ > 0) + { + if( !do_gcd_) + std::cerr << __FUNCTION__ << " Warning: NO +-1 coefficient found, integer rounding cannot be guaranteed. Try using the GCD option! " << gmm::mat_const_row(_constraints, i) << std::endl; + else + std::cerr << __FUNCTION__ << " Warning: GCD of non-integer cannot be computed! " << gmm::mat_const_row(_constraints, i) << std::endl; + + } + } + } + + + // is this condition dependent? + if( elim_j != -1 ) + { + // get elim variable value + double elim_val_cur = _constraints(i, elim_j); + + // copy col + CVector col = constraints_c.col(elim_j); + + // iterate over column + typename gmm::linalg_traits::const_iterator c_it = gmm::vect_const_begin(col); + typename gmm::linalg_traits::const_iterator c_end = gmm::vect_const_end(col); + + for(; c_it != c_end; ++c_it) + // if( c_it.index() > i) + if( !row_visited[c_it.index()]) + { + // sw.start(); + double val = -(*c_it)/elim_val_cur; + add_row_simultaneously( c_it.index(), val, gmm::mat_row(_constraints, i), _constraints, constraints_c); + // make sure the eliminated entry is 0 on all other rows and not 1e-17 + _constraints( c_it.index(), elim_j) = 0; + constraints_c(c_it.index(), elim_j) = 0; + + int cur_idx = c_it.index(); + int cur_nnz = gmm::nnz( gmm::mat_row(_constraints,cur_idx)); + if( _constraints(cur_idx,n_vars-1) != 0.0) --cur_nnz; + + queue.update(cur_idx, cur_nnz); + + // update linear transition of rhs + gmm::add(gmm::scaled(gmm::mat_row(rhs_update_table_.D_, i), val), + gmm::mat_row(rhs_update_table_.D_, c_it.index())); + } + } + } + // // check result + // for(unsigned int i=0; i elim_temp2(_c_elim); + // std::sort(elim_temp2.begin(), elim_temp2.end()); + // std::cerr << elim_temp2 << std::endl; + + + std::vector elim_temp(_c_elim); + _c_elim.resize(0); _c_elim.resize( elim_temp.size(),-1); + + for(unsigned int i=0; i +bool +ConstrainedSolver:: +update_constraint_gcd( RMatrixT& _constraints, + int _row_i, + int& _elim_j, + std::vector& _v_gcd, + int& _n_ints) +{ + // find gcd + double i_gcd = find_gcd(_v_gcd, _n_ints); + + if( fabs(i_gcd) == 1.0) + return false; + + // divide by gcd + typedef typename gmm::linalg_traits::const_sub_row_type CRowT; + typedef typename gmm::linalg_traits::const_iterator RIter; + + // get current constraint row + RIter row_it = gmm::vect_const_begin( gmm::mat_const_row( _constraints, _row_i)); + RIter row_end = gmm::vect_const_end( gmm::mat_const_row( _constraints, _row_i)); + + for( ; row_it!=row_end; ++row_it) + { + int cur_j = row_it.index(); + _constraints(_row_i, cur_j) = (*row_it)/i_gcd; + } + int elim_coeff = abs(_constraints(_row_i, _elim_j)); + if( elim_coeff != 1) + std::cerr << __FUNCTION__ << " Error: elimination coefficient " << elim_coeff << " will (most probably) NOT lead to an integer solution!" << std::endl; + return true; +} + +//----------------------------------------------------------------------------- + +template +void +ConstrainedSolver:: +eliminate_constraints( + gmm::row_matrix& _constraints, + gmm::row_matrix& _B, + VectorIT& _idx_to_round, + std::vector& _c_elim, + std::vector& _new_idx, + gmm::col_matrix& _Bcol) +{ + // copy into column matrix + gmm::resize(_Bcol, gmm::mat_nrows(_B), gmm::mat_ncols(_B)); + gmm::copy( _B, _Bcol); + + // store columns which should be eliminated + std::vector elim_cols; + elim_cols.reserve( _c_elim.size()); + + for(unsigned int i=0; i<_c_elim.size(); ++i) + { + int cur_j = _c_elim[i]; + + if( cur_j != -1) + { + double cur_val = _constraints(i,cur_j); + + // store index + elim_cols.push_back(_c_elim[i]); + + // copy col + SVector3T col = _Bcol.col(cur_j); + + // iterate over column + typename gmm::linalg_traits::const_iterator c_it = gmm::vect_const_begin(col); + typename gmm::linalg_traits::const_iterator c_end = gmm::vect_const_end(col); + + for(; c_it != c_end; ++c_it) + add_row( c_it.index(), -(*c_it)/cur_val, gmm::mat_row(_constraints, i), _Bcol); + } + } + + // eliminate columns + eliminate_columns( _Bcol, elim_cols); + + // TODO FIXME Size -1 ?!?! + // init _new_idx vector + _new_idx.resize(gmm::mat_ncols(_constraints)); + for(unsigned int i=0; i<_new_idx.size(); ++i) + _new_idx[i] = i; + + // update _new_idx w.r.t. eliminated cols + COMISO_GMM::eliminate_vars_idx( elim_cols, _new_idx, -1); + + // update _idx_to_round (in place) + std::vector round_old(_idx_to_round); + unsigned int wi = 0; + for(unsigned int i=0; i<_idx_to_round.size(); ++i) + { + if(_new_idx[ _idx_to_round[i]] != -1) + { + _idx_to_round[wi] = _new_idx[_idx_to_round[i]]; + ++wi; + } + } + + // resize, sort and make unique + _idx_to_round.resize(wi); + + std::sort(_idx_to_round.begin(), _idx_to_round.end()); + _idx_to_round.resize( std::unique(_idx_to_round.begin(), _idx_to_round.end()) -_idx_to_round.begin()); + + + if( noisy_ > 2 ) + { + std::cerr << __FUNCTION__ << "remaining variables: " << gmm::mat_ncols(_Bcol) << std::endl; + std::cerr << __FUNCTION__ << "remaining integer variables: " << _idx_to_round.size() << std::endl; + std::cerr << __FUNCTION__ << std::endl; + } +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +eliminate_constraints( + gmm::row_matrix& _constraints, + gmm::col_matrix& _A, + std::vector& _x, + std::vector& _rhs, + VectorIT& _idx_to_round, + std::vector& _v_elim, + std::vector& _new_idx, + CSCMatrixT& _Acsc) +{ + COMISO::StopWatch sw; + sw.start(); + // define iterator on matrix A and on constraints C + typedef typename gmm::linalg_traits::const_iterator AIter; + typedef typename gmm::linalg_traits::const_iterator CIter; + + // store variable indices to be eliminated + std::vector elim_varids; + elim_varids.reserve( _v_elim.size()); + + rhs_update_table_.clear(); + std::vector constraint_rhs_vec(_constraints.nrows()); + + for( unsigned int i=0; i < _v_elim.size(); ++i) + { + int cur_j = _v_elim[i]; + + if( cur_j != -1) + { + double cur_val = _constraints(i, cur_j); + + // store index + elim_varids.push_back(cur_j); + rhs_update_table_.add_elim_id(cur_j); + + // copy col + SVector2T col ( _A.col( cur_j)); + + // get a reference to current constraint vector + SVector1T& constraint( _constraints.row(i)); + + // add cur_j-th row multiplied with constraint[k] to each row k + // iterator of matrix column + AIter col_it, col_end; + + // constraint rhs + double constraint_rhs = constraint[ constraint.size()-1]; + constraint_rhs_vec[i] = -constraint_rhs; + + //std::cerr << "constraint_rhs " << constraint_rhs << std::endl; + // temporarliy set last element to zero (to avoid iterator finding it) + constraint[ constraint.size()-1] = 0; + + double cur_rhs = _rhs[cur_j]; + + // iterator of constraint + CIter con_it = gmm::vect_const_begin( constraint); + CIter con_end = gmm::vect_const_end( constraint); + + // loop over all constraint entries over all column entries + // should not hit last element (rhs) since set to zero + for ( ; con_it != con_end; ++con_it ) + { + col_it = gmm::vect_const_begin( col ); + col_end = gmm::vect_const_end( col ); + for ( ; col_it != col_end; ++col_it ) + _A( con_it.index(), col_it.index() ) -= ( *col_it )*(( *con_it )/cur_val); + + //_rhs[con_it.index()] -= cur_rhs * (( *con_it )/cur_val); +// rhs_update_table_.append(con_it.index(), -1.0 * (( *con_it )/cur_val), cur_j); + rhs_update_table_.append(con_it.index(), -1.0 * (( *con_it )/cur_val), cur_j, false); + //std::cerr << con_it.index() << " += " << -1.0*(( *con_it )/cur_val) << " * " << cur_rhs << " (["< elim_varvals( elim_varids.size(), 0); + COMISO_GMM::eliminate_csc_vars2( elim_varids, elim_varvals, _Acsc, _x, _rhs); + + if( noisy_ > 2) + std::cerr << __FUNCTION__ << " Constraints eliminated " << sw.stop()/1000.0 << std::endl; + sw.start(); + // init _new_idx vector +// _new_idx.resize( gmm::mat_ncols(_constraints)); + _new_idx.resize( gmm::mat_ncols(_A)+1); + for( unsigned int i=0; i<_new_idx.size(); ++i) + _new_idx[i] = i; + + // update _new_idx w.r.t. eliminated cols + COMISO_GMM::eliminate_vars_idx( elim_varids, _new_idx, -1); + + // update _idx_to_round (in place) + unsigned int wi = 0; + for( unsigned int i=0; i<_idx_to_round.size(); ++i) + { + if(_new_idx[ _idx_to_round[i]] != -1) + { + _idx_to_round[wi] = _new_idx[_idx_to_round[i]]; + ++wi; + } + } + + // resize, sort and make unique + _idx_to_round.resize(wi); + + std::sort(_idx_to_round.begin(), _idx_to_round.end()); + _idx_to_round.resize( std::unique(_idx_to_round.begin(), _idx_to_round.end()) -_idx_to_round.begin()); + + if( noisy_ > 2) + std::cerr << __FUNCTION__ << "Indices reindexed " << sw.stop()/1000.0 << std::endl << std::endl; +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +add_row( int _row_i, + double _coeff, + RowT _row, + MatrixT& _mat ) +{ + typedef typename gmm::linalg_traits::const_iterator RIter; + RIter r_it = gmm::vect_const_begin(_row); + RIter r_end = gmm::vect_const_end(_row); + + for(; r_it!=r_end; ++r_it) + _mat(_row_i, r_it.index()) += _coeff*(*r_it); +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +add_row_simultaneously( int _row_i, + double _coeff, + RowT _row, + RMatrixT& _rmat, + CMatrixT& _cmat ) +{ + typedef typename gmm::linalg_traits::const_iterator RIter; + RIter r_it = gmm::vect_const_begin(_row); + RIter r_end = gmm::vect_const_end(_row); + + for(; r_it!=r_end; ++r_it) + { + _rmat(_row_i, r_it.index()) += _coeff*(*r_it); + _cmat(_row_i, r_it.index()) += _coeff*(*r_it); + // if( _rmat(_row_i, r_it.index())*_rmat(_row_i, r_it.index()) < epsilon_squared_ ) + if( fabs(_rmat(_row_i, r_it.index())) < epsilon_ ) + { + _rmat(_row_i, r_it.index()) = 0.0; + _cmat(_row_i, r_it.index()) = 0.0; + } + } +} + + +//----------------------------------------------------------------------------- + + +template +double +ConstrainedSolver:: +setup_and_solve_system( CMatrixT& _B, + VectorT& _x, + VectorIT& _idx_to_round, + double _reg_factor, + bool _show_miso_settings) +{ + // show options dialog + if( _show_miso_settings) + miso_.show_options_dialog(); + + COMISO::StopWatch s1; + COMISO::StopWatch sw; sw.start(); + unsigned int m = gmm::mat_nrows(_B); + unsigned int n = gmm::mat_ncols(_B); + + s1.start(); + // set up B transposed + CMatrixT Bt; + gmm::resize( Bt, n, m); + gmm::copy( gmm::transposed( _B), Bt); + if( noisy_ > 1 ) + std::cerr << __FUNCTION__ << " Bt took " << s1.stop()/1000.0 << std::endl; + s1.start(); + + // setup BtB + CMatrixT BtB; + gmm::resize( BtB, n, n); + gmm::mult( Bt, _B, BtB); + if( noisy_ > 1 ) + std::cerr << __FUNCTION__ << " BtB took " << s1.stop()/1000.0 << std::endl; + s1.start(); + + // extract rhs + std::vector< double > rhs( n); + gmm::copy( gmm::scaled(gmm::mat_const_col( BtB, n - 1),-1.0), rhs); + rhs.resize( n - 1); + + if( noisy_ > 1) + std::cerr << __FUNCTION__ << " rhs extract resize " << s1.stop()/1000.0 << std::endl; + s1.start(); + + // resize BtB to only contain the actual system matrix (and not the rhs) + gmm::resize( BtB, n - 1, n - 1); + + if( noisy_ > 1) + std::cerr << __FUNCTION__ << " BtB resize took " << s1.stop()/1000.0 << std::endl; + s1.start(); + _x.resize( n - 1); + if( noisy_ > 1) + std::cerr << __FUNCTION__ << " x resize took " << s1.stop()/1000.0 << std::endl; + + // regularize if necessary + if(_reg_factor != 0.0) + COMISO_GMM::regularize_hack(BtB, _reg_factor); + s1.start(); + + // BtB -> CSC + CSCMatrix BtBCSC; + BtBCSC.init_with_good_format( BtB); + + if( noisy_ > 1) + std::cerr << __FUNCTION__ << " CSC init " << s1.stop()/1000.0 << std::endl; + double setup_time = sw.stop()/1000.0; + + + COMISO::StopWatch misw; + misw.start(); + // miso solve + miso_.solve( BtBCSC, _x, rhs, _idx_to_round); + if( noisy_ > 1) + std::cerr << __FUNCTION__ << " Miso Time " << misw.stop()/1000.0 << "s." << std::endl << std::endl; + return setup_time; +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +restore_eliminated_vars( RMatrixT& _constraints, + VectorT& _x, + std::vector& _c_elim, + std::vector& _new_idx) +{ + // restore original ordering of _x + _x.resize(_new_idx.size()); + // last variable is the constant term 1.0 + _x.back() = 1.0; + + // reverse iterate from prelast element + for(int i=_new_idx.size()-2; i>= 0; --i) + { + if( _new_idx[i] != -1) + { + // error handling + if( i < _new_idx[i] && noisy_ > 0) std::cerr << "Warning: UNSAFE Ordering!!!\n"; + + _x[i] = _x[_new_idx[i]]; + } + } + + // reverse iterate + for(int i=_c_elim.size()-1; i>=0; --i) + { + int cur_var = _c_elim[i]; + + if( cur_var != -1) + { + // get variable value and set to zero + double cur_val = _constraints(i, cur_var); + + //_constraints(i, cur_var) = 0.0; + //_x[cur_var] = -gmm::vect_sp(_x, _constraints.row(i))/cur_val; + //reformulated to keep _constraints intact for further use: + _x[cur_var] -= gmm::vect_sp(_x, _constraints.row(i))/cur_val; + + } + } + + // resize + _x.resize(_x.size()-1); +} + + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver:: +verify_mi_factored( const RMatrixT& _conditions, + const RMatrixT& _B, + const VectorT& _x, + const VectorIT& _idx_to_round ) +{ + std::cerr << "######### Verify Constrained Solver Result ############\n"; + + // create extended x vector + std::vector x(_x); + x.resize(x.size()+1); + x.back() = 1.0; + + // verify conditions + std::vector a(gmm::mat_nrows(_conditions)); + + gmm::mult(_conditions, x, a); + + int conditions_not_ok = 0; + for(unsigned int i=0; i 1e-6) + { + ++conditions_not_ok; + } + + if( conditions_not_ok == 0) + std::cerr << "all conditions are ok!\n"; + else + std::cerr << conditions_not_ok + << " conditions are not fullfilled: " + << std::endl; + + // verify rounding + int roundings_not_ok = 0; + for(unsigned int i=0; i<_idx_to_round.size(); ++i) + { + double d = _x[_idx_to_round[i]]; + if( fabs(d-round(d)) > 1e-6) + ++roundings_not_ok; + } + + if( roundings_not_ok) + std::cerr << roundings_not_ok << " Integer variables are not rounded\n"; + else + std::cerr << "all Integer roundings are ok\n"; + + // evaluate energy + VectorT Bx(x); + gmm::mult(_B, x, Bx); + std::cerr << "Total energy: " << gmm::vect_sp(Bx, Bx) << std::endl; + + std::cerr << "######### FINISHED ############\n"; +} + + + +//----------------------------------------------------------------------------- + + +template +double +ConstrainedSolver::verify_constrained_system( + const RMatrixT& _conditions, + const CMatrixT& _A, + const VectorT& _x, + const VectorT& _rhs, + double _eps) +{ + typedef typename gmm::linalg_traits::const_sub_row_type RowT; + typedef typename gmm::linalg_traits::const_iterator RIter; + + VectorT Ax( _x.size()); + gmm::mult(_A, _x, Ax); + + gmm::add(_rhs, gmm::scaled(Ax, -1.0), Ax); + double norm = gmm::vect_norm2(Ax); + //std::cerr << __FUNCTION__ << ": Error residual: " << norm << " vector : " << Ax << std::endl; + + std::cerr << __FUNCTION__ << ": Checking constraints..." << std::endl; + + unsigned int row_cond = gmm::mat_nrows( _conditions); + unsigned int col_cond = gmm::mat_ncols( _conditions); + bool all_conditions_ok = true; + for( unsigned int r = 0; r < row_cond; ++r) + { + double cond_value = 0.0; + RowT row = gmm::mat_const_row( _conditions, r); + RIter row_it = gmm::vect_const_begin( row); + RIter row_end = gmm::vect_const_end( row); + //std::cerr << "\t checking row : " << row << std::endl; + + for( ; row_it != row_end; ++row_it) + { + if( row_it.index() == col_cond -1) + cond_value += (*row_it); + else + cond_value += _x[row_it.index()]*(*row_it); + } + //std::cerr << "\t Value is : " << cond_value << std::endl; + //std::cerr << "--- --- --- --- ---\n"; + if( fabs(cond_value) > _eps) + { + std::cerr << "\t Error on row " << r << " with vector " << row << " and condition value " << cond_value << std::endl; + all_conditions_ok = false; + } + } + std::cerr << __FUNCTION__ << (all_conditions_ok? ": All conditions ok!" : ": Some conditions not ok!") << std::endl; + return norm; +} + +//----------------------------------------------------------------------------- + + +template +double +ConstrainedSolver:: +verify_constrained_system_round( + const RMatrixT& _conditions, + const CMatrixT& _A, + const VectorT& _x, + const VectorT& _rhs, + const VectorIT& _idx_to_round, + double _eps) +{ + // test integer roundings + std::cerr << __FUNCTION__ << ": Testing integer roundings..." << std::endl; + bool all_roundings_ok = true; + + for( unsigned int i = 0; i < _idx_to_round.size(); ++i) + if(fabs(ROUND(_x[_idx_to_round[i]])-_x[_idx_to_round[i]]) != 0.0) + { + std::cerr << "\t Warning: variable " << _idx_to_round[i] << " was not rounded!" << " Value is = " << _x[_idx_to_round[i]] << std::endl; + all_roundings_ok = false; + } + std::cerr << __FUNCTION__ << (all_roundings_ok? ": All roundings ok!" : ": Some roundings not ok!") << std::endl; + + // also test other stuff + return verify_constrained_system(_conditions, _A, _x, _rhs, _eps); +} + +//----------------------------------------------------------------------------- + + +template +void +ConstrainedSolver::eliminate_columns( CMatrixT& _M, + const std::vector< int >& _columns) +{ + // nothing to do? + if( _columns.size() == 0) return; + + // eliminate columns in place by first copying to the right place + // and a subsequent resize + std::vector< int > columns( _columns); + std::sort( columns.begin(), columns.end()); + + std::vector< int >::iterator col_it = columns.begin(); + std::vector< int >::iterator col_end = columns.end(); + + int next_i = *col_it; + for( int i = *col_it; i < (int)_M.ncols(); ++i) + { + if( col_it != col_end && i == *col_it) + { + ++col_it; + } + else + { + _M.col(next_i) = _M.col(i); + ++next_i; + } + } + gmm::resize( _M, _M.nrows(), _M.ncols() - columns.size()); +} + + +//============================================================================= +} // namespace COMISO +//============================================================================= diff --git a/src/external/CoMISo/Solver/EigenLDLTSolver.cc b/src/external/CoMISo/Solver/EigenLDLTSolver.cc new file mode 100644 index 000000000..24ca6bd08 --- /dev/null +++ b/src/external/CoMISo/Solver/EigenLDLTSolver.cc @@ -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 . * + * * +\*===========================================================================*/ + + + +#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& _colptr, + const std::vector& _rowind, + const std::vector& _values) +{ + std::cerr << "Info: EigenLDLTSolver::calc_system( const std::vector ...) not implemented yet..." << std::endl; + return false; +} + + + //----------------------------------------------------------------------------- + + +bool EigenLDLTSolver::update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ) +{ + std::cerr << "Info: EigenLDLTSolver::update_system( const std::vector ...) not implemented yet..." << std::endl; + return false; +} + + +//----------------------------------------------------------------------------- + + +bool EigenLDLTSolver::solve( double * _x, double * _b) +{ + // map arrays to Eigen-Vectors + Eigen::Map x(_x,n_); + Eigen::Map 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& _x0, std::vector& _b) +{ + return solve( &(_x0[0]), &(_b[0])); +} + +//----------------------------------------------------------------------------- + +bool& EigenLDLTSolver:: +show_timings() +{ + return show_timings_; +} + + +} + +//============================================================================= +#endif // COMISO_EIGEN3_AVAILABLE +//============================================================================= diff --git a/src/external/CoMISo/Solver/EigenLDLTSolver.hh b/src/external/CoMISo/Solver/EigenLDLTSolver.hh new file mode 100644 index 000000000..0284ed21e --- /dev/null +++ b/src/external/CoMISo/Solver/EigenLDLTSolver.hh @@ -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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS CholmodSolver +// +//============================================================================= + +#ifndef COMISO_EIGEN_LDLT_SOLVER_HH +#define COMISO_EIGEN_LDLT_SOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if (COMISO_EIGEN3_AVAILABLE) +//== INCLUDES ================================================================= + + +#include +#include + +#include +#include + + +#include +#include +#include + + +//== 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& _colptr, + const std::vector& _rowind, + const std::vector& _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& _colptr, + const std::vector& _rowind, + const std::vector& _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& _x0, std::vector& _b); + + bool& show_timings(); + + int dimension(); + +private: + + // dimension n_ + unsigned int n_; + + Eigen::SimplicialLDLT > 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 +//============================================================================= diff --git a/src/external/CoMISo/Solver/EigenLDLTSolverT.cc b/src/external/CoMISo/Solver/EigenLDLTSolverT.cc new file mode 100644 index 000000000..dd6565ee9 --- /dev/null +++ b/src/external/CoMISo/Solver/EigenLDLTSolverT.cc @@ -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 . * + * * +\*===========================================================================*/ + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if (COMISO_EIGEN3_AVAILABLE) +//== INCLUDES ================================================================= + +#define COMISO_EIGEN_LDLT_SOLVER_TEMPLATES_C + +#include +#include +#include + + +namespace COMISO { + + +template< class GMM_MatrixT> +bool EigenLDLTSolver::calc_system_gmm( const GMM_MatrixT& _mat) +{ + if(show_timings_) sw_.start(); + + Eigen::SparseMatrix 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 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 +//============================================================================= diff --git a/src/external/CoMISo/Solver/Eigen_Tools.cc b/src/external/CoMISo/Solver/Eigen_Tools.cc new file mode 100644 index 000000000..d408ad093 --- /dev/null +++ b/src/external/CoMISo/Solver/Eigen_Tools.cc @@ -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 . * + * * +\*===========================================================================*/ + + + +//============================================================================= +// +// CLASS Eigen_Tools - IMPLEMENTATION +// +//============================================================================= + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_EIGEN3_AVAILABLE + + +#define COMISO_Eigen_TOOLS_C + +//== INCLUDES ================================================================= + +#include "Eigen_Tools.hh" +#include +#include +#include +#include + + +//== NAMESPACES =============================================================== + +namespace COMISO_EIGEN +{ + +//== IMPLEMENTATION ========================================================== + + +//----------------------------------------------------------------------------- + +template +void get_ccs_symmetric_data( const MatrixT& _mat, + const char _uplo, + std::vector& _values, + std::vector& _rowind, + std::vector& _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= 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 +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::max(); + Scalar vmax = std::numeric_limits::min(); + Scalar vmin_abs = std::numeric_limits::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 +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 +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 +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 values; + std::vector rowind; + std::vector 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 values; + std::vector rowind; + std::vector 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; ix))[i] = values[i]; + ((int*) (_AC->i))[i] = rowind[i]; + } + for(unsigned int i=0; ip))[i] = colptr[i]; + } + +} +#endif + +/* +/// Eigen to Cholmod_dense interface +template +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 +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 values; + std::vector rowind; + std::vector 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 values; + std::vector rowind; + std::vector 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; ix))[i] = values[i]; + ((int*) (_AC->i))[i] = rowind[i]; + } + for(unsigned int i=0; ip))[i] = colptr[i]; + } + +}*/ + +// convert a gmm col-sparse matrix into an eigen sparse matrix +template +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::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::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. * + * * +\*===========================================================================*/ + + +#ifndef COMISO_Eigen_TOOLS_HH +#define COMISO_Eigen_TOOLS_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_EIGEN3_AVAILABLE + +//== INCLUDES ================================================================= + +#include +#include +#include +#include +#include + + +#include +#define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET +#include + +#if COMISO_SUITESPARSE_AVAILABLE +#include +#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 +void get_ccs_symmetric_data( const MatrixT& _mat, + const char _c, + std::vector& _values, + std::vector& _rowind, + std::vector& _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 +void inspect_matrix( const MatrixT& _A); + +/** checks for symmetry + * @param _A matrix + * @return symmetric? (bool)*/ +template +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 +void cholmod_to_eigen( const cholmod_sparse& _AC, MatrixT& _A); + +template +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 +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 +//============================================================================= + diff --git a/src/external/CoMISo/Solver/GMM_Tools.cc b/src/external/CoMISo/Solver/GMM_Tools.cc new file mode 100644 index 000000000..e05bf0374 --- /dev/null +++ b/src/external/CoMISo/Solver/GMM_Tools.cc @@ -0,0 +1,1262 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + + +//============================================================================= +// +// CLASS GMM_Tools - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_GMM_TOOLS_C + +//== INCLUDES ================================================================= + +#include "GMM_Tools.hh" +#define GMM_USES_LAPACK +#include +#include +#include +#include + + +//== NAMESPACES =============================================================== + +namespace COMISO_GMM +{ + +//== IMPLEMENTATION ========================================================== + + +//----------------------------------------------------------------------------- + + +// too many if-statements, seems slower in most cases +// use eliminate_csc_vars2 +template +void eliminate_csc_vars( + const std::vector& _evar, + const std::vector& _eval, + typename gmm::csc_matrix& _A, + VectorT& _x, + VectorT& _rhs ) +{ + typedef unsigned int uint; + typedef typename gmm::csc_matrix MatrixT; + + unsigned int nc = _A.nc; + unsigned int nr = _A.nr; + + unsigned int n_new = nc - _evar.size(); + + // modify rhs + for ( unsigned int k=0; k<_evar.size(); ++k ) + { + IntegerT i = _evar[k]; + + // number of elements in this column + uint n_elem = _A.jc[i+1]-_A.jc[i]; + uint r_idx = 0; + RealT entry = 0.0; + for( uint i_elem = _A.jc[i]; i_elem < _A.jc[i+1]; ++i_elem) + { + r_idx = _A.ir[i_elem]; + entry = _A.pr[i_elem]; + _rhs[r_idx] -= _eval[k]*( entry ); + } + } + + // sort vector + std::vector evar( _evar ); + std::sort( evar.begin(), evar.end() ); + evar.push_back( std::numeric_limits::max() ); + + // build subindex set and update rhs + std::vector si( n_new ); + int cur_evar_idx=0; + for ( unsigned int i=0; i (uint) evar[next_evar_row]) + { + ++next_evar_row; + ++offset_update; + } + _A.pr[e-offset] = _A.pr[e]; + _A.ir[e-offset] = _A.ir[e]-offset_update; + if( _A.ir[e] == (uint)evar[next_evar_row]) + { + ++offset; + } + } + last_jc = _A.jc[c+1]; + _A.jc[c+1-col_offset] = _A.jc[c+1]-offset; + } + else + { + ++col_offset; + offset+=el_span; + ++next_evar_col; + last_jc = _A.jc[c+1]; + } + } + _A.nc = nc - evar.size()+1; + _A.nr = nr - evar.size()+1; +} + + +//----------------------------------------------------------------------------- + + +template +void eliminate_csc_vars2( + const std::vector& _evar, + const std::vector& _eval, + typename gmm::csc_matrix& _A, + VectorT& _x, + VectorT& _rhs ) +{ + typedef unsigned int uint; + typedef typename gmm::csc_matrix MatrixT; + + unsigned int nc = _A.nc; + unsigned int nr = _A.nr; + + unsigned int n_new = nc - _evar.size(); + + // modify rhs + for ( unsigned int k=0; k<_evar.size(); ++k ) + { + IntegerT i = _evar[k]; + + // number of elements in this column + // uint n_elem = _A.jc[i+1]-_A.jc[i]; + uint r_idx = 0; + RealT entry = 0.0; + for( uint i_elem = _A.jc[i]; i_elem < _A.jc[i+1]; ++i_elem) + { + r_idx = _A.ir[i_elem]; + entry = _A.pr[i_elem]; + _rhs[r_idx] -= _eval[k]*( entry ); + } + } + + // sort vector + std::vector evar( _evar ); + std::sort( evar.begin(), evar.end() ); + evar.push_back( std::numeric_limits::max() ); + + // build subindex set and update rhs + std::vector si( n_new ); + int cur_evar_idx=0; + for ( unsigned int i=0; i new_row_idx_map( nr, -1); + // build re-indexing map + // -1 means deleted + { + int next_evar_idx(0); + int offset(0); + for( int i = 0; i < (int)nr; ++i) + { + if( i == (int)evar[next_evar_idx]) + { + ++next_evar_idx; + ++offset; + } + else + { + new_row_idx_map[i] = i-offset; + } + } + } + + // csc erasing rows and columns + int read(0), write(0), evar_col(0), last_jc(0); + for( unsigned int c = 0; c < nc; ++c) + { + if( c == (unsigned int)evar[evar_col] ) + { + ++evar_col; + read += _A.jc[c+1]-last_jc; + } + else + { + while( read < (int)_A.jc[c+1] ) + { + int new_idx = new_row_idx_map[_A.ir[read]]; + if( new_idx != -1) + { + _A.pr[write] = _A.pr[read]; + _A.ir[write] = new_idx; + ++write; + } + ++read; + } + } + last_jc = _A.jc[c+1]; + + _A.jc[c+1-evar_col] = write; + } + + _A.nc = nc - evar.size()+1; + _A.nr = nr - evar.size()+1; +} + + +//----------------------------------------------------------------------------- + + +template +void get_ccs_symmetric_data( const MatrixT& _mat, + const char _uplo, + std::vector& _values, + std::vector& _rowind, + std::vector& _colptr ) +{ + unsigned int m = gmm::mat_nrows( _mat ); + unsigned int n = gmm::mat_ncols( _mat ); + + gmm::csc_matrix csc_mat( m,n ); + gmm::copy( _mat, csc_mat ); + + _values.resize( 0 ); + _rowind.resize( 0 ); + _colptr.resize( 0 ); + + INTT iv( 0 ); + + switch ( _uplo ) + { + case 'l': + case 'L': + // for all columns + for ( unsigned int i=0; i= i ) + { + ++iv; + _values.push_back(( csc_mat.pr )[j] ); + _rowind.push_back(( csc_mat.ir )[j] ); + } + } + _colptr.push_back( iv ); + break; + + case 'u': + case 'U': + // for all columns + for ( unsigned int i=0; i +void eliminate_var( const unsigned int _j, + const ScalarT _value_j, + gmm::col_matrix& _A, + VectorT& _x, + VectorT& _rhs ) +{ + //ACG::StopWatch sw1; + + //sw1.start(); + + typedef typename gmm::linalg_traits< gmm::col_matrix< SVT > >::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::const_iterator CIter; + + unsigned int m = gmm::mat_nrows( _A ); + unsigned int n = gmm::mat_ncols( _A ); + + + // update rhs + ColT col = mat_const_col( _A, _j ); + CIter it = gmm::vect_const_begin( col ); + CIter ite = gmm::vect_const_end( col ); + + for ( ; it!=ite; ++it ) + { + _rhs[it.index()] -= _value_j*( *it ); + } + + _rhs.erase( _rhs.begin() + _j ); + _x.erase( _x.begin() + _j ); + + //std::cerr << " FIRST BLOCK " << sw1.stop()/1000.0 << std::endl; + /* + for(unsigned int i=_j; i_j) --i_new; + + for(; it!=ite; ++it) + { + unsigned int j_new = it.index(); + if( j_new == _j) continue; + if( j_new > _j) --j_new; + _A(j_new,i_new) = *it; + // if( it.index() != j_new || i_new != i) + // _A(it.index(), i) = 0.0; + + } + } + + gmm::resize( _A, m-1, n-1); + */ + //sw1.start(); + + typedef typename gmm::linalg_traits::const_iterator SIter; + + for ( unsigned int i=0; i_j ) --i_new; + + SVT* cur_col = &( _A.col( i ) ); + if ( i == i_new ) + { + cur_col = new SVT( _A.col( i ) ); + //gmm::copy( _A.col(i), *cur_col); + } + + SIter it = gmm::vect_const_begin( *cur_col ); + SIter ite = gmm::vect_const_end( *cur_col ); + + //mat_col(_A, i_new).clear(); + SVT& new_col = _A.col( i_new ); + new_col.clear(); + + for ( ; it!=ite; ++it ) + { + unsigned int j_new = it.index(); + if ( j_new == _j ) continue; + if ( j_new > _j ) --j_new; + //_A(j_new,i_new) = *it; + new_col[j_new] = *it; + // if( it.index() != j_new || i_new != i) + // _A(it.index(), i) = 0.0; + + } + if ( i == i_new ) + { + delete cur_col; + } + } + //std::cerr << " BLOCK TWO " << sw1.stop()/1000.0 << std::endl; + //sw1.start(); + + gmm::resize( _A, m-1, n-1 ); + //std::cerr << "RESIZE " << sw1.stop()/1000.0 << std::endl; +} + +//----------------------------------------------------------------------------- + + +template +void eliminate_var( const unsigned int _i, + const ScalarT _xi, + typename gmm::csc_matrix& _A, + VectorT& _x, + VectorT& _rhs ) +{ + unsigned int n = _A.nc; + + unsigned int iv_old( 0 ); + unsigned int iv_new( 0 ); + + // for all columns + for ( unsigned int j=0; j _i ) + { + _rhs[j-1] = _rhs[j]; + _x [j-1] = _x [j]; + } + + + if ( j == _i ) + { + // update rhs + for ( unsigned int i=_A.jc[j]; i<_A.jc[j+1]; ++i ) + { + _rhs[_A.ir[iv_old]] -= _xi*_A.pr[iv_old]; + ++iv_old; + } + } + else + { + // store index to update colptr + unsigned int iv_new_save = iv_new; + + for ( unsigned int i=_A.jc[j]; i<_A.jc[j+1]; ++i ) + { + if ( _A.ir[iv_old] < _i ) + { + _A.ir[iv_new] = _A.ir[iv_old]; + _A.pr[iv_new] = _A.pr[iv_old]; + ++iv_new; + } + else if ( _A.ir[iv_old] > _i ) + { + _A.ir[iv_new] = _A.ir[iv_old]-1; + _A.pr[iv_new] = _A.pr[iv_old]; + ++iv_new; + } + ++iv_old; + } + + if ( j<_i ) + _A.jc[j] = iv_new_save; + else + if ( j>_i ) + _A.jc[j-1] = iv_new_save; + } + } + + // store index to end + _A.jc[n-1] = iv_new; + + // resize matrix and vectors + _A.nc = n-1; + _A.nr = n-1; + _x.resize( _x.size()-1 ); + _rhs.resize( _rhs.size()-1 ); +} + + +//----------------------------------------------------------------------------- + + +template +void eliminate_vars( const std::vector& _evar, + const std::vector& _eval, + MatrixT& _A, + VectorT& _x, + VectorT& _rhs ) +{ + std::cerr << __FUNCTION__ << std::endl; + typedef typename gmm::linalg_traits::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::const_iterator CIter; + + // unsigned int m = gmm::mat_nrows( _A); + unsigned int n = gmm::mat_ncols( _A ); + + unsigned int n_new = n - _evar.size(); + + // modify rhs + for ( unsigned int k=0; k<_evar.size(); ++k ) + { + IntegerT i = _evar[k]; + + ColT col = mat_const_col( _A, i ); + + CIter it = gmm::vect_const_begin( col ); + CIter ite = gmm::vect_const_end( col ); + + for ( ; it!=ite; ++it ) + { + _rhs[it.index()] -= _eval[k]*( *it ); + } + } + + // sort vector + std::vector evar( _evar ); + std::sort( evar.begin(), evar.end() ); + evar.push_back( std::numeric_limits::max() ); + + // build subindex set and update rhs + std::vector si( n_new ); + int cur_evar_idx=0; + for ( unsigned int i=0; i::iterator col_it = evar.begin(); + typename std::vector< IntegerT >::iterator col_end = evar.end(); + + int next_i = *col_it; + for( int i = *col_it; i < (int)_A.ncols(); ++i) + { + if( col_it != col_end && i == *col_it) + { + ++col_it; + } + else + { + _A.col(next_i) = _A.col(i); + ++next_i; + } + } + + gmm::resize(_A, gmm::mat_nrows(_A), gmm::mat_ncols(_A)-evar.size()); + gmm::row_matrix< gmm::wsvector > Arow( gmm::mat_nrows(_A), gmm::mat_ncols(_A)); + gmm::copy(_A, Arow); + col_it = evar.begin(); + col_end = evar.end(); + + + int next_ii = *col_it; + for( int i = *col_it; i < (int)_A.nrows(); ++i) + { + if( col_it != col_end && i == *col_it) + { + ++col_it; + } + else + { + Arow.row(next_ii) = Arow.row(i); + ++next_ii; + } + } + + gmm::resize( _A, gmm::mat_ncols(Arow), gmm::mat_ncols(Arow)); + gmm::resize( Arow, gmm::mat_ncols(Arow), gmm::mat_ncols(Arow)); + gmm::copy( Arow, _A); + + + + + //alternative (probably not working anymore) + /* + MatrixT Atmp( gmm::mat_nrows(_A) - evar.size(), gmm::mat_ncols(_A) - evar.size()); + + evar.push_back(INT_MAX); + unsigned int next_evar_row=0, next_evar_col=0; + unsigned int col_offset = 0; + for( unsigned int c = 0; c < mat_ncols(_A); ++c) + { + if( c != evar[next_evar_col] ) + { + CIter it = gmm::vect_const_begin( mat_const_col( _A, c ) ); + CIter ite = gmm::vect_const_end( mat_const_col( _A, c) ); + + unsigned int row_offset = 0; + next_evar_row=0; + for( ; it != ite; ++it) + { + while( it.index() > evar[next_evar_row] ) + { + ++row_offset; + ++next_evar_row; + } + if( it.index() != evar[next_evar_row]) + { + Atmp( it.index() - row_offset, c - col_offset) = *it; + } + } + } + else + { + ++col_offset; + ++next_evar_col; + } + } + gmm::resize( _A, gmm::mat_nrows(Atmp), gmm::mat_ncols(Atmp)); + gmm::copy( Atmp, _A); + */ + +} + + +//----------------------------------------------------------------------------- + + +template +void eliminate_vars_idx( const std::vector& _evar, + std::vector& _idx, + IntegerT2 _dummy, + IntegerT2 _range ) +{ + // sort input + std::vector evar( _evar ); + std::sort( evar.begin(), evar.end() ); + + // precompute update + IntegerT2 range = _range; + if( range == -1 ) + range = _idx.size(); + std::vector update_map( range ); + + typename std::vector::iterator cur_var = evar.begin(); + unsigned int deleted_between = 0; + + for ( unsigned int i=0; i +void eliminate_var_idx( const IntegerT _evar, + std::vector& _idx, + IntegerT2 _dummy ) +{ + for ( unsigned int i=0; i<_idx.size(); ++i ) + { + if ( _idx[i] != _dummy ) + { + if ( _idx[i] == ( IntegerT2 )_evar ) + _idx[i] = _dummy; + else + { + if ( _idx[i] > ( IntegerT2 )_evar ) + --_idx[i]; + } + } + } +} + + + +//----------------------------------------------------------------------------- + + +template +void fix_var_csc_symmetric( const unsigned int _i, + const ScalarT _xi, + typename gmm::csc_matrix& _A, + VectorT& _x, + VectorT& _rhs ) +{ +// GMM CSC FORMAT +// T *pr; // values. +// IND_TYPE *ir; // row indices. +// IND_TYPE *jc; // column repartition on pr and ir. + + unsigned int n = _A.nc; + + // update x + _x[_i] = _xi; + + std::vector idx; idx.reserve(16); + + // clear i-th column and collect nonzeros + for( unsigned int iv=_A.jc[_i]; iv<_A.jc[_i+1]; ++iv) + { + if(_A.ir[iv] == _i) + { + _A.pr[iv] = 1.0; + _rhs[_i] = _xi; + } + else + { + // update rhs + _rhs[_A.ir[iv]] -= _A.pr[iv]*_xi; + // clear entry + _A.pr[iv] = 0; + // store index + idx.push_back( _A.ir[iv]); + } + + } + + for(unsigned int i=0; i +void regularize_hack( MatrixT& _mat, double _v ) +{ + unsigned int m = gmm::mat_nrows( _mat ); + unsigned int n = gmm::mat_ncols( _mat ); + + if ( m!=n ) + std::cerr << "ERROR: regularizing works only for square matrices...\n"; + else + { + double sum = 0.0; + for ( unsigned int i=0; i +int gauss_seidel_local( MatrixT& _A, VectorT& _x, VectorT& _rhs, std::vector _idxs, int _max_iter, double _tolerance ) +{ + typedef typename gmm::linalg_traits::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::const_iterator CIter; + + double t2 = _tolerance*_tolerance; + + // static variables to prevent memory allocation in each step + std::vector i_temp; + std::queue q; + +// // clear old data +// i_temp.clear(); +// q.clear(); + + for ( unsigned int i=0; i<_idxs.size(); ++i ) + q.push( _idxs[i] ); + + int it_count = 0; + + while ( !q.empty() && it_count < _max_iter ) + { + ++it_count; + unsigned int cur_i = q.front(); + q.pop(); + 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 +double residuum_norm( MatrixT& _A, VectorT& _x, VectorT& _rhs ) +{ + if ( gmm::mat_ncols( _A ) != _x.size() ) + std::cerr << "DIM ERROR (residuum_norm): " << gmm::mat_ncols( _A ) << " vs " << _x.size() << std::endl; + if ( gmm::mat_nrows( _A) !=_rhs.size() ) + std::cerr << "DIM ERROR 2 (residuum_norm): " << gmm::mat_nrows( _A) << " vs " << _rhs.size() << std::endl; + + // temp vectors + VectorT Ax( _rhs.size()); + VectorT res( _rhs.size() ); + + gmm::mult( _A,_x, Ax ); + gmm::add( Ax, gmm::scaled( _rhs, -1.0 ), res ); + + return gmm::vect_norm2( res ); +} + + +//----------------------------------------------------------------------------- + + +template +void factored_to_quadratic( MatrixT& _F, MatrixT2& _Q, VectorT& _rhs) +{ + unsigned int m = gmm::mat_nrows(_F); + unsigned int n = gmm::mat_ncols(_F); + + // resize result matrix and vector + gmm::resize(_Q, n-1, n-1); + gmm::resize(_rhs, n); + +// // set up transposed +// MatrixT Ft(n,m); +// gmm::copy(gmm::transposed(_F), Ft); + + // compute quadratic matrix + MatrixT Q(n,n); +// gmm::mult(Ft,_F,Q); + gmm::mult(gmm::transposed(_F),_F,Q); + + // extract rhs + gmm::copy( gmm::scaled(gmm::mat_const_row( Q, n - 1),-1.0), _rhs); + + // resize and copy output + gmm::resize( Q, n-1, n-1); + _rhs.resize( n - 1); + gmm::copy ( Q, _Q); +} + + +//----------------------------------------------------------------------------- + + +// inspect the matrix: dimension, symmetry, zero_rows, zero_cols, nnz, max, min, max_abs, min_abs, NAN, INF +template +void inspect_matrix( const MatrixT& _A) +{ + typedef typename MatrixT::value_type VType; + + int m = gmm::mat_nrows(_A); + int n = gmm::mat_ncols(_A); + + std::cerr << "################### INSPECT MATRIX ##################\n"; + std::cerr << "#rows : " << m << std::endl; + std::cerr << "#cols : " << n << std::endl; + std::cerr << "#nonzeros : " << gmm::nnz(_A) << std::endl; + std::cerr << "#nonzeros/row: " << (double(gmm::nnz(_A))/double(m)) << std::endl; + std::cerr << "symmetric : " << gmm::is_symmetric(_A) << std::endl; + + gmm::col_matrix > Acol( m, n); + gmm::row_matrix > Arow( m, n); + + gmm::copy(_A, Acol); + gmm::copy(_A, Arow); + + int zero_rows = 0; + int zero_cols = 0; + + for(int i=0; i::max(); + VType vmax = std::numeric_limits::min(); + VType vmin_abs = std::numeric_limits::max(); + VType vmax_abs = 0; + + int n_nan = 0; + int n_inf = 0; + + // inspect elements + for(int i=0; i > >::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::const_iterator CIter; + + ColT col = mat_const_col( Acol, i ); + CIter it = gmm::vect_const_begin( col ); + CIter ite = gmm::vect_const_end( col ); + + for(; it != ite; ++it) + { + if( *it < vmin ) vmin = *it; + if( *it > vmax ) vmax = *it; + + if( fabs(*it) < vmin_abs) vmin_abs = fabs(*it); + if( fabs(*it) > vmax_abs) vmax_abs = fabs(*it); + + if( std::isnan(*it)) ++n_nan; + if( std::isinf(*it)) ++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; +} + + +//----------------------------------------------------------------------------- + + +template +void print_dense( const MatrixT& _A) +{ + gmm::dense_matrix A(gmm::mat_nrows(_A), gmm::mat_ncols(_A)); + gmm::copy(_A, A); + std::cerr << A << std::endl; +} + + +//----------------------------------------------------------------------------- +#if COMISO_SUITESPARSE_AVAILABLE + +/// GMM to Cholmod_sparse interface +template +void cholmod_to_gmm( const cholmod_sparse& _AC, MatrixT& _A) +{ + // initialize dimensions + gmm::resize(_A,_AC.nrow, _AC.ncol); + gmm::clear(_A); + + 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]; + } + 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]; + } + + } + 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 +void gmm_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 = gmm::mat_nrows(_A); + int n = gmm::mat_ncols(_A); + + // 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 values; + std::vector rowind; + std::vector colptr; + + // get data of gmm matrix + COMISO_GMM::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 values; + std::vector rowind; + std::vector colptr; + + // get data of gmm matrix + COMISO_GMM::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; ix))[i] = values[i]; + ((int*) (_AC->i))[i] = rowind[i]; + } + for(unsigned int i=0; ip))[i] = colptr[i]; + } +} +#endif + +//============================================================================= +} // namespace COMISO +//============================================================================= diff --git a/src/external/CoMISo/Solver/GMM_Tools.hh b/src/external/CoMISo/Solver/GMM_Tools.hh new file mode 100644 index 000000000..d1ce2e54c --- /dev/null +++ b/src/external/CoMISo/Solver/GMM_Tools.hh @@ -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 . * + * * +\*===========================================================================*/ + + +#ifndef COMISO_GMM_TOOLS_HH +#define COMISO_GMM_TOOLS_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include + +//== INCLUDES ================================================================= + +#include +#include +#include +#include + +#if COMISO_SUITESPARSE_AVAILABLE +#include +#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 +void eliminate_csc_vars( + const std::vector& _evar, + const std::vector& _eval, + typename gmm::csc_matrix& _A, + VectorT& _x, + VectorT& _rhs ); + +/// Eliminate variables from a CSC matric. +template +void eliminate_csc_vars2( + const std::vector& _evar, + const std::vector& _eval, + typename gmm::csc_matrix& _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 +void eliminate_var( + const unsigned int _j, + const ScalarT _value_j, + typename gmm::csc_matrix& _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 +void eliminate_vars( + const std::vector& _evar, + const std::vector& _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 +void eliminate_var( + const unsigned int _j, + const ScalarT _value_j, + gmm::col_matrix& _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 +void eliminate_vars_idx( + const std::vector& _evar, + std::vector& _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 +void eliminate_var_idx( + const IntegerT _evar, + std::vector& _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 +void fix_var_csc_symmetric( const unsigned int _j, + const ScalarT _value_j, + typename gmm::csc_matrix& _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 +void get_ccs_symmetric_data( const MatrixT& _mat, + const char _c, + std::vector& _values, + std::vector& _rowind, + std::vector& _colptr ); + +/// Regularize matrix +/** Makes matrices with rank(_mat) +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 +int gauss_seidel_local( + MatrixT& _A, + VectorT& _x, + VectorT& _rhs, + std::vector _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 +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 +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 +void inspect_matrix( const MatrixT& _A); + +/// Print the matrix as dense matrix +template +void print_dense( const MatrixT& _A); + + +#if COMISO_SUITESPARSE_AVAILABLE + +/// GMM to Cholmod_sparse interface +template +void cholmod_to_gmm( const cholmod_sparse& _AC, MatrixT& _A); + +template +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 +//============================================================================= + diff --git a/src/external/CoMISo/Solver/IterativeSolverT.cc b/src/external/CoMISo/Solver/IterativeSolverT.cc new file mode 100644 index 000000000..a264345b2 --- /dev/null +++ b/src/external/CoMISo/Solver/IterativeSolverT.cc @@ -0,0 +1,253 @@ +//============================================================================= +// +// CLASS IterativeSolverT - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_ITERATIVESOLVERT_C + +//== INCLUDES ================================================================= + +#include "IterativeSolverT.hh" + +//== NAMESPACES =============================================================== + +namespace COMISO{ + +//== IMPLEMENTATION ========================================================== + +template +bool +IterativeSolverT:: +gauss_seidel_local( typename gmm::csc_matrix& _A, + std::vector& _x, + std::vector& _rhs, + std::vector& _idxs, + int& _max_iter, + Real& _tolerance ) +{ + if( _max_iter == 0) return false; + + typedef typename gmm::linalg_traits< gmm::csc_matrix >::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::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 +bool +IterativeSolverT:: +gauss_seidel_local2( typename gmm::csc_matrix& _A, + std::vector& _x, + std::vector& _rhs, + std::vector& _idxs, + int& _max_iter, + Real& _tolerance ) +{ + typedef typename gmm::linalg_traits< gmm::csc_matrix >::const_sub_col_type ColT; + typedef typename gmm::linalg_traits::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::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 +bool +IterativeSolverT:: +conjugate_gradient( typename gmm::csc_matrix& _A, + std::vector& _x, + std::vector& _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 +typename IterativeSolverT::Real +IterativeSolverT:: +vect_norm_rel(const std::vector& _v, const std::vector& _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 +//============================================================================= diff --git a/src/external/CoMISo/Solver/IterativeSolverT.hh b/src/external/CoMISo/Solver/IterativeSolverT.hh new file mode 100644 index 000000000..34b7aad0b --- /dev/null +++ b/src/external/CoMISo/Solver/IterativeSolverT.hh @@ -0,0 +1,104 @@ +//============================================================================= +// +// CLASS IterativeSolverT +// +//============================================================================= + + +#ifndef COMISO_ITERATIVESOLVERT_HH +#define COMISO_ITERATIVESOLVERT_HH + + +//== INCLUDES ================================================================= + +#include +#include +#include +#include + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + + +/** \class IterativeSolverT IterativeSolverT.hh + + Brief Description. + + A more elaborate description follows. +*/ + +template +class IterativeSolverT +{ +public: + + typedef RealT Real; + + /// Constructor + IterativeSolverT() {} + + /// Destructor + ~IterativeSolverT() {} + + + // local gauss_seidel + bool gauss_seidel_local( typename gmm::csc_matrix& _A, + std::vector& _x, + std::vector& _rhs, + std::vector& _idxs, + int& _max_iter, + Real& _tolerance ); + + // local gauss_seidel + bool gauss_seidel_local2( typename gmm::csc_matrix& _A, + std::vector& _x, + std::vector& _rhs, + std::vector& _idxs, + int& _max_iter, + Real& _tolerance ); + + // conjugate gradient + bool conjugate_gradient( typename gmm::csc_matrix& _A, + std::vector& _x, + std::vector& _rhs, + int& _max_iter, + Real& _tolerance ); + +private: + // compute relative norm + Real vect_norm_rel(const std::vector& _v, const std::vector& _diag) const; + + +private: + + // helper for conjugate gradient + std::vector p_; + std::vector q_; + std::vector r_; + std::vector d_; + + // helper for local gauss seidel + std::vector i_temp; + std::deque q; + std::set s; +}; + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_ITERATIVESOLVERT_C) +#define COMISO_ITERATIVESOLVERT_TEMPLATES +#include "IterativeSolverT.cc" +#endif +//============================================================================= +#endif // COMISO_ITERATIVESOLVERT_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/Solver/MISolver.cc b/src/external/CoMISo/Solver/MISolver.cc new file mode 100644 index 000000000..924bc474c --- /dev/null +++ b/src/external/CoMISo/Solver/MISolver.cc @@ -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 . * + * * +\*===========================================================================*/ + + +#include +#include "MISolver.hh" + +#if(COMISO_QT4_AVAILABLE) +#include +#endif + +#if COMISO_GUROBI_AVAILABLE + #include +#endif + +#include + +#include +#include + +// 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 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 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 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 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 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 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 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 tr_best; + + sw.start(); + + RoundingSet rset; + rset.set_threshold(multiple_rounding_threshold_); + + // find index yielding smallest rounding error + for(unsigned int j=0; j 5) + std::cerr << "round " << tr_best.size() << " variables simultaneously\n"; + + // clear neigh for local update + neigh_i.clear(); + + for(unsigned int j = 0; j 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 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 vars; + for( unsigned int i=0; iexec(); +#else + std::cerr << "Warning: Qt not available to show solver dialog!!!" << std::endl; +#endif +} + + +// end namespace COMISO +}// ---------------------- diff --git a/src/external/CoMISo/Solver/MISolver.hh b/src/external/CoMISo/Solver/MISolver.hh new file mode 100644 index 000000000..e14f0fb23 --- /dev/null +++ b/src/external/CoMISo/Solver/MISolver.hh @@ -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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS MISolver +// +//============================================================================= + + +#ifndef COMISO_MISOLVER_HH +#define COMISO_MISOLVER_HH + + +//== INCLUDES ================================================================= +#include +#include + +#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 + +#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 + 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 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::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& _ids ) + { + _ids.clear(); + _ids.reserve( rset_.size()); + std::set::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 rset_; + + std::set 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 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 +//============================================================================= + diff --git a/src/external/CoMISo/Solver/MISolverT.cc b/src/external/CoMISo/Solver/MISolverT.cc new file mode 100644 index 000000000..9bf569f92 --- /dev/null +++ b/src/external/CoMISo/Solver/MISolverT.cc @@ -0,0 +1,189 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + + +//============================================================================= +// +// CLASS MISolver - IMPLEMENTATION +// +//============================================================================= + +#define COMISO_MISOLVER_C +//== INCLUDES ================================================================= + +#include "MISolver.hh" + +#if COMISO_CPLEX_AVAILABLE + #include + ILOSTLBEGIN +#endif + + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== IMPLEMENTATION ========================================================== + + + +// inline function... +void +MISolver::solve( + CSCMatrix& _A, + Vecd& _x, + Vecd& _rhs, + Veci& _to_round, + bool _fixed_order ) +{ + std::cerr << "# integer variables: " << _to_round.size() << std::endl; + std::cerr << "# continuous variables: " << _x.size()-_to_round.size() << std::endl; + + // nothing to solve? + if( gmm::mat_ncols(_A) == 0 || gmm::mat_nrows(_A) == 0) + return; + + if( gurobi_rounding_) + solve_gurobi(_A, _x, _rhs, _to_round); + else + if( cplex_rounding_) + solve_cplex(_A, _x, _rhs, _to_round); + else + if( no_rounding_ || _to_round.size() == 0) + solve_no_rounding( _A, _x, _rhs); + else + if( direct_rounding_) + solve_direct_rounding( _A, _x, _rhs, _to_round); + else + if( multiple_rounding_) + solve_multiple_rounding( _A, _x, _rhs, _to_round); + else + solve_iterative( _A, _x, _rhs, _to_round, _fixed_order); +} + + +//----------------------------------------------------------------------------- + +// inline function... +void +MISolver::solve_cplex( + CSCMatrix& _A, + Vecd& _x, + Vecd& _rhs, + Veci& _to_round) +{ +#if COMISO_CPLEX_AVAILABLE + + // get round-indices in set + std::set to_round; + for(unsigned int i=0; i<_to_round.size();++i) + to_round.insert(_to_round[i]); + + try { + + IloEnv env_; + IloModel model(env_); + + // set time limite + // model.getEnv().set(GRB_DoubleParam_TimeLimit, gurobi_max_time_); + + unsigned int n = _rhs.size(); + + // 1. allocate variables + std::vector vars; + for( unsigned int i=0; i. * + * * +\*===========================================================================*/ + + + +#include "SparseQRSolver.hh" + +//== BUILD-TIME DEPENDENCIES ================================================================= +#if(COMISO_SUITESPARSE_SPQR_AVAILABLE) +//============================================================================================ + + +namespace COMISO { + +SparseQRSolver::SparseQRSolver() +{ + mp_cholmodCommon = new cholmod_common; + cholmod_l_start( mp_cholmodCommon ); + + tolerance_ = 1e-8; + + mp_F = 0; + + ordering_ = CHOLMOD_AMD; + + show_timings_ = false; +} + + + //----------------------------------------------------------------------------- + + +SparseQRSolver::~SparseQRSolver() +{ + if( mp_F ) + { + SuiteSparseQR_free( &mp_F, mp_cholmodCommon); + } + + cholmod_l_finish( mp_cholmodCommon ); + delete mp_cholmodCommon; + mp_cholmodCommon = NULL; +} + + +//----------------------------------------------------------------------------- + + +bool SparseQRSolver::calc_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _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 = 0; + matA.itype = CHOLMOD_LONG; + matA.xtype = CHOLMOD_REAL; + matA.dtype = CHOLMOD_DOUBLE; +// matA.sorted = 1; + matA.sorted = 1; + matA.packed = 1; + +// cholmod_l_print_common("CholmodCommon A", mp_cholmodCommon); + cholmod_l_print_sparse(&matA, "Matrix A", mp_cholmodCommon); + + // clean up + if( mp_F ) + { + SuiteSparseQR_free( &mp_F, mp_cholmodCommon); + } + + if(show_timings_) + { + std::cerr << " SuiteSparseQR Timing cleanup: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + +// if( !(mp_F = SuiteSparseQR_symbolic(ordering_, int(tolerance_!=0.0), &matA, mp_cholmodCommon))) +// { +// std::cerr << "SuiteSparseQR_symbolic failed" << std::endl; +// cholmod_l_print_common("CholmodCommon A", mp_cholmodCommon); +// return false; +// } +// if(show_timings_) +// { +// std::cerr << " SuiteSparseQR_symbolic Timing: " << sw_.stop()/1000.0 << "s\n"; +// sw_.start(); +// } +// +// if( !SuiteSparseQR_numeric( tolerance_, &matA, mp_F, mp_cholmodCommon)) +// { +// std::cout << "SuiteSparseQR_numeric failed" << std::endl; +// return false; +// } + + if( !(mp_F = SuiteSparseQR_factorize(ordering_, tolerance_, &matA, mp_cholmodCommon))) + { + std::cerr << "SuiteSparseQR_factorize failed" << std::endl; + cholmod_l_print_common("CholmodCommon A", mp_cholmodCommon); + return false; + } + + if(show_timings_) + { + std::cerr << " SuiteSparseQR_numeric Timing: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + return true; +} + + + //----------------------------------------------------------------------------- + + +bool SparseQRSolver::update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ) +{ + if( !mp_F ) + 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 = 0; + matA.itype = CHOLMOD_LONG; + matA.xtype = CHOLMOD_REAL; + matA.dtype = CHOLMOD_DOUBLE; + matA.sorted = 1; + matA.packed = 1; + + + if( !(mp_F = SuiteSparseQR_symbolic(ordering_, int(tolerance_==0.0), &matA, mp_cholmodCommon))) + { + std::cout << "SuiteSparseQR_symbolic failed" << std::endl; + return false; + } + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool SparseQRSolver::solve( double * _x, double * _b) +{ + const unsigned int n = colptr_.size() - 1; + + cholmod_dense *x, *Qtb, 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; + + // mult by Q^t + if( !(Qtb = SuiteSparseQR_qmult(0,mp_F, &b, mp_cholmodCommon))) + { + std::cout << "sparseqr_solve failed" << std::endl; + return false; + } + + // solve triangular system and permute + if( !(x = SuiteSparseQR_solve( 1, mp_F, Qtb, mp_cholmodCommon )) ) + { + std::cout << "sparseqr_solve failed" << std::endl; + return false; + } + + for( unsigned int i = 0; i < n; ++i ) + _x[i] = ((double*)x->x)[i]; + + cholmod_l_free_dense( &Qtb, mp_cholmodCommon ); + cholmod_l_free_dense( &x, mp_cholmodCommon ); + + return true; +} + + +//----------------------------------------------------------------------------- + + + +} + +//== BUILD-TIME DEPENDENCIES ================================================== +#endif +//============================================================================= diff --git a/src/external/CoMISo/Solver/SparseQRSolver.hh b/src/external/CoMISo/Solver/SparseQRSolver.hh new file mode 100644 index 000000000..768b92892 --- /dev/null +++ b/src/external/CoMISo/Solver/SparseQRSolver.hh @@ -0,0 +1,173 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS CholmodSolver +// +//============================================================================= + +#ifndef COMISO_SPARSE_QR_SOLVER_HH +#define COMISO_SPARSE_QR_SOLVER_HH + + +//== INCLUDES ================================================================= + + +#include +#include +#include "GMM_Tools.hh" + +#include + +#include +#include + + +//== BUILD-TIME DEPENDENCIES ================================================================= +#if(COMISO_SUITESPARSE_SPQR_AVAILABLE) +//============================================================================================ + +#include "SuiteSparseQR.hpp" +#include "cholmod.h" + + +//typedef struct cholmod_common_struct cholmod_common; + +//== NAMESPACES =============================================================== + +namespace COMISO { + +typedef struct SuiteSparseQR_factorization sparseqr_factor; + + +//== CLASS DEFINITION ========================================================= +class COMISODLLEXPORT SparseQRSolver +{ +public: + + typedef UF_long Int; + + + SparseQRSolver(); + ~SparseQRSolver(); + + bool calc_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ); + + + template< class GMM_MatrixT> + bool calc_system_gmm( const GMM_MatrixT& _mat); + + + template< class GMM_MatrixT> + bool update_system_gmm( const GMM_MatrixT& _mat); + + template< class Eigen_MatrixT> + bool calc_system_eigen( const Eigen_MatrixT& _mat); + + + template< class Eigen_MatrixT> + bool update_system_eigen( const Eigen_MatrixT& _mat); + + bool update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ); + + + + bool solve ( double * _x0, double * _b); + + bool solve ( std::vector& _x0, const std::vector& _b) + {return solve( &(_x0[0]), (double*)&(_b[0]));} + + double tolerance() { return tolerance_; } + + int ordering() { return ordering_; } + + bool& show_timings() { return show_timings_;} + + // factorize _A*P = _Q*_R and return rank + template< class GMM_MatrixT, class GMM_MatrixT2, class GMM_MatrixT3, class IntT> + int factorize_system_gmm( const GMM_MatrixT& _A, GMM_MatrixT2& _Q, GMM_MatrixT3& _R, std::vector& _P); + + // factorize _A*P = _Q*_R and return rank + template< class Eigen_MatrixT, class IntT > + int factorize_system_eigen( const Eigen_MatrixT& _A, Eigen_MatrixT& _Q, Eigen_MatrixT& _R, std::vector& _P); + + // Solve Ax=b, not the most efficient as it uses SparseMatrices also for _b and _x + template< class Eigen_MatrixT> + void solve_system_eigen( const Eigen_MatrixT& _A, const Eigen_MatrixT& _b, Eigen_MatrixT& _x); + + // Solve Ax=b, min( ||x||_2) not the most efficient as it uses SparseMatrices also for _b and _x + template< class Eigen_MatrixT> + void solve_system_eigen_min2norm( const Eigen_MatrixT& _A, const Eigen_MatrixT& _b, Eigen_MatrixT& _x); + + +private: + + cholmod_common * mp_cholmodCommon; + + sparseqr_factor * mp_F; + + double tolerance_; + + // specify Permutation ordering + // 1. user-provided permutation (only for cholmod analyze p). + // 2. AMD with default parameters. + // 3. METIS with default parameters. + // 4. NESDIS with default parameters + // 5. natural ordering (with weighted postorder). + // 6. NESDIS, nd small = 20000, prune dense = 10. + // 7. NESDIS, nd small = 4, prune dense = 10, no constrained minimum degree. + // 8. NESDIS, nd small = 200, prune dense = 0. + // 9. COLAMD for A*A^T or AMD for A + int ordering_; + + // dimension of the mxn matrix + int m_; + int n_; + + std::vector values_; + std::vector colptr_; + std::vector rowind_; + + bool show_timings_; + StopWatch sw_; +}; + +//============================================================================= +} // namespace COMISO +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_SPARSE_QR_SOLVER_TEMPLATES_C) +#define COMISO_SPARSE_QR_SOLVER_TEMPLATES +#include "SparseQRSolverT.cc" +#endif +//== BUILD-TIME DEPENDENCIES ================================================== +#endif +//============================================================================= +#endif // COMISO_SPARSE_QR_SOLVER_HH defined +//============================================================================= diff --git a/src/external/CoMISo/Solver/SparseQRSolverT.cc b/src/external/CoMISo/Solver/SparseQRSolverT.cc new file mode 100644 index 000000000..e74f2632a --- /dev/null +++ b/src/external/CoMISo/Solver/SparseQRSolverT.cc @@ -0,0 +1,368 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + + +#define COMISO_SPARSE_QR_SOLVER_TEMPLATES_C + +#include "SparseQRSolver.hh" +#include + + +namespace COMISO { + + +template< class GMM_MatrixT> +bool SparseQRSolver::calc_system_gmm( const GMM_MatrixT& _mat) +{ +// std::vector colptr; +// std::vector rowind; +// std::vector values; + + + if(show_timings_) sw_.start(); + + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'c', + values_, + rowind_, + colptr_ ); + + if(show_timings_) + { + std::cerr << "SparseQRSolver Timing GMM convert: " << sw_.stop()/1000.0 << "s\n"; + } + + return calc_system( colptr_, rowind_, values_); +} + + +//----------------------------------------------------------------------------- + + +template< class GMM_MatrixT> +bool SparseQRSolver::update_system_gmm( const GMM_MatrixT& _mat) +{ +// std::vector colptr; +// std::vector rowind; +// std::vector values; + + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'c', + values_, + rowind_, + colptr_ ); + + return update_system( colptr_, rowind_, values_); +} + + +//----------------------------------------------------------------------------- + +template< class Eigen_MatrixT> +bool SparseQRSolver::calc_system_eigen( const Eigen_MatrixT& _mat) +{ + if(show_timings_) sw_.start(); + + COMISO_EIGEN::get_ccs_symmetric_data( _mat, + 'c', + values_, + rowind_, + colptr_ ); + + if(show_timings_) + { + std::cerr << "SparseQRSolver Timing EIGEN convert: " << sw_.stop()/1000.0 << "s\n"; + } + + return calc_system( colptr_, rowind_, values_); +} + +//----------------------------------------------------------------------------- + +template< class Eigen_MatrixT> +bool SparseQRSolver::update_system_eigen( const Eigen_MatrixT& _mat) +{ + + COMISO_EIGEN::get_ccs_symmetric_data( _mat, + 'c', + values_, + rowind_, + colptr_ ); + + return update_system( colptr_, rowind_, values_); +} + + +//----------------------------------------------------------------------------- + + +template< class GMM_MatrixT, class GMM_MatrixT2, class GMM_MatrixT3, class IntT> +int +SparseQRSolver:: +factorize_system_gmm( const GMM_MatrixT& _A, GMM_MatrixT2& _Q, GMM_MatrixT3& _R, std::vector& _P) +{ + std::cerr << "factorize_system_gmm" << std::endl; + // get dimensions + int m = gmm::mat_nrows(_A); + int n = gmm::mat_ncols(_A); + + // 1. _A -> cholmod_sparse A + cholmod_sparse* AC(0); + COMISO_GMM::gmm_to_cholmod(_A, AC, mp_cholmodCommon, 0, true); + std::cerr << "gmm_to_cholmod finished" << std::endl; + cholmod_print_sparse(AC, "AC", mp_cholmodCommon); + + // 2. factorize A -> Q,R,P + UF_long econ = m; + cholmod_sparse *Q, *R; +// UF_long *P = new UF_long[n]; + UF_long *P; + double rank = SuiteSparseQR(ordering_, tolerance_, econ, AC, &Q, &R, &P, mp_cholmodCommon); + std::cerr << "factorization finished" << std::endl; + std::cerr << "rank: " << rank << std::endl; + cholmod_print_sparse(Q, "Q", mp_cholmodCommon); + + // 3. convert Q,R,P -> _Q, _R, _P + COMISO_GMM::cholmod_to_gmm(*Q, _Q); + COMISO_GMM::cholmod_to_gmm(*R, _R); + std::cerr << "cholmod_to_gmm finished" << std::endl; + + _P.clear(); _P.resize(n); + for( int i=0; i UF_long SuiteSparseQR // returns rank(A) estimate +//( +// int ordering, // all, except 3:given treated as 0:fixed +// double tol, +// UF_long econ, +// cholmod_sparse *A, // m-by-n sparse matrix +// // outputs +// cholmod_sparse **Q, // m-by-e sparse matrix where e=max(econ,rank(A)) +// cholmod_sparse **R, // e-by-n sparse matrix +// UF_long **E, // permutation of 0:n-1, NULL if identity +// cholmod_common *cc // workspace and parameters +//) ; + + std::cerr << " ############## QR Factorization Info #############\n"; + std::cerr << " m: " << m << ", n: " << n << ", rank: " << rank << std::endl; + + return rank; +} + + +//----------------------------------------------------------------------------- + + +template< class Eigen_MatrixT, class IntT > +int +SparseQRSolver:: +factorize_system_eigen( const Eigen_MatrixT& _A, Eigen_MatrixT& _Q, Eigen_MatrixT& _R, std::vector& _P) +{ + std::cerr << "factorize_system_eigen" << std::endl; + // get dimensions + int m = _A.innerSize(); + int n = _A.outerSize(); + std::cerr << " m " << m << " n " << n << std::endl; + + // 1. _A -> cholmod_sparse A + cholmod_sparse* AC(0); + COMISO_EIGEN::eigen_to_cholmod(_A, AC, mp_cholmodCommon, 0, true); + //COMISO_GMM::gmm_to_cholmod(_A, AC, mp_cholmodCommon, 0, true); + std::cerr << "eigen_to_cholmod finished" << std::endl; + cholmod_print_sparse(AC, "AC", mp_cholmodCommon); + + // 2. factorize A -> Q,R,P + UF_long econ = m; + cholmod_sparse *Q, *R; +// UF_long *P = new UF_long[n]; + UF_long *P; + double rank = SuiteSparseQR(ordering_, tolerance_, econ, AC, &Q, &R, &P, mp_cholmodCommon); + std::cerr << "factorization finished" << std::endl; + std::cerr << "rank: " << rank << std::endl; + cholmod_print_sparse(Q, "Q", mp_cholmodCommon); + + // 3. convert Q,R,P -> _Q, _R, _P + COMISO_EIGEN::cholmod_to_eigen(*Q, _Q); + COMISO_EIGEN::cholmod_to_eigen(*R, _R); + std::cerr << "cholmod_to_eigen finished" << std::endl; + + _P.clear(); _P.resize(n); + for( int i=0; i UF_long SuiteSparseQR // returns rank(A) estimate +//( +// int ordering, // all, except 3:given treated as 0:fixed +// double tol, +// UF_long econ, +// cholmod_sparse *A, // m-by-n sparse matrix +// // outputs +// cholmod_sparse **Q, // m-by-e sparse matrix where e=max(econ,rank(A)) +// cholmod_sparse **R, // e-by-n sparse matrix +// UF_long **E, // permutation of 0:n-1, NULL if identity +// cholmod_common *cc // workspace and parameters +//) ; + + std::cerr << " ############## QR Factorization Info #############\n"; + std::cerr << " m: " << m << ", n: " << n << ", rank: " << rank << std::endl; + + return rank; +} + + +//----------------------------------------------------------------------------- + + +template< class Eigen_MatrixT > +void +SparseQRSolver:: +solve_system_eigen( const Eigen_MatrixT& _A, const Eigen_MatrixT& _b, Eigen_MatrixT& _x) +{ + std::cerr << __FUNCTION__ << std::endl; + + // 1. _A -> cholmod_sparse A, x, b + cholmod_sparse* AC(0); + COMISO_EIGEN::eigen_to_cholmod(_A, AC, mp_cholmodCommon, 0, true); + cholmod_print_sparse(AC, "AC", mp_cholmodCommon); + + cholmod_sparse* bC(0); + COMISO_EIGEN::eigen_to_cholmod(_b, bC, mp_cholmodCommon, 0, true); + cholmod_print_sparse(AC, "bC", mp_cholmodCommon); + + cholmod_sparse* xC(0); + // allocation of X done internally + //COMISO_EIGEN::eigen_to_cholmod_sparse(_x, xC, mp_cholmodCommon, 0, true); + //cholmod_print_sparse(AC, "xC", mp_cholmodCommon); + + + // 2. solve Ax=b + xC = SuiteSparseQR(ordering_, tolerance_, AC, bC, mp_cholmodCommon); + + std::cerr << "solve finished" << std::endl; + cholmod_print_sparse(xC, "xC", mp_cholmodCommon); + + // 3. convert solution xC to eigen + COMISO_EIGEN::cholmod_to_eigen(*xC, _x); + std::cerr << "cholmod_to_eigen finished" << std::endl; + + cholmod_l_free_sparse(&AC, mp_cholmodCommon); + cholmod_l_free_sparse(&bC, mp_cholmodCommon); + cholmod_l_free_sparse(&xC, mp_cholmodCommon); + std::cerr << "free1 finished" << std::endl; + + + +//// X = A\sparse(B) +//template cholmod_sparse *SuiteSparseQR +//( +// int ordering, // all, except 3:given treated as 0:fixed +// double tol, +// cholmod_sparse *A, // m-by-n sparse matrix +// cholmod_sparse *B, // m-by-nrhs +// cholmod_common *cc // workspace and parameters +//) ; +} + + +//----------------------------------------------------------------------------- + + +template< class Eigen_MatrixT > +void +SparseQRSolver:: +solve_system_eigen_min2norm( const Eigen_MatrixT& _A, const Eigen_MatrixT& _b, Eigen_MatrixT& _x) +{ + std::cerr << __FUNCTION__ << std::endl; + + // 1. _A -> cholmod_sparse A, x, b + cholmod_sparse* AC(0); + COMISO_EIGEN::eigen_to_cholmod(_A, AC, mp_cholmodCommon, 0, true); + //cholmod_print_sparse(AC, "AC", mp_cholmodCommon); + + cholmod_sparse* bC(0); + COMISO_EIGEN::eigen_to_cholmod(_b, bC, mp_cholmodCommon, 0, true); + //cholmod_print_sparse(AC, "bC", mp_cholmodCommon); + + cholmod_sparse* xC(0); + // allocation of X done internally + //COMISO_EIGEN::eigen_to_cholmod_sparse(_x, xC, mp_cholmodCommon, 0, true); + //cholmod_print_sparse(AC, "xC", mp_cholmodCommon); + + + // 2. solve Ax=b + xC = SuiteSparseQR_min2norm(ordering_, tolerance_, AC, bC, mp_cholmodCommon); + + //std::cerr << "solve finished" << std::endl; + //cholmod_print_sparse(xC, "xC", mp_cholmodCommon); + + // 3. convert solution xC to eigen + COMISO_EIGEN::cholmod_to_eigen(*xC, _x); + //std::cerr << "cholmod_to_eigen finished" << std::endl; + + cholmod_l_free_sparse(&AC, mp_cholmodCommon); + cholmod_l_free_sparse(&bC, mp_cholmodCommon); + cholmod_l_free_sparse(&xC, mp_cholmodCommon); + //std::cerr << "free1 finished" << std::endl; + + + +//template cholmod_sparse *SuiteSparseQR_min2norm +//( +// int ordering, // all, except 3:given treated as 0:fixed +// double tol, +// cholmod_sparse *A, +// cholmod_sparse *B, +// cholmod_common *cc +//) ; + +} + + + +} diff --git a/src/external/CoMISo/Solver/TaucsSolver.cc b/src/external/CoMISo/Solver/TaucsSolver.cc new file mode 100644 index 000000000..1d618c04a --- /dev/null +++ b/src/external/CoMISo/Solver/TaucsSolver.cc @@ -0,0 +1,269 @@ +#include "TaucsSolver.hh" + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_TAUCS_AVAILABLE + +namespace COMISO { + +TaucsSolver::TaucsSolver(int _size, bool _write_log) + : PAP_(0), + LSN_(0), + perm_(0), + invperm_(0), + px_(0), + pb_(0) + { + if (_write_log) + taucs_logfile((char*) "taucs.log"); + resize( _size); + } + + + //----------------------------------------------------------------------------- + + +TaucsSolver::~TaucsSolver() + { + // free matrices + if(LSN_) + { + taucs_supernodal_factor_free_numeric(LSN_); + taucs_supernodal_factor_free( LSN_); + } + + if(perm_) delete [] perm_; + if(invperm_) delete [] invperm_; + if(px_) delete [] px_; + if(pb_) delete [] pb_; + + } + + +//----------------------------------------------------------------------------- + + +void TaucsSolver::calc_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values) + { + colptr_ = _colptr; + rowind_ = _rowind; + values_ = _values; + + calc_system(); + } + +//----------------------------------------------------------------------------- + + +void TaucsSolver::calc_system() + { + int n = colptr_.size()-1; + + // free matrices + // if(PAP_) taucs_ccs_free(PAP_); + if(LSN_) + { + taucs_supernodal_factor_free_numeric(LSN_); + taucs_supernodal_factor_free( LSN_); + } + + mat_.n = n; + mat_.m = mat_.n; + mat_.flags = TAUCS_DOUBLE | TAUCS_SYMMETRIC | TAUCS_LOWER; + + mat_.colptr = &colptr_[0]; + mat_.rowind = &rowind_[0]; + mat_.values.d = &values_[0]; + + // calc permutation + taucs_ccs_order(&mat_, &perm_, &invperm_, (char*)"metis"); + + // permute Matrix + PAP_ = taucs_ccs_permute_symmetrically(&mat_, perm_, invperm_); + + // factor symbolic + LSN_ = taucs_ccs_factor_llt_symbolic( PAP_); + + // factor numeric + taucs_ccs_factor_llt_numeric(PAP_,LSN_); + + // free permuted matrix + taucs_ccs_free(PAP_); + } + + + //----------------------------------------------------------------------------- + + +void TaucsSolver::update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values) + { + colptr_ = _colptr; + rowind_ = _rowind; + values_ = _values; + + update_system(); + } + + + //----------------------------------------------------------------------------- + + +void TaucsSolver::update_system() + { + int n = colptr_.size()-1; + + mat_.n = n; + mat_.m = mat_.n; + mat_.flags = TAUCS_DOUBLE | TAUCS_SYMMETRIC | TAUCS_LOWER; + + mat_.colptr = &colptr_[0]; + mat_.rowind = &rowind_[0]; + mat_.values.d = &values_[0]; + + // free numeric part of matrix + if(LSN_){taucs_supernodal_factor_free_numeric(LSN_);} + + // permute Matrix + PAP_ = taucs_ccs_permute_symmetrically(&mat_, perm_, invperm_); + + // factor numeric + taucs_ccs_factor_llt_numeric(PAP_,LSN_); + + // free permuted matrix + taucs_ccs_free(PAP_); + } + + + //----------------------------------------------------------------------------- + + + void TaucsSolver::solve( double * _x, double * _b) + { + // solve x coords + taucs_vec_permute(mat_.n, mat_.flags, _b, pb_, perm_); + taucs_supernodal_solve_llt(LSN_, px_, pb_); + taucs_vec_ipermute(mat_.n, mat_.flags, px_, _x, perm_); + } + + + //----------------------------------------------------------------------------- + + + void TaucsSolver::solve_cg( double* _x0, double* _b, int _maxiter, double _max_error, bool /*_precond*/) + { +// // preconditioner +// taucs_ccs_matrix *M; +// M = taucs_ccs_factor_llt(&mat_, 1E-1, 1); + +// // solve system +// taucs_conjugate_gradients( &mat_, taucs_ccs_solve_llt, M, _x0, _b, _maxiter, _max_error ); + + // solve system + taucs_conjugate_gradients( &mat_, 0, 0, _x0, _b, _maxiter, _max_error ); + } + + + //----------------------------------------------------------------------------- + + + void TaucsSolver::eliminate_var( int _i, double _xi, double* _x, double* _rhs) + { + int n = colptr_.size()-1; + + int iv_old(0); + int iv_new(0); + + // for all columns + for(int j=0; j<(int)colptr_.size()-1; ++j) + { + // update x and rhs + if( j > _i) + { + _rhs[j-1] = _rhs[j]; + _x [j-1] = _x [j]; + } + + if( j == _i) + { + // update rhs + for(int i=colptr_[j]; i _i) + { + rowind_[iv_new] = rowind_[iv_old]-1; + values_[iv_new] = values_[iv_old]; + ++iv_new; + } + else + { + if( j< _i) + _rhs[j] -= _xi*values_[iv_old]; + else + _rhs[j-1] -= _xi*values_[iv_old]; + + } + ++iv_old; + } + + if( j<_i) + colptr_[j] = iv_new_save; + else + if( j>_i) + colptr_[j-1] = iv_new_save; + } + } + + // store index to end + colptr_[colptr_.size()-2] = iv_new; + // resize vectors + colptr_.resize( colptr_.size()-1); + values_.resize( iv_new); + rowind_.resize( iv_new); + + mat_.n = n-1; + mat_.m = n-1; + } + + + //----------------------------------------------------------------------------- + + + void TaucsSolver::resize( int _size) + { + if(perm_) delete [] perm_; + if(invperm_) delete [] invperm_; + if(px_) delete [] px_; + if(pb_) delete [] pb_; + + perm_ = new int[_size]; + invperm_ = new int[_size]; + px_ = new double[_size]; + pb_ = new double[_size]; + } + + +} + +//============================================================================= +#endif // COMISO_TAUCS_AVAILABLE \ No newline at end of file diff --git a/src/external/CoMISo/Solver/TaucsSolver.hh b/src/external/CoMISo/Solver/TaucsSolver.hh new file mode 100644 index 000000000..51591128a --- /dev/null +++ b/src/external/CoMISo/Solver/TaucsSolver.hh @@ -0,0 +1,123 @@ +//============================================================================= +// +// CLASS TaucsSolver +// +// Author: David Bommes +// +// Version: $Revision: 1$ +// Date: $Date: 02-04-200X$ +// +//============================================================================= + +#ifndef COMISO_TAUCS_SOLVER_HH +#define COMISO_TAUCS_SOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_TAUCS_AVAILABLE + +//== INCLUDES ================================================================= +#include + +#include "GMM_Tools.hh" +#include +#include + +#ifdef WIN32 + extern "C" + { + #include + } + #undef min + #undef max +#else + #include +#endif + + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= +class COMISODLLEXPORT TaucsSolver + { + public: + + // _size is maximal size this instance can handle (smaller problems are possible!!!) + TaucsSolver(int _size, bool _write_log = false); + ~TaucsSolver(); + + void calc_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ); + + + template< class GMM_MatrixT> + void calc_system_gmm( const GMM_MatrixT& _mat); + + + void update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ); + + + template< class GMM_MatrixT> + void update_system_gmm( const GMM_MatrixT& _mat); + + + void solve( std::vector& _x0, std::vector& _b) { solve( &(_x0[0]), &(_b[0])); } + void solve( double* _x0, double* _b); + + void resize ( int _size); + + // CG support + + template< class GMM_MatrixT> + void init_system_gmm( const GMM_MatrixT& _mat); + + void solve_cg( std::vector& _x0, std::vector& _b, int _maxiter = 50, double _max_error=1e-6, bool _precond=true) { solve_cg( &(_x0[0]), &(_b[0]), _maxiter, _max_error, _precond); } + void solve_cg( double* _x0, double* _b, int _maxiter = 50, double _max_error=1e-6, bool _precond=true); + + void eliminate_var( int _i, double _xi, std::vector& _x, std::vector& _rhs) {eliminate_var(_i, _xi, &(_x[0]), &(_rhs[0])); _rhs.resize(_rhs.size()-1); _x.resize(_x.size()-1);} + void eliminate_var( int _i, double _xi, double* _x, double* _rhs); + + template< class GMM_MatrixT> + void get_matrix_gmm( GMM_MatrixT& _mat); + + + void calc_system(); + void update_system(); + + private: + + taucs_ccs_matrix mat_; + taucs_ccs_matrix *PAP_; + + void *LSN_; + + int *perm_; + int *invperm_; + + double *px_; + double *pb_; + + + std::vector values_; + std::vector rowind_; + std::vector colptr_; + }; + +//============================================================================= +} // namespace COMISO +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_TAUCS_SOLVER_TEMPLATES_C) +#define COMISO_TAUCS_SOLVER_TEMPLATES +#include "TaucsSolverT.cc" +#endif +//============================================================================= +#endif // COMISO_TAUCS_AVAILABLE +//============================================================================= +#endif // COMISO_TAUCS_SOLVER_HH defined +//============================================================================= diff --git a/src/external/CoMISo/Solver/TaucsSolverT.cc b/src/external/CoMISo/Solver/TaucsSolverT.cc new file mode 100644 index 000000000..9684259df --- /dev/null +++ b/src/external/CoMISo/Solver/TaucsSolverT.cc @@ -0,0 +1,93 @@ +#define COMISO_TAUCS_SOLVER_TEMPLATES_C + +#include "TaucsSolver.hh" + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_TAUCS_AVAILABLE + +namespace COMISO { + + +template< class GMM_MatrixT> +void TaucsSolver::calc_system_gmm( const GMM_MatrixT& _mat) + { + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'l', + values_, + rowind_, + colptr_ ); + + calc_system(); + } + + + //----------------------------------------------------------------------------- + + +template< class GMM_MatrixT> +void TaucsSolver::update_system_gmm( const GMM_MatrixT& _mat) + { + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'l', + values_, + rowind_, + colptr_ ); + + update_system(); + } + + + + //----------------------------------------------------------------------------- + + +template< class GMM_MatrixT> +void TaucsSolver::init_system_gmm( const GMM_MatrixT& _mat) + { + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'l', + values_, + rowind_, + colptr_ ); + int n = colptr_.size()-1; + + mat_.n = n; + mat_.m = n; + mat_.flags = TAUCS_DOUBLE | TAUCS_SYMMETRIC | TAUCS_LOWER; + + mat_.colptr = &(colptr_[0]); + mat_.rowind = &(rowind_[0]); + mat_.values.d = &(values_[0]); + + } + + +//----------------------------------------------------------------------------- + +template< class GMM_MatrixT> +void TaucsSolver::get_matrix_gmm( GMM_MatrixT& _mat) + { + gmm::resize( _mat, mat_.n, mat_.n); + gmm::clear( _mat); + + // for all columns + for(int j=0; j<(int)colptr_.size()-1; ++j) + { + // for all lower triangular values + for(int i=colptr_[j]; i. * + * * +\*===========================================================================*/ + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_SUITESPARSE_AVAILABLE + +#include "UMFPACKSolver.hh" + + +namespace COMISO { + +UMFPACKSolver::UMFPACKSolver() +{ + // initialize zero pointers + symbolic_ = 0; + numeric_ = 0; + + tolerance_ = 1e-8; + + // ordering_ = CHOLMOD_AMD; + + show_timings_ = false; +} + + + //----------------------------------------------------------------------------- + + +UMFPACKSolver::~UMFPACKSolver() +{ + if( symbolic_ ) + { + umfpack_di_free_symbolic( &symbolic_); + symbolic_ = 0; + } + + if( numeric_ ) + { + umfpack_di_free_numeric( &numeric_); + numeric_ = 0; + } +} + + +//----------------------------------------------------------------------------- + + +bool UMFPACKSolver::calc_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values) +{ + if(show_timings_) sw_.start(); + + colptr_ = _colptr; + rowind_ = _rowind; + values_ = _values; + + int n = colptr_.size()-1; + + // clean up + if( symbolic_ ) + { + umfpack_di_free_symbolic( &symbolic_); + symbolic_ = 0; + } + if( numeric_ ) + { + umfpack_di_free_numeric( &numeric_); + numeric_ = 0; + } + + if(show_timings_) + { + std::cerr << " UMFPACK Timing cleanup: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + int status; + + // symbolic factorization + status = umfpack_di_symbolic(n,n,&(colptr_[0]), &(rowind_[0]), &(values_[0]), &symbolic_, 0, 0); + + if( status != UMFPACK_OK ) + { + std::cout << "UMFPACK_symbolic failed" << std::endl; + print_error( status); + return false; + } + + if(show_timings_) + { + std::cerr << " SuiteSparseQR_symbolic Timing: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + // numeric factorization + status = umfpack_di_numeric ( &(colptr_[0]), &(rowind_[0]), &(values_[0]), symbolic_, &numeric_, 0, 0); + + if( status != UMFPACK_OK ) + { + std::cout << "UMFPACK_numeric failed" << std::endl; + print_error( status); + return false; + } + + if(show_timings_) + { + std::cerr << " SuiteSparseQR_numeric Timing: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + return true; +} + + + + //----------------------------------------------------------------------------- + + +void UMFPACKSolver::print_error( int _status ) +{ + switch(_status) + { + case UMFPACK_OK : std::cerr << "UMFPACK Error: UMFPACK_OK\n"; + case UMFPACK_ERROR_n_nonpositive : std::cerr << "UMFPACK Error: UMFPACK_ERROR_n_nonpositive\n"; + case UMFPACK_ERROR_invalid_matrix : std::cerr << "UMFPACK Error: UMFPACK_ERROR_invalid_matrix\n"; + case UMFPACK_ERROR_out_of_memory : std::cerr << "UMFPACK Error: UMFPACK_ERROR_out_of_memory\n"; + case UMFPACK_ERROR_argument_missing: std::cerr << "UMFPACK Error: UMFPACK_ERROR_argument_missing\n"; + case UMFPACK_ERROR_internal_error : std::cerr << "UMFPACK Error: UMFPACK_ERROR_internal_error\n"; + default: std::cerr << "UMFPACK Error: UNSPECIFIED ERROR\n"; + } +} + + //----------------------------------------------------------------------------- + + +bool UMFPACKSolver::update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ) +{ + if( !symbolic_ ) + return false; + + + if(show_timings_) sw_.start(); + + colptr_ = _colptr; + rowind_ = _rowind; + values_ = _values; + + if( numeric_ ) + { + umfpack_di_free_numeric( &numeric_); + numeric_ = 0; + } + + if(show_timings_) + { + std::cerr << " UMFPACK Timing cleanup: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + int status; + + // numeric factorization + status = umfpack_di_numeric ( &(colptr_[0]), &(rowind_[0]), &(values_[0]), symbolic_, &numeric_, 0, 0); + + if( status != UMFPACK_OK ) + { + std::cout << "UMFPACK_numeric failed" << std::endl; + print_error( status); + return false; + } + + if(show_timings_) + { + std::cerr << " SuiteSparseQR_numeric Timing: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + return true; +} + + +//----------------------------------------------------------------------------- + + +bool UMFPACKSolver::solve( double * _x, double * _b) +{ + if(show_timings_) sw_.start(); + + // const unsigned int n = colptr_.size() - 1; + + int status = umfpack_di_solve( UMFPACK_A, &(colptr_[0]), &(rowind_[0]), &(values_[0]), + _x, _b, numeric_, 0, 0); + + + if( status != UMFPACK_OK ) + { + std::cout << "UMFPACK_solve failed" << std::endl; + print_error( status); + return false; + } + + if(show_timings_) + { + std::cerr << " UMFPACK_sove Timing: " << sw_.stop()/1000.0 << "s\n"; + sw_.start(); + } + + + return true; +} + + +//----------------------------------------------------------------------------- + + + +} + +//============================================================================= +#endif // COMISO_SUITESPARSE_AVAILABLE +//============================================================================= diff --git a/src/external/CoMISo/Solver/UMFPACKSolver.hh b/src/external/CoMISo/Solver/UMFPACKSolver.hh new file mode 100644 index 000000000..bb439612d --- /dev/null +++ b/src/external/CoMISo/Solver/UMFPACKSolver.hh @@ -0,0 +1,139 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + +//============================================================================= +// +// CLASS UMPFACKSolver +// +//============================================================================= + +#ifndef COMISO_UMFPACK_SOLVER_HH +#define COMISO_UMFPACK_SOLVER_HH + + +//== COMPILE-TIME PACKAGE REQUIREMENTS ======================================== +#include +#if COMISO_SUITESPARSE_AVAILABLE + +//== INCLUDES ================================================================= + + +#include +#include "GMM_Tools.hh" + +#include + +#include +#include + +#include "umfpack.h" + + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= +class COMISODLLEXPORT UMFPACKSolver +{ +public: + + + // _size is maximal size this instance can handle (smaller problems are possible!!!) + UMFPACKSolver(); + ~UMFPACKSolver(); + + bool calc_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ); + + + template< class GMM_MatrixT> + bool calc_system_gmm( const GMM_MatrixT& _mat); + + + bool update_system( const std::vector& _colptr, + const std::vector& _rowind, + const std::vector& _values ); + + + template< class GMM_MatrixT> + bool update_system_gmm( const GMM_MatrixT& _mat); + + + bool solve ( double * _x0, double * _b); + + bool solve ( std::vector& _x0, std::vector& _b) + {return solve( &(_x0[0]), &(_b[0]));} + + double tolerance() { return tolerance_; } + + int ordering() { return ordering_; } + + bool& show_timings() { return show_timings_;} + + + private: + void print_error( int _status ); + + private: + + void *symbolic_; + void *numeric_; + + double tolerance_; + + // specify Permutation ordering + // 1. user-provided permutation (only for cholmod analyze p). + // 2. AMD with default parameters. + // 3. METIS with default parameters. + // 4. NESDIS with default parameters + // 5. natural ordering (with weighted postorder). + // 6. NESDIS, nd small = 20000, prune dense = 10. + // 7. NESDIS, nd small = 4, prune dense = 10, no constrained minimum degree. + // 8. NESDIS, nd small = 200, prune dense = 0. + // 9. COLAMD for A*A’ or AMD for A + int ordering_; + + std::vector values_; + std::vector colptr_; + std::vector rowind_; + + bool show_timings_; + StopWatch sw_; +}; + +//============================================================================= +} // namespace COMISO +//============================================================================= +#if defined(INCLUDE_TEMPLATES) && !defined(COMISO_UMFPACK_SOLVER_TEMPLATES_C) +#define COMISO_UMFPACK_SOLVER_TEMPLATES +#include "UMFPACKSolverT.cc" +#endif +//============================================================================= +#endif // COMISO_SUITESPARSE_AVAILABLE +//============================================================================= +#endif // COMISO_UMFPACK_SOLVER_HH defined +//============================================================================= diff --git a/src/external/CoMISo/Solver/UMFPACKSolverT.cc b/src/external/CoMISo/Solver/UMFPACKSolverT.cc new file mode 100644 index 000000000..b438acae0 --- /dev/null +++ b/src/external/CoMISo/Solver/UMFPACKSolverT.cc @@ -0,0 +1,80 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + + +#define COMISO_UMFPACK_SOLVER_TEMPLATES_C + +#include "UMFPACKSolver.hh" + + +namespace COMISO { + + +template< class GMM_MatrixT> +bool UMFPACKSolver::calc_system_gmm( const GMM_MatrixT& _mat) +{ +// std::vector colptr; +// std::vector rowind; +// std::vector values; + + + if(show_timings_) sw_.start(); + + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'c', + values_, + rowind_, + colptr_ ); + + if(show_timings_) + { + std::cerr << "UMFPACK Timing GMM convert: " << sw_.stop()/1000.0 << "s\n"; + } + + return calc_system( colptr_, rowind_, values_); +} + + + //----------------------------------------------------------------------------- + + +template< class GMM_MatrixT> +bool UMFPACKSolver::update_system_gmm( const GMM_MatrixT& _mat) +{ +// std::vector colptr; +// std::vector rowind; +// std::vector values; + + COMISO_GMM::get_ccs_symmetric_data( _mat, + 'c', + values_, + rowind_, + colptr_ ); + + return update_system( colptr_, rowind_, values_); +} + + +} diff --git a/src/external/CoMISo/Utils/MutablePriorityQueueT.hh b/src/external/CoMISo/Utils/MutablePriorityQueueT.hh new file mode 100644 index 000000000..64894e0a2 --- /dev/null +++ b/src/external/CoMISo/Utils/MutablePriorityQueueT.hh @@ -0,0 +1,133 @@ +//============================================================================= +// +// CLASS MutablePriorityQueue +// +//============================================================================= + + +#ifndef COMISO_MUTABLEPRIORITYQUEUET_HH +#define COMISO_MUTABLEPRIORITYQUEUET_HH + + +//== INCLUDES ================================================================= + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +namespace COMISO { + +//== CLASS DEFINITION ========================================================= + + + +/** \class MutablePriorityQueue MutablePriorityQueue.hh + + Brief Description. + + A more elaborate description follows. +*/ + + +// Helper Class for sorting triples +template +class Triple +{ +public: + + // default constructor + Triple() {} + Triple(const A& _a, const B& _b, const C& _c) : first(_a), second(_b), third(_c) {} + + bool operator<(const Triple& _t) const + { return ( this->first < _t.first || + (this->first == _t.first && ( this->second < _t.second || + ( this->second == _t.second && this->third < _t.third))));} + + void print_info() + { std::cerr << first << " " << second << " " << third << std::endl; } + + A first; + B second; + C third; +}; + +template +class MutablePriorityQueueT +{ +public: + + + typedef Triple TripleVII; + + /// Default constructor + MutablePriorityQueueT() {} + + /// Destructor + ~MutablePriorityQueueT() {} + + // reset timestamps + void clear(int _n) + { + timestamp_.clear(); + timestamp_.resize(_n,0); + } + + // update value of index _id + void update(const IType& _id, const VType& _value) + { + queue_.insert( TripleVII(_value,_id, ++timestamp_[_id])); + } + + // get index of next element4 + IType get_next() + { + while(!queue_.empty()) + { + // get and delete first element + TripleVII tri = *queue_.begin(); + queue_.erase(queue_.begin()); + + // if valid -> return + if( timestamp_[tri.second] == tri.third) + return tri.second; + } + + // if empty return dummy + return IType(0); + } + + + // priority queue empty? + bool empty() + { + while(!queue_.empty()) + { + // get and delete first element + TripleVII tri = *queue_.begin(); + + // if valid -> return true + if( timestamp_[tri.second] == tri.third) + return false; + + queue_.erase(queue_.begin()); + } + return true; + } + +private: + + // timestamps + std::vector timestamp_; + + // priority queue + std::set queue_; +}; + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#endif // COMISO_MUTABLEPRIORITYQUEUET_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/Utils/SmartPointer.hh b/src/external/CoMISo/Utils/SmartPointer.hh new file mode 100644 index 000000000..24c4964ce --- /dev/null +++ b/src/external/CoMISo/Utils/SmartPointer.hh @@ -0,0 +1,52 @@ +#ifndef SMARTPOINTER_HH +#define SMARTPOINTER_HH + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +//== DEFINITION ========================================================= + +/** This set of defines maps the pointer namespaces to the namespace ptr depending on + * the current architecture and compilers. + */ +#if (__cplusplus >= 201103L) + // C++11: + #include + namespace ptr = std; + #define ACG_UNIQUE_POINTER_SUPPORTED 1 +#elif defined(__GXX_EXPERIMENTAL_CXX0X__) + // C++11 via -std=c++0x on gcc: + #include + namespace ptr = std; + #define ACG_UNIQUE_POINTER_SUPPORTED 1 +#else + // C++98 and TR1: + #if (_MSC_VER >= 1600) + // VStudio 2010 supports some C++11 features + #include + namespace ptr = std; + #define ACG_UNIQUE_POINTER_SUPPORTED 1 + #elif (_MSC_VER >= 1500) + // hope for TR1 equivalents + #if(_HAS_TR1) + #include + namespace ptr = std::tr1; + #define ACG_UNIQUE_POINTER_SUPPORTED 0 + #else + #pragma warning "TR1 not available! Please install Visual Studio Service Pack 1!" + #endif + #else + // hope for TR1 equivalents + #include + namespace ptr = std::tr1; + #define ACG_UNIQUE_POINTER_SUPPORTED 0 + #endif +#endif + + +//============================================================================= +#endif // SMARTPOINTER_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/Utils/StopWatch.hh b/src/external/CoMISo/Utils/StopWatch.hh new file mode 100644 index 000000000..6444c5191 --- /dev/null +++ b/src/external/CoMISo/Utils/StopWatch.hh @@ -0,0 +1,164 @@ +//============================================================================= +// +// OpenFlipper +// Copyright (C) 2008 by Computer Graphics Group, RWTH Aachen +// www.openflipper.org +// +//----------------------------------------------------------------------------- +// +// License +// +// OpenFlipper is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// OpenFlipper 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 Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with OpenFlipper. If not, see . +// +//----------------------------------------------------------------------------- +// +// $Revision: 3468 $ +// $Author: moebius $ +// $Date: 2008-10-17 14:58:52 +0200 (Fri, 17 Oct 2008) $ +// +//============================================================================= + + + + +//============================================================================= +// +// CLASS StopWatch +// +//============================================================================= + + +#ifndef COMISO_STOPWATCH_HH +#define COMISO_STOPWATCH_HH + + +//== INCLUDES ================================================================= + + +#ifdef _WIN32 + +#include + +#else // Linux + +#include + +#endif + +#include + + +//== NAMESPACES =============================================================== + + +namespace COMISO { + + +//== CLASS DEFINITION ========================================================= + + + +/** \class StopWatch StopWatch.hh + + This class can be used for measuring time, providing milli-second + precision by using the gettimeofday() funtion. It is e.g. used in + the class COMISO::TimedTracing. +**/ + +class COMISODLLEXPORT StopWatch +{ +public: + + /// Constructor + StopWatch() { + #ifdef _WIN32 + QueryPerformanceFrequency(&freq_); + #else + starttime_.tv_sec = starttime_.tv_usec = 0; + endtime_.tv_sec = endtime_.tv_usec = 0; + #endif + } + + /// Destructor + ~StopWatch() {} + + /// Start time measurement + void start() { + #ifdef _WIN32 + QueryPerformanceCounter(&starttime_); + #else + starttime_ = current_time(); + #endif + } + + /// Restart, return time elapsed until now. + double restart() { + #ifdef _WIN32 + QueryPerformanceCounter(&endtime_); + #else + endtime_ = current_time(); + #endif + + double t = elapsed(); + start(); + return t; + } + + /// Stop time measurement, return time. + double stop() { + #ifdef _WIN32 + QueryPerformanceCounter(&endtime_); + #else + endtime_ = current_time(); + #endif + + return elapsed(); + } + + /// Get the total time in milli-seconds (watch has to be stopped). + double elapsed() const { + #ifdef _WIN32 + return (double)(endtime_.QuadPart - starttime_.QuadPart) + / (double)freq_.QuadPart * 1000.0f; + #else + return ((endtime_.tv_sec - starttime_.tv_sec )*1000.0 + + (endtime_.tv_usec - starttime_.tv_usec)*0.001); + #endif + } + + +private: + + #ifdef _WIN32 + LARGE_INTEGER starttime_, endtime_; + LARGE_INTEGER freq_; + #else // Linux + timeval current_time() const { + struct timeval tv; + gettimeofday(&tv, 0); + return tv; + } + + timeval starttime_, endtime_; + #endif + +}; + + +//============================================================================= +} // namespace COMISO +//============================================================================= +#endif // COMISO_STOPWATCH_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/Utils/VSToolsT.hh b/src/external/CoMISo/Utils/VSToolsT.hh new file mode 100644 index 000000000..6c60dbd12 --- /dev/null +++ b/src/external/CoMISo/Utils/VSToolsT.hh @@ -0,0 +1,82 @@ +/*===========================================================================*\ + * * + * 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 . * + * * +\*===========================================================================*/ + + + + +#ifndef VSTOOLS_HH +#define VSTOOLS_HH + + +//== FORWARDDECLARATIONS ====================================================== + +//== NAMESPACES =============================================================== + +//== DEFINITION ========================================================= + +/** These functions are required for Visual Studio to work around missing + functions. Basic equivalent functions for double exist in the float + header but are named different. So this wrapper makes them standard compatible. + */ +#ifdef WIN32 + #include + + namespace std { + + inline int isnan(double x) + { + return _isnan(x); + } + + // Which idiot defines isinf as a macro somewhere? + #ifdef isinf + #undef isinf + #endif + + inline int isinf(double x) + { + return !_finite(x); + } + + } + + inline double nearbyint(double x) { + if( x >= 0.0 ) + return int( x + 0.5 ); + else + return int( x - 0.5 ); + } + + inline double round ( double _value ) { + return nearbyint(_value); + } + + +#endif + + +//============================================================================= +#endif // VSTOOLS_HH defined +//============================================================================= + diff --git a/src/external/CoMISo/VERSION b/src/external/CoMISo/VERSION new file mode 100644 index 000000000..fa0e3df9e --- /dev/null +++ b/src/external/CoMISo/VERSION @@ -0,0 +1,5 @@ +VERSION=1.1 +MAJOR=1 +MINOR=1 +PATCH=0 +ID=COMISO diff --git a/src/external/CoMISo/cmake/ACGCommon.cmake b/src/external/CoMISo/cmake/ACGCommon.cmake new file mode 100644 index 000000000..1e187f122 --- /dev/null +++ b/src/external/CoMISo/cmake/ACGCommon.cmake @@ -0,0 +1,673 @@ +if (EXISTS ${CMAKE_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.cmake) + include (${CMAKE_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.cmake) +endif () + +# prevent build in source directory + +# add option to disable plugin build +option ( + BLOCK_IN_SOURCE_BUILD + "Disable building inside the source tree" + ON +) + +if ( BLOCK_IN_SOURCE_BUILD ) + if ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") + message (SEND_ERROR "Building in the source directory is not supported.") + message (FATAL_ERROR "Please remove the created \"CMakeCache.txt\" file, the \"CMakeFiles\" directory and create a build directory and call \"${CMAKE_COMMAND} \".") + endif ("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") +endif() + +# allow only Debug and Release builds +set (CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) +mark_as_advanced (CMAKE_CONFIGURATION_TYPES) + +# set Debus as default build target +if (NOT CMAKE_BUILD_TYPE) + set (CMAKE_BUILD_TYPE Debug CACHE STRING + "Choose the type of build, options are: Debug, Release." + FORCE) +endif () + +# create our output directroy +if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build) + file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build) +endif () + +#generate the global doc target (but only once!) +GET_TARGET_PROPERTY(target_location doc EchoString) +if ( NOT target_location STREQUAL "Building Documentation" ) + ADD_CUSTOM_TARGET( doc ) + SET_TARGET_PROPERTIES( doc PROPERTIES EchoString "Building Documentation" ) +endif() + +# read version from file +macro (acg_get_version) + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}/VERSION") + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/${ARGN}/VERSION" _file) + else () + file (READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" _file) + endif () + + string ( + REGEX REPLACE + "^.*ID=([^\n]*).*$" "\\1" + _id ${_file} + ) + string ( + REGEX REPLACE + "^.*VERSION=([^\n]*).*$" "\\1" + _version ${_file} + ) + string ( + REGEX REPLACE + "^.*MAJOR=([^\n]*).*$" "\\1" + _major ${_file} + ) + string ( + REGEX REPLACE + "^.*MINOR=([^\n]*).*$" "\\1" + _minor ${_file} + ) + string ( + REGEX REPLACE + "^.*PATCH=([^\n]*).*$" "\\1" + _patch ${_file} + ) + + set (${_id}_VERSION ${_version}) + set (${_id}_VERSION_MAJOR ${_major}) + set (${_id}_VERSION_MINOR ${_minor}) + set (${_id}_VERSION_PATCH ${_patch}) +endmacro () + + +# set directory structures for the different platforms +if (WIN32) + set (ACG_PROJECT_DATADIR ".") + set (ACG_PROJECT_LIBDIR "lib") + set (ACG_PROJECT_BINDIR ".") + set (ACG_PROJECT_PLUGINDIR "Plugins") + if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}) + file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}) + endif () +else () + set (ACG_PROJECT_DATADIR "share/${CMAKE_PROJECT_NAME}") + set (ACG_PROJECT_LIBDIR "lib/${CMAKE_PROJECT_NAME}") + set (ACG_PROJECT_PLUGINDIR "lib/${CMAKE_PROJECT_NAME}/plugins") + set (ACG_PROJECT_BINDIR "bin") +endif () + +if( NOT APPLE ) + # check 64 bit + if( CMAKE_SIZEOF_VOID_P MATCHES 4 ) + set( HAVE_64_BIT 0 ) + else( CMAKE_SIZEOF_VOID_P MATCHES 4 ) + set( HAVE_64_BIT 1 ) + endif( CMAKE_SIZEOF_VOID_P MATCHES 4 ) +endif ( NOT APPLE ) + +# allow a project to modify the directories +if (COMMAND acg_modify_project_dirs) + acg_modify_project_dirs () +endif () + +if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}) + file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}) +endif () + + +# sets default build properties +macro (acg_set_target_props target) + if (WIN32) + set_target_properties ( + ${target} PROPERTIES + BUILD_WITH_INSTALL_RPATH 1 + SKIP_BUILD_RPATH 0 + ) + elseif (APPLE AND NOT ACG_PROJECT_MACOS_BUNDLE) + set_target_properties ( + ${target} PROPERTIES + INSTALL_NAME_DIR "@executable_path/../lib/${CMAKE_PROJECT_NAME}" + BUILD_WITH_INSTALL_RPATH 1 + SKIP_BUILD_RPATH 0 + ) + elseif (NOT APPLE) + + set_target_properties ( + ${target} PROPERTIES + INSTALL_RPATH "$ORIGIN/../lib/${CMAKE_PROJECT_NAME}" + BUILD_WITH_INSTALL_RPATH 1 + SKIP_BUILD_RPATH 0 + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}" + ) + + # prepare for cross compiling + if ( HAVE_64_BIT ) + if ( NOT CROSS_COMPILE_32) + # Already in cache, be silent + set( CROSS_COMPILE_32 false CACHE BOOL "Compile for 32-bit architecture") + endif( NOT CROSS_COMPILE_32 ) + + if ( CROSS_COMPILE_32 ) + add_definitions( -m32 ) + set_target_properties( ${target} PROPERTIES LINK_FLAGS -m32 ) + endif ( CROSS_COMPILE_32 ) + + else ( HAVE_64_BIT ) + + if ( NOT CROSS_COMPILE_64) + # Already in cache, be silent + set( CROSS_COMPILE_64 false CACHE BOOL "Compile for 64-bit architecture") + endif( NOT CROSS_COMPILE_64 ) + + if ( CROSS_COMPILE_64 ) + add_definitions( -m64 ) + set_target_properties( ${target} PROPERTIES LINK_FLAGS -m64 ) + endif ( CROSS_COMPILE_64 ) + + endif( HAVE_64_BIT ) + + endif () +endmacro () + +include (AddFileDependencies) +include (ACGCompiler) + +# define INCLUDE_TEMPLATES for everything we build +add_definitions (-DINCLUDE_TEMPLATES) + +# look for selected qt dependencies +macro (acg_qt4) + if (NOT QT4_FOUND) + + set (QT_MIN_VERSION ${ARGN}) + + find_package (Qt4 COMPONENTS QtCore QtGui ) + + set (QT_USE_QTOPENGL 1) + set (QT_USE_QTNETWORK 1) + set (QT_USE_QTSCRIPT 1) + set (QT_USE_QTSQL 1) + set (QT_USE_QTXML 1) + set (QT_USE_QTXMLPATTERNS 1) + set (QT_USE_QTHELP 1) + set (QT_USE_QTWEBKIT 1) + set (QT_USE_QTUITOOLS 1) + + if (QT_QTSCRIPTTOOLS_FOUND) + set (QT_USE_QTSCRIPTTOOLS 1) + endif() + + include (${QT_USE_FILE}) + endif () +endmacro () + +# unsets the given variable +macro (acg_unset var) + set (${var} "" CACHE INTERNAL "") +endmacro () + +# sets the given variable +macro (acg_set var value) + set (${var} ${value} CACHE INTERNAL "") +endmacro () + +# test for OpenMP +macro (acg_openmp) + if (NOT OPENMP_NOTFOUND) + # Set off OpenMP on Darwin architectures + # since it causes crashes sometimes + if(NOT APPLE) + find_package(OpenMP) + if (OPENMP_FOUND) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + add_definitions(-DUSE_OPENMP) + else () + set (OPENMP_NOTFOUND 1) + endif () + endif() + endif () +endmacro () + +# test for FTGL +macro (acg_ftgl) + find_package (Freetype) + + if (FREETYPE_FOUND) + find_package (FTGL) + + if (FTGL_FOUND) + add_definitions (-DUSE_FTGL) + include_directories (${FTGL_INCLUDE_DIR} ${FREETYPE_INCLUDE_DIR_freetype2}) + set (FTGL_LIBS ${FREETYPE_LIBRARIES} ${FTGL_LIBRARIES}) + endif () + endif () +endmacro () + +# append all files with extension "ext" in the "dirs" directories to "ret" +# excludes all files starting with a '.' (dot) +macro (acg_append_files ret ext) + foreach (_dir ${ARGN}) + file (GLOB _files "${_dir}/${ext}") + foreach (_file ${_files}) + get_filename_component (_filename ${_file} NAME) + if (_filename MATCHES "^[.]") + list (REMOVE_ITEM _files ${_file}) + endif () + endforeach () + list (APPEND ${ret} ${_files}) + endforeach () +endmacro () + +# append all files with extension "ext" in the "dirs" directories and its subdirectories to "ret" +# excludes all files starting with a '.' (dot) +macro (acg_append_files_recursive ret ext) + foreach (_dir ${ARGN}) + file (GLOB_RECURSE _files "${_dir}/${ext}") + foreach (_file ${_files}) + get_filename_component (_filename ${_file} NAME) + if (_filename MATCHES "^[.]") + list (REMOVE_ITEM _files ${_file}) + endif () + endforeach () + list (APPEND ${ret} ${_files}) + endforeach () +endmacro () + + +# drop all "*T.cc" files from list +macro (acg_drop_templates list) + foreach (_file ${${list}}) + if (_file MATCHES "T.cc$") + list (REMOVE_ITEM ${list} ${_file}) + endif () + endforeach () +endmacro () + +# generate moc targets for sources in list +macro (acg_qt4_automoc moc_SRCS) + qt4_get_moc_flags (_moc_INCS) + + set (_matching_FILES ) + foreach (_current_FILE ${ARGN}) + + get_filename_component (_abs_FILE ${_current_FILE} ABSOLUTE) + # if "SKIP_AUTOMOC" is set to true, we will not handle this file here. + # here. this is required to make bouic work correctly: + # we need to add generated .cpp files to the sources (to compile them), + # but we cannot let automoc handle them, as the .cpp files don't exist yet when + # cmake is run for the very first time on them -> however the .cpp files might + # exist at a later run. at that time we need to skip them, so that we don't add two + # different rules for the same moc file + get_source_file_property (_skip ${_abs_FILE} SKIP_AUTOMOC) + + if ( NOT _skip AND EXISTS ${_abs_FILE} ) + + file (READ ${_abs_FILE} _contents) + + get_filename_component (_abs_PATH ${_abs_FILE} PATH) + + string (REGEX MATCHALL "Q_OBJECT" _match "${_contents}") + if (_match) + get_filename_component (_basename ${_current_FILE} NAME_WE) + set (_header ${_abs_FILE}) + set (_moc ${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp) + + add_custom_command (OUTPUT ${_moc} + COMMAND ${QT_MOC_EXECUTABLE} + ARGS ${_moc_INCS} ${_header} -o ${_moc} + DEPENDS ${_header} + ) + + add_file_dependencies (${_abs_FILE} ${_moc}) + set (${moc_SRCS} ${${moc_SRCS}} ${_moc}) + + endif () + endif () + endforeach () +endmacro () + +# generate uic targets for sources in list +macro (acg_qt4_autouic uic_SRCS) + + set (_matching_FILES ) + foreach (_current_FILE ${ARGN}) + + get_filename_component (_abs_FILE ${_current_FILE} ABSOLUTE) + + if ( EXISTS ${_abs_FILE} ) + + file (READ ${_abs_FILE} _contents) + + get_filename_component (_abs_PATH ${_abs_FILE} PATH) + + get_filename_component (_basename ${_current_FILE} NAME_WE) + string (REGEX REPLACE "Ui$" "" _cbasename ${_basename}) + set (_outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${_basename}.hh) + set (_header ${_basename}.hh) + set (_source ${_abs_PATH}/${_cbasename}.cc) + + add_custom_command (OUTPUT ${_outfile} + COMMAND ${QT_UIC_EXECUTABLE} + ARGS -o ${_outfile} ${_abs_FILE} + DEPENDS ${_abs_FILE}) + + add_file_dependencies (${_source} ${_outfile}) + set (${uic_SRCS} ${${uic_SRCS}} ${_outfile}) + + endif () + endforeach () +endmacro () + + +# generate qrc targets for sources in list +macro (acg_qt4_autoqrc qrc_SRCS) + + set (_matching_FILES ) + foreach (_current_FILE ${ARGN}) + + get_filename_component (_abs_FILE ${_current_FILE} ABSOLUTE) + + if ( EXISTS ${_abs_FILE} ) + + file (READ ${_abs_FILE} _contents) + + get_filename_component (_abs_PATH ${_abs_FILE} PATH) + + get_filename_component (_basename ${_current_FILE} NAME_WE) + set (_outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${_basename}.cpp) + + add_custom_command (OUTPUT ${_outfile} + COMMAND ${QT_RCC_EXECUTABLE} + ARGS -o ${_outfile} ${_abs_FILE} + DEPENDS ${_abs_FILE}) + + add_file_dependencies (${_source} ${_outfile}) + set (${qrc_SRCS} ${${qrc_SRCS}} ${_outfile}) + + endif () + endforeach () +endmacro () + +# get all files in directory, but ignore svn +macro (acg_get_files_in_dir ret dir) + file (GLOB_RECURSE __files RELATIVE "${dir}" "${dir}/*") + foreach (_file ${__files}) + if (NOT _file MATCHES ".*svn.*") + list (APPEND ${ret} "${_file}") + endif () + endforeach () +endmacro () + +# copy the whole directory without svn files +function (acg_copy_after_build target src dst) + acg_unset (_files) + acg_get_files_in_dir (_files ${src}) + foreach (_file ${_files}) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${src}/${_file}" "${dst}/${_file}" + ) + endforeach () +endfunction () + +# install the whole directory without svn files +function (acg_install_dir src dst) + acg_unset (_files) + acg_get_files_in_dir (_files ${src}) + foreach (_file ${_files}) + get_filename_component (_file_PATH ${_file} PATH) + install(FILES "${src}/${_file}" + DESTINATION "${dst}/${_file_PATH}" + ) + endforeach () +endfunction () + +# extended version of add_executable that also copies output to out Build directory +function (acg_add_executable _target) + add_executable (${_target} ${ARGN}) + + # set common target properties defined in common.cmake + acg_set_target_props (${_target}) + + if (WIN32) + # copy exe file to "Build" directory + # Visual studio will create this file in a subdirectory so we can't use + # RUNTIME_OUTPUT_DIRECTORY directly here + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target}.exe + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}/${_target}.exe) + elseif (APPLE AND NOT ACG_PROJECT_MACOS_BUNDLE) + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_target} + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}/${_target}) + endif () + if (NOT ACG_PROJECT_MACOS_BUNDLE OR NOT APPLE) + install (TARGETS ${_target} DESTINATION ${ACG_PROJECT_BINDIR}) + endif () +endfunction () + +# extended version of add_library that also copies output to out Build directory +function (acg_add_library _target _libtype) + + if (${_libtype} STREQUAL SHAREDANDSTATIC) + set (_type SHARED) + if (NOT WIN32) + set (_and_static 1) + else () + set (_and_static 0) + endif () + else () + set (_type ${_libtype}) + set (_and_static 0) + endif () + + add_library (${_target} ${_type} ${ARGN} ) + + # set common target properties defined in common.cmake + acg_set_target_props (${_target}) + + if (_and_static) + add_library (${_target}Static STATIC ${ARGN}) + + # set common target properties defined in common.cmake + acg_set_target_props (${_target}Static) + + if (NOT APPLE) + set_target_properties (${_target}Static PROPERTIES + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" + ) + endif () + endif () + + if( ${CMAKE_BUILD_TYPE} STREQUAL Debug ) + set ( postfix ${CMAKE_DEBUG_POSTFIX} ) + else () + set ( postfix "" ) + endif () + + set( fullname ${_target}${postfix} ) + + + if (WIN32) + # copy exe file to "Build" directory + # Visual studio will create this file in a subdirectory so we can't use + # RUNTIME_OUTPUT_DIRECTORY directly here + if (${_type} STREQUAL SHARED) + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${fullname}.dll + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_BINDIR}/${fullname}.dll) + elseif (${_type} STREQUAL MODULE) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}) + file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}) + endif () + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${fullname}.dll + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}/${fullname}.dll) + endif () + if (${_type} STREQUAL SHARED OR ${_type} STREQUAL STATIC) + if("${CMAKE_GENERATOR}" MATCHES "MinGW Makefiles") + SET(OUTPUTNAME "lib${fullname}.a") + else() + SET(OUTPUTNAME "${fullname}.lib") + endif() + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${OUTPUTNAME} + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/${OUTPUTNAME}) + endif () + elseif (APPLE AND NOT ACG_PROJECT_MACOS_BUNDLE) + if (${_type} STREQUAL SHARED) + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${fullname}.dylib + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${fullname}.dylib) + elseif (${_type} STREQUAL MODULE) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}) + file (MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}) + endif () + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${fullname}.so + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_PLUGINDIR}/lib${fullname}.so) + elseif (${_type} STREQUAL STATIC) + add_custom_command (TARGET ${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${fullname}.a + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${fullname}.a) + endif () + if (_and_static) + add_custom_command (TARGET ${_target}Static POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}Static${postfix}.a + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${fullname}.a) + endif () + + elseif (NOT APPLE AND _and_static) + add_custom_command (TARGET ${_target}Static POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}Static${postfix}.a + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}/lib${fullname}.a) + + endif () + + + # Block installation of libraries by setting ACG_NO_LIBRARY_INSTALL + if ( NOT ACG_NO_LIBRARY_INSTALL ) + if (NOT ACG_PROJECT_MACOS_BUNDLE OR NOT APPLE) + if (${_type} STREQUAL SHARED OR ${_type} STREQUAL STATIC ) + install (TARGETS ${_target} + RUNTIME DESTINATION ${ACG_PROJECT_BINDIR} + LIBRARY DESTINATION ${ACG_PROJECT_LIBDIR} + ARCHIVE DESTINATION ${ACG_PROJECT_LIBDIR}) + if (_and_static) + install (FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${_target}Static${postfix}.a + DESTINATION ${ACG_PROJECT_LIBDIR} + RENAME lib${fullname}.a + PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + endif () + elseif (${_type} STREQUAL MODULE) + install (TARGETS ${_target} DESTINATION ${ACG_PROJECT_PLUGINDIR}) + endif () + endif () + endif() + +endfunction () + +#generates qt translations +function (acg_add_translations _target _languages _sources) + + string (TOUPPER ${_target} _TARGET) + # generate/use translation files + # run with UPDATE_TRANSLATIONS set to on to build qm files + option (UPDATE_TRANSLATIONS_${_TARGET} "Update source translation *.ts files (WARNING: make clean will delete the source .ts files! Danger!)") + + set (_new_ts_files) + set (_ts_files) + + foreach (lang ${_languages}) + if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/translations/${_target}_${lang}.ts" OR UPDATE_TRANSLATIONS_${_TARGET}) + list (APPEND _new_ts_files "translations/${_target}_${lang}.ts") + else () + list (APPEND _ts_files "translations/${_target}_${lang}.ts") + endif () + endforeach () + + + set (_qm_files) + if ( _new_ts_files ) + qt4_create_translation(_qm_files ${_sources} ${_new_ts_files}) + endif () + + if ( _ts_files ) + qt4_add_translation(_qm_files2 ${_ts_files}) + list (APPEND _qm_files ${_qm_files2}) + endif () + + # create a target for the translation files ( and object files ) + # Use this target, to update only the translations + add_custom_target (translations_target_${_target} DEPENDS ${_qm_files}) + + # Build translations with the application + add_dependencies(${_target} translations_target_${_target} ) + + if (NOT EXISTS ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}/Translations) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}/Translations ) + endif () + + foreach (_qm ${_qm_files}) + get_filename_component (_qm_name "${_qm}" NAME) + add_custom_command (TARGET translations_target_${_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E + copy_if_different + ${_qm} + ${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_DATADIR}/Translations/${_qm_name}) + endforeach () + + if (NOT ACG_PROJECT_MACOS_BUNDLE OR NOT APPLE) + install (FILES ${_qm_files} DESTINATION "${ACG_PROJECT_DATADIR}/Translations") + endif () +endfunction () + +# Function that writes all generated qch files into one Help.qhcp project file +function (generate_qhp_file files_loc plugin_name) + + set(qhp_file "${files_loc}/${plugin_name}.qhp") + # Read in template file + file(STRINGS "${CMAKE_SOURCE_DIR}/OpenFlipper/Documentation/QtHelpResources/QtHelpProject.qhp" qhp_template) + + # Initialize new project file + file(WRITE ${qhp_file} "") + foreach (_line ${qhp_template}) + string(STRIP ${_line} stripped) + if("${stripped}" STREQUAL "files") + acg_get_files_in_dir (_files ${files_loc}) + foreach (_file ${_files}) + string(REGEX MATCH ".+[.]+((html)|(htm)|(xml))$" fileresult ${_file}) + string(LENGTH "${fileresult}" len) + if(${len} GREATER 0) + file(APPEND ${qhp_file} "${_file}\n") + endif() + endforeach() + else() + string(REGEX REPLACE "plugin" ${plugin} newline ${_line}) + file(APPEND ${qhp_file} "${newline}\n") + endif() + endforeach() +endfunction() diff --git a/src/external/CoMISo/cmake/ACGCompiler.cmake b/src/external/CoMISo/cmake/ACGCompiler.cmake new file mode 100644 index 000000000..2be45e900 --- /dev/null +++ b/src/external/CoMISo/cmake/ACGCompiler.cmake @@ -0,0 +1,196 @@ +################################################################################ +# Custom settings for compiler flags and similar +################################################################################ + +if ( WIN32 ) + ################################################################################ + # Windows large memory support + ################################################################################ + if ( NOT DEFINED WINDOWS_LARGE_MEMORY_SUPPORT ) + set( WINDOWS_LARGE_MEMORY_SUPPORT true CACHE BOOL "Enable or disable binary support for large memory" ) + endif() + + set( ADDITIONAL_CMAKE_EXE_LINKER_FLAGS ) + set( ADDITIONAL_CMAKE_SHARED_LINKER_FLAGS ) + set( ADDITIONAL_CMAKE_MODULE_LINKER_FLAGS ) + + if ( WINDOWS_LARGE_MEMORY_SUPPORT ) + list(APPEND ADDITIONAL_CMAKE_EXE_LINKER_FLAGS "/LARGEADDRESSAWARE" ) + list(APPEND ADDITIONAL_CMAKE_SHARED_LINKER_FLAGS "/LARGEADDRESSAWARE" ) + list(APPEND ADDITIONAL_CMAKE_MODULE_LINKER_FLAGS "/LARGEADDRESSAWARE" ) + endif() + + + foreach( flag ${ADDITIONAL_CMAKE_EXE_LINKER_FLAGS} ) + if( NOT CMAKE_EXE_LINKER_FLAGS MATCHES "${flag}" ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${flag} ") + endif() + endforeach() + + foreach( flag ${ADDITIONAL_CMAKE_SHARED_LINKER_FLAGS} ) + if( NOT CMAKE_SHARED_LINKER_FLAGS MATCHES "${flag}" ) + set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${flag} ") + endif() + endforeach() + + foreach( flag ${ADDITIONAL_CMAKE_MODULE_LINKER_FLAGS} ) + if( NOT CMAKE_MODULE_LINKER_FLAGS MATCHES "${flag}" ) + set( CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${flag} ") + endif() + endforeach() + +endif( WIN32 ) + +if (UNIX) + + set ( ADDITIONAL_CXX_DEBUG_FLAGS ) + set ( ADDITIONAL_CXX_RELEASE_FLAGS ) + set ( ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS ) + + set ( ADDITIONAL_C_DEBUG_FLAGS ) + set ( ADDITIONAL_C_RELEASE_FLAGS ) + set ( ADDITIONAL_C_RELWITHDEBINFO_FLAGS ) + + ################################################################################ + # Defaults + ################################################################################ + + # add our standard flags for Template inclusion + list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-DINCLUDE_TEMPLATES" ) + list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-DINCLUDE_TEMPLATES" ) + list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-DINCLUDE_TEMPLATES" ) + + # add our standard flags for Template inclusion + list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-DINCLUDE_TEMPLATES" ) + list(APPEND ADDITIONAL_C_RELEASE_FLAGS "-DINCLUDE_TEMPLATES" ) + list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-DINCLUDE_TEMPLATES" ) + + # Increase the template depth as this might be exceeded from time to time + IF( NOT CMAKE_SYSTEM MATCHES "SunOS*") + list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-ftemplate-depth-100" ) + list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-ftemplate-depth-100" ) + list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-ftemplate-depth-100" ) + ENDIF() + + ################################################################################ + # OS Defines + ################################################################################ + + if (APPLE) + add_definitions( -DARCH_DARWIN ) + endif() + + ################################################################################ + # Build/Release Defines + ################################################################################ + IF( NOT CMAKE_SYSTEM MATCHES "SunOS*") + list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-DDEBUG" ) + list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS "-DNDEBUG" ) + list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-DDEBUG" ) + + list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-DDEBUG" ) + list(APPEND ADDITIONAL_C_RELEASE_FLAGS "-DNDEBUG" ) + list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-DDEBUG" ) + ENDIF() + + ################################################################################ + # Warnings + ################################################################################ + + # Add the standard compiler warnings + if ( NOT COMPILER_WARNINGS ) + + IF ( APPLE ) + # Skip unused parameters as it has to be used for the documentation via doxygen and the interfaces + set ( COMPILER_WARNINGS "-W" "-Wall" "-Wno-unused" "-Wextra" "-Wno-non-virtual-dtor" "-Wno-unused-parameter" CACHE STRINGLIST "This list contains the warning flags used during compilation " ) + ELSEIF ( CMAKE_SYSTEM MATCHES "SunOS*" ) + set ( COMPILER_WARNINGS "" CACHE STRINGLIST "This list contains the warning flags used during compilation " ) + ELSE () + set ( COMPILER_WARNINGS "-W" "-Wall" "-Wno-unused" "-Wextra" CACHE STRINGLIST "This list contains the warning flags used during compilation " ) + ENDIF() + + endif ( NOT COMPILER_WARNINGS ) + + list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS ${COMPILER_WARNINGS} ) + list(APPEND ADDITIONAL_CXX_RELEASE_FLAGS ${COMPILER_WARNINGS} ) + list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS ${COMPILER_WARNINGS} ) + + list(APPEND ADDITIONAL_C_DEBUG_FLAGS ${COMPILER_WARNINGS} ) + list(APPEND ADDITIONAL_C_RELEASE_FLAGS ${COMPILER_WARNINGS} ) + list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS ${COMPILER_WARNINGS} ) + + ################################################################################ + # STL Vector checks + ################################################################################ + + # Pre initialize stl vector check variable + if ( NOT STL_VECTOR_CHECKS ) + set ( STL_VECTOR_CHECKS false CACHE BOOL "Include full stl vector checks in debug mode (This option is only used in debug Mode!)" ) + endif ( NOT STL_VECTOR_CHECKS ) + + # Add a flag to check stl vectors in debugging mode + if ( STL_VECTOR_CHECKS AND NOT CMAKE_SYSTEM MATCHES "SunOS*" ) + list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-D_GLIBCXX_DEBUG" ) + list(APPEND ADDITIONAL_CXX_DEBUG_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC") + list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG" ) + list(APPEND ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC") + + list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-D_GLIBCXX_DEBUG" ) + list(APPEND ADDITIONAL_C_DEBUG_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC") + list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG" ) + list(APPEND ADDITIONAL_C_RELWITHDEBINFO_FLAGS "-D_GLIBCXX_DEBUG_PEDANTIC") + endif() + + ################################################################################ + # Process the additional flags: + ################################################################################ + + # Add the debug flags + foreach( flag ${ADDITIONAL_CXX_DEBUG_FLAGS} ) + if( NOT CMAKE_CXX_FLAGS_DEBUG MATCHES "${flag}" ) + set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${flag} ") + endif() + endforeach() + + # Add the release flags + foreach( flag ${ADDITIONAL_CXX_RELEASE_FLAGS} ) + if( NOT CMAKE_CXX_FLAGS_RELEASE MATCHES "${flag}" ) + set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${flag} ") + endif() + endforeach() + + # Add the release with debug info flags + foreach( flag ${ADDITIONAL_CXX_RELWITHDEBINFO_FLAGS} ) + if( NOT CMAKE_CXX_FLAGS_RELWITHDEBINFO MATCHES "${flag}" ) + set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${flag} ") + endif() + endforeach() + + # Add the debug flags + foreach( flag ${ADDITIONAL_C_DEBUG_FLAGS} ) + if( NOT CMAKE_C_FLAGS_DEBUG MATCHES "${flag}" ) + set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${flag} ") + endif() + endforeach() + + # Add the release flags + foreach( flag ${ADDITIONAL_C_RELEASE_FLAGS} ) + if( NOT CMAKE_C_FLAGS_RELEASE MATCHES "${flag}" ) + set( CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${flag} ") + endif() + endforeach() + + # Add the release with debug info flags + foreach( flag ${ADDITIONAL_C_RELWITHDEBINFO_FLAGS} ) + if( NOT CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES "${flag}" ) + set( CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${flag} ") + endif() + endforeach() + + #TODO : Test and remove it?! + IF( CMAKE_SYSTEM MATCHES "SunOS*") + set (CMAKE_CFLAGS_RELEASE "-xO3") + set (CMAKE_CXX_FLAGS_RELEASE "-xO3") + endif ( CMAKE_SYSTEM MATCHES "SunOS*" ) + +endif () diff --git a/src/external/CoMISo/cmake/ACGOutput.cmake b/src/external/CoMISo/cmake/ACGOutput.cmake new file mode 100644 index 000000000..e4505bf70 --- /dev/null +++ b/src/external/CoMISo/cmake/ACGOutput.cmake @@ -0,0 +1,39 @@ +# fill string with spaces +macro (acg_format_string str length return) + string (LENGTH "${str}" _str_len) + math (EXPR _add_chr "${length} - ${_str_len}") + set (${return} "${str}") + while (_add_chr GREATER 0) + set (${return} "${${return}} ") + math (EXPR _add_chr "${_add_chr} - 1") + endwhile () +endmacro () + +# print message with color escape sequences if CMAKE_COLOR_MAKEFILE is set +string (ASCII 27 _escape) +function (acg_color_message _str) + if (CMAKE_COLOR_MAKEFILE AND NOT WIN32) + message (${_str}) + else () + string (REGEX REPLACE "${_escape}.[0123456789;]*m" "" __str ${_str}) + message (${__str}) + endif () +endfunction () + +# info header +function (acg_print_configure_header _id _name) + acg_format_string ("${_name}" 40 _project) + acg_format_string ("${${_id}_VERSION}" 40 _version) + acg_color_message ("\n${_escape}[40;37m************************************************************${_escape}[0m") + acg_color_message ("${_escape}[40;37m* ${_escape}[1;31mACG ${_escape}[0;40;34mBuildsystem${_escape}[0m${_escape}[40;37m *${_escape}[0m") + acg_color_message ("${_escape}[40;37m* *${_escape}[0m") + acg_color_message ("${_escape}[40;37m* Package : ${_escape}[32m${_project} ${_escape}[37m *${_escape}[0m") + acg_color_message ("${_escape}[40;37m* Version : ${_escape}[32m${_version} ${_escape}[37m *${_escape}[0m") + acg_color_message ("${_escape}[40;37m************************************************************${_escape}[0m") +endfunction () + +# info line +function (acg_print_configure_footer) + acg_color_message ("${_escape}[40;37m************************************************************${_escape}[0m\n") +endfunction () + diff --git a/src/external/CoMISo/cmake/CGAL_FindPackageHandleStandardArgs.cmake b/src/external/CoMISo/cmake/CGAL_FindPackageHandleStandardArgs.cmake new file mode 100644 index 000000000..ebb8e90e9 --- /dev/null +++ b/src/external/CoMISo/cmake/CGAL_FindPackageHandleStandardArgs.cmake @@ -0,0 +1,55 @@ +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME (DEFAULT_MSG|"Custom failure message") VAR1 ... ) +# This macro is intended to be used in FindXXX.cmake modules files. +# It handles the REQUIRED and QUIET argument to FIND_PACKAGE() and +# it also sets the _FOUND variable. +# The package is found if all variables listed are TRUE. +# Example: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARIES LIBXML2_INCLUDE_DIR) +# +# LibXml2 is considered to be found, if both LIBXML2_LIBRARIES and +# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE. +# If it is not found and REQUIRED was used, it fails with FATAL_ERROR, +# independent whether QUIET was used or not. +# If it is found, the location is reported using the VAR1 argument, so +# here a message "Found LibXml2: /usr/lib/libxml2.so" will be printed out. +# If the second argument is DEFAULT_MSG, the message in the failure case will +# be "Could NOT find LibXml2", if you don't like this message you can specify +# your own custom failure message there. + +macro(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FAIL_MSG _VAR1 ) + + if("${_FAIL_MSG}" STREQUAL "DEFAULT_MSG") + set(_FAIL_MESSAGE "Could NOT find ${_NAME}") + else() + set(_FAIL_MESSAGE "${_FAIL_MSG}") + endif() + + string(TOUPPER ${_NAME} _NAME_UPPER) + + set(${_NAME_UPPER}_FOUND TRUE) + if(NOT ${_VAR1}) + set(${_NAME_UPPER}_FOUND FALSE) + endif() + + foreach(_CURRENT_VAR ${ARGN}) + if(NOT ${_CURRENT_VAR}) + set(${_NAME_UPPER}_FOUND FALSE) + endif() + endforeach() + + if (${_NAME_UPPER}_FOUND) + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "Found ${_NAME}: ${${_VAR1}}") + endif() + else() + if (${_NAME}_FIND_REQUIRED) + message(FATAL_ERROR "${_FAIL_MESSAGE}") + else() + if (NOT ${_NAME}_FIND_QUIETLY) + message(STATUS "${_FAIL_MESSAGE}") + endif() + endif() + endif() + +endmacro() diff --git a/src/external/CoMISo/cmake/CGAL_GeneratorSpecificSettings.cmake b/src/external/CoMISo/cmake/CGAL_GeneratorSpecificSettings.cmake new file mode 100644 index 000000000..5dc9164ec --- /dev/null +++ b/src/external/CoMISo/cmake/CGAL_GeneratorSpecificSettings.cmake @@ -0,0 +1,41 @@ +if ( NOT CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED ) + set( CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED 1 ) + + message( STATUS "Targetting ${CMAKE_GENERATOR}") + + if ( MSVC ) + message( STATUS "Target build enviroment supports auto-linking" ) + set(CGAL_AUTO_LINK_ENABLED TRUE) + endif() + + if ( MSVC90 ) + set(CGAL_TOOLSET "vc90") + message( STATUS "Using VC90 compiler." ) + elseif ( MSVC80 ) + set(CGAL_TOOLSET "vc80") + message( STATUS "Using VC80 compiler." ) + elseif ( MSVC71 ) + set(CGAL_TOOLSET "vc71") + message( STATUS "Using VC71 compiler." ) + else() + message( STATUS "Using ${CMAKE_CXX_COMPILER} compiler." ) + endif() + + + # From james Bigler, in the cmake users list. + IF (APPLE) + exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION) + string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION}) + message(STATUS "DARWIN_VERSION=${DARWIN_VERSION}") + if (DARWIN_VERSION GREATER 8) + message(STATUS "Mac Leopard detected") + set(CGAL_APPLE_LEOPARD 1) + endif() + endif() + + if ( NOT "${CMAKE_CFG_INTDIR}" STREQUAL "." ) + set(HAS_CFG_INTDIR TRUE CACHE INTERNAL "Generator uses intermediate configuration directory" ) + message( STATUS "Generator uses intermediate configuration directory: ${CMAKE_CFG_INTDIR}" ) + endif() + +endif() diff --git a/src/external/CoMISo/cmake/CGAL_Locate_CGAL_TAUCS.cmake b/src/external/CoMISo/cmake/CGAL_Locate_CGAL_TAUCS.cmake new file mode 100644 index 000000000..371475c34 --- /dev/null +++ b/src/external/CoMISo/cmake/CGAL_Locate_CGAL_TAUCS.cmake @@ -0,0 +1,120 @@ +# Find TAUCS library shipped with CGAL +# +# This module searches for TAUCS in CGAL "auxiliary" folder +# and in in $CGAL_TAUCS_DIR environment variable. +# +# This module sets the following variables: +# CGAL_TAUCS_FOUND - set to true if TAUCS library shipped with CGAL +# is found +# CGAL_TAUCS_PLATFORM - name of TAUCS subfolder corresponding to the current compiler +# CGAL_TAUCS_INCLUDE_DIR - list of folders (using full path name) containing +# TAUCS (and optionaly BLAS and LAPACK) headers +# CGAL_TAUCS_LIBRARIES_DIR -list of folders (using full path name) containing +# TAUCS (and optionaly BLAS and LAPACK) libraries + +include(CGAL_Macros) + +if ( NOT CGAL_TAUCS_FOUND ) + + # + # Find out TAUCS name for the current platform. + # This code is a translation of TAUCS "configure" script. + # + + # The first task is to figure out CMAKE_SYSTEM_NAME + # (on unix this is uname -s, for windows it is Windows). + #message("DEBUG: CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}") + #message("DEBUG: CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}") + set( CGAL_TAUCS_PLATFORM "${CMAKE_SYSTEM_NAME}" ) + + # Convert to lower case + STRING(TOLOWER "${CGAL_TAUCS_PLATFORM}" CGAL_TAUCS_PLATFORM) + + # Sometimes uname returns a value that is + # inconsistent with the way CGAL_TAUCS_PLATFORM is set. For example, on + # Solaris, CGAL_TAUCS_PLATFORM=solaris but uname returns SunOS. + if ( ${CGAL_TAUCS_PLATFORM} STREQUAL "sunos" ) + set( CGAL_TAUCS_PLATFORM "solaris" ) + endif() + if ( ${CGAL_TAUCS_PLATFORM} STREQUAL "windows" ) + set( CGAL_TAUCS_PLATFORM "win32" ) + endif() + + # LS 2007: added "darwin_intel" for Intel Macs. + # "darwin" = original Darwin platform = PowerPC architecture. + if ( ${CGAL_TAUCS_PLATFORM} STREQUAL "darwin" ) + # CMAKE_SYSTEM_PROCESSOR=uname -p + if ( ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386" ) + set( CGAL_TAUCS_PLATFORM "darwin_intel" ) + endif() + endif() + + # LS 2007: append "64" if 64 bits processor (tested on Linux only) + + if ( ${CGAL_TAUCS_PLATFORM} STREQUAL "linux" ) + # CMAKE_SYSTEM_PROCESSOR=uname -p + if ( ${CMAKE_SYSTEM_PROCESSOR} MATCHES ".*64.*" ) + set( CGAL_TAUCS_PLATFORM "${CGAL_TAUCS_PLATFORM}64" ) + endif() + endif() + + #message("DEBUG: CGAL_TAUCS_PLATFORM = ${CGAL_TAUCS_PLATFORM}") + + + # + # Search for TAUCS folder. + # + + #message("DEBUG: CGAL_SOURCE_DIRECTORY = ${CGAL_SOURCE_DIRECTORY}") + + # VC++ uses auto-link, thus we search for a folder containing the output of + # build_taucs_win32_for_CGAL.bat/build_taucs_win64_for_CGAL.bat, + # ie TAUCS libraries compiled for all Windows runtimes. + if ( MSVC ) + + # Check $CGAL_TAUCS_DIR environment variable + fetch_env_var(CGAL_TAUCS_DIR) + #message("DEBUG: CGAL_TAUCS_DIR = ${CGAL_TAUCS_DIR}") + if (NOT "${CGAL_TAUCS_DIR}" STREQUAL "" AND EXISTS ${CGAL_TAUCS_DIR}) + + set( CGAL_TAUCS_INCLUDE_DIR "${CGAL_TAUCS_DIR}/include") + set( CGAL_TAUCS_LIBRARIES_DIR "${CGAL_TAUCS_DIR}/lib" ) + set( CGAL_TAUCS_FOUND TRUE ) + + # Else, search for TAUCS in CGAL "auxiliary" folder + elseif ( EXISTS "${CGAL_SOURCE_DIRECTORY}/auxiliary/taucs" ) + + set( CGAL_TAUCS_INCLUDE_DIR "${CGAL_SOURCE_DIRECTORY}/auxiliary/taucs/include") + set( CGAL_TAUCS_LIBRARIES_DIR "${CGAL_SOURCE_DIRECTORY}/auxiliary/taucs/lib" ) + set( CGAL_TAUCS_FOUND TRUE ) + + endif() + + # On Unix, search for TAUCS "taucs_full" folder + else ( MSVC ) + + # Check $CGAL_TAUCS_DIR environment variable + fetch_env_var(CGAL_TAUCS_DIR) + #message("DEBUG: CGAL_TAUCS_DIR = ${CGAL_TAUCS_DIR}") + if (NOT "${CGAL_TAUCS_DIR}" STREQUAL "" AND EXISTS ${CGAL_TAUCS_DIR}) + + set( CGAL_TAUCS_INCLUDE_DIR "${CGAL_TAUCS_DIR}/build/${CGAL_TAUCS_PLATFORM}" + "${CGAL_TAUCS_DIR}/src" ) + set( CGAL_TAUCS_LIBRARIES_DIR "${CGAL_TAUCS_DIR}/external/lib/${CGAL_TAUCS_PLATFORM}" + "${CGAL_TAUCS_DIR}/lib/${CGAL_TAUCS_PLATFORM}" ) + set( CGAL_TAUCS_FOUND TRUE ) + + endif() + + endif ( MSVC ) + + # Add variables to cache + set( CGAL_TAUCS_DIR "${CGAL_TAUCS_DIR}" + CACHE PATH "Directory containing BLAS, LAPACK and TAUCS" ) + + #message("DEBUG: CGAL_TAUCS_INCLUDE_DIR = ${CGAL_TAUCS_INCLUDE_DIR}") + #message("DEBUG: CGAL_TAUCS_LIBRARIES_DIR = ${CGAL_TAUCS_LIBRARIES_DIR}") + #message("DEBUG: CGAL_TAUCS_FOUND = ${CGAL_TAUCS_FOUND}") + +endif ( NOT CGAL_TAUCS_FOUND ) + diff --git a/src/external/CoMISo/cmake/CGAL_Macros.cmake b/src/external/CoMISo/cmake/CGAL_Macros.cmake new file mode 100644 index 000000000..f34497d24 --- /dev/null +++ b/src/external/CoMISo/cmake/CGAL_Macros.cmake @@ -0,0 +1,378 @@ +if( NOT CGAL_MACROS_FILE_INCLUDED ) + set(CGAL_MACROS_FILE_INCLUDED 1 ) + + macro(assert _arg ) + if ( NOT ${_arg} ) + message( FATAL_ERROR "Variable ${_arg} must be defined" ) + endif() + endmacro() + + macro( hide_variable var ) + set ( ${var} ${${var}} CACHE INTERNAL "Variable hidden from user" FORCE ) + endmacro() + + macro( cache_set var ) + set ( ${var} ${ARGN} CACHE INTERNAL "" ) + set ( ${var} ${ARGN} CACHE INTERNAL "" ) + endmacro() + + macro( typed_cache_set type doc var ) + set ( ${var} ${ARGN} CACHE ${type} ${doc} FORCE ) + set ( ${var} ${ARGN} CACHE ${type} ${doc} FORCE ) + endmacro() + + macro( cache_get var ) + set ( ${var} ) + endmacro() + + # Splits inlist in the first element (head) and the rest (tail) + macro( list_split head tail ) + set( ${head} ) + set( ${tail} ) + set( _LS_is_head TRUE ) + foreach( _LS_item ${ARGN} ) + if ( _LS_is_head ) + set( ${head} ${_LS_item} ) + set( _LS_is_head FALSE ) + else() + list( APPEND ${tail} ${_LS_item} ) + endif() + endforeach() + endmacro() + + # adds elements to an internal cached list + macro( add_to_cached_list listname ) + cache_get ( ${listname} ) + set( _ATC_${listname}_tmp ${${listname}} ) + if ( NOT "${ARGN}" STREQUAL "" ) + list( APPEND _ATC_${listname}_tmp ${ARGN} ) + endif() + cache_set ( ${listname} ${_ATC_${listname}_tmp} ) + endmacro() + + # adds elements to an in-memory variable named 'listname' + macro( add_to_memory_list listname ) + if ( NOT "${ARGN}" STREQUAL "" ) + list( APPEND ${listname} ${ARGN} ) + endif() + endmacro() + + # adds elements to a list. + # If the first argument after 'listname' is PERSISTENT then 'listname' + # is a persistent internal cached variable, otherwise is a memory variable. + macro( add_to_list listname ) + list_split( _ATL_ARGN_HEAD _ATL_ARGN_TAIL ${ARGN} ) + if ( "${_ATL_ARGN_HEAD}" STREQUAL "PERSISTENT" ) + add_to_cached_list( ${listname} ${_ATL_ARGN_TAIL} ) + else() + add_to_memory_list( ${listname} ${ARGN} ) + endif() + endmacro() + + macro( at list idx var ) + list( LENGTH ${list} ${list}_length ) + if ( ${idx} LESS ${${list}_length} ) + list( GET ${list} ${idx} ${var} ) + else() + set( ${var} "NOTFOUND" ) + endif() + endmacro() + + macro( found_in_list item_list item result ) + set( ${result} "FALSE" ) + foreach( element ${${item_list}} ) + if ( "${element}" STREQUAL "${item}" ) + set( ${result} "TRUE" ) + endif() + endforeach() + endmacro() + + macro( uniquely_add_flags target_var ) + if ( "${ARGC}" GREATER "1" ) + set( target_list "${${target_var}}" ) + set( source_list "${ARGN}" ) + separate_arguments( target_list ) + separate_arguments( source_list ) + foreach( flag ${source_list} ) + found_in_list( target_list ${flag} ${flag}_FOUND ) + if ( NOT ${flag}_FOUND ) + typed_cache_set( STRING "User-defined flags" ${target_var} "${${target_var}} ${flag}" ) + endif() + endforeach() + endif() + endmacro() + + macro( get_dependency_version LIB ) + + if ( "${ARGC}" GREATER "1" ) + set( PKG ${ARGV1} ) + else() + set( PKG ${LIB} ) + endif() + + if ( ${PKG}_FOUND ) + + set ( ${LIB}_VERSION "unknown" ) + + try_run( ${LIB}_RUN_RES + ${LIB}_COMPILE_RES + "${CMAKE_BINARY_DIR}" + "${CMAKE_SOURCE_DIR}/config/support/print_${LIB}_version.cpp" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${${PKG}_DEPENDENCY_INCLUDE_DIR};${${PKG}_INCLUDE_DIR}" + "-DLINK_LIBRARIES:STRING=${${PKG}_DEPENDENCY_LIBRARIES};${${PKG}_LIBRARIES}" + "-DLINK_DIRECTORIES:STRING=${${PKG}_DEPENDENCY_LIBRARY_DIR};${${PKG}_LIBRARY_DIR}" + OUTPUT_VARIABLE ${LIB}_OUTPUT + ) + + if ( ${LIB}_COMPILE_RES ) + + if ( ${LIB}_RUN_RES EQUAL "0" ) + + string( REGEX MATCH "version=.*\$" ${LIB}_VERSION_LINE ${${LIB}_OUTPUT} ) + string( REPLACE "\n" "" ${LIB}_VERSION_LINE2 ${${LIB}_VERSION_LINE} ) + string( REPLACE "\r" "" ${LIB}_VERSION_LINE3 ${${LIB}_VERSION_LINE2} ) + string( REPLACE "version=" "" ${LIB}_VERSION ${${LIB}_VERSION_LINE3} ) + + else() + + message( STATUS "WARNING: ${LIB} found but print_${LIB}_version.cpp exited with error condition: ${${LIB}_RUN_RES}" ) + message( STATUS "${PKG}_INCLUDE_DIR=${${PKG}_INCLUDE_DIR}" ) + message( STATUS "${PKG}_LIBRARIES=${${PKG}_LIBRARIES}" ) + message( STATUS "${PKG}_LIBRARY_DIR=${${PKG}_LIBRARY_DIR}" ) + message( STATUS "${${LIB}_OUTPUT}" ) + + endif() + + else() + + message( STATUS "WARNING: ${LIB} found but could not compile print_${LIB}_version.cpp:") + message( STATUS "${PKG}_INCLUDE_DIR=${${PKG}_INCLUDE_DIR}" ) + message( STATUS "${PKG}_LIBRARIES=${${PKG}_LIBRARIES}" ) + message( STATUS "${PKG}_LIBRARY_DIR=${${PKG}_LIBRARY_DIR}" ) + message( STATUS "${${LIB}_OUTPUT}" ) + + endif() + + message( STATUS "USING ${LIB}_VERSION = '${${LIB}_VERSION}'" ) + + endif() + + endmacro() + + macro( create_CGALconfig_files ) + # FindCGAL and UseCGAL are platform specific so they are generated and stored in the binary folder. + configure_file(${CGAL_MODULES_DIR}/CGALConfig_binary.cmake.in ${CMAKE_BINARY_DIR}/CGALConfig.cmake @ONLY IMMEDIATE) + + if ( SOURCE_INSTALL ) + configure_file(${CGAL_MODULES_DIR}/CGALConfig_install.cmake.source.in ${CMAKE_BINARY_DIR}/config/CGALConfig.cmake @ONLY IMMEDIATE) + else() + configure_file(${CGAL_MODULES_DIR}/CGALConfig_install.cmake.fhs.in ${CMAKE_BINARY_DIR}/config/CGALConfig.cmake @ONLY IMMEDIATE) + endif() + endmacro() + + macro ( fetch_env_var VAR ) + if ( "${${VAR}}" STREQUAL "" ) + set( ${VAR}_env_value "$ENV{${VAR}}" ) + if ( NOT "${${VAR}_env_value}" STREQUAL "" ) + set( ${VAR} ${${VAR}_env_value} ) + endif() + endif() + endmacro() + + # Composes a tagged list of libraries: a list with interpersed keywords or tags + # indicating that all following libraries, up to the next tag, are to be linked only for the + # corresponding build type. The 'general' tag indicates libraries that corresponds to all build types. + # 'optimized' corresponds to release builds and 'debug' to debug builds. Tags are case sensitve and + # the inital range of libraries listed before any tag is implicitely 'general' + # + # This macro takes 3 lists of general, optimized and debug libraries, resp, and populates the list + # given in the fourth argument. + # + # The first three parameters must be strings containing a semi-colon separated list of elements. + # All three lists must be passed, but any of them can be an empty string "". + # The fourth parameter, corresponding to the result, must be a variable name and it will be APPENDED + # (retaining any previous contents) + # + # If there is a last parameter whose value is "PERSISTENT" then the result is an internal cached variable, + # otherwise it is an in-memory variable + # + macro( compose_tagged_libraries libs_general libs_optimized libs_debug libs ) + + if ( "${ARGN}" STREQUAL "PERSISTENT" ) + set( _CTL_IN_CACHE "PERSISTENT" ) + else() + set( _CTL_IN_CACHE ) + endif() + + if ( NOT "${libs_general}" STREQUAL "" ) + add_to_list( ${libs} ${_CTL_IN_CACHE} ${libs_general} ) + endif() + + if ( NOT "${libs_optimized}" STREQUAL "" ) + add_to_list( ${libs} ${_CTL_IN_CACHE} optimized ${libs_optimized} ) + endif() + + if ( NOT "${libs_debug}" STREQUAL "" ) + add_to_list( ${libs} ${_CTL_IN_CACHE} debug ${libs_debug} ) + endif() + + endmacro() + + # Decomposes a tagged list of libraries (see macro compose_tagged_libraries). + # The first argument is the tagged list and the next 3 arguments are the lists + # where the general, optimized and debug libraries are collected. + # + # The first parameter must be a string containing a semi-colon separated list of elements. + # It cannot be ommitted, but it can be an empty string "" + # + # TThe next three arguments must be the names of the variables containing the result, and they + # will be APPENDED (retaining any previous contents) + # + # If there is a last parameter whose value is "PERSISTENT" then the result variables are internal in the cache, + # otherwise they are in-memory. + # + macro( decompose_tagged_libraries libs libs_general libs_optimized libs_debug ) + + if ( "${ARGN}" STREQUAL "PERSISTENT" ) + set( _DTL_IN_CACHE "PERSISTENT" ) + else() + set( _DTL_IN_CACHE ) + endif() + + set( _DTL_tag general ) + + foreach( _DTL_lib ${libs} ) + + if ( "${_DTL_lib}" STREQUAL "general" OR "${_DTL_lib}" STREQUAL "optimized" OR "${_DTL_lib}" STREQUAL "debug" ) + + set( _DTL_tag "${_DTL_lib}" ) + + else() + + if ( "${_DTL_tag}" STREQUAL "general" ) + set( _DTL_target ${libs_general} ) + elseif ( "${_DTL_tag}" STREQUAL "optimized" ) + set( _DTL_target ${libs_optimized} ) + else() + set( _DTL_target ${libs_debug} ) + endif() + + add_to_list( ${_DTL_target} ${_DTL_IN_CACHE} ${_DTL_lib} ) + + endif() + + endforeach() + + endmacro() + + # Given lists of optimized and debug libraries, creates a tagged list which will + # contain the libraries listed in the 'general' section if any of the two lists is empty, + # + # All arguments are variable names (not values), thus the input list can be undefined or empty. + # The return variable ('libs') will be APPENDED the result (retaining any previous contents) + # + # If there is a last parameter whose value is "PERSISTENT" then the result is an internal cached variable, + # otherwise it is an in-memory variable + # + # Example: + # + # set( LIBS_1 libA.so libB.so ) + # set( LIBS_2 libC.so ) + # + # tag_libraries( LIBS_1 LIBS_2 LIBS_R ) + # + # LIBS_R -> optimized;libA.so;libB.so;debug;libC.so + # + # tag_libraries( LIBS_1 SOME_UNDEFINED_VARIABLE_OR_EMPTY_LIST LIBS_R ) + # + # LIBS_R -> libA.so;libB.so (implicitely 'general' since there is no tag) + # + # tag_libraries( SOME_UNDEFINED_VARIABLE_OR_EMPTY_LIST LIBS_2 LIBS_R ) + # + # LIBS_R -> libC.so (implicitely 'general' since there is no tag) + # + macro( tag_libraries libs_general_or_optimized libs_general_or_debug libs ) + + list( LENGTH ${libs_general_or_optimized} _TL_libs_general_or_optimized_len ) + list( LENGTH ${libs_general_or_debug} _TL_libs_general_or_debug_len ) + + if ( _TL_libs_general_or_optimized_len EQUAL 0 ) + compose_tagged_libraries( "${${libs_general_or_debug}}" "" "" ${libs} ${ARGN} ) + elseif ( _TL_libs_general_or_debug_len EQUAL 0 ) + compose_tagged_libraries( "${${libs_general_or_optimized}}" "" "" ${libs} ${ARGN} ) + else() + compose_tagged_libraries( "" "${${libs_general_or_optimized}}" "${${libs_general_or_debug}}" ${libs} ${ARGN} ) + endif() + + endmacro() + + # add_to_tagged_libraries( libsR ${libsA} ) + # + # Appends the list of tagged libraries contained in the variable 'libA' to the list + # of tagged libraries contained in the variable 'libR', properly redistributing each tagged subsequence. + # + # The first argument is the name of the variable recieving the list. It will be APPENDED + # (retaining any previous contents). + # The second parameter is a single string value containing the tagged + # lists of libraries to append (as a semi-colon separated list). It can be empty, in which case noting is added. + # + # If there is a third parameter whose value is PERSISTENT, then 'libR' is an internal cached variable, otherwise + # it is an in-memory variable. + # + # It is not possible to append more than one list in the same call. + # + # Example: + # + # set( LIBS_1 libG0.so libG1.so optimized libO0.so) + # set( LIBS_2 libG2.so debug libD0.so) + # set( LIBS_3 debug libD1.so optimized libO1.so libO2.so ) + # + # concat_tagged_libraries( LIBS_R ${LIBS_1} PERSISTENT ) + # concat_tagged_libraries( LIBS_R ${LIBS_2} PERSISTENT ) + # concat_tagged_libraries( LIBS_R ${LIBS_3} PERSISTENT ) + # + # LIBS_R -> libG0.so;libG1.so;libG2.so;optimized;libO0.so;libO1.so;libO2.so;debug;libD0.so;libD1.so, in the cache + # + macro( add_to_tagged_libraries libsR in_cache libsA ) + + if ( "${in_cache}" STREQUAL "PERSISTENT" ) + set( _CTL_IN_CACHE "PERSISTENT" ) + else() + set( _CTL_IN_CACHE ) + endif() + + set( _CTL_general_0 ) + set( _CTL_optimized_0 ) + set( _CTL_debug_0 ) + set( _CTL_general_1 ) + set( _CTL_optimized_1 ) + set( _CTL_debug_0 ) + + decompose_tagged_libraries( "${${libsR}}" _CTL_general_0 _CTL_optimized_0 _CTL_debug_0 ) + decompose_tagged_libraries( "${libsA}" _CTL_general_1 _CTL_optimized_1 _CTL_debug_1 ) + + add_to_list( _CTL_general_0 ${_CTL_general_1} ) + add_to_list( _CTL_optimized_0 ${_CTL_optimized_1} ) + add_to_list( _CTL_debug_0 ${_CTL_debug_1} ) + + if ( "${_CTL_IN_CACHE}" STREQUAL "PERSISTENT" ) + cache_set( ${libsR} ) + else() + set( ${libsR} ) + endif() + + compose_tagged_libraries( "${_CTL_general_0}" "${_CTL_optimized_0}" "${_CTL_debug_0}" ${libsR} ${_CTL_IN_CACHE} ) + + endmacro() + + + macro( add_to_persistent_tagged_libraries libsR ) + add_to_tagged_libraries( ${libsR} PERSISTENT "${ARGN}" ) + endmacro() + + macro( add_to_in_memory_tagged_libraries libsR ) + add_to_tagged_libraries( ${libsR} NOT_PERSISTENT "${ARGN}" ) + endmacro() + + +endif() \ No newline at end of file diff --git a/src/external/CoMISo/cmake/CheckCSourceRuns.cmake b/src/external/CoMISo/cmake/CheckCSourceRuns.cmake new file mode 100644 index 000000000..764c756d4 --- /dev/null +++ b/src/external/CoMISo/cmake/CheckCSourceRuns.cmake @@ -0,0 +1,86 @@ +# - Check if the given C source code compiles and runs. +# CHECK_C_SOURCE_RUNS( ) +# - source code to try to compile +# - variable to store the result +# (1 for success, empty for failure) +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link + +#============================================================================= +# Copyright 2006-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +MACRO(CHECK_C_SOURCE_RUNS SOURCE VAR) + IF("${VAR}" MATCHES "^${VAR}$") + SET(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + IF(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") + ELSE(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) + ENDIF(CMAKE_REQUIRED_LIBRARIES) + IF(CMAKE_REQUIRED_INCLUDES) + SET(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + ELSE(CMAKE_REQUIRED_INCLUDES) + SET(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES) + ENDIF(CMAKE_REQUIRED_INCLUDES) + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c" + "${SOURCE}\n") + + MESSAGE(STATUS "Performing Test ${VAR}") + TRY_RUN(${VAR}_EXITCODE ${VAR}_COMPILED + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} + "${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}" + "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" + COMPILE_OUTPUT_VARIABLE OUTPUT) + # if it did not compile make the return value fail code of 1 + IF(NOT ${VAR}_COMPILED) + SET(${VAR}_EXITCODE 1) + ENDIF(NOT ${VAR}_COMPILED) + # if the return value was 0 then it worked + IF("${${VAR}_EXITCODE}" EQUAL 0) + SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}") + MESSAGE(STATUS "Performing Test ${VAR} - Success") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}}\n" + "Source file was:\n${SOURCE}\n") + ELSE("${${VAR}_EXITCODE}" EQUAL 0) + IF(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + SET(${VAR} "${${VAR}_EXITCODE}") + ELSE(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + SET(${VAR} "" CACHE INTERNAL "Test ${VAR}") + ENDIF(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + + MESSAGE(STATUS "Performing Test ${VAR} - Failed") + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}_EXITCODE}\n" + "Source file was:\n${SOURCE}\n") + + ENDIF("${${VAR}_EXITCODE}" EQUAL 0) + ENDIF("${VAR}" MATCHES "^${VAR}$") +ENDMACRO(CHECK_C_SOURCE_RUNS) + diff --git a/src/external/CoMISo/cmake/CoMISoExample.cmake b/src/external/CoMISo/cmake/CoMISoExample.cmake new file mode 100644 index 000000000..63d0ef645 --- /dev/null +++ b/src/external/CoMISo/cmake/CoMISoExample.cmake @@ -0,0 +1,127 @@ +# add our macro directory to cmake search path +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake) + +include (ACGCommon) +find_package(CoMISo) + +#find_package(MUMPS) +if (MUMPS_FOUND ) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${MUMPS_INCLUDE_DIR} ) + list( APPEND COMISO_LINK_LIBRARIES ${MUMPS_LIBRARY} ) +endif () + +#find_package (IPOPT) +if (IPOPT_FOUND AND MUMPS_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${IPOPT_INCLUDE_DIR} ) + list( APPEND COMISO_LINK_DIRECTORIES ${IPOPT_LIBRARY_DIR} ) + list( APPEND COMISO_LINK_LIBRARIES ${IPOPT_LIBRARY} ) +endif () + +#find_package(LAPACK) +#find_package(Taucs) +if(LAPACK_FOUND AND TAUCS_FOUND) + 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} ) +endif() + +#find_package(GUROBI) +if( GUROBI_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${GUROBI_INCLUDE_DIR} ) + list( APPEND COMISO_LINK_DIRECTORIES ${GUROBI_LIBRARY_DIR} ) + list( APPEND COMISO_LINK_LIBRARIES ${GUROBI_LIBRARY} ) +endif() + +#find_package(ARPACK) +if( ARPACK_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${ARPACK_INCLUDE_DIR} ) + list( APPEND COMISO_LINK_LIBRARIES ${ARPACK_LIBRARIES} ) +endif() + +#FIND_PACKAGE( Boost 1.42.0 COMPONENTS system filesystem regex) +if( Boost_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIR} ) + list( APPEND COMISO_LINK_DIRECTORIES ${Boost_LIBRARY_DIRS} ) + list( APPEND COMISO_LINK_LIBRARIES ${Boost_LIBRARIES} ) +endif() + +#FIND_PACKAGE( MPI) +if( MPI_FOUND) + list( APPEND COMISO_LINK_LIBRARIES ${MPI_CXX_LIBRARIES} ) +endif() + +#FIND_PACKAGE( PETSC) +if( PETSC_FOUND) + list( APPEND COMISO_LINK_LIBRARIES ${PETSC_LIBRARY} ) + list( APPEND COMISO_LINK_LIBRARIES ${TAO_LIBRARY} ) + list( APPEND COMISO_LINK_DIRECTORIES ${PETSC_LIBRARY_DIR} ) +endif() + +#FIND_PACKAGE( TAO) +if( TAO_FOUND) + list( APPEND COMISO_LINK_DIRECTORIES ${TAO_LIBRARY_DIR}) +endif() + +#FIND_PACKAGE( SUITESPARSE) +if(SUITESPARSE_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${SUITESPARSE_INCLUDE_DIRS}) + list( APPEND COMISO_LINK_LIBRARIES ${SUITESPARSE_LIBRARIES} ) + list( APPEND COMISO_LINK_DIRECTORIES ${SUITESPARSE_LIBRARY_DIRS} ) +endif() + +#FIND_PACKAGE( EIGEN3) +if(EIGEN3_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${EIGEN3_INCLUDE_DIR}) +endif() + +if (CGAL_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${CGAL_INCLUDE_DIR} ) + list( APPEND COMISO_LINK_DIRECTORIES ${CGAL_LIBRARY_DIR} ) + list( APPEND COMISO_LINK_LIBRARIES ${CGAL_LIBRARIES} ) +endif() + +if (CPLEX_FOUND) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${CPLEX_INCLUDE_DIRS} ) + list( APPEND COMISO_LINK_LIBRARIES ${CPLEX_LIBRARIES} ) + #enable c++ support + add_definitions(-DIL_STD) +endif() + +if (GUROBI_FOUND ) + list( APPEND COMISO_INCLUDE_DIRECTORIES ${GUROBI_INCLUDE_DIRS} ) + list( APPEND COMISO_LINK_LIBRARIES ${GUROBI_LIBRARIES} ) +endif () + +#MESSAGE( ${COMISO_LINK_LIBRARIES}) + +#ToDo: +#list( APPEND COMISO_LINK_LIBRARIES "pthread" ) + +include_directories ( + .. + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${COMISO_INCLUDE_DIR} + ${COMISO_INCLUDE_DIRECTORIES} +) + +link_directories ( + ${COMISO_LINK_DIRECTORIES} +) + +# source code directories +set (directories + ${CMAKE_CURRENT_SOURCE_DIR} +) + +# collect all header and source files +set(headers "") +set(sources "") +acg_append_files (headers "*.hh" ${directories}) +acg_append_files (sources "*.cc" ${directories}) + +# remove template cc files from source file list +acg_drop_templates (sources) diff --git a/src/external/CoMISo/cmake/FindADOLC.cmake b/src/external/CoMISo/cmake/FindADOLC.cmake new file mode 100644 index 000000000..4d2cada3b --- /dev/null +++ b/src/external/CoMISo/cmake/FindADOLC.cmake @@ -0,0 +1,63 @@ +# - Try to find ADOLC +# Once done this will define +# ADOLC_FOUND - System has ADOLC +# ADOLC_INCLUDE_DIRS - The ADOLC include directories +# ADOLC_LIBRARIES - The libraries needed to use ADOLC + +if (ADOLC_INCLUDE_DIR) + # in cache already + set(ADOLC_FOUND TRUE) + set(ADOLC_INCLUDE_DIRS "${ADOLC_INCLUDE_DIR}" ) + set(ADOLC_LIBRARIES "${ADOLC_LIBRARY}" ) +else (ADOLC_INCLUDE_DIR) + +message( status "adolc include dir: ${ADOLC_DIR}/include/") + +find_path( ADOLC_INCLUDE_DIR + NAMES adolc/adolc.h + PATHS $ENV{ADOLC_DIR}/include/ + /usr/include/adolc + /usr/local/include + /usr/local/include/adolc/ + /opt/local/include/adolc/ + "c:\\libs\\adolc\\include" + "c:\\libs\\adolc\\include" + ${PROJECT_SOURCE_DIR}/MacOS/Libs/adolc/include + ../../External/include + ${module_file_path}/../../../External/include + ) + +find_library( ADOLC_LIBRARY + adolc + PATHS $ENV{ADOLC_DIR}/lib + $ENV{ADOLC_DIR}/lib64 + /usr/lib/adolc + /usr/local/lib + /usr/local/lib/adolc/ + /opt/local/lib/adolc/ + "c:\\libs\\adolc\\lib" + "c:\\libs\\adolc\\lib" + ${PROJECT_SOURCE_DIR}/MacOS/Libs/adolc/lib + /usr/lib64/adolc + /usr/local/lib64 + /usr/local/lib64/adolc/ + /opt/local/lib64/adolc/ + "c:\\libs\\adolc\\lib64" + "c:\\libs\\adolc\\lib64" + ${PROJECT_SOURCE_DIR}/MacOS/Libs/adolc/lib64 + DOC "ADOL-C library" + ) + +set(ADOLC_INCLUDE_DIRS "${ADOLC_INCLUDE_DIR}" ) +set(ADOLC_LIBRARIES "${ADOLC_LIBRARY}" ) + + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(ADOLC DEFAULT_MSG + ADOLC_LIBRARY ADOLC_INCLUDE_DIR) + +mark_as_advanced(ADOLC_INCLUDE_DIR ADOLC_LIBRARY) + +endif(ADOLC_INCLUDE_DIR) diff --git a/src/external/CoMISo/cmake/FindARPACK.cmake b/src/external/CoMISo/cmake/FindARPACK.cmake new file mode 100644 index 000000000..55c68ef46 --- /dev/null +++ b/src/external/CoMISo/cmake/FindARPACK.cmake @@ -0,0 +1,43 @@ +# - Try to find ARPACK +# Once done this will define +# +# ARPACK_FOUND - system has ARPACK +# ARPACK_INCLUDE_DIR - the ARPACK include directories +# ARPACK_LIBRARY - Link this to use ARPACK +# ARPACKpp_LIBRARY - Link this to use ARPACK++ +# ARPACK_LIBRARIES - Link this to use ARPACK together with ARPACK++ + + +find_path (ARPACK_INCLUDE_DIR NAMES arpack++/argeig.h + HINTS ENV ARPACK_INCLUDE_DIR + PATHS /usr/include/arpack++ $ENV{HOME}/opt/arpack++/include "C:\\libs\\arpack++\\include" + DOC "ARPACK Include Directory") + +IF ( WIN32 ) +find_library( ARPACK_LIBRARY arpack.lib + PATHS "C:\\libs\\arpack++\\lib" + ) +ELSE( WIN32 ) + find_library( ARPACK_LIBRARY arpack + PATHS /usr/lib /usr/lib64 + ) + find_library( ARPACKpp_LIBRARY arpack++ + PATHS /usr/lib /usr/lib64 ${ARPACK_INCLUDE_DIR}/../src/.libs + ) + + list( APPEND ARPACK_LIBRARIES ${ARPACK_LIBRARY} ) + IF(ARPACKpp_LIBRARY) + list( APPEND ARPACK_LIBRARIES ${ARPACKpp_LIBRARY} ) + ENDIF(ARPACKpp_LIBRARY) + +ENDIF( WIN32 ) + +IF (ARPACK_INCLUDE_DIR AND ARPACK_LIBRARY) + SET(ARPACK_FOUND TRUE) +ELSE () + SET(ARPACK_FOUND FALSE) +ENDIF () + + + + diff --git a/src/external/CoMISo/cmake/FindBLAS.cmake b/src/external/CoMISo/cmake/FindBLAS.cmake new file mode 100644 index 000000000..22b1d3e94 --- /dev/null +++ b/src/external/CoMISo/cmake/FindBLAS.cmake @@ -0,0 +1,446 @@ +# Find BLAS library +# +# This module finds an installed library that implements the BLAS +# linear-algebra interface (see http://www.netlib.org/blas/). +# The list of libraries searched for is mainly taken +# from the autoconf macro file, acx_blas.m4 (distributed at +# http://ac-archive.sourceforge.net/ac-archive/acx_blas.html). +# +# This module sets the following variables: +# BLAS_FOUND - set to true if a library implementing the BLAS interface +# is found +# BLAS_INCLUDE_DIR - Directories containing the BLAS header files +# BLAS_DEFINITIONS - Compilation options to use BLAS +# BLAS_LINKER_FLAGS - Linker flags to use BLAS (excluding -l +# and -L). +# BLAS_LIBRARY_DIR - Directories containing the BLAS libraries. +# May be null if BLAS_LIBRARIES contains libraries name using full path. +# BLAS_LIBRARIES - List of libraries to link against BLAS interface. +# May be null if the compiler supports auto-link (e.g. VC++). +# BLAS_USE_FILE - The name of the cmake module to include to compile +# applications or libraries using BLAS. +# +# This module was modified by CGAL team: +# - find BLAS library shipped with TAUCS +# - find libraries for a C++ compiler, instead of Fortran +# - added BLAS_INCLUDE_DIR, BLAS_DEFINITIONS and BLAS_LIBRARY_DIR +# - removed BLAS95_LIBRARIES +# +# TODO (CGAL): +# - find CBLAS (http://www.netlib.org/cblas) on Unix? + + +include(CheckFunctionExists) + +include(CGAL_GeneratorSpecificSettings) + + +# This macro checks for the existence of the combination of fortran libraries +# given by _list. If the combination is found, this macro checks (using the +# check_function_exists macro) whether can link against that library +# combination using the name of a routine given by _name using the linker +# flags given by _flags. If the combination of libraries is found and passes +# the link test, LIBRARIES is set to the list of complete library paths that +# have been found and DEFINITIONS to the required definitions. +# Otherwise, LIBRARIES is set to FALSE. +# N.B. _prefix is the prefix applied to the names of all cached variables that +# are generated internally and marked advanced by this macro. +macro(check_fortran_libraries DEFINITIONS LIBRARIES _prefix _name _flags _list _path) + #message("DEBUG: check_fortran_libraries(${_list} in ${_path})") + + # Check for the existence of the libraries given by _list + set(_libraries_found TRUE) + set(_libraries_work FALSE) + set(${DEFINITIONS} "") + set(${LIBRARIES} "") + set(_combined_name) + foreach(_library ${_list}) + set(_combined_name ${_combined_name}_${_library}) + + if(_libraries_found) + # search first in ${_path} + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS ${_path} NO_DEFAULT_PATH + ) + # if not found, search in environment variables and system + if ( WIN32 ) + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS ENV LIB + ) + elseif ( APPLE ) + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 ENV DYLD_LIBRARY_PATH + ) + else () + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 ENV LD_LIBRARY_PATH + ) + endif() + mark_as_advanced(${_prefix}_${_library}_LIBRARY) + set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) + set(_libraries_found ${${_prefix}_${_library}_LIBRARY}) + endif(_libraries_found) + endforeach(_library ${_list}) + if(_libraries_found) + set(_libraries_found ${${LIBRARIES}}) + endif() + + # Test this combination of libraries with the Fortran/f2c interface. + # We test the Fortran interface first as it is well standardized. + if(_libraries_found AND NOT _libraries_work) + set(${DEFINITIONS} "-D${_prefix}_USE_F2C") + set(${LIBRARIES} ${_libraries_found}) + # Some C++ linkers require the f2c library to link with Fortran libraries. + # I do not know which ones, thus I just add the f2c library if it is available. + find_package( F2C QUIET ) + if ( F2C_FOUND ) + set(${DEFINITIONS} ${${DEFINITIONS}} ${F2C_DEFINITIONS}) + set(${LIBRARIES} ${${LIBRARIES}} ${F2C_LIBRARIES}) + endif() + set(CMAKE_REQUIRED_DEFINITIONS ${${DEFINITIONS}}) + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}}) + #message("DEBUG: CMAKE_REQUIRED_DEFINITIONS = ${CMAKE_REQUIRED_DEFINITIONS}") + #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}") + # Check if function exists with f2c calling convention (ie a trailing underscore) + check_function_exists(${_name}_ ${_prefix}_${_name}_${_combined_name}_f2c_WORKS) + set(CMAKE_REQUIRED_DEFINITIONS} "") + set(CMAKE_REQUIRED_LIBRARIES "") + mark_as_advanced(${_prefix}_${_name}_${_combined_name}_f2c_WORKS) + set(_libraries_work ${${_prefix}_${_name}_${_combined_name}_f2c_WORKS}) + endif(_libraries_found AND NOT _libraries_work) + + # If not found, test this combination of libraries with a C interface. + # A few implementations (ie ACML) provide a C interface. Unfortunately, there is no standard. + if(_libraries_found AND NOT _libraries_work) + set(${DEFINITIONS} "") + set(${LIBRARIES} ${_libraries_found}) + set(CMAKE_REQUIRED_DEFINITIONS "") + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}}) + #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}") + check_function_exists(${_name} ${_prefix}_${_name}${_combined_name}_WORKS) + set(CMAKE_REQUIRED_LIBRARIES "") + mark_as_advanced(${_prefix}_${_name}${_combined_name}_WORKS) + set(_libraries_work ${${_prefix}_${_name}${_combined_name}_WORKS}) + endif(_libraries_found AND NOT _libraries_work) + + # on failure + if(NOT _libraries_work) + set(${DEFINITIONS} "") + set(${LIBRARIES} FALSE) + endif() + #message("DEBUG: ${DEFINITIONS} = ${${DEFINITIONS}}") + #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}") +endmacro(check_fortran_libraries) + + +# +# main +# + +# Is it already configured? +if (BLAS_LIBRARY_DIR OR BLAS_LIBRARIES) + + set(BLAS_FOUND TRUE) + +else() + + # reset variables + set( BLAS_INCLUDE_DIR "" ) + set( BLAS_DEFINITIONS "" ) + set( BLAS_LINKER_FLAGS "" ) + set( BLAS_LIBRARIES "" ) + set( BLAS_LIBRARY_DIR "" ) + + # Look first for the TAUCS library distributed with CGAL in auxiliary/taucs. + # Set CGAL_TAUCS_FOUND, CGAL_TAUCS_INCLUDE_DIR and CGAL_TAUCS_LIBRARIES_DIR. + include(CGAL_Locate_CGAL_TAUCS) + + # Search for BLAS in CGAL_TAUCS_INCLUDE_DIR/CGAL_TAUCS_LIBRARIES_DIR (TAUCS shipped with CGAL), + # else in $BLAS_INC_DIR/$BLAS_LIB_DIR environment variables. + if(CGAL_TAUCS_FOUND AND CGAL_AUTO_LINK_ENABLED) + + # if VC++: done + set( BLAS_INCLUDE_DIR "${CGAL_TAUCS_INCLUDE_DIR}" ) + set( BLAS_LIBRARY_DIR "${CGAL_TAUCS_LIBRARIES_DIR}" ) + + else(CGAL_TAUCS_FOUND AND CGAL_AUTO_LINK_ENABLED) + + # + # If Unix, search for BLAS function in possible libraries + # + + # BLAS in ATLAS library? (http://math-atlas.sourceforge.net/) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "cblas;f77blas;atlas" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # BLAS in PhiPACK libraries? (requires generic BLAS lib, too) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "sgemm;dgemm;blas" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # BLAS in Alpha CXML library? + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "cxml" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # BLAS in Alpha DXML library? (now called CXML, see above) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "dxml" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # BLAS in Sun Performance library? + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "-xlic_lib=sunperf" + "sunperf;sunmath" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + if(BLAS_LIBRARIES) + # Extra linker flag + set(BLAS_LINKER_FLAGS "-xlic_lib=sunperf") + endif() + endif() + + # BLAS in SCSL library? (SGI/Cray Scientific Library) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "scsl" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # BLAS in SGIMATH library? + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "complib.sgimath" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # BLAS in IBM ESSL library? (requires generic BLAS lib, too) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "essl;blas" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + #BLAS in intel mkl 10 library? (em64t 64bit) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "mkl_intel_lp64;mkl_intel_thread;mkl_core;guide;pthread" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + ### windows version of intel mkl 10? + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + SGEMM + "" + "mkl_c_dll;mkl_intel_thread_dll;mkl_core_dll;libguide40" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + #older versions of intel mkl libs + + # BLAS in intel mkl library? (shared) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "mkl;guide;pthread" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + #BLAS in intel mkl library? (static, 32bit) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "mkl_ia32;guide;pthread" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + #BLAS in intel mkl library? (static, em64t 64bit) + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "mkl_em64t;guide;pthread" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + #BLAS in acml library? + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "acml" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + # Apple BLAS library? + if(NOT BLAS_LIBRARIES) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "Accelerate" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + if ( NOT BLAS_LIBRARIES ) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "vecLib" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif ( NOT BLAS_LIBRARIES ) + + # Generic BLAS library? + # This configuration *must* be the last try as this library is notably slow. + if ( NOT BLAS_LIBRARIES ) + check_fortran_libraries( + BLAS_DEFINITIONS + BLAS_LIBRARIES + BLAS + sgemm + "" + "blas" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV BLAS_LIB_DIR" + ) + endif() + + endif(CGAL_TAUCS_FOUND AND CGAL_AUTO_LINK_ENABLED) + + if(BLAS_LIBRARY_DIR OR BLAS_LIBRARIES) + set(BLAS_FOUND TRUE) + else() + set(BLAS_FOUND FALSE) + endif() + + if(NOT BLAS_FIND_QUIETLY) + if(BLAS_FOUND) + message(STATUS "A library with BLAS API found.") + else(BLAS_FOUND) + if(BLAS_FIND_REQUIRED) + message(FATAL_ERROR "A required library with BLAS API not found. Please specify library location.") + else() + message(STATUS "A library with BLAS API not found. Please specify library location.") + endif() + endif(BLAS_FOUND) + endif(NOT BLAS_FIND_QUIETLY) + + # Add variables to cache + set( BLAS_INCLUDE_DIR "${BLAS_INCLUDE_DIR}" + CACHE PATH "Directories containing the BLAS header files" FORCE ) + set( BLAS_DEFINITIONS "${BLAS_DEFINITIONS}" + CACHE STRING "Compilation options to use BLAS" FORCE ) + set( BLAS_LINKER_FLAGS "${BLAS_LINKER_FLAGS}" + CACHE STRING "Linker flags to use BLAS" FORCE ) + set( BLAS_LIBRARIES "${BLAS_LIBRARIES}" + CACHE FILEPATH "BLAS libraries name" FORCE ) + set( BLAS_LIBRARY_DIR "${BLAS_LIBRARY_DIR}" + CACHE PATH "Directories containing the BLAS libraries" FORCE ) + + #message("DEBUG: BLAS_INCLUDE_DIR = ${BLAS_INCLUDE_DIR}") + #message("DEBUG: BLAS_DEFINITIONS = ${BLAS_DEFINITIONS}") + #message("DEBUG: BLAS_LINKER_FLAGS = ${BLAS_LINKER_FLAGS}") + #message("DEBUG: BLAS_LIBRARIES = ${BLAS_LIBRARIES}") + #message("DEBUG: BLAS_LIBRARY_DIR = ${BLAS_LIBRARY_DIR}") + #message("DEBUG: BLAS_FOUND = ${BLAS_FOUND}") + +endif(BLAS_LIBRARY_DIR OR BLAS_LIBRARIES) + +if(BLAS_FOUND) + set(BLAS_USE_FILE "CGAL_UseBLAS") +endif(BLAS_FOUND) diff --git a/src/external/CoMISo/cmake/FindCGAL.cmake b/src/external/CoMISo/cmake/FindCGAL.cmake new file mode 100644 index 000000000..9818f078a --- /dev/null +++ b/src/external/CoMISo/cmake/FindCGAL.cmake @@ -0,0 +1,107 @@ +# - Find CGAL +# Find the CGAL autolinking headers. +# +# CGAL_INCLUDE_DIR - where to find CGAL.h, etc. +# CGAL_FOUND - True if CGAL found. + +IF (CGAL_INCLUDE_DIR) + # Already in cache, be silent + SET(CGAL_FIND_QUIETLY TRUE) +ENDIF (CGAL_INCLUDE_DIR) + +GET_FILENAME_COMPONENT(module_file_path ${CMAKE_CURRENT_LIST_FILE} PATH ) + +IF (NOT APPLE ) + # Look for the header file. + FIND_PATH(CGAL_INCLUDE_DIR NAMES CGAL/auto_link/auto_link.h + PATHS /usr/include + ../../External/include + "C:/libs/CGAL-3.6/include" + "C:/Program Files/CGAL-3.5/include" + "C:/Programme/CGAL-3.5/include" + "C:/libs/CGAL-3.5/include" + "C:/Program Files/CGAL-3.4/include" + "C:/Programme/CGAL-3.4/include" + "C:/libs/CGAL-3.4/include" + "C:/Programme/CGAL-3.9/include" + "C:/Program Files/CGAL-3.9/include" + "C:/Program Files (x86)/CGAL-3.9/include" + ${module_file_path}/../../../External/include) +ELSE( NOT APPLE) + # Look for the header file. + FIND_PATH(CGAL_INCLUDE_DIR NAMES CGAL/auto_link/auto_link.h + PATHS "/opt/local/include" + ) + +ENDIF( NOT APPLE ) + + + +MARK_AS_ADVANCED(CGAL_INCLUDE_DIR) + + +# Copy the results to the output variables. +IF(CGAL_INCLUDE_DIR ) + SET(CGAL_FOUND 1) + SET(CGAL_INCLUDE_DIR ${CGAL_INCLUDE_DIR}) + # Look for the taucs dir. + FIND_PATH(CGAL_TAUCS_DIR NAMES include/taucs.h + PATHS ${CGAL_INCLUDE_DIR}/../auxiliary/taucs) + + IF(WIN32) + include(CGAL_GeneratorSpecificSettings) + find_path(CGAL_LIBRARY_DIR + NAMES "CGAL-${CGAL_TOOLSET}-mt.lib" "CGAL-${CGAL_TOOLSET}-mt-gd.lib" + PATHS "${CGAL_INCLUDE_DIR}/../lib" + DOC "Directory containing the CGAL library" + ) + #add_definitions (-DCGAL_AUTOLINK) + ELSEIF( APPLE) + find_path(CGAL_LIBRARY_DIR + NAMES "libCGAL.dylib" + PATHS "/opt/local/lib/" + DOC "Directory containing the CGAL library" + ) + list ( APPEND CGAL_LIBRARIES CGAL CGAL_Core CGAL_ImageIO mpfr ) + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -frounding-math") + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -frounding-math") + + ELSE( WIN32 ) + find_path(CGAL_LIBRARY_DIR + NAMES "libCGAL.so" + PATHS "/usr/lib/" "/usr/lib64" + DOC "Directory containing the CGAL library" + ) + list ( APPEND CGAL_LIBRARIES CGAL CGAL_Core CGAL_ImageIO CGAL_Qt4) + set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -frounding-math") + set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -frounding-math") + + + # This is needed to link correctly against lapack + add_definitions (-DCGAL_USE_F2C) + ENDIF(WIN32) + + + + +ELSE(CGAL_INCLUDE_DIR ) + SET(CGAL_FOUND 0) + SET(CGAL_INCLUDE_DIR) +ENDIF(CGAL_INCLUDE_DIR ) + +# Report the results. +IF(NOT CGAL_FOUND) + SET(CGAL_DIR_MESSAGE + "CGAL was not found. Make sure CGAL_INCLUDE_DIR is set to the directories containing the include files for CGAL. .") + IF(CGAL_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "${CGAL_DIR_MESSAGE}") + ELSEIF(NOT CGAL_FIND_QUIETLY) + MESSAGE(STATUS "${CGAL_DIR_MESSAGE}") + ELSE(NOT CGAL_FIND_QUIETLY) + ENDIF(CGAL_FIND_REQUIRED) +ELSE (NOT CGAL_FOUND) + IF(NOT CGAL_FIND_QUIETLY) + MESSAGE(STATUS "Looking for CGAL - found") + ENDIF(NOT CGAL_FIND_QUIETLY) +ENDIF(NOT CGAL_FOUND) + diff --git a/src/external/CoMISo/cmake/FindCPLEX.cmake b/src/external/CoMISo/cmake/FindCPLEX.cmake new file mode 100644 index 000000000..bc6215e22 --- /dev/null +++ b/src/external/CoMISo/cmake/FindCPLEX.cmake @@ -0,0 +1,67 @@ +# - Try to find CPLEX +# Once done this will define +# CPLEX_FOUND - System has Cplex +# CPLEX_INCLUDE_DIRS - The Cplex include directories +# CPLEX_LIBRARIES - The libraries needed to use Cplex + +if (CPLEX_INCLUDE_DIR) + # in cache already + set(CPLEX_FOUND TRUE) + set(CPLEX_INCLUDE_DIRS "${CPLEX_INCLUDE_DIR};${CPLEX_CONCERT_INCLUDE_DIR}" ) + set(CPLEX_LIBRARIES "${CPLEX_LIBRARY};${CPLEX_ILO_LIBRARY};${CPLEX_CONCERT_LIBRARY};${CPLEX_PTHREAD_LIBRARY}" ) +else (CPLEX_INCLUDE_DIR) + +find_path(CPLEX_INCLUDE_DIR + NAMES ilcplex/cplex.h + PATHS "$ENV{CPLEX_DIR}/cplex/include" + ) + +find_path(CPLEX_CONCERT_INCLUDE_DIR + NAMES ilconcert/ilomodel.h + PATHS "$ENV{CPLEX_DIR}/concert/include" + ) + +find_library( CPLEX_LIBRARY + cplex + PATHS "$ENV{CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic" + "$ENV{CPLEX_DIR}/cplex/lib/x86-64_darwin/static_pic/" + ) + +find_library( CPLEX_ILO_LIBRARY + ilocplex + PATHS "$ENV{CPLEX_DIR}/cplex/lib/x86-64_sles10_4.1/static_pic" + "$ENV{CPLEX_DIR}/cplex/lib/x86-64_darwin/static_pic/" + ) + +find_library( CPLEX_CONCERT_LIBRARY + concert + PATHS "$ENV{CPLEX_DIR}/concert/lib/x86-64_sles10_4.1/static_pic" + "$ENV{CPLEX_DIR}/concert/lib/x86-64_darwin/static_pic/" + ) + +find_library( CPLEX_PTHREAD_LIBRARY + pthread + PATHS "/usr/lib" + "/usr/lib64" + "/lib" + "/lib64" + ) + + +set(CPLEX_INCLUDE_DIRS "${CPLEX_INCLUDE_DIR};${CPLEX_CONCERT_INCLUDE_DIR}" ) +#set(CPLEX_LIBRARIES "${CPLEX_LIBRARY};${CPLEX_ILO_LIBRARY};${CPLEX_CONCERT_LIBRARY}" ) +set(CPLEX_LIBRARIES "${CPLEX_LIBRARY};${CPLEX_ILO_LIBRARY};${CPLEX_CONCERT_LIBRARY};${CPLEX_PTHREAD_LIBRARY}" ) + + +# use c++ headers as default +set(CPLEX_COMPILER_FLAGS "-DIL_STD" CACHE STRING "Cplex Compiler Flags") + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(CPLEX DEFAULT_MSG + CPLEX_LIBRARY CPLEX_INCLUDE_DIR CPLEX_CONCERT_INCLUDE_DIR CPLEX_ILO_LIBRARY CPLEX_CONCERT_LIBRARY) + +mark_as_advanced(CPLEX_INCLUDE_DIR CPLEX_LIBRARY CPLEX_CONCERT_INCLUDE_DIR CPLEX_ILO_LIBRARY CPLEX_CONCERT_LIBRARY CPLEX_PTHREAD_LIBRARY) + +endif(CPLEX_INCLUDE_DIR) diff --git a/src/external/CoMISo/cmake/FindCoMISo.cmake b/src/external/CoMISo/cmake/FindCoMISo.cmake new file mode 100644 index 000000000..299c4671c --- /dev/null +++ b/src/external/CoMISo/cmake/FindCoMISo.cmake @@ -0,0 +1,227 @@ +# - Try to find COMISO +# Once done this will define +# +# COMISO_FOUND - system has COMISO +# COMISO_INCLUDE_DIR - the COMISO include directory +# COMISO_LIBRARY_DIR - where the libraries are +# COMISO_LIBRARY - Link these to use COMISO + + +IF (COMISO_INCLUDE_DIR) + # Already in cache, be silent + SET(COMISO_FIND_QUIETLY TRUE) +ENDIF (COMISO_INCLUDE_DIR) + + +# Find CoMISo config file +FIND_PATH( COMISO_INCLUDE_DIR CoMISo/Config/config.hh + PATHS "${CMAKE_SOURCE_DIR}/../" "${CMAKE_SOURCE_DIR}/libs/" ) + +if ( COMISO_INCLUDE_DIR ) + + FILE(READ ${COMISO_INCLUDE_DIR}/CoMISo/Config/config.hh CURRENT_COMISO_CONFIG) + + set(COMISO_OPT_DEPS "") + + + STRING(REGEX MATCH "\#define COMISO_MPI_AVAILABLE 1" COMISO_MPI_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_MPI_BUILD_TIME_AVAILABLE ) + + find_package(MPI) + + if ( NOT MPI_FOUND ) + message(ERROR "COMISO configured with mpi but mpi not available") + endif() + + list (APPEND COMISO_OPT_DEPS "MPI") + + endif() + + STRING(REGEX MATCH "\#define COMISO_BOOST_AVAILABLE 1" COMISO_BOOST_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_BOOST_BUILD_TIME_AVAILABLE ) + + find_package( Boost 1.42.0 COMPONENTS system filesystem regex QUIET) + + if ( NOT Boost_FOUND ) + message(ERROR "COMISO configured with Boost but Boost not available") + endif() + + list (APPEND COMISO_OPT_DEPS "Boost") + + endif() + + + STRING(REGEX MATCH "\#define COMISO_SUITESPARSE_AVAILABLE 1" COMISO_SUITESPARSE_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_SUITESPARSE_BUILD_TIME_AVAILABLE ) + + find_package(SUITESPARSE) + + if ( NOT SUITESPARSE_FOUND ) + message(ERROR "COMISO configured with Suitesparse but Suitesparse not available") + endif() + + list (APPEND COMISO_OPT_DEPS "SUITESPARSE") + + endif() + + STRING(REGEX MATCH "\#define COMISO_PETSC_AVAILABLE 1" COMISO_PETSC_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_PETSC_BUILD_TIME_AVAILABLE ) + + find_package(PETSC) + + if ( NOT PETSC_FOUND ) + message(ERROR "COMISO configured with petsc but petsc not available") + endif() + + list (APPEND COMISO_OPT_DEPS "PETSC") + + endif() + + STRING(REGEX MATCH "\#define COMISO_IPOPT_AVAILABLE 1" COMISO_IPOPT_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_IPOPT_BUILD_TIME_AVAILABLE ) + + find_package(IPOPT) + + if ( NOT IPOPT_FOUND ) + message(ERROR "COMISO configured with ipopt but ipopt not available") + endif() + + list (APPEND COMISO_OPT_DEPS "IPOPT") + + endif() + + STRING(REGEX MATCH "\#define COMISO_METIS_AVAILABLE 1" COMISO_METIS_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_METIS_BUILD_TIME_AVAILABLE ) + + find_package(METIS) + + if ( NOT METIS_FOUND ) + message(ERROR "COMISO configured with Metis but Metis not available") + endif() + + list (APPEND COMISO_OPT_DEPS "METIS") + + endif() + + STRING(REGEX MATCH "\#define COMISO_MUMPS_AVAILABLE 1" COMISO_MUMPS_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_MUMPS_BUILD_TIME_AVAILABLE ) + + find_package(MUMPS) + + if ( NOT MUMPS_FOUND ) + message(ERROR "COMISO configured with mumps but mumps not available") + endif() + + list (APPEND COMISO_OPT_DEPS "MUMPS") + + endif() + + STRING(REGEX MATCH "\#define COMISO_TAO_AVAILABLE 1" COMISO_TAO_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_TAO_BUILD_TIME_AVAILABLE ) + + find_package(TAO) + + if ( NOT TAO_FOUND ) + message(ERROR "COMISO configured with tao but tao not available") + endif() + + list (APPEND COMISO_OPT_DEPS "TAO") + endif() + + STRING(REGEX MATCH "\#define COMISO_TAUCS_AVAILABLE 1" COMISO_TAUCS_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_TAUCS_BUILD_TIME_AVAILABLE ) + + find_package(Taucs) + + if ( NOT TAUCS_FOUND ) + message(ERROR "COMISO configured with Taucs but Taucs not available") + endif() + + list (APPEND COMISO_OPT_DEPS "Taucs") + + endif() + + STRING(REGEX MATCH "\#define COMISO_GUROBI_AVAILABLE 1" COMISO_GUROBI_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_GUROBI_BUILD_TIME_AVAILABLE ) + + find_package(GUROBI) + + if ( NOT GUROBI_FOUND ) + message(ERROR "COMISO configured with GUROBI but GUROBI not available") + endif() + + list (APPEND COMISO_OPT_DEPS "GUROBI") + + endif() + + + STRING(REGEX MATCH "\#define COMISO_ARPACK_AVAILABLE 1" COMISO_ARPACK_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_ARPACK_BUILD_TIME_AVAILABLE ) + + find_package(ARPACK) + + if ( NOT ARPACK_FOUND ) + message(ERROR "COMISO configured with ARPACK but ARPACK not available") + endif() + + list (APPEND COMISO_OPT_DEPS "ARPACK") + + endif() + + STRING(REGEX MATCH "\#define COMISO_CPLEX_AVAILABLE 1" COMISO_CPLEX_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_CPLEX_BUILD_TIME_AVAILABLE ) + + find_package(CPLEX) + + if ( NOT CPLEX_FOUND ) + message(ERROR "COMISO configured with CPLEX but CPLEX not available") + endif() + + list (APPEND COMISO_OPT_DEPS "CPLEX") + + endif() + + STRING(REGEX MATCH "\#define COMISO_EIGEN3_AVAILABLE 1" COMISO_EIGEN3_BUILD_TIME_AVAILABLE ${CURRENT_COMISO_CONFIG} ) + + if ( COMISO_EIGEN3_BUILD_TIME_AVAILABLE ) + + find_package(EIGEN3) + + if ( NOT EIGEN3_FOUND ) + message(ERROR "COMISO configured with EIGEN3 but EIGEN3 not available") + endif() + + list (APPEND COMISO_OPT_DEPS "EIGEN3") + + endif() + + add_definitions (-DCOMISODLL -DUSECOMISO ) + +endif(COMISO_INCLUDE_DIR) + +IF (COMISO_INCLUDE_DIR) + include(FindPackageHandleStandardArgs) + SET(COMISO_FOUND TRUE) + SET( COMISO_LIBRARY_DIR "${CMAKE_BINARY_DIR}/Build/${ACG_PROJECT_LIBDIR}" ) + SET( COMISO_LIBRARY "CoMISo") +# SET( COMISO_DEPS "GMM;BLAS;SUITESPARSE" ) + SET( COMISO_DEPS "GMM") +# SET( COMISO_OPT_DEPS ${COMISO_OPT_DEPS} CACHE STRING "Comiso optional dependecies") +# mark_as_advanced(COMISO_DEPS COMISO_OPT_DEPS) +ELSE (COMISO_INCLUDE_DIR) + SET( COMISO_FOUND FALSE ) + SET( COMISO_LIBRARY_DIR ) +ENDIF (COMISO_INCLUDE_DIR) + diff --git a/src/external/CoMISo/cmake/FindEIGEN3.cmake b/src/external/CoMISo/cmake/FindEIGEN3.cmake new file mode 100644 index 000000000..3e306a702 --- /dev/null +++ b/src/external/CoMISo/cmake/FindEIGEN3.cmake @@ -0,0 +1,37 @@ +# - Try to find EIGEN3 +# Once done this will define +# EIGEN3_FOUND - System has EIGEN3 +# EIGEN3_INCLUDE_DIRS - The EIGEN3 include directories + +if (EIGEN3_INCLUDE_DIR) + # in cache already + set(EIGEN3_FOUND TRUE) + set(EIGEN3_INCLUDE_DIRS "${EIGEN3_INCLUDE_DIR}" ) +else (EIGEN3_INCLUDE_DIR) + +find_path( EIGEN3_INCLUDE_DIR + NAMES Eigen/Dense + PATHS $ENV{EIGEN_DIR} + /usr/include/eigen3 + /usr/local/include + /usr/local/include/eigen3/ + /opt/local/include/eigen3/ + "d:\\code\\vcglib\\eigenlib\\" + "c:\\libs\\eigen\\include" + ${PROJECT_SOURCE_DIR}/MacOS/Libs/eigen3/include + ../../External/include + ${module_file_path}/../../../External/include + ) + +set(EIGEN3_INCLUDE_DIRS "${EIGEN3_INCLUDE_DIR}" ) + + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(EIGEN3 DEFAULT_MSG + EIGEN3_INCLUDE_DIR) + +mark_as_advanced(EIGEN3_INCLUDE_DIR) + +endif(EIGEN3_INCLUDE_DIR) diff --git a/src/external/CoMISo/cmake/FindGMM.cmake b/src/external/CoMISo/cmake/FindGMM.cmake new file mode 100644 index 000000000..c1389f938 --- /dev/null +++ b/src/external/CoMISo/cmake/FindGMM.cmake @@ -0,0 +1,50 @@ +# - Try to find GMM +# Once done this will define +# GMM_FOUND - System has GMM +# GMM_INCLUDE_DIRS - The GMM include directories +# GMM_COMPILER_FLAGS - Compiler flags that are necessary for GMM + +if (GMM_INCLUDE_DIR) + # in cache already + set(GMM_FOUND TRUE) + set(GMM_INCLUDE_DIRS "${GMM_INCLUDE_DIR}" ) +else (GMM_INCLUDE_DIR) + +find_path( GMM_INCLUDE_DIR + NAMES gmm/gmm.h + PATHS $ENV{GMM_DIR} + /usr/include + /usr/include + /usr/local/include + ~/sw/gmm-4.1/include + "d:\\code\\gmm-4.2\\include" + "c:\\libs\\gmm-3.0\\include" + ${PROJECT_SOURCE_DIR}/MacOS/Libs/gmm-3.1/include + ../../External/include + /ACG/acgdev/gcc-4.3-i686/gmm-4.1/include/ + /ACG/acgdev/gcc-4.3-i686/gmm-3/include/ + ${module_file_path}/../../../External/include + $ENV{HOME}/opt/gmm/gmm-4.2/include + ) + +set(GMM_INCLUDE_DIRS "${GMM_INCLUDE_DIR}" ) + + +# use c++ headers as default +IF (WIN32) + set(GMM_COMPILER_FLAGS "-D_SCL_SECURE_NO_DEPRECATE" CACHE STRING "GMM Compiler Flags") +# add_definitions(-D_SCL_SECURE_NO_DEPRECATE) +ELSE(WIN32) + set(GMM_COMPILER_FLAGS "" CACHE STRING "GMM Compiler Flags") +ENDIF(WIN32) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(GMM DEFAULT_MSG + GMM_INCLUDE_DIR) + +mark_as_advanced(GMM_INCLUDE_DIR GMM_COMPILER_FLAGS) + +endif(GMM_INCLUDE_DIR) + diff --git a/src/external/CoMISo/cmake/FindGMP.cmake b/src/external/CoMISo/cmake/FindGMP.cmake new file mode 100644 index 000000000..cb1dd2f07 --- /dev/null +++ b/src/external/CoMISo/cmake/FindGMP.cmake @@ -0,0 +1,64 @@ +# Try to find the GMP libraries +# GMP_FOUND - system has GMP lib +# GMP_INCLUDE_DIR - the GMP include directory +# GMP_LIBRARY_DIR - Directory where the GMP libraries are located +# GMP_LIBRARIES - the GMP libraries +# GMP_IN_CGAL_AUXILIARY - TRUE if the GMP found is the one distributed with CGAL in the auxiliary folder + +# TODO: support MacOSX + +include(CGAL_FindPackageHandleStandardArgs) +include(CGAL_GeneratorSpecificSettings) + +# Is it already configured? +if (GMP_INCLUDE_DIR AND GMP_LIBRARY_DIR ) + + set(GMP_FOUND TRUE) + +else() + find_package(CGAL) + if (NOT CGAL_FOUND) + message(STATUS "CGAL not found .. required to use taucs!") + set(GMP_FOUND FALSE) + else () + find_path(GMP_INCLUDE_DIR + NAMES gmp.h + PATHS "${CGAL_INCLUDE_DIR}/../auxiliary/gmp/include" + DOC "The directory containing the GMP header files" + ) + + if ( GMP_INCLUDE_DIR STREQUAL "${CMAKE_SOURCE_DIR}/auxiliary/gmp/include" ) + cache_set( GMP_IN_CGAL_AUXILIARY TRUE ) + endif() + + if ( CGAL_AUTO_LINK_ENABLED ) + message("AAAA") + find_path(GMP_LIBRARY_DIR + NAMES "gmp-${CGAL_TOOLSET}-mt.lib" "gmp-${CGAL_TOOLSET}-mt-gd.lib" libgmp-10.lib + PATHS "${CGAL_INCLUDE_DIR}/../auxiliary/gmp/lib" + DOC "Directory containing the GMP library" + ) + + list ( APPEND GMP_LIBRARIES libgmp-10.lib;libmpfr-4.lib ) + else() + + find_library(GMP_LIBRARIES NAMES gmp + PATHS ENV GMP_LIB_DIR + DOC "Path to the GMP library" + ) + + if ( GMP_LIBRARIES ) + get_filename_component(GMP_LIBRARY_DIR ${GMP_LIBRARIES} PATH CACHE ) + endif() + + endif() + + # Attempt to load a user-defined configuration for GMP if couldn't be found + if ( NOT GMP_INCLUDE_DIR OR NOT GMP_LIBRARY_DIR ) + include( GMPConfig OPTIONAL ) + endif() + + find_package_handle_standard_args(GMP "DEFAULT_MSG" GMP_INCLUDE_DIR GMP_LIBRARY_DIR) + + endif() +endif() diff --git a/src/external/CoMISo/cmake/FindGUROBI.cmake b/src/external/CoMISo/cmake/FindGUROBI.cmake new file mode 100644 index 000000000..fa7f099cb --- /dev/null +++ b/src/external/CoMISo/cmake/FindGUROBI.cmake @@ -0,0 +1,52 @@ +# - Try to find GUROBI +# Once done this will define +# GUROBI_FOUND - System has Gurobi +# GUROBI_INCLUDE_DIRS - The Gurobi include directories +# GUROBI_LIBRARIES - The libraries needed to use Gurobi + +if (GUROBI_INCLUDE_DIR) + # in cache already + set(GUROBI_FOUND TRUE) + set(GUROBI_INCLUDE_DIRS "${GUROBI_INCLUDE_DIR}" ) + set(GUROBI_LIBRARIES "${GUROBI_LIBRARY};${GUROBI_CXX_LIBRARY}" ) +else (GUROBI_INCLUDE_DIR) + +find_path(GUROBI_INCLUDE_DIR + NAMES gurobi_c++.h + PATHS "$ENV{GUROBI_HOME}/include" + "/Library/gurobi502/mac64/include" + "C:\\libs\\gurobi502\\include" + ) + +find_library( GUROBI_LIBRARY + NAMES gurobi + gurobi45 + gurobi46 + gurobi50 + PATHS "$ENV{GUROBI_HOME}/lib" + "/Library/gurobi502/mac64/lib" + "C:\\libs\\gurobi502\\lib" + ) + +find_library( GUROBI_CXX_LIBRARY + NAMES gurobi_c++ + PATHS "$ENV{GUROBI_HOME}/lib" + "/Library/gurobi502/mac64/lib" + "C:\\libs\\gurobi502\\lib" + ) + +set(GUROBI_INCLUDE_DIRS "${GUROBI_INCLUDE_DIR}" ) +set(GUROBI_LIBRARIES "${GUROBI_LIBRARY};${GUROBI_CXX_LIBRARY}" ) + +# use c++ headers as default +# set(GUROBI_COMPILER_FLAGS "-DIL_STD" CACHE STRING "Gurobi Compiler Flags") + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(GUROBI DEFAULT_MSG + GUROBI_LIBRARY GUROBI_CXX_LIBRARY GUROBI_INCLUDE_DIR) + +mark_as_advanced(GUROBI_INCLUDE_DIR GUROBI_LIBRARY GUROBI_CXX_LIBRARY) + +endif(GUROBI_INCLUDE_DIR) diff --git a/src/external/CoMISo/cmake/FindIPOPT.cmake b/src/external/CoMISo/cmake/FindIPOPT.cmake new file mode 100644 index 000000000..3d6d624cb --- /dev/null +++ b/src/external/CoMISo/cmake/FindIPOPT.cmake @@ -0,0 +1,84 @@ +# - Try to find IPOPT +# Once done this will define +# IPOPT_FOUND - System has IpOpt +# IPOPT_INCLUDE_DIRS - The IpOpt include directories +# IPOPT_LIBRARY_DIRS - The library directories needed to use IpOpt +# IPOPT_LIBRARIES - The libraries needed to use IpOpt + + +if (IPOPT_INCLUDE_DIR) + # in cache already + SET(IPOPT_FIND_QUIETLY TRUE) +endif (IPOPT_INCLUDE_DIR) + +if (WIN32) + find_path(IPOPT_INCLUDE_DIR NAMES IpNLP.hpp + PATHS + "C:\\libs\\Ipopt-3.8.2\\include\\coin" + ${IPOPT_DIR}/include + ) + + IF(IPOPT_INCLUDE_DIR) + find_library( IPOPT_LIBRARY_RELEASE + Ipopt + PATHS "C:\\libs\\Ipopt-3.8.2\\lib\\win32\\release" ) + find_library( IPOPT_LIBRARY_DEBUG + Ipopt + PATHS "C:\\libs\\Ipopt-3.8.2\\lib\\win32\\debug" ) + + set ( IPOPT_LIBRARY "optimized;${IPOPT_LIBRARY_RELEASE};debug;${IPOPT_LIBRARY_DEBUG}" CACHE STRING "IPOPT Libraries" ) + + SET(IPOPT_FOUND TRUE) + SET(IPOPT_INCLUDE_DIR ${IPOPT_INCLUDE_DIR}) + # Todo, set right version depending on build type (debug/release) + #GET_FILENAME_COMPONENT( IPOPT_LIBRARY_DIR ${GLEW_LIBRARY} PATH ) + ELSE(IPOPT_INCLUDE_DIR) + SET(IPOPT_FOUND FALSE) + SET(IPOPT_INCLUDE_DIR ${IPOPT_INCLUDE_DIR}) + ENDIF(IPOPT_INCLUDE_DIR) + +ELSE( WIN32 ) + find_path(IPOPT_INCLUDE_DIR NAMES IpNLP.hpp + PATHS "$ENV{IPOPT_HOME}/include/coin" + "/usr/include/coin" + + ) + + find_library( IPOPT_LIBRARY + ipopt + PATHS "$ENV{IPOPT_HOME}/lib" + "/usr/lib" ) + + #wrong config under Debian workaround + add_definitions( -DHAVE_CSTDDEF ) + + + # set optional path to HSL Solver + find_path(IPOPT_HSL_LIBRARY_DIR + NAMES libhsl.so + libhsl.dylib + PATHS "$ENV{IPOPT_HSL_LIBRARY_PATH}" + "$ENV{HOME}/opt/HSL/lib" + ) + + IF( IPOPT_HSL_LIBRARY_DIR) + IF( NOT IPOPT_FIND_QUIETLY ) + message ( "IPOPT_HSL_LIBRARY_DIR found at ${IPOPT_HSL_LIBRARY_DIR} ") + ENDIF() + set(IPOPT_LIBRARY_DIR ${IPOPT_HSL_LIBRARY_DIR}) + LIST( APPEND IPOPT_LIBRARY_DIRS "${IPOPT_HSL_LIBRARY_DIR}") + ENDIF(IPOPT_HSL_LIBRARY_DIR) + + + set(IPOPT_INCLUDE_DIRS "${IPOPT_INCLUDE_DIR}" ) + set(IPOPT_LIBRARIES "${IPOPT_LIBRARY}" ) + + include(FindPackageHandleStandardArgs) + # handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE + # if all listed variables are TRUE + find_package_handle_standard_args(IPOPT DEFAULT_MSG + IPOPT_LIBRARY IPOPT_INCLUDE_DIR) + + mark_as_advanced(IPOPT_INCLUDE_DIR IPOPT_LIBRARY ) + +ENDIF() diff --git a/src/external/CoMISo/cmake/FindLAPACK.cmake b/src/external/CoMISo/cmake/FindLAPACK.cmake new file mode 100644 index 000000000..05e0027b2 --- /dev/null +++ b/src/external/CoMISo/cmake/FindLAPACK.cmake @@ -0,0 +1,302 @@ +# Find LAPACK library +# +# This module finds an installed library that implements the LAPACK +# linear-algebra interface (see http://www.netlib.org/lapack/). +# The approach follows mostly that taken for the autoconf macro file, acx_lapack.m4 +# (distributed at http://ac-archive.sourceforge.net/ac-archive/acx_lapack.html). +# +# This module sets the following variables: +# LAPACK_FOUND - set to true if a library implementing the LAPACK interface +# is found +# LAPACK_INCLUDE_DIR - Directories containing the LAPACK header files +# LAPACK_DEFINITIONS - Compilation options to use LAPACK +# LAPACK_LINKER_FLAGS - Linker flags to use LAPACK (excluding -l +# and -L). +# LAPACK_LIBRARY_DIR - Directories containing the LAPACK libraries. +# May be null if LAPACK_LIBRARIES contains libraries name using full path. +# LAPACK_LIBRARIES - List of libraries to link against LAPACK interface. +# May be null if the compiler supports auto-link (e.g. VC++). +# LAPACK_USE_FILE - The name of the cmake module to include to compile +# applications or libraries using LAPACK. +# +# This module was modified by CGAL team: +# - find LAPACK library shipped with TAUCS +# - find libraries for a C++ compiler, instead of Fortran +# - added LAPACK_INCLUDE_DIR, LAPACK_DEFINITIONS and LAPACK_LIBRARY_DIR +# - removed LAPACK95_LIBRARIES +# +# TODO (CGAL): +# - find CLAPACK (http://www.netlib.org/clapack) on Unix? + +include(CGAL_Macros) + +include(CheckFunctionExists) + +include(CGAL_GeneratorSpecificSettings) + + + +# This macro checks for the existence of the combination of fortran libraries +# given by _list. If the combination is found, this macro checks (using the +# check_function_exists macro) whether can link against that library +# combination using the name of a routine given by _name using the linker +# flags given by _flags. If the combination of libraries is found and passes +# the link test, LIBRARIES is set to the list of complete library paths that +# have been found and DEFINITIONS to the required definitions. +# Otherwise, LIBRARIES is set to FALSE. +# N.B. _prefix is the prefix applied to the names of all cached variables that +# are generated internally and marked advanced by this macro. +macro(check_lapack_libraries DEFINITIONS LIBRARIES _prefix _name _flags _list _blas _path) + #message("DEBUG: check_lapack_libraries(${_list} in ${_path} with ${_blas})") + + # Check for the existence of the libraries given by _list + set(_libraries_found TRUE) + set(_libraries_work FALSE) + set(${DEFINITIONS} "") + set(${LIBRARIES} "") + set(_combined_name) + foreach(_library ${_list}) + set(_combined_name ${_combined_name}_${_library}) + + if(_libraries_found) + # search first in ${_path} + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS ${_path} NO_DEFAULT_PATH + ) + # if not found, search in environment variables and system + if ( WIN32 ) + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS ENV LIB + ) + elseif ( APPLE ) + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 ENV DYLD_LIBRARY_PATH + ) + else () + find_library(${_prefix}_${_library}_LIBRARY + NAMES ${_library} + PATHS /usr/local/lib /usr/lib /usr/local/lib64 /usr/lib64 ENV LD_LIBRARY_PATH + ) + endif() + mark_as_advanced(${_prefix}_${_library}_LIBRARY) + set(${LIBRARIES} ${${LIBRARIES}} ${${_prefix}_${_library}_LIBRARY}) + set(_libraries_found ${${_prefix}_${_library}_LIBRARY}) + endif(_libraries_found) + endforeach(_library ${_list}) + if(_libraries_found) + set(_libraries_found ${${LIBRARIES}}) + endif() + + # Test this combination of libraries with the Fortran/f2c interface. + # We test the Fortran interface first as it is well standardized. + if(_libraries_found AND NOT _libraries_work) + set(${DEFINITIONS} "-D${_prefix}_USE_F2C") + set(${LIBRARIES} ${_libraries_found}) + # Some C++ linkers require the f2c library to link with Fortran libraries. + # I do not know which ones, thus I just add the f2c library if it is available. + find_package( F2C QUIET ) + if ( F2C_FOUND ) + set(${DEFINITIONS} ${${DEFINITIONS}} ${F2C_DEFINITIONS}) + set(${LIBRARIES} ${${LIBRARIES}} ${F2C_LIBRARIES}) + endif() + set(CMAKE_REQUIRED_DEFINITIONS ${${DEFINITIONS}}) + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas}) + #message("DEBUG: CMAKE_REQUIRED_DEFINITIONS = ${CMAKE_REQUIRED_DEFINITIONS}") + #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}") + # Check if function exists with f2c calling convention (ie a trailing underscore) + check_function_exists(${_name}_ ${_prefix}_${_name}_${_combined_name}_f2c_WORKS) + set(CMAKE_REQUIRED_DEFINITIONS} "") + set(CMAKE_REQUIRED_LIBRARIES "") + mark_as_advanced(${_prefix}_${_name}_${_combined_name}_f2c_WORKS) + set(_libraries_work ${${_prefix}_${_name}_${_combined_name}_f2c_WORKS}) + endif(_libraries_found AND NOT _libraries_work) + + # If not found, test this combination of libraries with a C interface. + # A few implementations (ie ACML) provide a C interface. Unfortunately, there is no standard. + if(_libraries_found AND NOT _libraries_work) + set(${DEFINITIONS} "") + set(${LIBRARIES} ${_libraries_found}) + set(CMAKE_REQUIRED_DEFINITIONS "") + set(CMAKE_REQUIRED_LIBRARIES ${_flags} ${${LIBRARIES}} ${_blas}) + #message("DEBUG: CMAKE_REQUIRED_LIBRARIES = ${CMAKE_REQUIRED_LIBRARIES}") + check_function_exists(${_name} ${_prefix}_${_name}${_combined_name}_WORKS) + set(CMAKE_REQUIRED_LIBRARIES "") + mark_as_advanced(${_prefix}_${_name}${_combined_name}_WORKS) + set(_libraries_work ${${_prefix}_${_name}${_combined_name}_WORKS}) + endif(_libraries_found AND NOT _libraries_work) + + # on failure + if(NOT _libraries_work) + set(${DEFINITIONS} "") + set(${LIBRARIES} FALSE) + endif() + #message("DEBUG: ${DEFINITIONS} = ${${DEFINITIONS}}") + #message("DEBUG: ${LIBRARIES} = ${${LIBRARIES}}") +endmacro(check_lapack_libraries) + + +# +# main +# + +# LAPACK requires BLAS +if(LAPACK_FIND_QUIETLY OR NOT LAPACK_FIND_REQUIRED) + find_package(BLAS) +else() + find_package(BLAS REQUIRED) +endif() + +if (NOT BLAS_FOUND) + + message(STATUS "LAPACK requires BLAS.") + set(LAPACK_FOUND FALSE) + +# Is it already configured? +elseif (LAPACK_LIBRARY_DIR OR LAPACK_LIBRARIES) + + set(LAPACK_FOUND TRUE) + +else() + + # reset variables + set( LAPACK_INCLUDE_DIR "" ) + set( LAPACK_DEFINITIONS "" ) + set( LAPACK_LINKER_FLAGS "" ) # unused (yet) + set( LAPACK_LIBRARIES "" ) + set( LAPACK_LIBRARY_DIR "" ) + + # Look first for the TAUCS library distributed with CGAL in auxiliary/taucs. + # Set CGAL_TAUCS_FOUND, CGAL_TAUCS_INCLUDE_DIR and CGAL_TAUCS_LIBRARIES_DIR. + include(CGAL_Locate_CGAL_TAUCS) + + # Search for LAPACK in CGAL_TAUCS_INCLUDE_DIR/CGAL_TAUCS_LIBRARIES_DIR (TAUCS shipped with CGAL), + # else in $LAPACK_INC_DIR/$LAPACK_LIB_DIR environment variables. + if(CGAL_TAUCS_FOUND AND CGAL_AUTO_LINK_ENABLED) + + # if VC++: done + set( LAPACK_INCLUDE_DIR "${CGAL_TAUCS_INCLUDE_DIR}" ) + set( LAPACK_LIBRARY_DIR "${CGAL_TAUCS_LIBRARIES_DIR}" ) + + else(CGAL_TAUCS_FOUND AND CGAL_AUTO_LINK_ENABLED) + + # + # If Unix, search for LAPACK function in possible libraries + # + + #intel mkl lapack? + if(NOT LAPACK_LIBRARIES) + check_lapack_libraries( + LAPACK_DEFINITIONS + LAPACK_LIBRARIES + LAPACK + cheev + "" + "mkl_lapack" + "${BLAS_LIBRARIES}" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV LAPACK_LIB_DIR" + ) + endif() + + #acml lapack? + if(NOT LAPACK_LIBRARIES) + check_lapack_libraries( + LAPACK_DEFINITIONS + LAPACK_LIBRARIES + LAPACK + cheev + "" + "acml" + "${BLAS_LIBRARIES}" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV LAPACK_LIB_DIR" + ) + endif() + + # Apple LAPACK library? + if(NOT LAPACK_LIBRARIES) + check_lapack_libraries( + LAPACK_DEFINITIONS + LAPACK_LIBRARIES + LAPACK + cheev + "" + "Accelerate" + "${BLAS_LIBRARIES}" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV LAPACK_LIB_DIR" + ) + endif() + + if ( NOT LAPACK_LIBRARIES ) + check_lapack_libraries( + LAPACK_DEFINITIONS + LAPACK_LIBRARIES + LAPACK + cheev + "" + "vecLib" + "${BLAS_LIBRARIES}" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV LAPACK_LIB_DIR" + ) + endif ( NOT LAPACK_LIBRARIES ) + + # Generic LAPACK library? + # This configuration *must* be the last try as this library is notably slow. + if ( NOT LAPACK_LIBRARIES ) + check_lapack_libraries( + LAPACK_DEFINITIONS + LAPACK_LIBRARIES + LAPACK + cheev + "" + "lapack" + "${BLAS_LIBRARIES}" + "${CGAL_TAUCS_LIBRARIES_DIR} ENV LAPACK_LIB_DIR" + ) + endif() + + endif(CGAL_TAUCS_FOUND AND CGAL_AUTO_LINK_ENABLED) + + if(LAPACK_LIBRARY_DIR OR LAPACK_LIBRARIES) + set(LAPACK_FOUND TRUE) + else() + set(LAPACK_FOUND FALSE) + endif() + + if(NOT LAPACK_FIND_QUIETLY) + if(LAPACK_FOUND) + message(STATUS "A library with LAPACK API found.") + else(LAPACK_FOUND) + if(LAPACK_FIND_REQUIRED) + message(FATAL_ERROR "A required library with LAPACK API not found. Please specify library location.") + else() + message(STATUS "A library with LAPACK API not found. Please specify library location.") + endif() + endif(LAPACK_FOUND) + endif(NOT LAPACK_FIND_QUIETLY) + + # Add variables to cache + set( LAPACK_INCLUDE_DIR "${LAPACK_INCLUDE_DIR}" + CACHE PATH "Directories containing the LAPACK header files" FORCE ) + set( LAPACK_DEFINITIONS "${LAPACK_DEFINITIONS}" + CACHE STRING "Compilation options to use LAPACK" FORCE ) + set( LAPACK_LINKER_FLAGS "${LAPACK_LINKER_FLAGS}" + CACHE STRING "Linker flags to use LAPACK" FORCE ) + set( LAPACK_LIBRARIES "${LAPACK_LIBRARIES}" + CACHE FILEPATH "LAPACK libraries name" FORCE ) + set( LAPACK_LIBRARY_DIR "${LAPACK_LIBRARY_DIR}" + CACHE PATH "Directories containing the LAPACK libraries" FORCE ) + + #message("DEBUG: LAPACK_INCLUDE_DIR = ${LAPACK_INCLUDE_DIR}") + #message("DEBUG: LAPACK_DEFINITIONS = ${LAPACK_DEFINITIONS}") + #message("DEBUG: LAPACK_LINKER_FLAGS = ${LAPACK_LINKER_FLAGS}") + #message("DEBUG: LAPACK_LIBRARIES = ${LAPACK_LIBRARIES}") + #message("DEBUG: LAPACK_LIBRARY_DIR = ${LAPACK_LIBRARY_DIR}") + #message("DEBUG: LAPACK_FOUND = ${LAPACK_FOUND}") + +endif(NOT BLAS_FOUND) + +if(LAPACK_FOUND) + set(LAPACK_USE_FILE "CGAL_UseLAPACK") +endif(LAPACK_FOUND) diff --git a/src/external/CoMISo/cmake/FindMETIS.cmake b/src/external/CoMISo/cmake/FindMETIS.cmake new file mode 100644 index 000000000..c40210dd9 --- /dev/null +++ b/src/external/CoMISo/cmake/FindMETIS.cmake @@ -0,0 +1,38 @@ +# - Try to find METIS +# Once done this will define +# METIS_FOUND - System has Metis +# METIS_INCLUDE_DIRS - The Metis include directories +# METIS_LIBRARY_DIRS - The library directories needed to use Metis +# METIS_LIBRARIES - The libraries needed to use Metis + +if (METIS_INCLUDE_DIR) + # in cache already + SET(METIS_FIND_QUIETLY TRUE) +endif (METIS_INCLUDE_DIR) + +find_path(METIS_INCLUDE_DIR NAMES metis.h + PATHS "$ENV{IPOPT_HOME}/ThirdParty/Metis/metis-4.0/Lib/" + "/usr/include/" + "/usr/include/metis" + "/opt/local/include" + "/opt/local/include/metis" + + + ) + +find_library( METIS_LIBRARY + metis coinmetis + PATHS "$ENV{IPOPT_HOME}/lib/" + "/usr/lib" + "/opt/local/lib" ) + +set(METIS_INCLUDE_DIRS "${METIS_INCLUDE_DIR}" ) +set(METIS_LIBRARIES "${METIS_LIBRARY}" ) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(METIS DEFAULT_MSG + METIS_LIBRARY METIS_INCLUDE_DIR) + +mark_as_advanced(METIS_INCLUDE_DIR METIS_LIBRARY ) diff --git a/src/external/CoMISo/cmake/FindMPI.cmake b/src/external/CoMISo/cmake/FindMPI.cmake new file mode 100644 index 000000000..b462bcf39 --- /dev/null +++ b/src/external/CoMISo/cmake/FindMPI.cmake @@ -0,0 +1,617 @@ +# - Find a Message Passing Interface (MPI) implementation +# The Message Passing Interface (MPI) is a library used to write +# high-performance distributed-memory parallel applications, and +# is typically deployed on a cluster. MPI is a standard interface +# (defined by the MPI forum) for which many implementations are +# available. All of them have somewhat different include paths, +# libraries to link against, etc., and this module tries to smooth +# out those differences. +# +# === Variables === +# +# This module will set the following variables per language in your project, +# where is one of C, CXX, or Fortran: +# MPI__FOUND TRUE if FindMPI found MPI flags for +# MPI__COMPILER MPI Compiler wrapper for +# MPI__COMPILE_FLAGS Compilation flags for MPI programs +# MPI__INCLUDE_PATH Include path(s) for MPI header +# MPI__LINK_FLAGS Linking flags for MPI programs +# MPI__LIBRARIES All libraries to link MPI programs against +# Additionally, FindMPI sets the following variables for running MPI +# programs from the command line: +# MPIEXEC Executable for running MPI programs +# MPIEXEC_NUMPROC_FLAG Flag to pass to MPIEXEC before giving +# it the number of processors to run on +# MPIEXEC_PREFLAGS Flags to pass to MPIEXEC directly +# before the executable to run. +# MPIEXEC_POSTFLAGS Flags to pass to MPIEXEC after other flags +# === Usage === +# +# To use this module, simply call FindMPI from a CMakeLists.txt file, or +# run find_package(MPI), then run CMake. If you are happy with the auto- +# detected configuration for your language, then you're done. If not, you +# have two options: +# 1. Set MPI__COMPILER to the MPI wrapper (mpicc, etc.) of your +# choice and reconfigure. FindMPI will attempt to determine all the +# necessary variables using THAT compiler's compile and link flags. +# 2. If this fails, or if your MPI implementation does not come with +# a compiler wrapper, then set both MPI__LIBRARIES and +# MPI__INCLUDE_PATH. You may also set any other variables +# listed above, but these two are required. This will circumvent +# autodetection entirely. +# When configuration is successful, MPI__COMPILER will be set to the +# compiler wrapper for , if it was found. MPI__FOUND and other +# variables above will be set if any MPI implementation was found for , +# regardless of whether a compiler was found. +# +# When using MPIEXEC to execute MPI applications, you should typically use +# all of the MPIEXEC flags as follows: +# ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} PROCS +# ${MPIEXEC_PREFLAGS} EXECUTABLE ${MPIEXEC_POSTFLAGS} ARGS +# where PROCS is the number of processors on which to execute the program, +# EXECUTABLE is the MPI program, and ARGS are the arguments to pass to the +# MPI program. +# +# === Backward Compatibility === +# +# For backward compatibility with older versions of FindMPI, these +# variables are set, but deprecated: +# MPI_FOUND MPI_COMPILER MPI_LIBRARY +# MPI_COMPILE_FLAGS MPI_INCLUDE_PATH MPI_EXTRA_LIBRARY +# MPI_LINK_FLAGS MPI_LIBRARIES +# In new projects, please use the MPI__XXX equivalents. + +#============================================================================= +# Copyright 2001-2011 Kitware, Inc. +# Copyright 2010-2011 Todd Gamblin tgamblin@llnl.gov +# Copyright 2001-2009 Dave Partyka +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# include this to handle the QUIETLY and REQUIRED arguments +include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) +include(GetPrerequisites) + +# +# This part detects MPI compilers, attempting to wade through the mess of compiler names in +# a sensible way. +# +# The compilers are detected in this order: +# +# 1. Try to find the most generic availble MPI compiler, as this is usually set up by +# cluster admins. e.g., if plain old mpicc is available, we'll use it and assume it's +# the right compiler. +# +# 2. If a generic mpicc is NOT found, then we attempt to find one that matches +# CMAKE__COMPILER_ID. e.g. if you are using XL compilers, we'll try to find mpixlc +# and company, but not mpiicc. This hopefully prevents toolchain mismatches. +# +# If you want to force a particular MPI compiler other than what we autodetect (e.g. if you +# want to compile regular stuff with GNU and parallel stuff with Intel), you can always set +# your favorite MPI__COMPILER explicitly and this stuff will be ignored. +# + +# Start out with the generic MPI compiler names, as these are most commonly used. +set(_MPI_C_COMPILER_NAMES mpicc mpcc mpicc_r mpcc_r) +set(_MPI_CXX_COMPILER_NAMES mpicxx mpiCC mpcxx mpCC mpic++ mpc++ + mpicxx_r mpiCC_r mpcxx_r mpCC_r mpic++_r mpc++_r) +set(_MPI_Fortran_COMPILER_NAMES mpif95 mpif95_r mpf95 mpf95_r + mpif90 mpif90_r mpf90 mpf90_r + mpif77 mpif77_r mpf77 mpf77_r) + +# GNU compiler names +set(_MPI_GNU_C_COMPILER_NAMES mpigcc mpgcc mpigcc_r mpgcc_r) +set(_MPI_GNU_CXX_COMPILER_NAMES mpig++ mpg++ mpig++_r mpg++_r) +set(_MPI_GNU_Fortran_COMPILER_NAMES mpigfortran mpgfortran mpigfortran_r mpgfortran_r + mpig77 mpig77_r mpg77 mpg77_r) + +# Intel MPI compiler names +set(_MPI_Intel_C_COMPILER_NAMES mpiicc) +set(_MPI_Intel_CXX_COMPILER_NAMES mpiicpc mpiicxx mpiic++ mpiiCC) +set(_MPI_Intel_Fortran_COMPILER_NAMES mpiifort mpiif95 mpiif90 mpiif77) + +# PGI compiler names +set(_MPI_PGI_C_COMPILER_NAMES mpipgcc mppgcc) +set(_MPI_PGI_CXX_COMPILER_NAMES mpipgCC mppgCC) +set(_MPI_PGI_Fortran_COMPILER_NAMES mpipgf95 mpipgf90 mppgf95 mppgf90 mpipgf77 mppgf77) + +# XLC MPI Compiler names +set(_MPI_XL_C_COMPILER_NAMES mpxlc mpxlc_r mpixlc mpixlc_r) +set(_MPI_XL_CXX_COMPILER_NAMES mpixlcxx mpixlC mpixlc++ mpxlcxx mpxlc++ mpixlc++ mpxlCC + mpixlcxx_r mpixlC_r mpixlc++_r mpxlcxx_r mpxlc++_r mpixlc++_r mpxlCC_r) +set(_MPI_XL_Fortran_COMPILER_NAMES mpixlf95 mpixlf95_r mpxlf95 mpxlf95_r + mpixlf90 mpixlf90_r mpxlf90 mpxlf90_r + mpixlf77 mpixlf77_r mpxlf77 mpxlf77_r + mpixlf mpixlf_r mpxlf mpxlf_r) + +# append vendor-specific compilers to the list if we either don't know the compiler id, +# or if we know it matches the regular compiler. +foreach (lang C CXX Fortran) + foreach (id GNU Intel PGI XL) + if (NOT CMAKE_${lang}_COMPILER_ID OR "${CMAKE_${lang}_COMPILER_ID}" STREQUAL "${id}") + list(APPEND _MPI_${lang}_COMPILER_NAMES ${_MPI_${id}_${lang}_COMPILER_NAMES}) + endif() + unset(_MPI_${id}_${lang}_COMPILER_NAMES) # clean up the namespace here + endforeach() +endforeach() + + +# Names to try for MPI exec +set(_MPI_EXEC_NAMES mpiexec mpirun lamexec srun) + +# Grab the path to MPI from the registry if we're on windows. +set(_MPI_PREFIX_PATH) +if(WIN32) + list(APPEND _MPI_PREFIX_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/..") + list(APPEND _MPI_PREFIX_PATH "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH2;Path]") + list(APPEND _MPI_PREFIX_PATH "$ENV{ProgramW6432}/MPICH2/") +endif() + +# Build a list of prefixes to search for MPI. +foreach(SystemPrefixDir ${CMAKE_SYSTEM_PREFIX_PATH}) + foreach(MpiPackageDir ${_MPI_PREFIX_PATH}) + if(EXISTS ${SystemPrefixDir}/${MpiPackageDir}) + list(APPEND _MPI_PREFIX_PATH "${SystemPrefixDir}/${MpiPackageDir}") + endif() + endforeach() +endforeach() + + +# +# interrogate_mpi_compiler(lang try_libs) +# +# Attempts to extract compiler and linker args from an MPI compiler. The arguments set +# by this function are: +# +# MPI__INCLUDE_PATH MPI__LINK_FLAGS MPI__FOUND +# MPI__COMPILE_FLAGS MPI__LIBRARIES +# +# MPI__COMPILER must be set beforehand to the absolute path to an MPI compiler for +# . Additionally, MPI__INCLUDE_PATH and MPI__LIBRARIES may be set +# to skip autodetection. +# +# If try_libs is TRUE, this will also attempt to find plain MPI libraries in the usual +# way. In general, this is not as effective as interrogating the compilers, as it +# ignores language-specific flags and libraries. However, some MPI implementations +# (Windows implementations) do not have compiler wrappers, so this approach must be used. +# +function (interrogate_mpi_compiler lang try_libs) + # MPI_${lang}_NO_INTERROGATE will be set to a compiler name when the *regular* compiler was + # discovered to be the MPI compiler. This happens on machines like the Cray XE6 that use + # modules to set cc, CC, and ftn to the MPI compilers. If the user force-sets another MPI + # compiler, MPI_${lang}_COMPILER won't be equal to MPI_${lang}_NO_INTERROGATE, and we'll + # inspect that compiler anew. This allows users to set new compilers w/o rm'ing cache. + string(COMPARE NOTEQUAL "${MPI_${lang}_NO_INTERROGATE}" "${MPI_${lang}_COMPILER}" interrogate) + + # If MPI is set already in the cache, don't bother with interrogating the compiler. + if (interrogate AND ((NOT MPI_${lang}_INCLUDE_PATH) OR (NOT MPI_${lang}_LIBRARIES))) + if (MPI_${lang}_COMPILER) + # Check whether the -showme:compile option works. This indicates that we have either OpenMPI + # or a newer version of LAM-MPI, and implies that -showme:link will also work. + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -showme:compile + OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + + if (MPI_COMPILER_RETURN EQUAL 0) + # If we appear to have -showme:compile, then we should + # also have -showme:link. Try it. + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -showme:link + OUTPUT_VARIABLE MPI_LINK_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_LINK_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + + if (MPI_COMPILER_RETURN EQUAL 0) + # We probably have -showme:incdirs and -showme:libdirs as well, + # so grab that while we're at it. + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -showme:incdirs + OUTPUT_VARIABLE MPI_INCDIRS OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_INCDIRS ERROR_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -showme:libdirs + OUTPUT_VARIABLE MPI_LIBDIRS OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_LIBDIRS ERROR_STRIP_TRAILING_WHITESPACE) + + else() + # reset things here if something went wrong. + set(MPI_COMPILE_CMDLINE) + set(MPI_LINK_CMDLINE) + endif() + endif () + + # Older versions of LAM-MPI have "-showme". Try to find that. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -showme + OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + endif() + + # MVAPICH uses -compile-info and -link-info. Try them. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -compile-info + OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + + # If we have compile-info, also have link-info. + if (MPI_COMPILER_RETURN EQUAL 0) + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -link-info + OUTPUT_VARIABLE MPI_LINK_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_LINK_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + endif() + + # make sure we got compile and link. Reset vars if something's wrong. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + set(MPI_COMPILE_CMDLINE) + set(MPI_LINK_CMDLINE) + endif() + endif() + + # MPICH just uses "-show". Try it. + if (NOT MPI_COMPILER_RETURN EQUAL 0) + execute_process( + COMMAND ${MPI_${lang}_COMPILER} -show + OUTPUT_VARIABLE MPI_COMPILE_CMDLINE OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE MPI_COMPILE_CMDLINE ERROR_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE MPI_COMPILER_RETURN) + endif() + + if (MPI_COMPILER_RETURN EQUAL 0) + # We have our command lines, but we might need to copy MPI_COMPILE_CMDLINE + # into MPI_LINK_CMDLINE, if we didn't find the link line. + if (NOT MPI_LINK_CMDLINE) + set(MPI_LINK_CMDLINE ${MPI_COMPILE_CMDLINE}) + endif() + else() + message(STATUS "Unable to determine MPI from MPI driver ${MPI_${lang}_COMPILER}") + set(MPI_COMPILE_CMDLINE) + set(MPI_LINK_CMDLINE) + endif() + + # Here, we're done with the interrogation part, and we'll try to extract args we care + # about from what we learned from the compiler wrapper scripts. + + # If interrogation came back with something, extract our variable from the MPI command line + if (MPI_COMPILE_CMDLINE OR MPI_LINK_CMDLINE) + # Extract compile flags from the compile command line. + string(REGEX MATCHALL "(^| )-[Df]([^\" ]+|\"[^\"]+\")" MPI_ALL_COMPILE_FLAGS "${MPI_COMPILE_CMDLINE}") + set(MPI_COMPILE_FLAGS_WORK) + + foreach(FLAG ${MPI_ALL_COMPILE_FLAGS}) + if (MPI_COMPILE_FLAGS_WORK) + set(MPI_COMPILE_FLAGS_WORK "${MPI_COMPILE_FLAGS_WORK} ${FLAG}") + else() + set(MPI_COMPILE_FLAGS_WORK ${FLAG}) + endif() + endforeach() + + # Extract include paths from compile command line + string(REGEX MATCHALL "(^| )-I([^\" ]+|\"[^\"]+\")" MPI_ALL_INCLUDE_PATHS "${MPI_COMPILE_CMDLINE}") + foreach(IPATH ${MPI_ALL_INCLUDE_PATHS}) + string(REGEX REPLACE "^ ?-I" "" IPATH ${IPATH}) + string(REGEX REPLACE "//" "/" IPATH ${IPATH}) + list(APPEND MPI_INCLUDE_PATH_WORK ${IPATH}) + endforeach() + + # try using showme:incdirs if extracting didn't work. + if (NOT MPI_INCLUDE_PATH_WORK) + set(MPI_INCLUDE_PATH_WORK ${MPI_INCDIRS}) + separate_arguments(MPI_INCLUDE_PATH_WORK) + endif() + + # If all else fails, just search for mpi.h in the normal include paths. + if (NOT MPI_INCLUDE_PATH_WORK) + set(MPI_HEADER_PATH "MPI_HEADER_PATH-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + find_path(MPI_HEADER_PATH mpi.h + HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} + PATH_SUFFIXES include) + set(MPI_INCLUDE_PATH_WORK ${MPI_HEADER_PATH}) + endif() + + # Extract linker paths from the link command line + string(REGEX MATCHALL "(^| |-Wl,)-L([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_PATHS "${MPI_LINK_CMDLINE}") + set(MPI_LINK_PATH) + foreach(LPATH ${MPI_ALL_LINK_PATHS}) + string(REGEX REPLACE "^(| |-Wl,)-L" "" LPATH ${LPATH}) + string(REGEX REPLACE "//" "/" LPATH ${LPATH}) + list(APPEND MPI_LINK_PATH ${LPATH}) + endforeach() + + # try using showme:libdirs if extracting didn't work. + if (NOT MPI_LINK_PATH) + set(MPI_LINK_PATH ${MPI_LIBDIRS}) + separate_arguments(MPI_LINK_PATH) + endif() + + # Extract linker flags from the link command line + string(REGEX MATCHALL "(^| )-Wl,([^\" ]+|\"[^\"]+\")" MPI_ALL_LINK_FLAGS "${MPI_LINK_CMDLINE}") + set(MPI_LINK_FLAGS_WORK) + foreach(FLAG ${MPI_ALL_LINK_FLAGS}) + if (MPI_LINK_FLAGS_WORK) + set(MPI_LINK_FLAGS_WORK "${MPI_LINK_FLAGS_WORK} ${FLAG}") + else() + set(MPI_LINK_FLAGS_WORK ${FLAG}) + endif() + endforeach() + + # Extract the set of libraries to link against from the link command + # line + string(REGEX MATCHALL "(^| )-l([^\" ]+|\"[^\"]+\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}") + + # Determine full path names for all of the libraries that one needs + # to link against in an MPI program + foreach(LIB ${MPI_LIBNAMES}) + string(REGEX REPLACE "^ ?-l" "" LIB ${LIB}) + # MPI_LIB is cached by find_library, but we don't want that. Clear it first. + set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + find_library(MPI_LIB NAMES ${LIB} HINTS ${MPI_LINK_PATH}) + + if (MPI_LIB) + list(APPEND MPI_LIBRARIES_WORK ${MPI_LIB}) + elseif (NOT MPI_FIND_QUIETLY) + message(WARNING "Unable to find MPI library ${LIB}") + endif() + endforeach() + + # Sanity check MPI_LIBRARIES to make sure there are enough libraries + list(LENGTH MPI_LIBRARIES_WORK MPI_NUMLIBS) + list(LENGTH MPI_LIBNAMES MPI_NUMLIBS_EXPECTED) + if (NOT MPI_NUMLIBS EQUAL MPI_NUMLIBS_EXPECTED) + set(MPI_LIBRARIES_WORK "MPI_${lang}_LIBRARIES-NOTFOUND") + endif() + endif() + + elseif(try_libs) + # If we didn't have an MPI compiler script to interrogate, attempt to find everything + # with plain old find functions. This is nasty because MPI implementations have LOTS of + # different library names, so this section isn't going to be very generic. We need to + # make sure it works for MS MPI, though, since there are no compiler wrappers for that. + find_path(MPI_HEADER_PATH mpi.h + HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} + PATH_SUFFIXES include Inc) + set(MPI_INCLUDE_PATH_WORK ${MPI_HEADER_PATH}) + + # Decide between 32-bit and 64-bit libraries for Microsoft's MPI + if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + set(MS_MPI_ARCH_DIR amd64) + else() + set(MS_MPI_ARCH_DIR i386) + endif() + + set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + find_library(MPI_LIB + NAMES mpi mpich mpich2 msmpi + HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} + PATH_SUFFIXES lib lib/${MS_MPI_ARCH_DIR} Lib Lib/${MS_MPI_ARCH_DIR}) + set(MPI_LIBRARIES_WORK ${MPI_LIB}) + + # Right now, we only know about the extra libs for C++. + # We could add Fortran here (as there is usually libfmpich, etc.), but + # this really only has to work with MS MPI on Windows. + # Assume that other MPI's are covered by the compiler wrappers. + if (${lang} STREQUAL CXX) + set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + find_library(MPI_LIB + NAMES mpi++ mpicxx cxx mpi_cxx + HINTS ${_MPI_BASE_DIR} ${_MPI_PREFIX_PATH} + PATH_SUFFIXES lib) + if (MPI_LIBRARIES_WORK AND MPI_LIB) + set(MPI_LIBRARIES_WORK "${MPI_LIBRARIES_WORK};${MPI_LIB}") + endif() + endif() + + if (NOT MPI_LIBRARIES_WORK) + set(MPI_LIBRARIES_WORK "MPI_${lang}_LIBRARIES-NOTFOUND") + endif() + endif() + + # If we found MPI, set up all of the appropriate cache entries + set(MPI_${lang}_COMPILE_FLAGS ${MPI_COMPILE_FLAGS_WORK} CACHE STRING "MPI ${lang} compilation flags" FORCE) + set(MPI_${lang}_INCLUDE_PATH ${MPI_INCLUDE_PATH_WORK} CACHE STRING "MPI ${lang} include path" FORCE) + set(MPI_${lang}_LINK_FLAGS ${MPI_LINK_FLAGS_WORK} CACHE STRING "MPI ${lang} linking flags" FORCE) + set(MPI_${lang}_LIBRARIES ${MPI_LIBRARIES_WORK} CACHE STRING "MPI ${lang} libraries to link against" FORCE) + mark_as_advanced(MPI_${lang}_COMPILE_FLAGS MPI_${lang}_INCLUDE_PATH MPI_${lang}_LINK_FLAGS MPI_${lang}_LIBRARIES) + + # clear out our temporary lib/header detectionv variable here. + set(MPI_LIB "MPI_LIB-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI lib detection" FORCE) + set(MPI_HEADER_PATH "MPI_HEADER_PATH-NOTFOUND" CACHE INTERNAL "Scratch variable for MPI header detection" FORCE) + endif() + + # finally set a found variable for each MPI language + if (MPI_${lang}_INCLUDE_PATH AND MPI_${lang}_LIBRARIES) + set(MPI_${lang}_FOUND TRUE PARENT_SCOPE) + else() + set(MPI_${lang}_FOUND FALSE PARENT_SCOPE) + endif() +endfunction() + + +# This function attempts to compile with the regular compiler, to see if MPI programs +# work with it. This is a last ditch attempt after we've tried interrogating mpicc and +# friends, and after we've tried to find generic libraries. Works on machines like +# Cray XE6, where the modules environment changes what MPI version cc, CC, and ftn use. +function(try_regular_compiler lang success) + set(scratch_directory ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) + if (${lang} STREQUAL Fortran) + set(test_file ${scratch_directory}/cmake_mpi_test.f90) + file(WRITE ${test_file} + "program hello\n" + "include 'mpif.h'\n" + "integer ierror\n" + "call MPI_INIT(ierror)\n" + "call MPI_FINALIZE(ierror)\n" + "end\n") + else() + if (${lang} STREQUAL CXX) + set(test_file ${scratch_directory}/cmake_mpi_test.cpp) + else() + set(test_file ${scratch_directory}/cmake_mpi_test.c) + endif() + file(WRITE ${test_file} + "#include \n" + "int main(int argc, char **argv) {\n" + " MPI_Init(&argc, &argv);\n" + " MPI_Finalize();\n" + "}\n") + endif() + try_compile(compiler_has_mpi ${scratch_directory} ${test_file}) + if (compiler_has_mpi) + set(MPI_${lang}_NO_INTERROGATE ${CMAKE_${lang}_COMPILER} CACHE STRING "Whether to interrogate MPI ${lang} compiler" FORCE) + set(MPI_${lang}_COMPILER ${CMAKE_${lang}_COMPILER} CACHE STRING "MPI ${lang} compiler" FORCE) + set(MPI_${lang}_COMPILE_FLAGS "" CACHE STRING "MPI ${lang} compilation flags" FORCE) + set(MPI_${lang}_INCLUDE_PATH "" CACHE STRING "MPI ${lang} include path" FORCE) + set(MPI_${lang}_LINK_FLAGS "" CACHE STRING "MPI ${lang} linking flags" FORCE) + set(MPI_${lang}_LIBRARIES "" CACHE STRING "MPI ${lang} libraries to link against" FORCE) + endif() + set(${success} ${compiler_has_mpi} PARENT_SCOPE) + unset(compiler_has_mpi CACHE) +endfunction() + +# End definitions, commence real work here. + +# Most mpi distros have some form of mpiexec which gives us something we can reliably look for. +find_program(MPIEXEC + NAMES ${_MPI_EXEC_NAMES} + PATHS ${_MPI_PREFIX_PATH} + PATH_SUFFIXES bin + DOC "Executable for running MPI programs.") + +# call get_filename_component twice to remove mpiexec and the directory it exists in (typically bin). +# This gives us a fairly reliable base directory to search for /bin /lib and /include from. +get_filename_component(_MPI_BASE_DIR "${MPIEXEC}" PATH) +get_filename_component(_MPI_BASE_DIR "${_MPI_BASE_DIR}" PATH) + +set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "Flag used by MPI to specify the number of processes for MPIEXEC; the next option will be the number of processes.") +set(MPIEXEC_PREFLAGS "" CACHE STRING "These flags will be directly before the executable that is being run by MPIEXEC.") +set(MPIEXEC_POSTFLAGS "" CACHE STRING "These flags will come after all flags given to MPIEXEC.") +set(MPIEXEC_MAX_NUMPROCS "2" CACHE STRING "Maximum number of processors available to run MPI applications.") +mark_as_advanced(MPIEXEC MPIEXEC_NUMPROC_FLAG MPIEXEC_PREFLAGS MPIEXEC_POSTFLAGS MPIEXEC_MAX_NUMPROCS) + + +#============================================================================= +# Backward compatibility input hacks. Propagate the FindMPI hints to C and +# CXX if the respective new versions are not defined. Translate the old +# MPI_LIBRARY and MPI_EXTRA_LIBRARY to respective MPI_${lang}_LIBRARIES. +# +# Once we find the new variables, we translate them back into their old +# equivalents below. +foreach (lang C CXX) + # Old input variables. + set(_MPI_OLD_INPUT_VARS COMPILER COMPILE_FLAGS INCLUDE_PATH LINK_FLAGS) + + # Set new vars based on their old equivalents, if the new versions are not already set. + foreach (var ${_MPI_OLD_INPUT_VARS}) + if (NOT MPI_${lang}_${var} AND MPI_${var}) + set(MPI_${lang}_${var} "${MPI_${var}}") + endif() + endforeach() + + # Special handling for MPI_LIBRARY and MPI_EXTRA_LIBRARY, which we nixed in the + # new FindMPI. These need to be merged into MPI__LIBRARIES + if (NOT MPI_${lang}_LIBRARIES AND (MPI_LIBRARY OR MPI_EXTRA_LIBRARY)) + set(MPI_${lang}_LIBRARIES ${MPI_LIBRARY} ${MPI_EXTRA_LIBRARY}) + endif() +endforeach() +#============================================================================= + + +# This loop finds the compilers and sends them off for interrogation. +foreach (lang C CXX Fortran) + if (CMAKE_${lang}_COMPILER_WORKS) + # If the user supplies a compiler *name* instead of an absolute path, assume that we need to find THAT compiler. + if (MPI_${lang}_COMPILER) + is_file_executable(MPI_${lang}_COMPILER MPI_COMPILER_IS_EXECUTABLE) + if (NOT MPI_COMPILER_IS_EXECUTABLE) + # Get rid of our default list of names and just search for the name the user wants. + set(_MPI_${lang}_COMPILER_NAMES ${MPI_${lang}_COMPILER}) + set(MPI_${lang}_COMPILER "MPI_${lang}_COMPILER-NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + # If the user specifies a compiler, we don't want to try to search libraries either. + set(try_libs FALSE) + endif() + else() + set(try_libs TRUE) + endif() + + find_program(MPI_${lang}_COMPILER + NAMES ${_MPI_${lang}_COMPILER_NAMES} + PATHS "${MPI_HOME}/bin" "$ENV{MPI_HOME}/bin" ${_MPI_PREFIX_PATH}) + interrogate_mpi_compiler(${lang} ${try_libs}) + mark_as_advanced(MPI_${lang}_COMPILER) + + # last ditch try -- if nothing works so far, just try running the regular compiler and + # see if we can create an MPI executable. + set(regular_compiler_worked 0) + if (NOT MPI_${lang}_LIBRARIES OR NOT MPI_${lang}_INCLUDE_PATH) + try_regular_compiler(${lang} regular_compiler_worked) + endif() + + if (regular_compiler_worked) + find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_COMPILER) + else() + find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_LIBRARIES MPI_${lang}_INCLUDE_PATH) + endif() + endif() +endforeach() + + +#============================================================================= +# More backward compatibility stuff +# +# Bare MPI sans ${lang} vars are set to CXX then C, depending on what was found. +# This mimics the behavior of the old language-oblivious FindMPI. +set(_MPI_OLD_VARS FOUND COMPILER INCLUDE_PATH COMPILE_FLAGS LINK_FLAGS LIBRARIES) +if (MPI_CXX_FOUND) + foreach (var ${_MPI_OLD_VARS}) + set(MPI_${var} ${MPI_CXX_${var}}) + endforeach() +elseif (MPI_C_FOUND) + foreach (var ${_MPI_OLD_VARS}) + set(MPI_${var} ${MPI_C_${var}}) + endforeach() +else() + # Note that we might still have found Fortran, but you'll need to use MPI_Fortran_FOUND + set(MPI_FOUND FALSE) +endif() + +# Chop MPI_LIBRARIES into the old-style MPI_LIBRARY and MPI_EXTRA_LIBRARY, and set them in cache. +if (MPI_LIBRARIES) + list(GET MPI_LIBRARIES 0 MPI_LIBRARY_WORK) + set(MPI_LIBRARY ${MPI_LIBRARY_WORK} CACHE FILEPATH "MPI library to link against" FORCE) +else() + set(MPI_LIBRARY "MPI_LIBRARY-NOTFOUND" CACHE FILEPATH "MPI library to link against" FORCE) +endif() + +list(LENGTH MPI_LIBRARIES MPI_NUMLIBS) +if (MPI_NUMLIBS GREATER 1) + set(MPI_EXTRA_LIBRARY_WORK ${MPI_LIBRARIES}) + list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0) + set(MPI_EXTRA_LIBRARY ${MPI_EXTRA_LIBRARY_WORK} CACHE STRING "Extra MPI libraries to link against" FORCE) +else() + set(MPI_EXTRA_LIBRARY "MPI_EXTRA_LIBRARY-NOTFOUND" CACHE STRING "Extra MPI libraries to link against" FORCE) +endif() +#============================================================================= + +# unset these vars to cleanup namespace +unset(_MPI_OLD_VARS) +unset(_MPI_PREFIX_PATH) +unset(_MPI_BASE_DIR) +foreach (lang C CXX Fortran) + unset(_MPI_${lang}_COMPILER_NAMES) +endforeach() diff --git a/src/external/CoMISo/cmake/FindMUMPS.cmake b/src/external/CoMISo/cmake/FindMUMPS.cmake new file mode 100644 index 000000000..5ca1377a9 --- /dev/null +++ b/src/external/CoMISo/cmake/FindMUMPS.cmake @@ -0,0 +1,33 @@ +# - Try to find MUMPS +# Once done this will define +# MUMPS_FOUND - System has Mumps +# MUMPS_INCLUDE_DIRS - The Mumps include directories +# MUMPS_LIBRARY_DIRS - The library directories needed to use Mumps +# MUMPS_LIBRARIES - The libraries needed to use Mumps + +if (MUMPS_INCLUDE_DIR) + # in cache already + SET(MUMPS_FIND_QUIETLY TRUE) +endif (MUMPS_INCLUDE_DIR) + +find_path(MUMPS_INCLUDE_DIR NAMES dmumps_c.h + PATHS "$ENV{IPOPT_HOME}/ThirdParty/Mumps/MUMPS/include/" + "/usr/include/" + + ) + +find_library( MUMPS_LIBRARY + dmumps coinmumps + PATHS "$ENV{IPOPT_HOME}/lib/" + "/usr/lib" ) + +set(MUMPS_INCLUDE_DIRS "${MUMPS_INCLUDE_DIR}" ) +set(MUMPS_LIBRARIES "${MUMPS_LIBRARY}" ) + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LIBCPLEX_FOUND to TRUE +# if all listed variables are TRUE +find_package_handle_standard_args(MUMPS DEFAULT_MSG + MUMPS_LIBRARY MUMPS_INCLUDE_DIR) + +mark_as_advanced(MUMPS_INCLUDE_DIR MUMPS_LIBRARY ) \ No newline at end of file diff --git a/src/external/CoMISo/cmake/FindPETSC.cmake b/src/external/CoMISo/cmake/FindPETSC.cmake new file mode 100644 index 000000000..0f8499c17 --- /dev/null +++ b/src/external/CoMISo/cmake/FindPETSC.cmake @@ -0,0 +1,60 @@ +if (PETSC_INCLUDE_DIRS) + # Already in cache, be silent + SET(PETSC_FIND_QUIETLY TRUE) +endif(PETSC_INCLUDE_DIRS) + +if (WIN32) + find_path(PETSC_INCLUDE_DIR NAMES petsc.h + PREFIXES SRC + PATHS + "C:\\libs\\gurobi45" + ${PETSC_DIR}/include + ) + + find_library( PETSC_LIBRARY_RELEASE + SuperLU + PATHS "C:\\libs\\gurobi45\\lib" ) + find_library( PETSC_LIBRARY_DEBUG + SuperLUd + PATHS "C:\\libs\\gurobi45\\lib" ) + + + set ( PETSC_LIBRARY "optimized;${PETSC_LIBRARY_RELEASE};debug;${PETSC_LIBRARY_DEBUG}" CACHE STRING "PETSC Libraries" ) + +ELSEIF(APPLE) + + find_path(PETSC_INCLUDE_DIR NAMES gurobi_c++.h + PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/gurobi40" + ${PETSC_INCLUDE_PATH} + ) + + find_library( PETSC_LIBRARY + SuperLU + PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/gurobi40") + +ELSE( WIN32 ) + find_path(PETSC_INCLUDE_DIR1 NAMES petsc.h + PATHS "$ENV{PETSC_DIR}/include" + ${PETSC_INCLUDE_DIR1} + ) + + find_path(PETSC_INCLUDE_DIR2 NAMES petscconf.h + PATHS "$ENV{PETSC_DIR}/$ENV{PETSC_ARCH}/include" + ${PETSC_INCLUDE_DIR2} + ) + +# MESSAGE(STATUS "$ENV{PETSC_HOME}/include") + IF(PETSC_INCLUDE_DIR1 AND PETSC_INCLUDE_DIR2) + SET(PETSC_FOUND TRUE) + SET(PETSC_INCLUDE_DIRS "${PETSC_INCLUDE_DIR1};${PETSC_INCLUDE_DIR2}") + SET(PETSC_LIBRARY_DIR "$ENV{PETSC_DIR}/$ENV{PETSC_ARCH}/lib" CACHE PATH "Path to PETSC Library") + SET(PETSC_LIBRARY "petsc" CACHE STRING "PETSC Libraries") + ELSE(PETSC_INCLUDE_DIR1 AND PETSC_INCLUDE_DIR2) + SET(PETSC_FOUND FALSE) + SET(PETSC_INCLUDE_DIR ${PETSC_INCLUDE_DIR}) + ENDIF(PETSC_INCLUDE_DIR1 AND PETSC_INCLUDE_DIR2) + + #find_library( PETSC_LIBRARY + # gurobi + # PATHS "${PETSC_HOME}/lib" ) +ENDIF() \ No newline at end of file diff --git a/src/external/CoMISo/cmake/FindPackageHandleStandardArgs.cmake b/src/external/CoMISo/cmake/FindPackageHandleStandardArgs.cmake new file mode 100644 index 000000000..1acb021e8 --- /dev/null +++ b/src/external/CoMISo/cmake/FindPackageHandleStandardArgs.cmake @@ -0,0 +1,260 @@ +# FIND_PACKAGE_HANDLE_STANDARD_ARGS( ... ) +# +# This function is intended to be used in FindXXX.cmake modules files. +# It handles the REQUIRED, QUIET and version-related arguments to FIND_PACKAGE(). +# It also sets the _FOUND variable. +# The package is considered found if all variables ... listed contain +# valid results, e.g. valid filepaths. +# +# There are two modes of this function. The first argument in both modes is +# the name of the Find-module where it is called (in original casing). +# +# The first simple mode looks like this: +# FIND_PACKAGE_HANDLE_STANDARD_ARGS( (DEFAULT_MSG|"Custom failure message") ... ) +# If the variables to are all valid, then _FOUND +# will be set to TRUE. +# If DEFAULT_MSG is given as second argument, then the function will generate +# itself useful success and error messages. You can also supply a custom error message +# for the failure case. This is not recommended. +# +# The second mode is more powerful and also supports version checking: +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS ...] +# [VERSION_VAR +# [CONFIG_MODE] +# [FAIL_MESSAGE "Custom failure message"] ) +# +# As above, if through are all valid, _FOUND +# will be set to TRUE. +# After REQUIRED_VARS the variables which are required for this package are listed. +# Following VERSION_VAR the name of the variable can be specified which holds +# the version of the package which has been found. If this is done, this version +# will be checked against the (potentially) specified required version used +# in the find_package() call. The EXACT keyword is also handled. The default +# messages include information about the required version and the version +# which has been actually found, both if the version is ok or not. +# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for +# a find_package(... NO_MODULE) call, in this case all the information +# provided by the config-mode of find_package() will be evaluated +# automatically. +# Via FAIL_MESSAGE a custom failure message can be specified, if this is not +# used, the default message will be displayed. +# +# Example for mode 1: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2 DEFAULT_MSG LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR) +# +# LibXml2 is considered to be found, if both LIBXML2_LIBRARY and +# LIBXML2_INCLUDE_DIR are valid. Then also LIBXML2_FOUND is set to TRUE. +# If it is not found and REQUIRED was used, it fails with FATAL_ERROR, +# independent whether QUIET was used or not. +# If it is found, success will be reported, including the content of . +# On repeated Cmake runs, the same message won't be printed again. +# +# Example for mode 2: +# +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON REQUIRED_VARS BISON_EXECUTABLE +# VERSION_VAR BISON_VERSION) +# In this case, BISON is considered to be found if the variable(s) listed +# after REQUIRED_VAR are all valid, i.e. BISON_EXECUTABLE in this case. +# Also the version of BISON will be checked by using the version contained +# in BISON_VERSION. +# Since no FAIL_MESSAGE is given, the default messages will be printed. +# +# Another example for mode 2: +# +# FIND_PACKAGE(Automoc4 QUIET NO_MODULE HINTS /opt/automoc4) +# FIND_PACKAGE_HANDLE_STANDARD_ARGS(Automoc4 CONFIG_MODE) +# In this case, FindAutmoc4.cmake wraps a call to FIND_PACKAGE(Automoc4 NO_MODULE) +# and adds an additional search directory for automoc4. +# The following FIND_PACKAGE_HANDLE_STANDARD_ARGS() call produces a proper +# success/error message. + +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +INCLUDE(FindPackageMessage) +INCLUDE(CMakeParseArguments) + +# internal helper macro +MACRO(_FPHSA_FAILURE_MESSAGE _msg) + IF (${_NAME}_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "${_msg}") + ELSE (${_NAME}_FIND_REQUIRED) + IF (NOT ${_NAME}_FIND_QUIETLY) + MESSAGE(STATUS "${_msg}") + ENDIF (NOT ${_NAME}_FIND_QUIETLY) + ENDIF (${_NAME}_FIND_REQUIRED) +ENDMACRO(_FPHSA_FAILURE_MESSAGE _msg) + + +# internal helper macro to generate the failure message when used in CONFIG_MODE: +MACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + # _CONFIG is set, but FOUND is false, this means that some other of the REQUIRED_VARS was not found: + IF(${_NAME}_CONFIG) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: missing: ${MISSING_VARS} (found ${${_NAME}_CONFIG} ${VERSION_MSG})") + ELSE(${_NAME}_CONFIG) + # If _CONSIDERED_CONFIGS is set, the config-file has been found, but no suitable version. + # List them all in the error message: + IF(${_NAME}_CONSIDERED_CONFIGS) + SET(configsText "") + LIST(LENGTH ${_NAME}_CONSIDERED_CONFIGS configsCount) + MATH(EXPR configsCount "${configsCount} - 1") + FOREACH(currentConfigIndex RANGE ${configsCount}) + LIST(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename) + LIST(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version) + SET(configsText "${configsText} ${filename} (version ${version})\n") + ENDFOREACH(currentConfigIndex) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}") + + ELSE(${_NAME}_CONSIDERED_CONFIGS) + # Simple case: No Config-file was found at all: + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: found neither ${_NAME}Config.cmake nor ${_NAME_LOWER}-config.cmake ${VERSION_MSG}") + ENDIF(${_NAME}_CONSIDERED_CONFIGS) + ENDIF(${_NAME}_CONFIG) +ENDMACRO(_FPHSA_HANDLE_FAILURE_CONFIG_MODE) + + +FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) + +# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in +# new extended or in the "old" mode: + SET(options CONFIG_MODE) + SET(oneValueArgs FAIL_MESSAGE VERSION_VAR) + SET(multiValueArgs REQUIRED_VARS) + SET(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} ) + LIST(FIND _KEYWORDS_FOR_EXTENDED_MODE "${_FIRST_ARG}" INDEX) + + IF(${INDEX} EQUAL -1) + SET(FPHSA_FAIL_MESSAGE ${_FIRST_ARG}) + SET(FPHSA_REQUIRED_VARS ${ARGN}) + SET(FPHSA_VERSION_VAR) + ELSE(${INDEX} EQUAL -1) + + CMAKE_PARSE_ARGUMENTS(FPHSA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${_FIRST_ARG} ${ARGN}) + + IF(FPHSA_UNPARSED_ARGUMENTS) + MESSAGE(FATAL_ERROR "Unknown keywords given to FIND_PACKAGE_HANDLE_STANDARD_ARGS(): \"${FPHSA_UNPARSED_ARGUMENTS}\"") + ENDIF(FPHSA_UNPARSED_ARGUMENTS) + + IF(NOT FPHSA_FAIL_MESSAGE) + SET(FPHSA_FAIL_MESSAGE "DEFAULT_MSG") + ENDIF(NOT FPHSA_FAIL_MESSAGE) + ENDIF(${INDEX} EQUAL -1) + +# now that we collected all arguments, process them + + IF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") + SET(FPHSA_FAIL_MESSAGE "Could NOT find ${_NAME}") + ENDIF("${FPHSA_FAIL_MESSAGE}" STREQUAL "DEFAULT_MSG") + + # In config-mode, we rely on the variable _CONFIG, which is set by find_package() + # when it successfully found the config-file, including version checking: + IF(FPHSA_CONFIG_MODE) + LIST(INSERT FPHSA_REQUIRED_VARS 0 ${_NAME}_CONFIG) + LIST(REMOVE_DUPLICATES FPHSA_REQUIRED_VARS) + SET(FPHSA_VERSION_VAR ${_NAME}_VERSION) + ENDIF(FPHSA_CONFIG_MODE) + + IF(NOT FPHSA_REQUIRED_VARS) + MESSAGE(FATAL_ERROR "No REQUIRED_VARS specified for FIND_PACKAGE_HANDLE_STANDARD_ARGS()") + ENDIF(NOT FPHSA_REQUIRED_VARS) + + LIST(GET FPHSA_REQUIRED_VARS 0 _FIRST_REQUIRED_VAR) + + STRING(TOUPPER ${_NAME} _NAME_UPPER) + STRING(TOLOWER ${_NAME} _NAME_LOWER) + + # collect all variables which were not found, so they can be printed, so the + # user knows better what went wrong (#6375) + SET(MISSING_VARS "") + SET(DETAILS "") + SET(${_NAME_UPPER}_FOUND TRUE) + # check if all passed variables are valid + FOREACH(_CURRENT_VAR ${FPHSA_REQUIRED_VARS}) + IF(NOT ${_CURRENT_VAR}) + SET(${_NAME_UPPER}_FOUND FALSE) + SET(MISSING_VARS "${MISSING_VARS} ${_CURRENT_VAR}") + ELSE(NOT ${_CURRENT_VAR}) + SET(DETAILS "${DETAILS}[${${_CURRENT_VAR}}]") + ENDIF(NOT ${_CURRENT_VAR}) + ENDFOREACH(_CURRENT_VAR) + + + # version handling: + SET(VERSION_MSG "") + SET(VERSION_OK TRUE) + SET(VERSION ${${FPHSA_VERSION_VAR}} ) + IF (${_NAME}_FIND_VERSION) + + IF(VERSION) + + IF(${_NAME}_FIND_VERSION_EXACT) # exact version required + IF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is exact version \"${${_NAME}_FIND_VERSION}\"") + SET(VERSION_OK FALSE) + ELSE (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + SET(VERSION_MSG "(found suitable exact version \"${VERSION}\")") + ENDIF (NOT "${${_NAME}_FIND_VERSION}" VERSION_EQUAL "${VERSION}") + + ELSE(${_NAME}_FIND_VERSION_EXACT) # minimum version specified: + IF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + SET(VERSION_MSG "Found unsuitable version \"${VERSION}\", but required is at least \"${${_NAME}_FIND_VERSION}\"") + SET(VERSION_OK FALSE) + ELSE ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + SET(VERSION_MSG "(found suitable version \"${VERSION}\", required is \"${${_NAME}_FIND_VERSION}\")") + ENDIF ("${${_NAME}_FIND_VERSION}" VERSION_GREATER "${VERSION}") + ENDIF(${_NAME}_FIND_VERSION_EXACT) + + ELSE(VERSION) + + # if the package was not found, but a version was given, add that to the output: + IF(${_NAME}_FIND_VERSION_EXACT) + SET(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") + ELSE(${_NAME}_FIND_VERSION_EXACT) + SET(VERSION_MSG "(Required is at least version \"${${_NAME}_FIND_VERSION}\")") + ENDIF(${_NAME}_FIND_VERSION_EXACT) + + ENDIF(VERSION) + ELSE (${_NAME}_FIND_VERSION) + IF(VERSION) + SET(VERSION_MSG "(found version \"${VERSION}\")") + ENDIF(VERSION) + ENDIF (${_NAME}_FIND_VERSION) + + IF(VERSION_OK) + SET(DETAILS "${DETAILS}[v${VERSION}(${${_NAME}_FIND_VERSION})]") + ELSE(VERSION_OK) + SET(${_NAME_UPPER}_FOUND FALSE) + ENDIF(VERSION_OK) + + + # print the result: + IF (${_NAME_UPPER}_FOUND) + FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG}" "${DETAILS}") + ELSE (${_NAME_UPPER}_FOUND) + + IF(FPHSA_CONFIG_MODE) + _FPHSA_HANDLE_FAILURE_CONFIG_MODE() + ELSE(FPHSA_CONFIG_MODE) + IF(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE}: ${VERSION_MSG} (found ${${_FIRST_REQUIRED_VAR}})") + ELSE(NOT VERSION_OK) + _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} (missing: ${MISSING_VARS}) ${VERSION_MSG}") + ENDIF(NOT VERSION_OK) + ENDIF(FPHSA_CONFIG_MODE) + + ENDIF (${_NAME_UPPER}_FOUND) + + SET(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE) + +ENDFUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _FIRST_ARG) diff --git a/src/external/CoMISo/cmake/FindPackageMultipass.cmake b/src/external/CoMISo/cmake/FindPackageMultipass.cmake new file mode 100644 index 000000000..9ceca4c33 --- /dev/null +++ b/src/external/CoMISo/cmake/FindPackageMultipass.cmake @@ -0,0 +1,91 @@ +# PackageMultipass - this module defines two macros +# +# FIND_PACKAGE_MULTIPASS (Name CURRENT +# STATES VAR0 VAR1 ... +# DEPENDENTS DEP0 DEP1 ...) +# +# This function creates a cache entry _CURRENT which +# the user can set to "NO" to trigger a reconfiguration of the package. +# The first time this function is called, the values of +# _VAR0, ... are saved. If _CURRENT +# is false or if any STATE has changed since the last time +# FIND_PACKAGE_MULTIPASS() was called, then CURRENT will be set to "NO", +# otherwise CURRENT will be "YES". IF not CURRENT, then +# _DEP0, ... will be FORCED to NOTFOUND. +# Example: +# find_path (FOO_DIR include/foo.h) +# FIND_PACKAGE_MULTIPASS (Foo foo_current +# STATES DIR +# DEPENDENTS INCLUDES LIBRARIES) +# if (NOT foo_current) +# # Make temporary files, run programs, etc, to determine FOO_INCLUDES and FOO_LIBRARIES +# endif (NOT foo_current) +# +# MULTIPASS_C_SOURCE_RUNS (Name INCLUDES LIBRARIES SOURCE RUNS) +# Always runs the given test, use this when you need to re-run tests +# because parent variables have made old cache entries stale. + +macro (FIND_PACKAGE_MULTIPASS _name _current) + string (TOUPPER ${_name} _NAME) + set (_args ${ARGV}) + list (REMOVE_AT _args 0 1) + + set (_states_current "YES") + list (GET _args 0 _cmd) + if (_cmd STREQUAL "STATES") + list (REMOVE_AT _args 0) + list (GET _args 0 _state) + while (_state AND NOT _state STREQUAL "DEPENDENTS") + # The name of the stored value for the given state + set (_stored_var PACKAGE_MULTIPASS_${_NAME}_${_state}) + if (NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") + set (_states_current "NO") + endif (NOT "${${_stored_var}}" STREQUAL "${${_NAME}_${_state}}") + set (${_stored_var} "${${_NAME}_${_state}}" CACHE INTERNAL "Stored state for ${_name}." FORCE) + list (REMOVE_AT _args 0) + list (GET _args 0 _state) + endwhile (_state AND NOT _state STREQUAL "DEPENDENTS") + endif (_cmd STREQUAL "STATES") + + set (_stored ${_NAME}_CURRENT) + if (NOT ${_stored}) + set (${_stored} "YES" CACHE BOOL "Is the configuration for ${_name} current? Set to \"NO\" to reconfigure." FORCE) + set (_states_current "NO") + endif (NOT ${_stored}) + + set (${_current} ${_states_current}) + if (NOT ${_current}) + message (STATUS "Clearing ${_name} dependent variables") + # Clear all the dependent variables so that the module can reset them + list (GET _args 0 _cmd) + if (_cmd STREQUAL "DEPENDENTS") + list (REMOVE_AT _args 0) + foreach (dep ${_args}) + set (${_NAME}_${dep} "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) + endforeach (dep) + endif (_cmd STREQUAL "DEPENDENTS") + set (${_NAME}_FOUND "NOTFOUND" CACHE INTERNAL "Cleared" FORCE) + endif (NOT ${_current}) +endmacro (FIND_PACKAGE_MULTIPASS) + + +macro (MULTIPASS_C_SOURCE_RUNS name includes libraries source runs) + include (CheckCSourceRuns) + string (TOUPPER ${name} _NAME) + # This is a ridiculous hack. CHECK_C_SOURCE_* thinks that if the + # *name* of the return variable doesn't change, then the test does + # not need to be re-run. We keep an internal count which we + # increment to guarantee that every test name is unique. If we've + # gotten here, then the configuration has changed enough that the + # test *needs* to be rerun. + if (NOT MULTIPASS_TEST_COUNT) + set (MULTIPASS_TEST_COUNT 00) + endif (NOT MULTIPASS_TEST_COUNT) + math (EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1") # Why can't I add to a cache variable? + set (MULTIPASS_TEST_COUNT ${_tmp} CACHE INTERNAL "Unique test ID") + set (testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs}) + set (CMAKE_REQUIRED_INCLUDES ${includes}) + set (CMAKE_REQUIRED_LIBRARIES ${libraries}) + check_c_source_runs ("${source}" ${testname}) + set (${runs} "${${testname}}") +endmacro (MULTIPASS_C_SOURCE_RUNS) diff --git a/src/external/CoMISo/cmake/FindQt4.cmake b/src/external/CoMISo/cmake/FindQt4.cmake new file mode 100644 index 000000000..90411ebc4 --- /dev/null +++ b/src/external/CoMISo/cmake/FindQt4.cmake @@ -0,0 +1,1481 @@ +# - Find QT 4 +# This module can be used to find Qt4. +# The most important issue is that the Qt4 qmake is available via the system path. +# This qmake is then used to detect basically everything else. +# This module defines a number of key variables and macros. +# First is QT_USE_FILE which is the path to a CMake file that can be included +# to compile Qt 4 applications and libraries. By default, the QtCore and QtGui +# libraries are loaded. This behavior can be changed by setting one or more +# of the following variables to true before doing INCLUDE(${QT_USE_FILE}): +# QT_DONT_USE_QTCORE +# QT_DONT_USE_QTGUI +# QT_USE_QT3SUPPORT +# QT_USE_QTASSISTANT +# QT_USE_QTDESIGNER +# QT_USE_QTMOTIF +# QT_USE_QTMAIN +# QT_USE_QTNETWORK +# QT_USE_QTNSPLUGIN +# QT_USE_QTOPENGL +# QT_USE_QTSQL +# QT_USE_QTXML +# QT_USE_QTSVG +# QT_USE_QTTEST +# QT_USE_QTUITOOLS +# QT_USE_QTDBUS +# QT_USE_QTSCRIPT +# QT_USE_QTASSISTANTCLIENT +# QT_USE_QTHELP +# QT_USE_QTWEBKIT +# QT_USE_QTXMLPATTERNS +# QT_USE_PHONON +# +# The file pointed to by QT_USE_FILE will set up your compile environment +# by adding include directories, preprocessor defines, and populate a +# QT_LIBRARIES variable containing all the Qt libraries and their dependencies. +# Add the QT_LIBRARIES variable to your TARGET_LINK_LIBRARIES. +# +# Typical usage could be something like: +# FIND_PACKAGE(Qt4) +# SET(QT_USE_QTXML 1) +# INCLUDE(${QT_USE_FILE}) +# ADD_EXECUTABLE(myexe main.cpp) +# TARGET_LINK_LIBRARIES(myexe ${QT_LIBRARIES}) +# +# +# There are also some files that need processing by some Qt tools such as moc +# and uic. Listed below are macros that may be used to process those files. +# +# macro QT4_WRAP_CPP(outfiles inputfile ... OPTIONS ...) +# create moc code from a list of files containing Qt class with +# the Q_OBJECT declaration. Per-direcotry preprocessor definitions +# are also added. Options may be given to moc, such as those found +# when executing "moc -help". +# +# macro QT4_WRAP_UI(outfiles inputfile ... OPTIONS ...) +# create code from a list of Qt designer ui files. +# Options may be given to uic, such as those found +# when executing "uic -help" +# +# macro QT4_ADD_RESOURCES(outfiles inputfile ... OPTIONS ...) +# create code from a list of Qt resource files. +# Options may be given to rcc, such as those found +# when executing "rcc -help" +# +# macro QT4_GENERATE_MOC(inputfile outputfile ) +# creates a rule to run moc on infile and create outfile. +# Use this if for some reason QT4_WRAP_CPP() isn't appropriate, e.g. +# because you need a custom filename for the moc file or something similar. +# +# macro QT4_AUTOMOC(sourcefile1 sourcefile2 ... ) +# This macro is still experimental. +# It can be used to have moc automatically handled. +# So if you have the files foo.h and foo.cpp, and in foo.h a +# a class uses the Q_OBJECT macro, moc has to run on it. If you don't +# want to use QT4_WRAP_CPP() (which is reliable and mature), you can insert +# #include "foo.moc" +# in foo.cpp and then give foo.cpp as argument to QT4_AUTOMOC(). This will the +# scan all listed files at cmake-time for such included moc files and if it finds +# them cause a rule to be generated to run moc at build time on the +# accompanying header file foo.h. +# If a source file has the SKIP_AUTOMOC property set it will be ignored by this macro. +# +# macro QT4_ADD_DBUS_INTERFACE(outfiles interface basename) +# create a the interface header and implementation files with the +# given basename from the given interface xml file and add it to +# the list of sources +# +# macro QT4_ADD_DBUS_INTERFACES(outfiles inputfile ... ) +# create the interface header and implementation files +# for all listed interface xml files +# the name will be automatically determined from the name of the xml file +# +# macro QT4_ADD_DBUS_ADAPTOR(outfiles xmlfile parentheader parentclassname [basename] ) +# create a dbus adaptor (header and implementation file) from the xml file +# describing the interface, and add it to the list of sources. The adaptor +# forwards the calls to a parent class, defined in parentheader and named +# parentclassname. The name of the generated files will be +# adaptor.{cpp,h} where basename is the basename of the xml file. +# +# macro QT4_GENERATE_DBUS_INTERFACE( header [interfacename] ) +# generate the xml interface file from the given header. +# If the optional argument interfacename is omitted, the name of the +# interface file is constructed from the basename of the header with +# the suffix .xml appended. +# +# macro QT4_CREATE_TRANSLATION( qm_files directories ... sources ... +# ts_files ... OPTIONS ...) +# out: qm_files +# in: directories sources ts_files +# options: flags to pass to lupdate, such as -extensions to specify +# extensions for a directory scan. +# generates commands to create .ts (vie lupdate) and .qm +# (via lrelease) - files from directories and/or sources. The ts files are +# created and/or updated in the source tree (unless given with full paths). +# The qm files are generated in the build tree. +# Updating the translations can be done by adding the qm_files +# to the source list of your library/executable, so they are +# always updated, or by adding a custom target to control when +# they get updated/generated. +# +# macro QT4_ADD_TRANSLATION( qm_files ts_files ... ) +# out: qm_files +# in: ts_files +# generates commands to create .qm from .ts - files. The generated +# filenames can be found in qm_files. The ts_files +# must exists and are not updated in any way. +# +# +# QT_FOUND If false, don't try to use Qt. +# QT4_FOUND If false, don't try to use Qt 4. +# +# QT_VERSION_MAJOR The major version of Qt found. +# QT_VERSION_MINOR The minor version of Qt found. +# QT_VERSION_PATCH The patch version of Qt found. +# +# QT_EDITION Set to the edition of Qt (i.e. DesktopLight) +# QT_EDITION_DESKTOPLIGHT True if QT_EDITION == DesktopLight +# QT_QTCORE_FOUND True if QtCore was found. +# QT_QTGUI_FOUND True if QtGui was found. +# QT_QT3SUPPORT_FOUND True if Qt3Support was found. +# QT_QTASSISTANT_FOUND True if QtAssistant was found. +# QT_QTDBUS_FOUND True if QtDBus was found. +# QT_QTDESIGNER_FOUND True if QtDesigner was found. +# QT_QTDESIGNERCOMPONENTS True if QtDesignerComponents was found. +# QT_QTMOTIF_FOUND True if QtMotif was found. +# QT_QTNETWORK_FOUND True if QtNetwork was found. +# QT_QTNSPLUGIN_FOUND True if QtNsPlugin was found. +# QT_QTOPENGL_FOUND True if QtOpenGL was found. +# QT_QTSQL_FOUND True if QtSql was found. +# QT_QTXML_FOUND True if QtXml was found. +# QT_QTSVG_FOUND True if QtSvg was found. +# QT_QTSCRIPT_FOUND True if QtScript was found. +# QT_QTTEST_FOUND True if QtTest was found. +# QT_QTUITOOLS_FOUND True if QtUiTools was found. +# QT_QTASSISTANTCLIENT_FOUND True if QtAssistantClient was found. +# QT_QTHELP_FOUND True if QtHelp was found. +# QT_QTWEBKIT_FOUND True if QtWebKit was found. +# QT_QTXMLPATTERNS_FOUND True if QtXmlPatterns was found. +# QT_PHONON_FOUND True if phonon was found. +# +# +# QT_DEFINITIONS Definitions to use when compiling code that uses Qt. +# You do not need to use this if you include QT_USE_FILE. +# The QT_USE_FILE will also define QT_DEBUG and QT_NO_DEBUG +# to fit your current build type. Those are not contained +# in QT_DEFINITIONS. +# +# QT_INCLUDES List of paths to all include directories of +# Qt4 QT_INCLUDE_DIR and QT_QTCORE_INCLUDE_DIR are +# always in this variable even if NOTFOUND, +# all other INCLUDE_DIRS are +# only added if they are found. +# You do not need to use this if you include QT_USE_FILE. +# +# +# Include directories for the Qt modules are listed here. +# You do not need to use these variables if you include QT_USE_FILE. +# +# QT_INCLUDE_DIR Path to "include" of Qt4 +# QT_QT_INCLUDE_DIR Path to "include/Qt" +# QT_QT3SUPPORT_INCLUDE_DIR Path to "include/Qt3Support" +# QT_QTASSISTANT_INCLUDE_DIR Path to "include/QtAssistant" +# QT_QTCORE_INCLUDE_DIR Path to "include/QtCore" +# QT_QTDESIGNER_INCLUDE_DIR Path to "include/QtDesigner" +# QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR Path to "include/QtDesigner" +# QT_QTDBUS_INCLUDE_DIR Path to "include/QtDBus" +# QT_QTGUI_INCLUDE_DIR Path to "include/QtGui" +# QT_QTMOTIF_INCLUDE_DIR Path to "include/QtMotif" +# QT_QTNETWORK_INCLUDE_DIR Path to "include/QtNetwork" +# QT_QTNSPLUGIN_INCLUDE_DIR Path to "include/QtNsPlugin" +# QT_QTOPENGL_INCLUDE_DIR Path to "include/QtOpenGL" +# QT_QTSQL_INCLUDE_DIR Path to "include/QtSql" +# QT_QTXML_INCLUDE_DIR Path to "include/QtXml" +# QT_QTSVG_INCLUDE_DIR Path to "include/QtSvg" +# QT_QTSCRIPT_INCLUDE_DIR Path to "include/QtScript" +# QT_QTTEST_INCLUDE_DIR Path to "include/QtTest" +# QT_QTASSISTANTCLIENT_INCLUDE_DIR Path to "include/QtAssistant" +# QT_QTHELP_INCLUDE_DIR Path to "include/QtHelp" +# QT_QTWEBKIT_INCLUDE_DIR Path to "include/QtWebKit" +# QT_QTXMLPATTERNS_INCLUDE_DIR Path to "include/QtXmlPatterns" +# QT_PHONON_INCLUDE_DIR Path to "include/phonon" +# +# QT_LIBRARY_DIR Path to "lib" of Qt4 +# +# QT_PLUGINS_DIR Path to "plugins" for Qt4 +# +# +# The Qt toolkit may contain both debug and release libraries. +# In that case, the following library variables will contain both. +# You do not need to use these variables if you include QT_USE_FILE, +# and use QT_LIBRARIES. +# +# QT_QT3SUPPORT_LIBRARY The Qt3Support library +# QT_QTASSISTANT_LIBRARY The QtAssistant library +# QT_QTCORE_LIBRARY The QtCore library +# QT_QTDBUS_LIBRARY The QtDBus library +# QT_QTDESIGNER_LIBRARY The QtDesigner library +# QT_QTDESIGNERCOMPONENTS_LIBRARY The QtDesignerComponents library +# QT_QTGUI_LIBRARY The QtGui library +# QT_QTMOTIF_LIBRARY The QtMotif library +# QT_QTNETWORK_LIBRARY The QtNetwork library +# QT_QTNSPLUGIN_LIBRARY The QtNsPLugin library +# QT_QTOPENGL_LIBRARY The QtOpenGL library +# QT_QTSQL_LIBRARY The QtSql library +# QT_QTXML_LIBRARY The QtXml library +# QT_QTSVG_LIBRARY The QtSvg library +# QT_QTSCRIPT_LIBRARY The QtScript library +# QT_QTTEST_LIBRARY The QtTest library +# QT_QTMAIN_LIBRARY The qtmain library for Windows +# QT_QTUITOOLS_LIBRARY The QtUiTools library +# QT_QTASSISTANTCLIENT_LIBRARY The QtAssistantClient library +# QT_QTHELP_LIBRARY The QtHelp library +# QT_QTWEBKIT_LIBRARY The QtWebKit library +# QT_QTXMLPATTERNS_LIBRARY The QtXmlPatterns library +# QT_PHONON_LIBRARY The phonon library +# +# also defined, but NOT for general use are +# QT_MOC_EXECUTABLE Where to find the moc tool. +# QT_UIC_EXECUTABLE Where to find the uic tool. +# QT_UIC3_EXECUTABLE Where to find the uic3 tool. +# QT_RCC_EXECUTABLE Where to find the rcc tool +# QT_DBUSCPP2XML_EXECUTABLE Where to find the qdbuscpp2xml tool. +# QT_DBUSXML2CPP_EXECUTABLE Where to find the qdbusxml2cpp tool. +# QT_LUPDATE_EXECUTABLE Where to find the lupdate tool. +# QT_LRELEASE_EXECUTABLE Where to find the lrelease tool. +# +# QT_DOC_DIR Path to "doc" of Qt4 +# QT_MKSPECS_DIR Path to "mkspecs" of Qt4 +# +# +# These are around for backwards compatibility +# they will be set +# QT_WRAP_CPP Set true if QT_MOC_EXECUTABLE is found +# QT_WRAP_UI Set true if QT_UIC_EXECUTABLE is found +# +# These variables do _NOT_ have any effect anymore (compared to FindQt.cmake) +# QT_MT_REQUIRED Qt4 is now always multithreaded +# +# These variables are set to "" Because Qt structure changed +# (They make no sense in Qt4) +# QT_QT_LIBRARY Qt-Library is now split + +# If Qt3 has already been found, fail. +IF(QT_QT_LIBRARY) + IF(Qt4_FIND_REQUIRED) + MESSAGE( FATAL_ERROR "Qt3 and Qt4 cannot be used together in one project.") + ELSE(Qt4_FIND_REQUIRED) + IF(NOT Qt4_FIND_QUIETLY) + MESSAGE( STATUS "Qt3 and Qt4 cannot be used together in one project.") + ENDIF(NOT Qt4_FIND_QUIETLY) + RETURN() + ENDIF(Qt4_FIND_REQUIRED) +ENDIF(QT_QT_LIBRARY) + + +INCLUDE(CheckSymbolExists) +INCLUDE(MacroAddFileDependencies) + +SET(QT_USE_FILE ${CMAKE_ROOT}/Modules/UseQt4.cmake) + +SET( QT_DEFINITIONS "") + +SET(QT4_INSTALLED_VERSION_TOO_OLD FALSE) + +# macro for asking qmake to process pro files +MACRO(QT_QUERY_QMAKE outvar invar) + IF(QT_QMAKE_EXECUTABLE) + FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake/tmp.pro + "message(CMAKE_MESSAGE<$$${invar}>)") + + # Invoke qmake with the tmp.pro program to get the desired + # information. Use the same variable for both stdout and stderr + # to make sure we get the output on all platforms. + EXECUTE_PROCESS(COMMAND ${QT_QMAKE_EXECUTABLE} + WORKING_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake + OUTPUT_VARIABLE _qmake_query_output + RESULT_VARIABLE _qmake_result + ERROR_VARIABLE _qmake_query_output ) + + FILE(REMOVE_RECURSE + "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmpQmake") + + IF(_qmake_result) + MESSAGE(WARNING " querying qmake for ${invar}. qmake reported:\n${_qmake_query_output}") + ELSE(_qmake_result) + STRING(REGEX REPLACE ".*CMAKE_MESSAGE<([^>]*).*" "\\1" ${outvar} "${_qmake_query_output}") + ENDIF(_qmake_result) + + ENDIF(QT_QMAKE_EXECUTABLE) +ENDMACRO(QT_QUERY_QMAKE) + +GET_FILENAME_COMPONENT(qt_install_version "[HKEY_CURRENT_USER\\Software\\trolltech\\Versions;DefaultQtVersion]" NAME) +# check for qmake +FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake qmake4 qmake-qt4 PATHS + "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" + "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" + "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\${qt_install_version};InstallDir]/bin" + $ENV{QTDIR}/bin +) + +IF (QT_QMAKE_EXECUTABLE) + + SET(QT4_QMAKE_FOUND FALSE) + + EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} ARGS "-query QT_VERSION" OUTPUT_VARIABLE QTVERSION) + + # check for qt3 qmake and then try and find qmake4 or qmake-qt4 in the path + IF("${QTVERSION}" MATCHES "Unknown") + SET(QT_QMAKE_EXECUTABLE NOTFOUND CACHE FILEPATH "" FORCE) + FIND_PROGRAM(QT_QMAKE_EXECUTABLE NAMES qmake4 qmake-qt4 PATHS + "[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\4.0.0;InstallDir]/bin" + "[HKEY_CURRENT_USER\\Software\\Trolltech\\Versions\\4.0.0;InstallDir]/bin" + $ENV{QTDIR}/bin + ) + IF(QT_QMAKE_EXECUTABLE) + EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} + ARGS "-query QT_VERSION" OUTPUT_VARIABLE QTVERSION) + ENDIF(QT_QMAKE_EXECUTABLE) + ENDIF("${QTVERSION}" MATCHES "Unknown") + + # check that we found the Qt4 qmake, Qt3 qmake output won't match here + STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" qt_version_tmp "${QTVERSION}") + IF (qt_version_tmp) + + # we need at least version 4.0.0 + IF (NOT QT_MIN_VERSION) + SET(QT_MIN_VERSION "4.0.0") + ENDIF (NOT QT_MIN_VERSION) + + #now parse the parts of the user given version string into variables + STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" req_qt_major_vers "${QT_MIN_VERSION}") + IF (NOT req_qt_major_vers) + MESSAGE( FATAL_ERROR "Invalid Qt version string given: \"${QT_MIN_VERSION}\", expected e.g. \"4.0.1\"") + ENDIF (NOT req_qt_major_vers) + + # now parse the parts of the user given version string into variables + STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" req_qt_major_vers "${QT_MIN_VERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" req_qt_minor_vers "${QT_MIN_VERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" req_qt_patch_vers "${QT_MIN_VERSION}") + + IF (NOT req_qt_major_vers EQUAL 4) + MESSAGE( FATAL_ERROR "Invalid Qt version string given: \"${QT_MIN_VERSION}\", major version 4 is required, e.g. \"4.0.1\"") + ENDIF (NOT req_qt_major_vers EQUAL 4) + + # and now the version string given by qmake + STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" QT_VERSION_MAJOR "${QTVERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+.*" "\\1" QT_VERSION_MINOR "${QTVERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" QT_VERSION_PATCH "${QTVERSION}") + + # compute an overall version number which can be compared at once + MATH(EXPR req_vers "${req_qt_major_vers}*10000 + ${req_qt_minor_vers}*100 + ${req_qt_patch_vers}") + MATH(EXPR found_vers "${QT_VERSION_MAJOR}*10000 + ${QT_VERSION_MINOR}*100 + ${QT_VERSION_PATCH}") + + IF (found_vers LESS req_vers) + SET(QT4_QMAKE_FOUND FALSE) + SET(QT4_INSTALLED_VERSION_TOO_OLD TRUE) + ELSE (found_vers LESS req_vers) + SET(QT4_QMAKE_FOUND TRUE) + ENDIF (found_vers LESS req_vers) + ENDIF (qt_version_tmp) + +ENDIF (QT_QMAKE_EXECUTABLE) + +IF (QT4_QMAKE_FOUND) + + # ask qmake for the library dir + # Set QT_LIBRARY_DIR + IF (NOT QT_LIBRARY_DIR) + EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} + ARGS "-query QT_INSTALL_LIBS" + OUTPUT_VARIABLE QT_LIBRARY_DIR_TMP ) + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH "${QT_LIBRARY_DIR_TMP}" QT_LIBRARY_DIR_TMP) + IF(EXISTS "${QT_LIBRARY_DIR_TMP}") + SET(QT_LIBRARY_DIR ${QT_LIBRARY_DIR_TMP} CACHE PATH "Qt library dir") + ELSE(EXISTS "${QT_LIBRARY_DIR_TMP}") + MESSAGE("Warning: QT_QMAKE_EXECUTABLE reported QT_INSTALL_LIBS as ${QT_LIBRARY_DIR_TMP}") + MESSAGE("Warning: ${QT_LIBRARY_DIR_TMP} does NOT exist, Qt must NOT be installed correctly.") + ENDIF(EXISTS "${QT_LIBRARY_DIR_TMP}") + ENDIF(NOT QT_LIBRARY_DIR) + + IF (APPLE) + IF (EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) + SET(QT_USE_FRAMEWORKS ON + CACHE BOOL "Set to ON if Qt build uses frameworks.") + ELSE (EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) + SET(QT_USE_FRAMEWORKS OFF + CACHE BOOL "Set to ON if Qt build uses frameworks.") + ENDIF (EXISTS ${QT_LIBRARY_DIR}/QtCore.framework) + + MARK_AS_ADVANCED(QT_USE_FRAMEWORKS) + ENDIF (APPLE) + + # ask qmake for the binary dir + IF (QT_LIBRARY_DIR AND NOT QT_BINARY_DIR) + EXEC_PROGRAM(${QT_QMAKE_EXECUTABLE} + ARGS "-query QT_INSTALL_BINS" + OUTPUT_VARIABLE qt_bins ) + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH "${qt_bins}" qt_bins) + SET(QT_BINARY_DIR ${qt_bins} CACHE INTERNAL "") + ENDIF (QT_LIBRARY_DIR AND NOT QT_BINARY_DIR) + + # ask qmake for the include dir + IF (QT_LIBRARY_DIR AND NOT QT_HEADERS_DIR) + EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} + ARGS "-query QT_INSTALL_HEADERS" + OUTPUT_VARIABLE qt_headers ) + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH "${qt_headers}" qt_headers) + SET(QT_HEADERS_DIR ${qt_headers} CACHE INTERNAL "") + ENDIF(QT_LIBRARY_DIR AND NOT QT_HEADERS_DIR) + + + # ask qmake for the documentation directory + IF (QT_LIBRARY_DIR AND NOT QT_DOC_DIR) + EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} + ARGS "-query QT_INSTALL_DOCS" + OUTPUT_VARIABLE qt_doc_dir ) + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH "${qt_doc_dir}" qt_doc_dir) + SET(QT_DOC_DIR ${qt_doc_dir} CACHE PATH "The location of the Qt docs") + ENDIF (QT_LIBRARY_DIR AND NOT QT_DOC_DIR) + + # ask qmake for the mkspecs directory + IF (QT_LIBRARY_DIR AND NOT QT_MKSPECS_DIR) + EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} + ARGS "-query QMAKE_MKSPECS" + OUTPUT_VARIABLE qt_mkspecs_dirs ) + # do not replace : on windows as it might be a drive letter + # and windows should already use ; as a separator + IF(UNIX) + STRING(REPLACE ":" ";" qt_mkspecs_dirs "${qt_mkspecs_dirs}") + ENDIF(UNIX) + FIND_PATH(QT_MKSPECS_DIR qconfig.pri PATHS ${qt_mkspecs_dirs} + DOC "The location of the Qt mkspecs containing qconfig.pri" + NO_DEFAULT_PATH ) + ENDIF (QT_LIBRARY_DIR AND NOT QT_MKSPECS_DIR) + + # ask qmake for the plugins directory + IF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR) + EXEC_PROGRAM( ${QT_QMAKE_EXECUTABLE} + ARGS "-query QT_INSTALL_PLUGINS" + OUTPUT_VARIABLE qt_plugins_dir ) + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH "${qt_plugins_dir}" qt_plugins_dir) + SET(QT_PLUGINS_DIR ${qt_plugins_dir} CACHE PATH "The location of the Qt plugins") + ENDIF (QT_LIBRARY_DIR AND NOT QT_PLUGINS_DIR) + ######################################## + # + # Setting the INCLUDE-Variables + # + ######################################## + + FIND_PATH(QT_QTCORE_INCLUDE_DIR QtGlobal + PATHS + ${QT_HEADERS_DIR}/QtCore + ${QT_LIBRARY_DIR}/QtCore.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_INCLUDE_DIR by removine "/QtCore" in the string ${QT_QTCORE_INCLUDE_DIR} + IF( QT_QTCORE_INCLUDE_DIR AND NOT QT_INCLUDE_DIR) + IF (QT_USE_FRAMEWORKS) + SET(QT_INCLUDE_DIR ${QT_HEADERS_DIR}) + ELSE (QT_USE_FRAMEWORKS) + STRING( REGEX REPLACE "/QtCore$" "" qt4_include_dir ${QT_QTCORE_INCLUDE_DIR}) + SET( QT_INCLUDE_DIR ${qt4_include_dir} CACHE PATH "") + ENDIF (QT_USE_FRAMEWORKS) + ENDIF( QT_QTCORE_INCLUDE_DIR AND NOT QT_INCLUDE_DIR) + + IF( NOT QT_INCLUDE_DIR) + IF(Qt4_FIND_REQUIRED) + MESSAGE( FATAL_ERROR "Could NOT find QtGlobal header") + ENDIF(Qt4_FIND_REQUIRED) + ENDIF( NOT QT_INCLUDE_DIR) + + ############################################# + # + # Find out what window system we're using + # + ############################################# + # Save required variable + SET(CMAKE_REQUIRED_INCLUDES_SAVE ${CMAKE_REQUIRED_INCLUDES}) + SET(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS}) + # Add QT_INCLUDE_DIR to CMAKE_REQUIRED_INCLUDES + SET(CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES};${QT_INCLUDE_DIR}") + # On Mac OS X when Qt has framework support, also add the framework path + IF( QT_USE_FRAMEWORKS ) + SET(CMAKE_REQUIRED_FLAGS "-F${QT_LIBRARY_DIR} ") + ENDIF( QT_USE_FRAMEWORKS ) + # Check for Window system symbols (note: only one should end up being set) + CHECK_SYMBOL_EXISTS(Q_WS_X11 "QtCore/qglobal.h" Q_WS_X11) + CHECK_SYMBOL_EXISTS(Q_WS_WIN "QtCore/qglobal.h" Q_WS_WIN) + CHECK_SYMBOL_EXISTS(Q_WS_QWS "QtCore/qglobal.h" Q_WS_QWS) + CHECK_SYMBOL_EXISTS(Q_WS_MAC "QtCore/qglobal.h" Q_WS_MAC) + + IF (QT_QTCOPY_REQUIRED) + CHECK_SYMBOL_EXISTS(QT_IS_QTCOPY "QtCore/qglobal.h" QT_KDE_QT_COPY) + IF (NOT QT_IS_QTCOPY) + MESSAGE(FATAL_ERROR "qt-copy is required, but hasn't been found") + ENDIF (NOT QT_IS_QTCOPY) + ENDIF (QT_QTCOPY_REQUIRED) + + # Restore CMAKE_REQUIRED_INCLUDES and CMAKE_REQUIRED_FLAGS variables + SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES_SAVE}) + SET(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE}) + # + ############################################# + + # Set QT_QT3SUPPORT_INCLUDE_DIR + FIND_PATH(QT_QT3SUPPORT_INCLUDE_DIR Qt3Support + PATHS + ${QT_INCLUDE_DIR}/Qt3Support + ${QT_LIBRARY_DIR}/Qt3Support.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QT_INCLUDE_DIR + FIND_PATH(QT_QT_INCLUDE_DIR qglobal.h + PATHS + ${QT_INCLUDE_DIR}/Qt + ${QT_LIBRARY_DIR}/QtCore.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTGUI_INCLUDE_DIR + FIND_PATH(QT_QTGUI_INCLUDE_DIR QtGui + PATHS + ${QT_INCLUDE_DIR}/QtGui + ${QT_LIBRARY_DIR}/QtGui.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTSVG_INCLUDE_DIR + FIND_PATH(QT_QTSVG_INCLUDE_DIR QtSvg + PATHS + ${QT_INCLUDE_DIR}/QtSvg + ${QT_LIBRARY_DIR}/QtSvg.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTSCRIPT_INCLUDE_DIR + FIND_PATH(QT_QTSCRIPT_INCLUDE_DIR QtScript + PATHS + ${QT_INCLUDE_DIR}/QtScript + ${QT_LIBRARY_DIR}/QtScript.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTTEST_INCLUDE_DIR + FIND_PATH(QT_QTTEST_INCLUDE_DIR QtTest + PATHS + ${QT_INCLUDE_DIR}/QtTest + ${QT_LIBRARY_DIR}/QtTest.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTUITOOLS_INCLUDE_DIR + FIND_PATH(QT_QTUITOOLS_INCLUDE_DIR QtUiTools + PATHS + ${QT_INCLUDE_DIR}/QtUiTools + ${QT_LIBRARY_DIR}/QtUiTools.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTMOTIF_INCLUDE_DIR + IF(Q_WS_X11) + FIND_PATH(QT_QTMOTIF_INCLUDE_DIR QtMotif + PATHS + ${QT_INCLUDE_DIR}/QtMotif + NO_DEFAULT_PATH ) + ENDIF(Q_WS_X11) + + # Set QT_QTNETWORK_INCLUDE_DIR + FIND_PATH(QT_QTNETWORK_INCLUDE_DIR QtNetwork + PATHS + ${QT_INCLUDE_DIR}/QtNetwork + ${QT_LIBRARY_DIR}/QtNetwork.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTNSPLUGIN_INCLUDE_DIR + FIND_PATH(QT_QTNSPLUGIN_INCLUDE_DIR QtNsPlugin + PATHS + ${QT_INCLUDE_DIR}/QtNsPlugin + ${QT_LIBRARY_DIR}/QtNsPlugin.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTOPENGL_INCLUDE_DIR + FIND_PATH(QT_QTOPENGL_INCLUDE_DIR QtOpenGL + PATHS + ${QT_INCLUDE_DIR}/QtOpenGL + ${QT_LIBRARY_DIR}/QtOpenGL.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTSQL_INCLUDE_DIR + FIND_PATH(QT_QTSQL_INCLUDE_DIR QtSql + PATHS + ${QT_INCLUDE_DIR}/QtSql + ${QT_LIBRARY_DIR}/QtSql.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTXML_INCLUDE_DIR + FIND_PATH(QT_QTXML_INCLUDE_DIR QtXml + PATHS + ${QT_INCLUDE_DIR}/QtXml + ${QT_LIBRARY_DIR}/QtXml.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTASSISTANT_INCLUDE_DIR + FIND_PATH(QT_QTASSISTANT_INCLUDE_DIR QtAssistant + PATHS + ${QT_INCLUDE_DIR}/QtAssistant + ${QT_LIBRARY_DIR}/QtAssistant.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTDESIGNER_INCLUDE_DIR + FIND_PATH(QT_QTDESIGNER_INCLUDE_DIR QDesignerComponents + PATHS + ${QT_INCLUDE_DIR}/QtDesigner + ${QT_LIBRARY_DIR}/QtDesigner.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR + FIND_PATH(QT_QTDESIGNERCOMPONENTS_INCLUDE_DIR QDesignerComponents + PATHS + ${QT_INCLUDE_DIR}/QtDesigner + ${QT_LIBRARY_DIR}/QtDesigner.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTDBUS_INCLUDE_DIR + FIND_PATH(QT_QTDBUS_INCLUDE_DIR QtDBus + PATHS + ${QT_INCLUDE_DIR}/QtDBus + ${QT_LIBRARY_DIR}/QtDBus.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTASSISTANTCLIENT_INCLUDE_DIR + FIND_PATH(QT_QTASSISTANTCLIENT_INCLUDE_DIR QAssistantClient + PATHS + ${QT_INCLUDE_DIR}/QtAssistant + ${QT_LIBRARY_DIR}/QtAssistant.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTHELP_INCLUDE_DIR + FIND_PATH(QT_QTHELP_INCLUDE_DIR QtHelp + PATHS + ${QT_INCLUDE_DIR}/QtHelp + ${QT_LIBRARY_DIR}/QtHelp.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTWEBKIT_INCLUDE_DIR + FIND_PATH(QT_QTWEBKIT_INCLUDE_DIR QtWebKit + PATHS + ${QT_INCLUDE_DIR}/QtWebKit + ${QT_LIBRARY_DIR}/QtWebKit.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_QTXMLPATTERNS_INCLUDE_DIR + FIND_PATH(QT_QTXMLPATTERNS_INCLUDE_DIR QtXmlPatterns + PATHS + ${QT_INCLUDE_DIR}/QtXmlPatterns + ${QT_LIBRARY_DIR}/QtXmlPatterns.framework/Headers + NO_DEFAULT_PATH + ) + + # Set QT_PHONON_INCLUDE_DIR + FIND_PATH(QT_PHONON_INCLUDE_DIR phonon + PATHS + ${QT_INCLUDE_DIR}/phonon + ${QT_LIBRARY_DIR}/phonon.framework/Headers + NO_DEFAULT_PATH + ) + + # Make variables changeble to the advanced user + MARK_AS_ADVANCED( QT_LIBRARY_DIR QT_INCLUDE_DIR QT_QT_INCLUDE_DIR QT_DOC_DIR QT_MKSPECS_DIR QT_PLUGINS_DIR) + + # Set QT_INCLUDES + SET( QT_INCLUDES ${QT_QT_INCLUDE_DIR} ${QT_MKSPECS_DIR}/default ${QT_INCLUDE_DIR} ) + + # Set QT_QTCORE_LIBRARY by searching for a lib with "QtCore." as part of the filename + FIND_LIBRARY(QT_QTCORE_LIBRARY_RELEASE NAMES QtCore QtCore4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH ) + FIND_LIBRARY(QT_QTCORE_LIBRARY_DEBUG NAMES QtCore_debug QtCored QtCored4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QT3SUPPORT_LIBRARY + FIND_LIBRARY(QT_QT3SUPPORT_LIBRARY_RELEASE NAMES Qt3Support Qt3Support4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QT3SUPPORT_LIBRARY_DEBUG NAMES Qt3Support_debug Qt3Supportd Qt3Supportd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTGUI_LIBRARY + FIND_LIBRARY(QT_QTGUI_LIBRARY_RELEASE NAMES QtGui QtGui4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTGUI_LIBRARY_DEBUG NAMES QtGui_debug QtGuid QtGuid4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTMOTIF_LIBRARY + IF(Q_WS_X11) + FIND_LIBRARY(QT_QTMOTIF_LIBRARY_RELEASE NAMES QtMotif PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTMOTIF_LIBRARY_DEBUG NAMES QtMotif_debug PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + ENDIF(Q_WS_X11) + + # Set QT_QTNETWORK_LIBRARY + FIND_LIBRARY(QT_QTNETWORK_LIBRARY_RELEASE NAMES QtNetwork QtNetwork4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTNETWORK_LIBRARY_DEBUG NAMES QtNetwork_debug QtNetworkd QtNetworkd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTNSPLUGIN_LIBRARY + FIND_LIBRARY(QT_QTNSPLUGIN_LIBRARY_RELEASE NAMES QtNsPlugin PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTNSPLUGIN_LIBRARY_DEBUG NAMES QtNsPlugin_debug PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTOPENGL_LIBRARY + FIND_LIBRARY(QT_QTOPENGL_LIBRARY_RELEASE NAMES QtOpenGL QtOpenGL4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTOPENGL_LIBRARY_DEBUG NAMES QtOpenGL_debug QtOpenGLd QtOpenGLd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTSQL_LIBRARY + FIND_LIBRARY(QT_QTSQL_LIBRARY_RELEASE NAMES QtSql QtSql4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTSQL_LIBRARY_DEBUG NAMES QtSql_debug QtSqld QtSqld4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTXML_LIBRARY + FIND_LIBRARY(QT_QTXML_LIBRARY_RELEASE NAMES QtXml QtXml4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTXML_LIBRARY_DEBUG NAMES QtXml_debug QtXmld QtXmld4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTSVG_LIBRARY + FIND_LIBRARY(QT_QTSVG_LIBRARY_RELEASE NAMES QtSvg QtSvg4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTSVG_LIBRARY_DEBUG NAMES QtSvg_debug QtSvgd QtSvgd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTUITOOLS_LIBRARY + FIND_LIBRARY(QT_QTUITOOLS_LIBRARY_RELEASE NAMES QtUiTools QtUiTools4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTUITOOLS_LIBRARY_DEBUG NAMES QtUiTools_debug QtUiToolsd QtUiToolsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + # QtUiTools not with other frameworks with binary installation (in /usr/lib) + IF(Q_WS_MAC AND QT_QTCORE_LIBRARY_RELEASE AND NOT QT_QTUITOOLS_LIBRARY_RELEASE) + FIND_LIBRARY(QT_QTUITOOLS_LIBRARY_RELEASE NAMES QtUiTools PATHS ${QT_LIBRARY_DIR}) + ENDIF(Q_WS_MAC AND QT_QTCORE_LIBRARY_RELEASE AND NOT QT_QTUITOOLS_LIBRARY_RELEASE) + + # Set QT_QTTEST_LIBRARY + FIND_LIBRARY(QT_QTTEST_LIBRARY_RELEASE NAMES QtTest QtTest4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTTEST_LIBRARY_DEBUG NAMES QtTest_debug QtTestd QtTestd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTDBUS_LIBRARY + # This was introduced with Qt 4.2, where also the naming scheme for debug libs was changed + # So does any of the debug lib names listed here actually exist ? + FIND_LIBRARY(QT_QTDBUS_LIBRARY_RELEASE NAMES QtDBus QtDBus4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTDBUS_LIBRARY_DEBUG NAMES QtDBus_debug QtDBusd QtDBusd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTSCRIPT_LIBRARY + FIND_LIBRARY(QT_QTSCRIPT_LIBRARY_RELEASE NAMES QtScript QtScript4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTSCRIPT_LIBRARY_DEBUG NAMES QtScript_debug QtScriptd QtScriptd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + IF( NOT QT_QTCORE_LIBRARY_DEBUG AND NOT QT_QTCORE_LIBRARY_RELEASE ) + + # try dropping a hint if trying to use Visual Studio with Qt built by mingw + IF(QT_LIBRARY_DIR AND MSVC) + IF(EXISTS ${QT_LIBRARY_DIR}/libqtmain.a) + MESSAGE( FATAL_ERROR "It appears you're trying to use Visual Studio with Qt built by mingw") + ENDIF(EXISTS ${QT_LIBRARY_DIR}/libqtmain.a) + ENDIF(QT_LIBRARY_DIR AND MSVC) + + IF(Qt4_FIND_REQUIRED) + MESSAGE( FATAL_ERROR "Could NOT find QtCore. Check ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log for more details.") + ENDIF(Qt4_FIND_REQUIRED) + ENDIF( NOT QT_QTCORE_LIBRARY_DEBUG AND NOT QT_QTCORE_LIBRARY_RELEASE ) + + # Set QT_QTASSISTANT_LIBRARY + FIND_LIBRARY(QT_QTASSISTANT_LIBRARY_RELEASE NAMES QtAssistantClient QtAssistantClient4 QtAssistant QtAssistant4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTASSISTANT_LIBRARY_DEBUG NAMES QtAssistantClientd QtAssistantClientd4 QtAssistantClient_debug QtAssistant_debug QtAssistantd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTDESIGNER_LIBRARY + FIND_LIBRARY(QT_QTDESIGNER_LIBRARY_RELEASE NAMES QtDesigner QtDesigner4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTDESIGNER_LIBRARY_DEBUG NAMES QtDesigner_debug QtDesignerd QtDesignerd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTDESIGNERCOMPONENTS_LIBRARY + FIND_LIBRARY(QT_QTDESIGNERCOMPONENTS_LIBRARY_RELEASE NAMES QtDesignerComponents QtDesignerComponents4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTDESIGNERCOMPONENTS_LIBRARY_DEBUG NAMES QtDesignerComponents_debug QtDesignerComponentsd QtDesignerComponentsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTMAIN_LIBRARY + IF(WIN32) + FIND_LIBRARY(QT_QTMAIN_LIBRARY_RELEASE NAMES qtmain PATHS ${QT_LIBRARY_DIR} + NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTMAIN_LIBRARY_DEBUG NAMES qtmaind PATHS ${QT_LIBRARY_DIR} + NO_DEFAULT_PATH) + ENDIF(WIN32) + + # Set QT_QTASSISTANTCLIENT_LIBRARY + FIND_LIBRARY(QT_QTASSISTANTCLIENT_LIBRARY_RELEASE NAMES QtAssistantClient QtAssistantClient4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTASSISTANTCLIENT_LIBRARY_DEBUG NAMES QtAssistantClient_debug QtAssistantClientd QtAssistantClientd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTHELP_LIBRARY + FIND_LIBRARY(QT_QTHELP_LIBRARY_RELEASE NAMES QtHelp QtHelp4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTHELP_LIBRARY_DEBUG NAMES QtHelp_debug QtHelpd QtHelpd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTCLUCENE_LIBRARY_RELEASE NAMES QtCLucene QtCLucene4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTCLUCENE_LIBRARY_DEBUG NAMES QtCLucene_debug QtCLucened QtCLucened4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + # QtCLucene not with other frameworks with binary installation (in /usr/lib) + IF(Q_WS_MAC AND QT_QTCORE_LIBRARY_RELEASE AND NOT QT_QTCLUCENE_LIBRARY_RELEASE) + FIND_LIBRARY(QT_QTCLUCENE_LIBRARY_RELEASE NAMES QtCLucene PATHS ${QT_LIBRARY_DIR}) + ENDIF(Q_WS_MAC AND QT_QTCORE_LIBRARY_RELEASE AND NOT QT_QTCLUCENE_LIBRARY_RELEASE) + + # Set QT_QTWEBKIT_LIBRARY + FIND_LIBRARY(QT_QTWEBKIT_LIBRARY_RELEASE NAMES QtWebKit QtWebKit4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTWEBKIT_LIBRARY_DEBUG NAMES QtWebKit_debug QtWebKitd QtWebKitd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_QTXMLPATTERNS_LIBRARY + FIND_LIBRARY(QT_QTXMLPATTERNS_LIBRARY_RELEASE NAMES QtXmlPatterns QtXmlPatterns4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_QTXMLPATTERNS_LIBRARY_DEBUG NAMES QtXmlPatterns_debug QtXmlPatternsd QtXmlPatternsd4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + # Set QT_PHONON_LIBRARY + FIND_LIBRARY(QT_PHONON_LIBRARY_RELEASE NAMES phonon phonon4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + FIND_LIBRARY(QT_PHONON_LIBRARY_DEBUG NAMES phonon_debug phonond phonond4 PATHS ${QT_LIBRARY_DIR} NO_DEFAULT_PATH) + + ############################################ + # + # Check the existence of the libraries. + # + ############################################ + + MACRO (_QT4_ADJUST_LIB_VARS basename) + IF (QT_${basename}_LIBRARY_RELEASE OR QT_${basename}_LIBRARY_DEBUG) + + # if only the release version was found, set the debug variable also to the release version + IF (QT_${basename}_LIBRARY_RELEASE AND NOT QT_${basename}_LIBRARY_DEBUG) + SET(QT_${basename}_LIBRARY_DEBUG ${QT_${basename}_LIBRARY_RELEASE}) + SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY_RELEASE}) + SET(QT_${basename}_LIBRARIES ${QT_${basename}_LIBRARY_RELEASE}) + ENDIF (QT_${basename}_LIBRARY_RELEASE AND NOT QT_${basename}_LIBRARY_DEBUG) + + # if only the debug version was found, set the release variable also to the debug version + IF (QT_${basename}_LIBRARY_DEBUG AND NOT QT_${basename}_LIBRARY_RELEASE) + SET(QT_${basename}_LIBRARY_RELEASE ${QT_${basename}_LIBRARY_DEBUG}) + SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY_DEBUG}) + SET(QT_${basename}_LIBRARIES ${QT_${basename}_LIBRARY_DEBUG}) + ENDIF (QT_${basename}_LIBRARY_DEBUG AND NOT QT_${basename}_LIBRARY_RELEASE) + + IF (QT_${basename}_LIBRARY_DEBUG AND QT_${basename}_LIBRARY_RELEASE) + # if the generator supports configuration types then set + # optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value + IF (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + SET(QT_${basename}_LIBRARY optimized ${QT_${basename}_LIBRARY_RELEASE} debug ${QT_${basename}_LIBRARY_DEBUG}) + ELSE(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + # if there are no configuration types and CMAKE_BUILD_TYPE has no value + # then just use the release libraries + SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY_RELEASE} ) + ENDIF(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE) + SET(QT_${basename}_LIBRARIES optimized ${QT_${basename}_LIBRARY_RELEASE} debug ${QT_${basename}_LIBRARY_DEBUG}) + ENDIF (QT_${basename}_LIBRARY_DEBUG AND QT_${basename}_LIBRARY_RELEASE) + + SET(QT_${basename}_LIBRARY ${QT_${basename}_LIBRARY} CACHE FILEPATH "The Qt ${basename} library") + + IF (QT_${basename}_LIBRARY) + SET(QT_${basename}_FOUND 1) + ENDIF (QT_${basename}_LIBRARY) + + ENDIF (QT_${basename}_LIBRARY_RELEASE OR QT_${basename}_LIBRARY_DEBUG) + + IF (QT_${basename}_INCLUDE_DIR) + #add the include directory to QT_INCLUDES + SET(QT_INCLUDES "${QT_${basename}_INCLUDE_DIR}" ${QT_INCLUDES}) + ENDIF (QT_${basename}_INCLUDE_DIR) + + # Make variables changeble to the advanced user + MARK_AS_ADVANCED(QT_${basename}_LIBRARY QT_${basename}_LIBRARY_RELEASE QT_${basename}_LIBRARY_DEBUG QT_${basename}_INCLUDE_DIR) + ENDMACRO (_QT4_ADJUST_LIB_VARS) + + + # Set QT_xyz_LIBRARY variable and add + # library include path to QT_INCLUDES + _QT4_ADJUST_LIB_VARS(QTCORE) + _QT4_ADJUST_LIB_VARS(QTGUI) + _QT4_ADJUST_LIB_VARS(QT3SUPPORT) + _QT4_ADJUST_LIB_VARS(QTASSISTANT) + _QT4_ADJUST_LIB_VARS(QTDESIGNER) + _QT4_ADJUST_LIB_VARS(QTDESIGNERCOMPONENTS) + _QT4_ADJUST_LIB_VARS(QTNETWORK) + _QT4_ADJUST_LIB_VARS(QTNSPLUGIN) + _QT4_ADJUST_LIB_VARS(QTOPENGL) + _QT4_ADJUST_LIB_VARS(QTSQL) + _QT4_ADJUST_LIB_VARS(QTXML) + _QT4_ADJUST_LIB_VARS(QTSVG) + _QT4_ADJUST_LIB_VARS(QTSCRIPT) + _QT4_ADJUST_LIB_VARS(QTUITOOLS) + _QT4_ADJUST_LIB_VARS(QTTEST) + _QT4_ADJUST_LIB_VARS(QTDBUS) + _QT4_ADJUST_LIB_VARS(QTASSISTANTCLIENT) + _QT4_ADJUST_LIB_VARS(QTHELP) + _QT4_ADJUST_LIB_VARS(QTWEBKIT) + _QT4_ADJUST_LIB_VARS(QTXMLPATTERNS) + _QT4_ADJUST_LIB_VARS(PHONON) + _QT4_ADJUST_LIB_VARS(QTCLUCENE) + + # platform dependent libraries + IF(Q_WS_X11) + _QT4_ADJUST_LIB_VARS(QTMOTIF) + ENDIF(Q_WS_X11) + IF(WIN32) + _QT4_ADJUST_LIB_VARS(QTMAIN) + ENDIF(WIN32) + + + ####################################### + # + # Check the executables of Qt + # ( moc, uic, rcc ) + # + ####################################### + + + # find moc and uic using qmake + QT_QUERY_QMAKE(QT_MOC_EXECUTABLE_INTERNAL "QMAKE_MOC") + QT_QUERY_QMAKE(QT_UIC_EXECUTABLE_INTERNAL "QMAKE_UIC") + + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH + "${QT_MOC_EXECUTABLE_INTERNAL}" QT_MOC_EXECUTABLE_INTERNAL) + # make sure we have / and not \ as qmake gives on windows + FILE(TO_CMAKE_PATH + "${QT_UIC_EXECUTABLE_INTERNAL}" QT_UIC_EXECUTABLE_INTERNAL) + + SET(QT_MOC_EXECUTABLE + ${QT_MOC_EXECUTABLE_INTERNAL} CACHE FILEPATH "The moc executable") + SET(QT_UIC_EXECUTABLE + ${QT_UIC_EXECUTABLE_INTERNAL} CACHE FILEPATH "The uic executable") + + FIND_PROGRAM(QT_UIC3_EXECUTABLE + NAMES uic3 + PATHS ${QT_BINARY_DIR} + NO_DEFAULT_PATH + ) + + FIND_PROGRAM(QT_RCC_EXECUTABLE + NAMES rcc + PATHS ${QT_BINARY_DIR} + NO_DEFAULT_PATH + ) + + FIND_PROGRAM(QT_DBUSCPP2XML_EXECUTABLE + NAMES qdbuscpp2xml + PATHS ${QT_BINARY_DIR} + NO_DEFAULT_PATH + ) + + FIND_PROGRAM(QT_DBUSXML2CPP_EXECUTABLE + NAMES qdbusxml2cpp + PATHS ${QT_BINARY_DIR} + NO_DEFAULT_PATH + ) + + FIND_PROGRAM(QT_LUPDATE_EXECUTABLE + NAMES lupdate + PATHS ${QT_BINARY_DIR} + NO_DEFAULT_PATH + ) + + FIND_PROGRAM(QT_LRELEASE_EXECUTABLE + NAMES lrelease + PATHS ${QT_BINARY_DIR} + NO_DEFAULT_PATH + ) + + IF (QT_MOC_EXECUTABLE) + SET(QT_WRAP_CPP "YES") + ENDIF (QT_MOC_EXECUTABLE) + + IF (QT_UIC_EXECUTABLE) + SET(QT_WRAP_UI "YES") + ENDIF (QT_UIC_EXECUTABLE) + + + + MARK_AS_ADVANCED( QT_UIC_EXECUTABLE QT_UIC3_EXECUTABLE QT_MOC_EXECUTABLE + QT_RCC_EXECUTABLE QT_DBUSXML2CPP_EXECUTABLE QT_DBUSCPP2XML_EXECUTABLE + QT_LUPDATE_EXECUTABLE QT_LRELEASE_EXECUTABLE) + + ###################################### + # + # Macros for building Qt files + # + ###################################### + + MACRO (QT4_EXTRACT_OPTIONS _qt4_files _qt4_options) + SET(${_qt4_files}) + SET(${_qt4_options}) + SET(_QT4_DOING_OPTIONS FALSE) + FOREACH(_currentArg ${ARGN}) + IF ("${_currentArg}" STREQUAL "OPTIONS") + SET(_QT4_DOING_OPTIONS TRUE) + ELSE ("${_currentArg}" STREQUAL "OPTIONS") + IF(_QT4_DOING_OPTIONS) + LIST(APPEND ${_qt4_options} "${_currentArg}") + ELSE(_QT4_DOING_OPTIONS) + LIST(APPEND ${_qt4_files} "${_currentArg}") + ENDIF(_QT4_DOING_OPTIONS) + ENDIF ("${_currentArg}" STREQUAL "OPTIONS") + ENDFOREACH(_currentArg) + ENDMACRO (QT4_EXTRACT_OPTIONS) + + # macro used to create the names of output files preserving relative dirs + MACRO (QT4_MAKE_OUTPUT_FILE infile prefix ext outfile ) + STRING(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength) + STRING(LENGTH ${infile} _infileLength) + SET(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR}) + IF(_infileLength GREATER _binlength) + STRING(SUBSTRING "${infile}" 0 ${_binlength} _checkinfile) + ENDIF(_infileLength GREATER _binlength) + IF(CMAKE_CURRENT_BINARY_DIR MATCHES "${_checkinfile}") + FILE(RELATIVE_PATH rel ${CMAKE_CURRENT_BINARY_DIR} ${infile}) + ELSE(CMAKE_CURRENT_BINARY_DIR MATCHES "${_checkinfile}") + FILE(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${infile}) + ENDIF(CMAKE_CURRENT_BINARY_DIR MATCHES "${_checkinfile}") + SET(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${rel}") + STRING(REPLACE ".." "__" _outfile ${_outfile}) + GET_FILENAME_COMPONENT(outpath ${_outfile} PATH) + GET_FILENAME_COMPONENT(_outfile ${_outfile} NAME_WE) + FILE(MAKE_DIRECTORY ${outpath}) + SET(${outfile} ${outpath}/${prefix}${_outfile}.${ext}) + ENDMACRO (QT4_MAKE_OUTPUT_FILE ) + + MACRO (QT4_GET_MOC_FLAGS _moc_flags) + SET(${_moc_flags}) + GET_DIRECTORY_PROPERTY(_inc_DIRS INCLUDE_DIRECTORIES) + + FOREACH(_current ${_inc_DIRS}) + SET(${_moc_flags} ${${_moc_flags}} "-I${_current}") + ENDFOREACH(_current ${_inc_DIRS}) + + GET_DIRECTORY_PROPERTY(_defines COMPILE_DEFINITIONS) + FOREACH(_current ${_defines}) + SET(${_moc_flags} ${${_moc_flags}} "-D${_current}") + ENDFOREACH(_current ${_defines}) + + IF(Q_WS_WIN) + SET(${_moc_flags} ${${_moc_flags}} -DWIN32) + ENDIF(Q_WS_WIN) + + ENDMACRO(QT4_GET_MOC_FLAGS) + + # helper macro to set up a moc rule + MACRO (QT4_CREATE_MOC_COMMAND infile outfile moc_flags moc_options) + # For Windows, create a parameters file to work around command line length limit + IF (WIN32) + # Pass the parameters in a file. Set the working directory to + # be that containing the parameters file and reference it by + # just the file name. This is necessary because the moc tool on + # MinGW builds does not seem to handle spaces in the path to the + # file given with the @ syntax. + GET_FILENAME_COMPONENT(_moc_outfile_name "${outfile}" NAME) + GET_FILENAME_COMPONENT(_moc_outfile_dir "${outfile}" PATH) + IF(_moc_outfile_dir) + SET(_moc_working_dir WORKING_DIRECTORY ${_moc_outfile_dir}) + ENDIF(_moc_outfile_dir) + SET (_moc_parameters_file ${outfile}_parameters) + SET (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}") + FILE (REMOVE ${_moc_parameters_file}) + FOREACH(arg ${_moc_parameters}) + FILE (APPEND ${_moc_parameters_file} "${arg}\n") + ENDFOREACH(arg) + ADD_CUSTOM_COMMAND(OUTPUT ${outfile} + COMMAND ${QT_MOC_EXECUTABLE} @${_moc_outfile_name}_parameters + DEPENDS ${infile} + ${_moc_working_dir} + VERBATIM) + ELSE (WIN32) + ADD_CUSTOM_COMMAND(OUTPUT ${outfile} + COMMAND ${QT_MOC_EXECUTABLE} + ARGS ${moc_flags} ${moc_options} -o ${outfile} ${infile} + DEPENDS ${infile}) + ENDIF (WIN32) + ENDMACRO (QT4_CREATE_MOC_COMMAND) + + + MACRO (QT4_GENERATE_MOC infile outfile ) + QT4_GET_MOC_FLAGS(moc_flags) + GET_FILENAME_COMPONENT(abs_infile ${infile} ABSOLUTE) + QT4_CREATE_MOC_COMMAND(${abs_infile} ${outfile} "${moc_flags}" "") + SET_SOURCE_FILES_PROPERTIES(${outfile} PROPERTIES SKIP_AUTOMOC TRUE) # dont run automoc on this file + ENDMACRO (QT4_GENERATE_MOC) + + + # QT4_WRAP_CPP(outfiles inputfile ... ) + + MACRO (QT4_WRAP_CPP outfiles ) + # get include dirs + QT4_GET_MOC_FLAGS(moc_flags) + QT4_EXTRACT_OPTIONS(moc_files moc_options ${ARGN}) + + FOREACH (it ${moc_files}) + GET_FILENAME_COMPONENT(it ${it} ABSOLUTE) + QT4_MAKE_OUTPUT_FILE(${it} moc_ cxx outfile) + QT4_CREATE_MOC_COMMAND(${it} ${outfile} "${moc_flags}" "${moc_options}") + SET(${outfiles} ${${outfiles}} ${outfile}) + ENDFOREACH(it) + + ENDMACRO (QT4_WRAP_CPP) + + + # QT4_WRAP_UI(outfiles inputfile ... ) + + MACRO (QT4_WRAP_UI outfiles ) + QT4_EXTRACT_OPTIONS(ui_files ui_options ${ARGN}) + + FOREACH (it ${ui_files}) + GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) + GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) + SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.h) + ADD_CUSTOM_COMMAND(OUTPUT ${outfile} + COMMAND ${QT_UIC_EXECUTABLE} + ARGS ${ui_options} -o ${outfile} ${infile} + MAIN_DEPENDENCY ${infile}) + SET(${outfiles} ${${outfiles}} ${outfile}) + ENDFOREACH (it) + + ENDMACRO (QT4_WRAP_UI) + + + # QT4_ADD_RESOURCES(outfiles inputfile ... ) + + MACRO (QT4_ADD_RESOURCES outfiles ) + QT4_EXTRACT_OPTIONS(rcc_files rcc_options ${ARGN}) + + FOREACH (it ${rcc_files}) + GET_FILENAME_COMPONENT(outfilename ${it} NAME_WE) + GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) + GET_FILENAME_COMPONENT(rc_path ${infile} PATH) + SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cxx) + # parse file for dependencies + # all files are absolute paths or relative to the location of the qrc file + FILE(READ "${infile}" _RC_FILE_CONTENTS) + STRING(REGEX MATCHALL "]*>" "" _RC_FILE "${_RC_FILE}") + STRING(REGEX MATCH "^/|([A-Za-z]:/)" _ABS_PATH_INDICATOR "${_RC_FILE}") + IF(NOT _ABS_PATH_INDICATOR) + SET(_RC_FILE "${rc_path}/${_RC_FILE}") + ENDIF(NOT _ABS_PATH_INDICATOR) + SET(_RC_DEPENDS ${_RC_DEPENDS} "${_RC_FILE}") + ENDFOREACH(_RC_FILE) + ADD_CUSTOM_COMMAND(OUTPUT ${outfile} + COMMAND ${QT_RCC_EXECUTABLE} + ARGS ${rcc_options} -name ${outfilename} -o ${outfile} ${infile} + MAIN_DEPENDENCY ${infile} + DEPENDS ${_RC_DEPENDS}) + SET(${outfiles} ${${outfiles}} ${outfile}) + ENDFOREACH (it) + + ENDMACRO (QT4_ADD_RESOURCES) + + MACRO(QT4_ADD_DBUS_INTERFACE _sources _interface _basename) + GET_FILENAME_COMPONENT(_infile ${_interface} ABSOLUTE) + SET(_header ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h) + SET(_impl ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp) + SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc) + + ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} + COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -p ${_basename} ${_infile} + DEPENDS ${_infile}) + + SET_SOURCE_FILES_PROPERTIES(${_impl} PROPERTIES SKIP_AUTOMOC TRUE) + + QT4_GENERATE_MOC(${_header} ${_moc}) + + SET(${_sources} ${${_sources}} ${_impl} ${_header} ${_moc}) + MACRO_ADD_FILE_DEPENDENCIES(${_impl} ${_moc}) + + ENDMACRO(QT4_ADD_DBUS_INTERFACE) + + + MACRO(QT4_ADD_DBUS_INTERFACES _sources) + FOREACH (_current_FILE ${ARGN}) + GET_FILENAME_COMPONENT(_infile ${_current_FILE} ABSOLUTE) + # get the part before the ".xml" suffix + STRING(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2" _basename ${_current_FILE}) + STRING(TOLOWER ${_basename} _basename) + QT4_ADD_DBUS_INTERFACE(${_sources} ${_infile} ${_basename}interface) + ENDFOREACH (_current_FILE) + ENDMACRO(QT4_ADD_DBUS_INTERFACES) + + + MACRO(QT4_GENERATE_DBUS_INTERFACE _header) # _customName ) + SET(_customName "${ARGV1}") + GET_FILENAME_COMPONENT(_in_file ${_header} ABSOLUTE) + GET_FILENAME_COMPONENT(_basename ${_header} NAME_WE) + + IF (_customName) + SET(_target ${CMAKE_CURRENT_BINARY_DIR}/${_customName}) + ELSE (_customName) + SET(_target ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.xml) + ENDIF (_customName) + + ADD_CUSTOM_COMMAND(OUTPUT ${_target} + COMMAND ${QT_DBUSCPP2XML_EXECUTABLE} ${_in_file} > ${_target} + DEPENDS ${_in_file} + ) + ENDMACRO(QT4_GENERATE_DBUS_INTERFACE) + + + MACRO(QT4_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optionalBasename ) + GET_FILENAME_COMPONENT(_infile ${_xml_file} ABSOLUTE) + + SET(_optionalBasename "${ARGV4}") + IF (_optionalBasename) + SET(_basename ${_optionalBasename} ) + ELSE (_optionalBasename) + STRING(REGEX REPLACE "(.*[/\\.])?([^\\.]+)\\.xml" "\\2adaptor" _basename ${_infile}) + STRING(TOLOWER ${_basename} _basename) + ENDIF (_optionalBasename) + + SET(_optionalClassName "${ARGV5}") + SET(_header ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h) + SET(_impl ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp) + SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_basename}.moc) + + IF(_optionalClassName) + ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} + COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -a ${_basename} -c ${_optionalClassName} -i ${_include} -l ${_parentClass} ${_infile} + DEPENDS ${_infile} + ) + ELSE(_optionalClassName) + ADD_CUSTOM_COMMAND(OUTPUT ${_impl} ${_header} + COMMAND ${QT_DBUSXML2CPP_EXECUTABLE} -m -a ${_basename} -i ${_include} -l ${_parentClass} ${_infile} + DEPENDS ${_infile} + ) + ENDIF(_optionalClassName) + + QT4_GENERATE_MOC(${_header} ${_moc}) + SET_SOURCE_FILES_PROPERTIES(${_impl} PROPERTIES SKIP_AUTOMOC TRUE) + MACRO_ADD_FILE_DEPENDENCIES(${_impl} ${_moc}) + + SET(${_sources} ${${_sources}} ${_impl} ${_header} ${_moc}) + ENDMACRO(QT4_ADD_DBUS_ADAPTOR) + + MACRO(QT4_AUTOMOC) + QT4_GET_MOC_FLAGS(_moc_INCS) + + SET(_matching_FILES ) + FOREACH (_current_FILE ${ARGN}) + + GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE) + # if "SKIP_AUTOMOC" is set to true, we will not handle this file here. + # This is required to make uic work correctly: + # we need to add generated .cpp files to the sources (to compile them), + # but we cannot let automoc handle them, as the .cpp files don't exist yet when + # cmake is run for the very first time on them -> however the .cpp files might + # exist at a later run. at that time we need to skip them, so that we don't add two + # different rules for the same moc file + GET_SOURCE_FILE_PROPERTY(_skip ${_abs_FILE} SKIP_AUTOMOC) + + IF ( NOT _skip AND EXISTS ${_abs_FILE} ) + + FILE(READ ${_abs_FILE} _contents) + + GET_FILENAME_COMPONENT(_abs_PATH ${_abs_FILE} PATH) + + STRING(REGEX MATCHALL "#include +[^ ]+\\.moc[\">]" _match "${_contents}") + IF(_match) + FOREACH (_current_MOC_INC ${_match}) + STRING(REGEX MATCH "[^ <\"]+\\.moc" _current_MOC "${_current_MOC_INC}") + GET_FILENAME_COMPONENT(_basename ${_current_MOC} NAME_WE) + SET(_header ${_abs_PATH}/${_basename}.h) + SET(_moc ${CMAKE_CURRENT_BINARY_DIR}/${_current_MOC}) + QT4_CREATE_MOC_COMMAND(${_header} ${_moc} "${_moc_INCS}" "") + MACRO_ADD_FILE_DEPENDENCIES(${_abs_FILE} ${_moc}) + ENDFOREACH (_current_MOC_INC) + ENDIF(_match) + ENDIF ( NOT _skip AND EXISTS ${_abs_FILE} ) + ENDFOREACH (_current_FILE) + ENDMACRO(QT4_AUTOMOC) + + MACRO(QT4_CREATE_TRANSLATION _qm_files) + QT4_EXTRACT_OPTIONS(_lupdate_files _lupdate_options ${ARGN}) + MESSAGE("lupdate_files ${_lupdate_files}") + MESSAGE("lupdate_options ${_lupdate_options}") + SET(_my_sources) + SET(_my_tsfiles) + FOREACH (_file ${_lupdate_files}) + GET_FILENAME_COMPONENT(_ext ${_file} EXT) + GET_FILENAME_COMPONENT(_abs_FILE ${_file} ABSOLUTE) + IF(_ext MATCHES "ts") + LIST(APPEND _my_tsfiles ${_abs_FILE}) + ELSE(_ext MATCHES "ts") + LIST(APPEND _my_sources ${_abs_FILE}) + ENDIF(_ext MATCHES "ts") + ENDFOREACH(_file) + FOREACH(_ts_file ${_my_tsfiles}) + ADD_CUSTOM_COMMAND(OUTPUT ${_ts_file} + COMMAND ${QT_LUPDATE_EXECUTABLE} + ARGS ${_lupdate_options} ${_my_sources} -ts ${_ts_file} + DEPENDS ${_my_sources}) + ENDFOREACH(_ts_file) + QT4_ADD_TRANSLATION(${_qm_files} ${_my_tsfiles}) + ENDMACRO(QT4_CREATE_TRANSLATION) + + MACRO(QT4_ADD_TRANSLATION _qm_files) + FOREACH (_current_FILE ${ARGN}) + GET_FILENAME_COMPONENT(_abs_FILE ${_current_FILE} ABSOLUTE) + GET_FILENAME_COMPONENT(qm ${_abs_FILE} NAME_WE) + SET(qm "${CMAKE_CURRENT_BINARY_DIR}/${qm}.qm") + + ADD_CUSTOM_COMMAND(OUTPUT ${qm} + COMMAND ${QT_LRELEASE_EXECUTABLE} + ARGS ${_abs_FILE} -qm ${qm} + DEPENDS ${_abs_FILE} + ) + SET(${_qm_files} ${${_qm_files}} ${qm}) + ENDFOREACH (_current_FILE) + ENDMACRO(QT4_ADD_TRANSLATION) + + + + + + ###################################### + # + # decide if Qt got found + # + ###################################### + + # if the includes,libraries,moc,uic and rcc are found then we have it + IF( QT_LIBRARY_DIR AND QT_INCLUDE_DIR AND QT_MOC_EXECUTABLE AND + QT_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE AND QT_QTCORE_LIBRARY) + SET( QT4_FOUND "YES" ) + INCLUDE(FindPackageMessage) + FIND_PACKAGE_MESSAGE(Qt4 "Found Qt-Version ${QTVERSION}" + "[${QT_LIBRARY_DIR}][${QT_INCLUDE_DIR}][${QT_MOC_EXECUTABLE}][${QT_UIC_EXECUTABLE}][${QT_RCC_EXECUTABLE}]") + ELSE( QT_LIBRARY_DIR AND QT_INCLUDE_DIR AND QT_MOC_EXECUTABLE AND + QT_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE AND QT_QTCORE_LIBRARY) + SET( QT4_FOUND "NO") + SET(QT_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}-NOTFOUND" CACHE FILEPATH "Invalid qmake found" FORCE) + IF( Qt4_FIND_REQUIRED) + MESSAGE( FATAL_ERROR "Qt libraries, includes, moc, uic or/and rcc NOT found!") + ENDIF( Qt4_FIND_REQUIRED) + ENDIF( QT_LIBRARY_DIR AND QT_INCLUDE_DIR AND QT_MOC_EXECUTABLE AND + QT_UIC_EXECUTABLE AND QT_RCC_EXECUTABLE AND QT_QTCORE_LIBRARY) + + SET(QT_FOUND ${QT4_FOUND}) + + + ####################################### + # + # Qt configuration + # + ####################################### + IF(EXISTS "${QT_MKSPECS_DIR}/qconfig.pri") + FILE(READ ${QT_MKSPECS_DIR}/qconfig.pri _qconfig_FILE_contents) + STRING(REGEX MATCH "QT_CONFIG[^\n]+" QT_QCONFIG "${_qconfig_FILE_contents}") + STRING(REGEX MATCH "CONFIG[^\n]+" QT_CONFIG "${_qconfig_FILE_contents}") + STRING(REGEX MATCH "EDITION[^\n]+" QT_EDITION "${_qconfig_FILE_contents}") + ENDIF(EXISTS "${QT_MKSPECS_DIR}/qconfig.pri") + IF("${QT_EDITION}" MATCHES "DesktopLight") + SET(QT_EDITION_DESKTOPLIGHT 1) + ENDIF("${QT_EDITION}" MATCHES "DesktopLight") + + + ############################################### + # + # configuration/system dependent settings + # + ############################################### + + # find dependencies for some Qt modules + # when doing builds against a static Qt, they are required + # when doing builds against a shared Qt, they are sometimes not required + # even some Linux distros do not require these dependencies + # if a user needs the dependencies, and they couldn't be found, they can set + # the variables themselves. + + SET(QT_QTGUI_LIB_DEPENDENCIES "") + SET(QT_QTCORE_LIB_DEPENDENCIES "") + SET(QT_QTNETWORK_LIB_DEPENDENCIES "") + SET(QT_QTOPENGL_LIB_DEPENDENCIES "") + SET(QT_QTDBUS_LIB_DEPENDENCIES "") + SET(QT_QTHELP_LIB_DEPENDENCIES ${QT_QTCLUCENE_LIBRARY}) + + # build using shared Qt needs -DQT_DLL + IF(NOT QT_CONFIG MATCHES "static") + # warning currently only qconfig.pri on Windows potentially contains "static" + # so QT_DLL might not get defined properly on other platforms. + SET(QT_DEFINITIONS ${QT_DEFINITIONS} -DQT_DLL) + ENDIF(NOT QT_CONFIG MATCHES "static") + + # QtOpenGL dependencies + QT_QUERY_QMAKE(QMAKE_LIBS_OPENGL "QMAKE_LIBS_OPENGL") + SET (QT_QTOPENGL_LIB_DEPENDENCIES ${QT_QTOPENGL_LIB_DEPENDENCIES} ${QMAKE_LIBS_OPENGL}) + + IF(Q_WS_X11) + # X11 libraries Qt absolutely depends on + QT_QUERY_QMAKE(QT_LIBS_X11 "QMAKE_LIBS_X11") + SEPARATE_ARGUMENTS(QT_LIBS_X11) + FOREACH(QT_X11_LIB ${QT_LIBS_X11}) + STRING(REGEX REPLACE "-l" "" QT_X11_LIB "${QT_X11_LIB}") + SET(QT_TMP_STR "QT_X11_${QT_X11_LIB}_LIBRARY") + FIND_LIBRARY(${QT_TMP_STR} NAMES "${QT_X11_LIB}" PATHS ${QMAKE_LIBDIR_X11}) + IF(${QT_TMP_STR}) + SET(QT_QTGUI_LIB_DEPENDENCIES ${QT_QTGUI_LIB_DEPENDENCIES} ${${QT_TMP_STR}}) + MARK_AS_ADVANCED(${QT_TMP_STR}) + ENDIF(${QT_TMP_STR}) + ENDFOREACH(QT_X11_LIB) + + QT_QUERY_QMAKE(QT_LIBS_THREAD "QMAKE_LIBS_THREAD") + SET(QT_QTCORE_LIB_DEPENDENCIES ${QT_QTCORE_LIB_DEPENDENCIES} ${QT_LIBS_THREAD}) + + QT_QUERY_QMAKE(QMAKE_LIBS_DYNLOAD "QMAKE_LIBS_DYNLOAD") + SET (QT_QTCORE_LIB_DEPENDENCIES ${QT_QTCORE_LIB_DEPENDENCIES} ${QMAKE_LIBS_DYNLOAD}) + + ENDIF(Q_WS_X11) + + IF(Q_WS_WIN) + SET(QT_QTGUI_LIB_DEPENDENCIES ${QT_QTGUI_LIB_DEPENDENCIES} imm32 winmm) + SET(QT_QTCORE_LIB_DEPENDENCIES ${QT_QTCORE_LIB_DEPENDENCIES} ws2_32) + ENDIF(Q_WS_WIN) + + IF(Q_WS_MAC) + SET(QT_QTGUI_LIB_DEPENDENCIES ${QT_QTGUI_LIB_DEPENDENCIES} "-framework Carbon") + + # Qt 4.0, 4.1, 4.2 use QuickTime + IF(QT_VERSION_MINOR LESS 3) + SET(QT_QTGUI_LIB_DEPENDENCIES ${QT_QTGUI_LIB_DEPENDENCIES} "-framework QuickTime") + ENDIF(QT_VERSION_MINOR LESS 3) + + # Qt 4.2+ use AppKit + IF(QT_VERSION_MINOR GREATER 1) + SET(QT_QTGUI_LIB_DEPENDENCIES ${QT_QTGUI_LIB_DEPENDENCIES} "-framework AppKit") + ENDIF(QT_VERSION_MINOR GREATER 1) + + SET(QT_QTCORE_LIB_DEPENDENCIES ${QT_QTCORE_LIB_DEPENDENCIES} "-framework ApplicationServices") + ENDIF(Q_WS_MAC) + + ####################################### + # + # compatibility settings + # + ####################################### + # Backwards compatibility for CMake1.4 and 1.2 + SET (QT_MOC_EXE ${QT_MOC_EXECUTABLE} ) + SET (QT_UIC_EXE ${QT_UIC_EXECUTABLE} ) + + SET( QT_QT_LIBRARY "") + +ELSE(QT4_QMAKE_FOUND) + + SET(QT_QMAKE_EXECUTABLE "${QT_QMAKE_EXECUTABLE}-NOTFOUND" CACHE FILEPATH "Invalid qmake found" FORCE) + IF(Qt4_FIND_REQUIRED) + IF(QT4_INSTALLED_VERSION_TOO_OLD) + MESSAGE(FATAL_ERROR "The installed Qt version ${QTVERSION} is too old, at least version ${QT_MIN_VERSION} is required") + ELSE(QT4_INSTALLED_VERSION_TOO_OLD) + MESSAGE( FATAL_ERROR "Qt qmake not found!") + ENDIF(QT4_INSTALLED_VERSION_TOO_OLD) + ELSE(Qt4_FIND_REQUIRED) + IF(QT4_INSTALLED_VERSION_TOO_OLD AND NOT Qt4_FIND_QUIETLY) + MESSAGE(STATUS "The installed Qt version ${QTVERSION} is too old, at least version ${QT_MIN_VERSION} is required") + ENDIF(QT4_INSTALLED_VERSION_TOO_OLD AND NOT Qt4_FIND_QUIETLY) + ENDIF(Qt4_FIND_REQUIRED) + +ENDIF (QT4_QMAKE_FOUND) + diff --git a/src/external/CoMISo/cmake/FindSUITESPARSE.cmake b/src/external/CoMISo/cmake/FindSUITESPARSE.cmake new file mode 100644 index 000000000..712fd7bc2 --- /dev/null +++ b/src/external/CoMISo/cmake/FindSUITESPARSE.cmake @@ -0,0 +1,131 @@ +# - Try to find SUITESPARSE +# Once done this will define +# +# SUITESPARSE_FOUND - system has SUITESPARSE +# SUITESPARSE_INCLUDE_DIRS - the SUITESPARSE include directory +# SUITESPARSE_LIBRARIES - Link these to use SUITESPARSE +# SUITESPARSE_SPQR_LIBRARY - name of spqr library (necessary due to error in debian package) +# SUITESPARSE_SPQR_LIBRARY_DIR - name of spqr library (necessary due to error in debian package) +# SUITESPARSE_LIBRARY_DIR - Library main directory containing suitesparse libs +# SUITESPARSE_LIBRARY_DIRS - all Library directories containing suitesparse libs +# SUITESPARSE_SPQR_VALID - automatic identification whether or not spqr package is installed correctly + +IF (SUITESPARSE_INCLUDE_DIRS) + # Already in cache, be silent + SET(SUITESPARSE_FIND_QUIETLY TRUE) +ENDIF (SUITESPARSE_INCLUDE_DIRS) + +if( WIN32 ) + # Find cholmod part of the suitesparse library collection + + FIND_PATH( CHOLMOD_INCLUDE_DIR cholmod.h + PATHS "C:\\libs\\win32\\SuiteSparse\\Include" ) + + # Add cholmod include directory to collection include directories + IF ( CHOLMOD_INCLUDE_DIR ) + list ( APPEND SUITESPARSE_INCLUDE_DIRS ${CHOLMOD_INCLUDE_DIR} ) + ENDIF( CHOLMOD_INCLUDE_DIR ) + + + # find path suitesparse library + FIND_PATH( SUITESPARSE_LIBRARY_DIRS + amd.lib + PATHS "C:\\libs\\win32\\SuiteSparse\\libs" ) + + # if we found the library, add it to the defined libraries + IF ( SUITESPARSE_LIBRARY_DIRS ) + list ( APPEND SUITESPARSE_LIBRARIES optimized;amd;optimized;camd;optimized;ccolamd;optimized;cholmod;optimized;colamd;optimized;metis;optimized;spqr;optimized;umfpack;debug;amdd;debug;camdd;debug;ccolamdd;debug;cholmodd;debug;spqrd;debug;umfpackd;debug;colamdd;debug;metisd;optimized;blas;optimized;libf2c;optimized;lapack;debug;blasd;debug;libf2cd;debug;lapackd ) + ENDIF( SUITESPARSE_LIBRARY_DIRS ) + +else( WIN32 ) + IF( APPLE) + FIND_PATH( CHOLMOD_INCLUDE_DIR cholmod.h + PATHS /opt/local/include/ufsparse ) + + FIND_PATH( SUITESPARSE_LIBRARY_DIR + NAMES libSuiteSparse.dylib + PATHS /opt/local/lib ) + + list ( APPEND SUITESPARSE_LIBRARY_DIRS ${SUITESPARSE_LIBRARY_DIR} ) + + list ( APPEND SUITESPARSE_LIBRARIES SuiteSparse) + + ELSE(APPLE) + FIND_PATH( CHOLMOD_INCLUDE_DIR cholmod.h + PATHS /usr/local/include + /usr/include + /usr/include/suitesparse/ + ${CMAKE_SOURCE_DIR}/MacOS/Libs/cholmod + PATH_SUFFIXES cholmod/ CHOLMOD/ ) + + + FIND_PATH( SUITESPARSE_LIBRARY_DIR + NAMES libcholmod.so + PATHS /usr/lib + /usr/lib64 + /usr/local/lib ) + + + ENDIF(APPLE) + + # Add cholmod include directory to collection include directories + IF ( CHOLMOD_INCLUDE_DIR ) + list ( APPEND SUITESPARSE_INCLUDE_DIRS ${CHOLMOD_INCLUDE_DIR} ) + ENDIF( CHOLMOD_INCLUDE_DIR ) + + + # if we found the library, add it to the defined libraries + IF ( SUITESPARSE_LIBRARY_DIR ) + + # Skipped, as this is set for apple in the block above + if (NOT APPLE) + list ( APPEND SUITESPARSE_LIBRARIES amd) + list ( APPEND SUITESPARSE_LIBRARIES btf) + list ( APPEND SUITESPARSE_LIBRARIES camd) + list ( APPEND SUITESPARSE_LIBRARIES ccolamd) + list ( APPEND SUITESPARSE_LIBRARIES cholmod) + list ( APPEND SUITESPARSE_LIBRARIES colamd) + # list ( APPEND SUITESPARSE_LIBRARIES csparse) + list ( APPEND SUITESPARSE_LIBRARIES cxsparse) + list ( APPEND SUITESPARSE_LIBRARIES klu) + # list ( APPEND SUITESPARSE_LIBRARIES spqr) + list ( APPEND SUITESPARSE_LIBRARIES umfpack) + endif() + + # Metis and spqr are optional + FIND_LIBRARY( SUITESPARSE_METIS_LIBRARY + NAMES metis + PATHS ${SUITESPARSE_LIBRARY_DIR} ) + IF (SUITESPARSE_METIS_LIBRARY) + list ( APPEND SUITESPARSE_LIBRARIES metis) + ENDIF(SUITESPARSE_METIS_LIBRARY) + + if(EXISTS "${CHOLMOD_INCLUDE_DIR}/SuiteSparseQR.hpp") + SET(SUITESPARSE_SPQR_VALID TRUE CACHE BOOL "SuiteSparseSPQR valid") + else() + SET(SUITESPARSE_SPQR_VALID false CACHE BOOL "SuiteSparseSPQR valid") + endif() + + if(SUITESPARSE_SPQR_VALID) + FIND_LIBRARY( SUITESPARSE_SPQR_LIBRARY + NAMES spqr + PATHS ${SUITESPARSE_LIBRARY_DIR} ) + IF (SUITESPARSE_SPQR_LIBRARY) + list ( APPEND SUITESPARSE_LIBRARIES spqr) + ENDIF (SUITESPARSE_SPQR_LIBRARY) + endif() + + ENDIF( SUITESPARSE_LIBRARY_DIR ) + +endif( WIN32 ) + + +IF (SUITESPARSE_INCLUDE_DIRS AND SUITESPARSE_LIBRARIES) + IF(WIN32) + list (APPEND SUITESPARSE_INCLUDE_DIRS ${CHOLMOD_INCLUDE_DIR}/../../UFconfig ) + ENDIF(WIN32) + SET(SUITESPARSE_FOUND TRUE) +ELSE (SUITESPARSE_INCLUDE_DIRS AND SUITESPARSE_LIBRARIES) + SET( SUITESPARSE_FOUND FALSE ) +ENDIF (SUITESPARSE_INCLUDE_DIRS AND SUITESPARSE_LIBRARIES) + diff --git a/src/external/CoMISo/cmake/FindTAO.cmake b/src/external/CoMISo/cmake/FindTAO.cmake new file mode 100644 index 000000000..bf348fec4 --- /dev/null +++ b/src/external/CoMISo/cmake/FindTAO.cmake @@ -0,0 +1,69 @@ +if (TAO_INCLUDE_DIRS) + # Already in cache, be silent + SET(TAO_FIND_QUIETLY TRUE) +endif (TAO_INCLUDE_DIRS) + +if (WIN32) + find_path(TAO_INCLUDE_DIR NAMES tao.h + PREFIXES SRC + PATHS + "C:\\libs\\gurobi45" + ${TAO_DIR}/include + ) + + find_library( TAO_LIBRARY_RELEASE + SuperLU + PATHS "C:\\libs\\gurobi45\\lib" ) + find_library( TAO_LIBRARY_DEBUG + SuperLUd + PATHS "C:\\libs\\gurobi45\\lib" ) + + + set ( TAO_LIBRARY "optimized;${TAO_LIBRARY_RELEASE};debug;${TAO_LIBRARY_DEBUG}" CACHE STRING "TAO Libraries" ) + +ELSEIF(APPLE) + + find_path(TAO_INCLUDE_DIR NAMES gurobi_c++.h + PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/gurobi40" + ${TAO_INCLUDE_PATH} + ) + + find_library( TAO_LIBRARY + SuperLU + PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/gurobi40") + +ELSE( WIN32 ) +find_path(TAO_INCLUDE_DIR NAMES "include/tao.h" + PATHS "$ENV{TAO_DIR}" + /usr/include/tao + ) + + +# MESSAGE(STATUS "$ENV{TAO_HOME}/include") + IF(TAO_INCLUDE_DIR) + SET(TAO_FOUND TRUE) + SET(TAO_INCLUDE_DIRS "${TAO_INCLUDE_DIR}/include;${TAO_INCLUDE_DIR}") + SET(TAO_INCLUDE_DIR ${TAO_INCLUDE_DIR}/include;${TAO_INCLUDE_DIR} CACHE PATH "Path to TAO Includes") + + #check VERSION 1.x or 2 + IF(IS_DIRECTORY "$ENV{TAO_DIR}/lib/$ENV{PETSC_ARCH}/") +# MESSAGE(STATUS "TAO Version 1.x") + SET(TAO_LIBRARY_DIR "$ENV{TAO_DIR}/lib/$ENV{PETSC_ARCH}/" CACHE PATH "Path to TAO Library") + SET(TAO_LIBRARY "tao;taopetsc;taofortran" CACHE STRING "TAO Libraries") + ELSE(IS_DIRECTORY "$ENV{TAO_DIR}/lib/$ENV{PETSC_ARCH}/") #VERSION 2 +# MESSAGE(STATUS "TAO Version 2.x") + SET(TAO_LIBRARY_DIR "$ENV{TAO_DIR}/$ENV{PETSC_ARCH}/lib" CACHE PATH "Path to TAO Library") + SET(TAO_LIBRARY "tao" CACHE STRING "TAO Libraries") + ENDIF(IS_DIRECTORY "$ENV{TAO_DIR}/lib/$ENV{PETSC_ARCH}/") + + # MESSAGE(STATUS "${TAO_LIBRARY_DIR}") +# MESSAGE(STATUS "${TAO_LIBRARY}") + ELSE(TAO_INCLUDE_DIR) + SET(TAO_FOUND FALSE) + SET(TAO_INCLUDE_DIR ${TAO_INCLUDE_DIR}) + ENDIF(TAO_INCLUDE_DIR) + + #find_library( TAO_LIBRARY + # gurobi + # PATHS "${TAO_HOME}/lib" ) +ENDIF() \ No newline at end of file diff --git a/src/external/CoMISo/cmake/FindTaucs.cmake b/src/external/CoMISo/cmake/FindTaucs.cmake new file mode 100644 index 000000000..edf850a1d --- /dev/null +++ b/src/external/CoMISo/cmake/FindTaucs.cmake @@ -0,0 +1,91 @@ +# - Find TAUCS +# Find the native TAUCS headers and libraries. +# +# TAUCS_INCLUDE_DIR - where to find TAUCS.h, etc. +# TAUCS_LIBRARY - List of libraries when using TAUCS. +# TAUCS_FOUND - True if TAUCS found. + +IF (TAUCS_INCLUDE_DIR) + # Already in cache, be silent + SET(TAUCS_FIND_QUIETLY TRUE) +ENDIF (TAUCS_INCLUDE_DIR) + + +# Look for the header file. +IF(WIN32) + find_package(CGAL) + if (NOT CGAL_FOUND) + message(STATUS "CGAL not found .. required to use taucs!") + endif() + + FIND_PATH(TAUCS_INCLUDE_DIR NAMES taucs.h + PATHS "${CGAL_TAUCS_DIR}/include" ) + +ELSE(WIN32) + + IF(APPLE) + FIND_PATH(TAUCS_INCLUDE_DIR NAMES taucs.h + PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/taucs/src" + ~/sw/taucs/include + ) + + ELSE (APPLE) + + FIND_PATH(TAUCS_INCLUDE_DIR NAMES taucs.h + PATHS /ACG/acgdev/gcc-4.3-x86_64/taucs-2.2-gfortran/include + ) + + ENDIF(APPLE) + + +ENDIF(WIN32) + +# Copy the results to the output variables. +IF(TAUCS_INCLUDE_DIR ) + SET(TAUCS_FOUND 1) + SET(TAUCS_INCLUDE_DIR ${TAUCS_INCLUDE_DIR}) + + IF(WIN32) +# find_package(CGAL) + SET(TAUCS_LIBRARY "${CGAL_TAUCS_DIR}/lib/libtaucs.lib" ) + ELSE(WIN32) + IF(APPLE) + FIND_LIBRARY( TAUCS_LIBRARY + NAMES taucs + PATHS "${CMAKE_SOURCE_DIR}/MacOS/Libs/taucs/lib/darwin9.0" + ~/sw/taucs/lib/darwin11 + ) + ELSE (APPLE) + FIND_LIBRARY( TAUCS_LIBRARY + NAMES taucs + PATHS /ACG/acgdev/gcc-4.3-x86_64/taucs-2.2.new/lib + ) + ENDIF( APPLE) + ENDIF(WIN32) + +ELSE(TAUCS_INCLUDE_DIR ) + SET(TAUCS_FOUND 0) + SET(TAUCS_INCLUDE_DIR) +ENDIF(TAUCS_INCLUDE_DIR ) + +# Report the results. +IF(NOT TAUCS_FOUND) + SET(TAUCS_DIR_MESSAGE + "TAUCS was not found. Make sure TAUCS_INCLUDE_DIR is set to the directories containing the include and lib files for TAUCS. .") + IF(TAUCS_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "${TAUCS_DIR_MESSAGE}") + ELSEIF(NOT TAUCS_FIND_QUIETLY) + MESSAGE(STATUS "${TAUCS_DIR_MESSAGE}") + ELSE(NOT TAUCS_FIND_QUIETLY) + ENDIF(TAUCS_FIND_REQUIRED) +ELSE (NOT TAUCS_FOUND) + IF(NOT TAUCS_FIND_QUIETLY) + MESSAGE(STATUS "Looking for TAUCS - found") + ENDIF(NOT TAUCS_FIND_QUIETLY) + IF ( NOT WIN32 ) + SET(TAUCS_LIBRARY "${TAUCS_LIBRARY};metis") + ELSE ( NOT WIN32 ) + SET(TAUCS_LIBRARY "${TAUCS_LIBRARY}") + ENDIF( NOT WIN32 ) +ENDIF(NOT TAUCS_FOUND) + diff --git a/src/external/CoMISo/cmake/ResolveCompilerPaths.cmake b/src/external/CoMISo/cmake/ResolveCompilerPaths.cmake new file mode 100644 index 000000000..f60620589 --- /dev/null +++ b/src/external/CoMISo/cmake/ResolveCompilerPaths.cmake @@ -0,0 +1,93 @@ +# ResolveCompilerPaths - this module defines two macros +# +# RESOLVE_LIBRARIES (XXX_LIBRARIES LINK_LINE) +# This macro is intended to be used by FindXXX.cmake modules. +# It parses a compiler link line and resolves all libraries +# (-lfoo) using the library path contexts (-L/path) in scope. +# The result in XXX_LIBRARIES is the list of fully resolved libs. +# Example: +# +# RESOLVE_LIBRARIES (FOO_LIBRARIES "-L/A -la -L/B -lb -lc -ld") +# +# will be resolved to +# +# FOO_LIBRARIES:STRING="/A/liba.so;/B/libb.so;/A/libc.so;/usr/lib/libd.so" +# +# if the filesystem looks like +# +# /A: liba.so libb.so libc.so +# /B: liba.so libb.so +# /usr/lib: liba.so libb.so libc.so libd.so +# +# and /usr/lib is a system directory. +# +# Note: If RESOLVE_LIBRARIES() resolves a link line differently from +# the native linker, there is a bug in this macro (please report it). +# +# RESOLVE_INCLUDES (XXX_INCLUDES INCLUDE_LINE) +# This macro is intended to be used by FindXXX.cmake modules. +# It parses a compile line and resolves all includes +# (-I/path/to/include) to a list of directories. Other flags are ignored. +# Example: +# +# RESOLVE_INCLUDES (FOO_INCLUDES "-I/A -DBAR='\"irrelevant -I/string here\"' -I/B") +# +# will be resolved to +# +# FOO_INCLUDES:STRING="/A;/B" +# +# assuming both directories exist. +# Note: as currently implemented, the -I/string will be picked up mistakenly (cry, cry) + +macro (RESOLVE_LIBRARIES LIBS LINK_LINE) + string (REGEX MATCHALL "((-L|-l|-Wl)([^\" ]+|\"[^\"]+\")|/[^\" ]+(a|so|dll))" _all_tokens "${LINK_LINE}") + set (_libs_found) + set (_directory_stack) + foreach (token ${_all_tokens}) + if (token MATCHES "-L([^\" ]+|\"[^\"]+\")") + # If it's a library path, push it on the stack + string (REGEX REPLACE "^-L" "" token ${token}) + string (REGEX REPLACE "//" "/" token ${token}) + list (INSERT _directory_stack 0 ${token}) + elseif (token MATCHES "^(-l([^\" ]+|\"[^\"]+\")|/[^\" ]+(a|so|dll))") + # It's a library, resolve the path by looking in the stack and then (by default) in system directories + string (REGEX REPLACE "^-l" "" token ${token}) + set (_root) + if (token MATCHES "^/") # We have an absolute path, add root to the search path + set (_root "/") + endif (token MATCHES "^/") + set (_lib "NOTFOUND" CACHE FILEPATH "Cleared" FORCE) + find_library (_lib ${token} HINTS ${_directory_stack} ${_root}) + if (_lib) + string (REPLACE "//" "/" _lib ${_lib}) + list (APPEND _libs_found ${_lib}) + else (_lib) + message (STATUS "Unable to find library ${token}") + endif (_lib) + endif (token MATCHES "-L([^\" ]+|\"[^\"]+\")") + endforeach (token) + set (_lib "NOTFOUND" CACHE INTERNAL "Scratch variable" FORCE) + # only the LAST occurence of each library is required since there should be no circular dependencies + if (_libs_found) + list (REVERSE _libs_found) + list (REMOVE_DUPLICATES _libs_found) + list (REVERSE _libs_found) + endif (_libs_found) + set (${LIBS} "${_libs_found}") +endmacro (RESOLVE_LIBRARIES) + +macro (RESOLVE_INCLUDES INCS COMPILE_LINE) + string (REGEX MATCHALL "-I([^\" ]+|\"[^\"]+\")" _all_tokens "${COMPILE_LINE}") + set (_incs_found) + foreach (token ${_all_tokens}) + string (REGEX REPLACE "^-I" "" token ${token}) + string (REGEX REPLACE "//" "/" token ${token}) + if (EXISTS ${token}) + list (APPEND _incs_found ${token}) + else (EXISTS ${token}) + message (STATUS "Include directory ${token} does not exist") + endif (EXISTS ${token}) + endforeach (token) + list (REMOVE_DUPLICATES _incs_found) + set (${INCS} "${_incs_found}") +endmacro (RESOLVE_INCLUDES) diff --git a/src/external/CoMISo/how_to_compile_with_vs.txt b/src/external/CoMISo/how_to_compile_with_vs.txt new file mode 100644 index 000000000..0c3a10c37 --- /dev/null +++ b/src/external/CoMISo/how_to_compile_with_vs.txt @@ -0,0 +1,11 @@ +- if the GMM_INCLUDE_DIR tag is not presented in CMAKE set the gmm path by hand in cmake/FindGMM.cmake +(for instance find_path( GMM_INCLUDE_DIR NAMES gmm/gmm.h PATHS $ENV{GMM_DIR}"d:\\code\\gmm-4.2\\include") ) + +- if EIGEN3 tag is not presented in CMAKE set the gmm path by hand in cmake/FindEIGEN3.cmake +(for instance find_path( EIGEN3_INCLUDE_DIR NAMES Eigen/Dense PATHS $ENV{EIGEN_DIR}) ) + +- add to the linking path of the CoMISo project properties the static lib generated by GotoBLAS2 + +- to test the example included with CoMISo go to the example properties and change from Linker->System->SubSystem->Console + +- some tests will not compile \ No newline at end of file