Scippy

    SCIP

    Solving Constraint Integer Programs

    queens.cpp
    Go to the documentation of this file.
    1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    2/* */
    3/* This file is part of the examples to */
    4/* An introduction to SCIP */
    5/* */
    6/* Copyright (C) 2007 Cornelius Schwarz */
    7/* */
    8/* 2007 University of Bayreuth */
    9/* */
    10/* */
    11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    12
    13/**
    14 * @file queens.cpp
    15 * @author Cornelius Schwarz
    16 * @brief n-queens examlple implementation
    17 */
    18
    19#include "queens.hpp"
    20#include <sstream>
    21#include "scip_exception.hpp"
    22#include "scip/pub_message.h"
    23
    24using namespace std;
    25using namespace scipexamples;
    26
    27/* constructor */
    29 : _scip(0), _n(n), _vars(n, vector<SCIP_VAR *>(n)), _cons()
    30{
    31 // initialize scip
    32 SCIP_CALL_EXC( SCIPcreate(& _scip) );
    33
    34 // load default plugins linke separators, heuristics, etc.
    36
    37 // disable scip output to stdout
    39
    40 // create an empty problem
    41 SCIP_CALL_EXC( SCIPcreateProb(_scip, "queens", NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
    42
    43 // set the objective sense to maximize, default is minimize
    45
    46 // create a binary variable for every field (i,j) on the chess board
    47 ostringstream namebuf;
    48 for( size_t i = 0; i < _n; ++i )
    49 {
    50 for( size_t j = 0; j < _n; ++j )
    51 {
    52 SCIP_VAR* var;
    53 namebuf.str("");
    54 namebuf << "x#" << i << "#" << j;
    55
    56 // create the SCIP_VAR object
    57 SCIP_CALL_EXC( SCIPcreateVar(_scip, & var, namebuf.str().c_str(), 0.0, 1.0, 1.0, SCIP_VARTYPE_BINARY, TRUE, FALSE, NULL, NULL, NULL, NULL, NULL) );
    58
    59 // add the SCIP_VAR object to the scip problem
    60 SCIP_CALL_EXC( SCIPaddVar(_scip, var) );
    61
    62 // storing the SCIP_VAR pointer for later access
    63 _vars[i][j] = var;
    64 }
    65 }
    66
    67 // create constraints
    68 // one queen per row
    69 for( size_t i = 0; i < _n; ++i )
    70 {
    71 SCIP_CONS * cons;
    72 namebuf.str("");
    73 namebuf<<"row_"<<i;
    74
    75 // create SCIP_CONS object
    76 // this is an equality since there must be a queen in every row
    77 SCIP_CALL_EXC( SCIPcreateConsLinear(_scip, & cons, namebuf.str().c_str(), 0, NULL, NULL, 1.0, 1.0,
    79
    80 // add the vars belonging to field in this row to the constraint
    81 for( size_t j = 0; j < _n; ++j )
    82 SCIP_CALL_EXC( SCIPaddCoefLinear(_scip, cons, _vars[i][j], 1.0) );
    83
    84 // add the constraint to scip
    85 SCIP_CALL_EXC( SCIPaddCons(_scip, cons) );
    86
    87 // store the constraint for later on
    88 _cons.push_back(cons);
    89 }
    90
    91 // this is the same with the col constraints ( one queen per column)
    92 for( size_t j = 0; j < _n; ++j )
    93 {
    94 SCIP_CONS * cons;
    95 namebuf.str("");
    96 namebuf << "col_" << j;
    97 SCIP_CALL_EXC( SCIPcreateConsLinear(_scip, & cons, namebuf.str().c_str(), 0, NULL, NULL, 1.0, 1.0,
    99
    100 for( size_t i = 0; i < _n; ++i )
    101 SCIP_CALL_EXC( SCIPaddCoefLinear(_scip, cons, _vars[i][j], 1.0) );
    102
    103 SCIP_CALL_EXC( SCIPaddCons(_scip, cons) );
    104 _cons.push_back(cons);
    105 }
    106
    107 // now we create the constraints for the diagonals
    108 // there is only one queen allowed in each diagonal, but there do not need to be one. Therefore we add a <= 1 constraint
    109 // in this problem case we can set the lhs to zero instead of -SCIPinfinity
    110 // diag col down
    111 for( size_t j = 0; j < _n; ++j )
    112 {
    113 SCIP_CONS * cons;
    114 namebuf.str("");
    115 namebuf << "diag_col_down_" << j;
    116 SCIP_CALL_EXC(SCIPcreateConsLinear(_scip, & cons, namebuf.str().c_str(), 0, NULL, NULL, 0.0, 1.0,
    118
    119 for( size_t i = 0; i < _n - j; ++i )
    120 SCIP_CALL_EXC( SCIPaddCoefLinear(_scip, cons, _vars[i][j+i], 1.0) );
    121 SCIP_CALL_EXC( SCIPaddCons(_scip, cons) );
    122 _cons.push_back(cons);
    123 }
    124
    125 // diag row down
    126 for( size_t i = 0; i < _n; ++i )
    127 {
    128 SCIP_CONS * cons;
    129 namebuf.str("");
    130 namebuf<<"diag_row_down_"<<i;
    131 SCIP_CALL_EXC( SCIPcreateConsLinear(_scip, & cons, namebuf.str().c_str(), 0, NULL, NULL, 0.0, 1.0,
    133
    134 for( size_t j = 0; j < _n - i; ++j )
    135 SCIP_CALL_EXC( SCIPaddCoefLinear(_scip, cons, _vars[i+j][j], 1.0) );
    136 SCIP_CALL_EXC( SCIPaddCons(_scip, cons) );
    137 _cons.push_back(cons);
    138 }
    139
    140 // diag col up
    141 for( size_t j = 0; j < _n; ++j )
    142 {
    143 SCIP_CONS * cons;
    144 namebuf.str("");
    145 namebuf<<"diag_col_up_"<<j;
    146 SCIP_CALL_EXC( SCIPcreateConsLinear(_scip, & cons, namebuf.str().c_str(), 0, NULL, NULL, 0.0, 1.0,
    148
    149 for( size_t i = 0; i < _n - j; ++i )
    150 SCIP_CALL_EXC( SCIPaddCoefLinear(_scip, cons, _vars[i][_n - j - i - 1], 1.0) );
    151 SCIP_CALL_EXC( SCIPaddCons(_scip, cons) );
    152 _cons.push_back(cons);
    153 }
    154
    155 // diag row up
    156 for( size_t i = 0; i < _n; ++i )
    157 {
    158 SCIP_CONS * cons;
    159 namebuf.str("");
    160 namebuf<<"diag_row_up"<<i;
    161 SCIP_CALL_EXC( SCIPcreateConsLinear(_scip, & cons, namebuf.str().c_str(), 0, NULL, NULL, 0.0, 1.0,
    163
    164 for( size_t j = 0; j < _n - i; ++j )
    165 SCIP_CALL_EXC( SCIPaddCoefLinear(_scip, cons, _vars[i+j][_n - j - 1], 1.0) );
    166 SCIP_CALL_EXC( SCIPaddCons(_scip, cons) );
    167 _cons.push_back(cons);
    168 }
    169}
    170
    171
    172/* display the solution */
    173void scipexamples::QueensSolver::disp(std::ostream& out)
    174{
    175 // get the best found solution from scip
    176 SCIP_SOL * sol = SCIPgetBestSol(_scip);
    177 out << "solution for " << _n << "-queens:" << endl << endl;
    178
    179 // when SCIP did not succeed then sol is NULL
    180 if (sol == NULL)
    181 {
    182 out << "no solution found" << endl;
    183 return;
    184 }
    185
    186 for( size_t i = 0; i < _n; ++i )
    187 {
    188 for( size_t j = 0; j < _n; ++j )
    189 out << " ---";
    190 out << endl;
    191
    192 for( size_t j = 0; j < _n; ++j )
    193 {
    194 out << "| ";
    195 // we display a D in every field if x[i][j] = 1 which means that a queen will be placed there
    196 if ( SCIPgetSolVal(_scip, sol, _vars[i][j]) > 0.5 )
    197 out << "D ";
    198 else
    199 out << " ";
    200 }
    201 out << "|" << endl;
    202 }
    203 for( size_t j = 0; j < _n; ++j)
    204 out << " ---";
    205 out << endl;
    206}
    207
    208
    209/* destructor */
    211{
    212 try
    213 {
    214 // since the SCIPcreateVar captures all variables, we have to release them now
    215 for( size_t i = 0; i < _n; ++i )
    216 {
    217 for ( size_t j = 0; j < _n; ++j )
    218 SCIP_CALL_EXC( SCIPreleaseVar(_scip, & _vars[i][j]) );
    219 }
    220 _vars.clear();
    221
    222 // the same for the constraints
    223 for( vector<SCIP_CONS *>::size_type i = 0; i < _cons.size(); ++i )
    224 SCIP_CALL_EXC( SCIPreleaseCons(_scip, &_cons[i]) );
    225 _cons.clear();
    226
    227 // after releasing all vars and cons we can free the scip problem
    228 // remember this has allways to be the last call to scip
    229 SCIP_CALL_EXC( SCIPfree(&_scip) );
    230 }
    231 catch ( SCIPException const & exp ) // catch SCIP errors
    232 {
    233 std::cerr << "SCIP Error: " << exp.what() << std::endl;
    234 abort();
    235 }
    236 catch (...) // catch other errors
    237 {
    238 // do nothing, but abort in debug mode
    239 abort();
    240 }
    241}
    242
    243/* solve the n-queens problem */
    245{
    246 // this tells scip to start the solution process
    247 SCIP_CALL_EXC( SCIPsolve(_scip) );
    248}
    exception handling class for SCIP
    const char * what(void) const
    returns the error message
    ~QueensSolver()
    destructor this is the place to release the SCIP_VAR and SCIP_CONS pointers and to free the SCIP poin...
    Definition: queens.cpp:210
    void solve(void)
    solves the queens problem using SCIPsolve
    Definition: queens.cpp:244
    QueensSolver(size_t n=8)
    constructs the BP model for the n-queens problem
    Definition: queens.cpp:28
    void disp(std::ostream &out=std::cout)
    display the solution
    Definition: queens.cpp:173
    #define NULL
    Definition: def.h:248
    #define TRUE
    Definition: def.h:93
    #define FALSE
    Definition: def.h:94
    SCIP_RETCODE SCIPaddCoefLinear(SCIP *scip, SCIP_CONS *cons, SCIP_VAR *var, SCIP_Real val)
    SCIP_RETCODE SCIPcreateConsLinear(SCIP *scip, SCIP_CONS **cons, const char *name, int nvars, SCIP_VAR **vars, SCIP_Real *vals, SCIP_Real lhs, SCIP_Real rhs, SCIP_Bool initial, SCIP_Bool separate, SCIP_Bool enforce, SCIP_Bool check, SCIP_Bool propagate, SCIP_Bool local, SCIP_Bool modifiable, SCIP_Bool dynamic, SCIP_Bool removable, SCIP_Bool stickingatnode)
    SCIP_RETCODE SCIPfree(SCIP **scip)
    Definition: scip_general.c:402
    SCIP_RETCODE SCIPcreate(SCIP **scip)
    Definition: scip_general.c:370
    SCIP_RETCODE SCIPaddVar(SCIP *scip, SCIP_VAR *var)
    Definition: scip_prob.c:1907
    SCIP_RETCODE SCIPaddCons(SCIP *scip, SCIP_CONS *cons)
    Definition: scip_prob.c:3274
    SCIP_RETCODE SCIPsetObjsense(SCIP *scip, SCIP_OBJSENSE objsense)
    Definition: scip_prob.c:1417
    SCIP_RETCODE SCIPcreateProb(SCIP *scip, const char *name, SCIP_DECL_PROBDELORIG((*probdelorig)), SCIP_DECL_PROBTRANS((*probtrans)), SCIP_DECL_PROBDELTRANS((*probdeltrans)), SCIP_DECL_PROBINITSOL((*probinitsol)), SCIP_DECL_PROBEXITSOL((*probexitsol)), SCIP_DECL_PROBCOPY((*probcopy)), SCIP_PROBDATA *probdata)
    Definition: scip_prob.c:119
    SCIP_MESSAGEHDLR * SCIPgetMessagehdlr(SCIP *scip)
    Definition: scip_message.c:88
    SCIP_RETCODE SCIPreleaseCons(SCIP *scip, SCIP_CONS **cons)
    Definition: scip_cons.c:1173
    SCIP_SOL * SCIPgetBestSol(SCIP *scip)
    Definition: scip_sol.c:2981
    SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
    Definition: scip_sol.c:1765
    SCIP_RETCODE SCIPsolve(SCIP *scip)
    Definition: scip_solve.c:2635
    SCIP_RETCODE SCIPreleaseVar(SCIP *scip, SCIP_VAR **var)
    Definition: scip_var.c:1887
    SCIP_RETCODE SCIPcreateVar(SCIP *scip, SCIP_VAR **var, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
    Definition: scip_var.c:120
    void SCIPmessagehdlrSetQuiet(SCIP_MESSAGEHDLR *messagehdlr, SCIP_Bool quiet)
    Definition: message.c:411
    Definition: pqueue.h:38
    public methods for message output
    n-queens example
    exception handling for SCIP
    #define SCIP_CALL_EXC(x)
    macro to call scip function with exception handling
    SCIP_RETCODE SCIPincludeDefaultPlugins(SCIP *scip)
    @ SCIP_OBJSENSE_MAXIMIZE
    Definition: type_prob.h:47
    @ SCIP_VARTYPE_BINARY
    Definition: type_var.h:64