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 f2a1c4e389 Squashed 'software/mza/' content from commit f970a59b17
git-subtree-dir: software/mza
git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
2021-07-11 16:34:30 +10:00

421 lines
12 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Guido Tack <guido.tack@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/. */
#ifndef __MINIZINC_MODEL_HH__
#define __MINIZINC_MODEL_HH__
#include <minizinc/ast.hh>
#include <minizinc/gc.hh>
#include <iterator>
#include <unordered_map>
#include <unordered_set>
#include <vector>
namespace MiniZinc {
class VarDeclIterator;
class ConstraintIterator;
class FunctionIterator;
class CopyMap;
class EnvI;
/// A MiniZinc model
class Model {
friend class GC;
friend class FZNSolverInstance;
friend Model* copy(EnvI& env, CopyMap& cm, Model* m, bool isFlatModel);
protected:
/// Previous model in root set list
Model* _roots_prev;
/// Next model in root set list
Model* _roots_next;
struct FnEntry {
std::vector<Type> t;
FunctionI* fi;
bool isPolymorphic;
FnEntry(FunctionI* fi0);
bool operator<(const FnEntry&) const;
static bool compare(const FnEntry& e1, const FnEntry& e2);
};
/// Add all instances of polymorphic entry \a fe to \a entries
void addPolymorphicInstances(Model::FnEntry& fe, std::vector<FnEntry>& entries);
/// Type of map from identifiers to function declarations
typedef ASTStringMap<std::vector<FnEntry> >::t FnMap;
/// Map from identifiers to function declarations
FnMap fnmap;
/// Type of map from Type (represented as int) to reverse mapper functions
typedef std::unordered_map<int, FunctionI*> RevMapperMap;
/// Map from Type (represented as int) to reverse mapper functions
RevMapperMap revmapmap;
/// Filename of the model
ASTString _filename;
/// Path of the model
ASTString _filepath;
/// Parent model if model was included
Model* _parent;
/// Items in the model
std::vector<Item*> _items;
/// Pointer to the solve item
SolveI* _solveItem;
/// Pointer to the output item
OutputI* _outputItem;
/// File-level documentation comment
std::string _docComment;
/// Store some declarations
struct FnDecls {
using TCheckedDecl = std::pair<bool, FunctionI*>; // bool means that it was checked
TCheckedDecl bounds_disj = {false, nullptr}; // SCIP's bound disjunction
} fnDecls;
public:
/// Construct empty model
Model(void);
/// Destructor
~Model(void);
/// Add \a i to the model
void addItem(Item* i);
/// Get parent model
Model* parent(void) const { return _parent; }
/// Set parent model to \a p
void setParent(Model* p) {
assert(_parent == NULL);
_parent = p;
}
/// Get file name
ASTString filename(void) const { return _filename; }
/// Get file path
ASTString filepath(void) const { return _filepath; }
/// Set file name
void setFilename(const std::string& f) {
assert(_filename.size() == 0);
_filename = ASTString(f);
}
/// Set file path
void setFilepath(const std::string& f) {
assert(_filepath.size() == 0);
_filepath = ASTString(f);
}
/// Register a builtin function item
void registerFn(EnvI& env, FunctionI* fi);
/// Sort functions by type
void sortFn(void);
/// Check that registered functions do not clash wrt overloading
void checkFnOverloading(EnvI& env);
/// Fix function table after type checking
void fixFnMap(void);
/// Return function declaration for \a id matching \a args
FunctionI* matchFn(EnvI& env, const ASTString& id, const std::vector<Expression*>& args,
bool strictEnums) const;
/// Return function declaration for \a id matching types \a t
FunctionI* matchFn(EnvI& env, const ASTString& id, const std::vector<Type>& t, bool strictEnums);
/// Return function declaration matching call \a c
FunctionI* matchFn(EnvI& env, Call* c, bool strictEnums) const;
/// Return function declaration for reverse mapper for type \a t
FunctionI* matchRevMap(EnvI& env, const Type& t) const;
/// Merge all builtin functions into \a m
void mergeStdLib(EnvI& env, Model* m) const;
/// Return item \a i
Item*& operator[](int i);
/// Return item \a i
const Item* operator[](int i) const;
/// Return number of items
unsigned int size(void) const;
typedef std::vector<Item*>::iterator iterator;
typedef std::vector<Item*>::const_iterator const_iterator;
/// Iterator for beginning of items
iterator begin(void);
/// Iterator for beginning of items
const_iterator begin(void) const;
/// Iterator for end of items
iterator end(void);
/// Iterator for end of items
const_iterator end(void) const;
ConstraintIterator begin_constraints(void);
ConstraintIterator end_constraints(void);
VarDeclIterator begin_vardecls(void);
VarDeclIterator end_vardecls(void);
FunctionIterator begin_functions(void);
FunctionIterator end_functions(void);
SolveI* solveItem(void);
OutputI* outputItem(void);
void setOutputItem(OutputI* oi);
/// Add a file-level documentation comment
void addDocComment(std::string s) { _docComment += s; }
/// Return the file-level documentation comment
const std::string& docComment(void) const { return _docComment; }
/// Remove all items marked as removed
void compact(void);
/// Get the stored function declarations
FnDecls& getFnDecls() { return fnDecls; }
};
class VarDeclIterator {
Model* _model;
Model::iterator _it;
public:
typedef Model::iterator::difference_type difference_type;
typedef Model::iterator::value_type value_type;
typedef VarDeclI& reference;
typedef VarDeclI* pointer;
typedef std::forward_iterator_tag iterator_category;
VarDeclIterator() {}
VarDeclIterator(const VarDeclIterator& vi) : _it(vi._it) {}
VarDeclIterator(Model* model, const Model::iterator& it) : _model(model), _it(it) {
while (_it != _model->end() && !(*_it)->isa<VarDeclI>()) {
++_it;
}
}
~VarDeclIterator() {}
VarDeclIterator& operator=(const VarDeclIterator& vi) {
if (this != &vi) {
_it = vi._it;
}
return *this;
}
bool operator==(const VarDeclIterator& vi) const { return _it == vi._it; }
bool operator!=(const VarDeclIterator& vi) const { return _it != vi._it; }
VarDeclIterator& operator++() {
do {
++_it;
} while (_it != _model->end() && !(*_it)->isa<VarDeclI>());
return *this;
}
reference operator*() const { return *(*_it)->cast<VarDeclI>(); }
pointer operator->() const { return (*_it)->cast<VarDeclI>(); }
};
class ConstraintIterator {
Model* _model;
Model::iterator _it;
public:
typedef Model::iterator::difference_type difference_type;
typedef Model::iterator::value_type value_type;
typedef ConstraintI& reference;
typedef ConstraintI* pointer;
typedef std::forward_iterator_tag iterator_category;
ConstraintIterator() {}
ConstraintIterator(const ConstraintIterator& vi) : _it(vi._it) {}
ConstraintIterator(Model* model, const Model::iterator& it) : _model(model), _it(it) {
while (_it != _model->end() && !(*_it)->isa<ConstraintI>()) {
++_it;
}
}
~ConstraintIterator() {}
ConstraintIterator& operator=(const ConstraintIterator& vi) {
if (this != &vi) {
_it = vi._it;
}
return *this;
}
bool operator==(const ConstraintIterator& vi) const { return _it == vi._it; }
bool operator!=(const ConstraintIterator& vi) const { return _it != vi._it; }
ConstraintIterator& operator++() {
do {
++_it;
} while (_it != _model->end() && !(*_it)->isa<ConstraintI>());
return *this;
}
reference operator*() const { return *(*_it)->cast<ConstraintI>(); }
pointer operator->() const { return (*_it)->cast<ConstraintI>(); }
};
class FunctionIterator {
Model* _model;
Model::iterator _it;
public:
typedef Model::iterator::difference_type difference_type;
typedef Model::iterator::value_type value_type;
typedef FunctionI& reference;
typedef FunctionI* pointer;
typedef std::forward_iterator_tag iterator_category;
FunctionIterator() {}
FunctionIterator(const FunctionIterator& vi) : _it(vi._it) {}
FunctionIterator(Model* model, const Model::iterator& it) : _model(model), _it(it) {
while (_it != _model->end() && !(*_it)->isa<FunctionI>()) {
++_it;
}
}
~FunctionIterator() {}
FunctionIterator& operator=(const FunctionIterator& vi) {
if (this != &vi) {
_it = vi._it;
}
return *this;
}
bool operator==(const FunctionIterator& vi) const { return _it == vi._it; }
bool operator!=(const FunctionIterator& vi) const { return _it != vi._it; }
FunctionIterator& operator++() {
do {
++_it;
} while (_it != _model->end() && !(*_it)->isa<FunctionI>());
return *this;
}
reference operator*() const { return *(*_it)->cast<FunctionI>(); }
pointer operator->() const { return (*_it)->cast<FunctionI>(); }
};
class EnvI;
/// Environment
class Env {
private:
EnvI* e;
public:
Env(Model* m = NULL, std::ostream& outstream = std::cout, std::ostream& errstream = std::cerr);
~Env(void);
Model* model(void);
void model(Model* m);
Model* flat(void);
void swap();
Model* output(void);
EnvI& envi(void);
const EnvI& envi(void) const;
std::ostream& dumpErrorStack(std::ostream& os);
const std::vector<std::string>& warnings(void);
void clearWarnings(void);
unsigned int maxCallStack(void) const;
std::ostream& evalOutput(std::ostream& os);
};
class CallStackItem {
public:
EnvI& env;
CallStackItem(EnvI& env0, Expression* e);
CallStackItem(EnvI& env0, Id* ident, IntVal i);
~CallStackItem(void);
};
/// Visitor for model items
class ItemVisitor {
public:
/// Enter model
bool enterModel(Model* m) { return true; }
/// Enter item
bool enter(Item* m) { return true; }
/// Visit include item
void vIncludeI(IncludeI*) {}
/// Visit variable declaration
void vVarDeclI(VarDeclI*) {}
/// Visit assign item
void vAssignI(AssignI*) {}
/// Visit constraint item
void vConstraintI(ConstraintI*) {}
/// Visit solve item
void vSolveI(SolveI*) {}
/// Visit output item
void vOutputI(OutputI*) {}
/// Visit function item
void vFunctionI(FunctionI*) {}
};
/// Iterator over items in a model and all its included models
template <class I>
class ItemIter {
protected:
I& iter;
public:
ItemIter(I& iter0) : iter(iter0) {}
void run(Model* m) {
std::unordered_set<Model*> seen;
std::vector<Model*> models;
models.push_back(m);
seen.insert(m);
while (!models.empty()) {
Model* cm = models.back();
models.pop_back();
if (!iter.enterModel(cm)) continue;
std::vector<Model*> includedModels;
for (unsigned int i = 0; i < cm->size(); i++) {
if ((*cm)[i]->removed()) continue;
if (!iter.enter((*cm)[i])) continue;
switch ((*cm)[i]->iid()) {
case Item::II_INC:
if (seen.find((*cm)[i]->cast<IncludeI>()->m()) == seen.end()) {
includedModels.push_back((*cm)[i]->cast<IncludeI>()->m());
seen.insert((*cm)[i]->cast<IncludeI>()->m());
}
iter.vIncludeI((*cm)[i]->cast<IncludeI>());
break;
case Item::II_VD:
iter.vVarDeclI((*cm)[i]->cast<VarDeclI>());
break;
case Item::II_ASN:
iter.vAssignI((*cm)[i]->cast<AssignI>());
break;
case Item::II_CON:
iter.vConstraintI((*cm)[i]->cast<ConstraintI>());
break;
case Item::II_SOL:
iter.vSolveI((*cm)[i]->cast<SolveI>());
break;
case Item::II_OUT:
iter.vOutputI((*cm)[i]->cast<OutputI>());
break;
case Item::II_FUN:
iter.vFunctionI((*cm)[i]->cast<FunctionI>());
break;
}
}
for (unsigned int i = static_cast<unsigned int>(includedModels.size()); i--;) {
models.push_back(includedModels[i]);
}
}
}
};
/// Run iterator \a i over all items of model \a m
template <class I>
void iterItems(I& i, Model* m) {
ItemIter<I>(i).run(m);
}
} // namespace MiniZinc
#endif