1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
Jip J. Dekker fad1b07018 Squashed 'software/minizinc/' content from commit 4f10c8205
git-subtree-dir: software/minizinc
git-subtree-split: 4f10c82056ffcb1041d7ffef29d77a7eef92cf76
2021-06-16 14:06:46 +10:00

160 lines
5.4 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Gleb Belov <gleb.belov@monash.edu>
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#pragma once
#include <minizinc/flattener.hh>
#include <minizinc/solver.hh>
#include <minizinc/solvers/MIP/MIP_wrap.hh>
namespace MiniZinc {
// can be redefined as compilation parameter
#ifndef GETMIPWRAPPER
#define GETMIPWRAPPER MIP_WrapperFactory::GetDefaultMIPWrapper()
#endif
class MIPSolver {
public:
typedef MIPWrapper::VarId Variable;
typedef MiniZinc::Statistics Statistics;
};
/// Generic cut generator
/// Callback should be able to produce previously generated cuts again if needed [Gurobi]
class CutGen {
public:
virtual ~CutGen() {}
/// Say what type of cuts
virtual int getMask() = 0;
/// Adds new cuts to the 2nd parameter
virtual void generate(const MIPWrapper::Output&, MIPWrapper::CutInput&) = 0;
virtual void print(std::ostream& /*os*/) {}
};
/// XBZ cut generator
class XBZCutGen : public CutGen {
XBZCutGen() {}
MIPWrapper* _pMIP = nullptr;
public:
XBZCutGen(MIPWrapper* pw) : _pMIP(pw) {}
std::vector<MIPWrapper::VarId> varX, varB;
/// Say what type of cuts
int getMask() override { return MIPWrapper::MaskConsType_Usercut; }
MIPWrapper::VarId varZ;
void generate(const MIPWrapper::Output& slvOut, MIPWrapper::CutInput& cutsIn) override;
void print(std::ostream& os) override;
};
/// SEC cut generator for circuit
class SECCutGen : public CutGen {
SECCutGen() {}
MIPWrapper* _pMIP = nullptr;
public:
SECCutGen(MIPWrapper* pw) : _pMIP(pw) {}
/// Say what type of cuts
int getMask() override {
return MIPWrapper::MaskConsType_Lazy | MIPWrapper::MaskConsType_Usercut;
}
std::vector<MIPWrapper::VarId> varXij;
int nN = 0; // N nodes
/// returns error message if fails
std::string validate() const;
void generate(const MIPWrapper::Output& slvOut, MIPWrapper::CutInput& cutsIn) override;
void print(std::ostream& os) override;
};
template <class MIPWrapper>
class MIPSolverinstance : public SolverInstanceImpl<MIPSolver> {
using SolverInstanceBase::_log;
protected:
const std::unique_ptr<MIPWrapper> _mipWrapper;
std::vector<std::unique_ptr<CutGen> > _cutGenerators;
public:
void registerCutGenerator(std::unique_ptr<CutGen>&& pCG) {
getMIPWrapper()->cbui.cutMask |= pCG->getMask();
_cutGenerators.push_back(move(pCG));
}
double lastIncumbent;
double dObjVarLB = -1e300, dObjVarUB = 1e300;
MIPSolverinstance(Env& env, std::ostream& log, typename MIPWrapper::FactoryOptions& factoryOpt,
typename MIPWrapper::Options* opt)
: SolverInstanceImpl(env, log, opt), _mipWrapper(new MIPWrapper(factoryOpt, opt)) {
assert(_mipWrapper.get());
registerConstraints();
}
virtual MIPWrapper* getMIPWrapper() const { return _mipWrapper.get(); }
Status next() override {
assert(0);
return SolverInstance::UNKNOWN;
}
void processFlatZinc() override;
virtual void processWarmstartAnnotations(const Annotation& ann);
virtual void processSearchAnnotations(const Annotation& ann);
virtual void processMultipleObjectives(const Annotation& ann);
Status solve() override;
void resetSolver() override {}
virtual void genCuts(const typename MIPWrapper::Output& slvOut,
typename MIPWrapper::CutInput& cutsIn, bool fMIPSol);
// void assignSolutionToOutput(); // needs to be public for the callback?
void printStatistics() override;
void printStatisticsLine(bool fLegend = false) override;
/// creates a var for a literal, if necessary
VarId exprToVar(Expression* arg);
void exprToArray(Expression* arg, std::vector<double>& vals);
void exprToVarArray(Expression* arg, std::vector<VarId>& vars);
std::pair<double, bool> exprToConstEasy(Expression* e);
double exprToConst(Expression* e);
Expression* getSolutionValue(Id* id) override;
void registerConstraints();
}; // MIPSolverinstance
template <class MIPWrapper>
class MIPSolverFactory : public SolverFactory {
public:
MIPSolverFactory();
bool processFactoryOption(int& i, std::vector<std::string>& argv,
const std::string& workingDir = std::string()) override;
void factoryOptionsFinished() override;
SolverInstanceBase::Options* createOptions() override { return new typename MIPWrapper::Options; }
SolverInstanceBase* doCreateSI(Env& env, std::ostream& log,
SolverInstanceBase::Options* opt) override {
return new MIPSolverinstance<MIPWrapper>(env, log, _factoryOptions,
static_cast<typename MIPWrapper::Options*>(opt));
}
bool processOption(SolverInstanceBase::Options* opt, int& i, std::vector<std::string>& argv,
const std::string& workingDir = std::string()) override;
std::string getDescription(SolverInstanceBase::Options* opt = nullptr) override;
std::string getVersion(SolverInstanceBase::Options* opt = nullptr) override;
std::string getId() override;
void printHelp(std::ostream& os) override { MIPWrapper::Options::printHelp(os); }
private:
typename MIPWrapper::FactoryOptions _factoryOptions;
std::vector<SolverConfig::ExtraFlag> _extraFlags;
};
} // namespace MiniZinc
#include <minizinc/solvers/MIP/MIP_solverinstance.hpp>