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

134 lines
4.7 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Jip J. Dekker <jip.dekker@monash.edu>
* 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/. */
#pragma once
#include <minizinc/interpreter/_val_decl.hh>
#include <minizinc/interpreter/rco.hh>
namespace MiniZinc {
class BytecodeProc;
class Constraint;
class Vec;
class Variable : public RefCountedObject {
friend class Trail;
friend class Interpreter;
friend class Val;
public:
enum SubscriptionEvent { SEV_VAL, SEV_UNIFY, SEV_DOM, SEV };
/// Event sets propagators can subscribe to: only value events, value+unification, or any change
enum SubscriptionEventSet { SES_VAL, SES_VALUNIFY, SES_ANY };
typedef std::unordered_map<Constraint*, SubscriptionEventSet> Subscriptions;
protected:
Variable* _prev;
Variable* _next;
Val _domain; // could be the domain, or the variable or value this variable is aliased to
Val _ann;
Subscriptions _subscriptions;
std::vector<Constraint*> _definitions;
/// Whether domain is binding
/// TODO: tag _domain pointer instead
bool _binding;
/// Whether variable is aliased
/// TODO: tag _domain pointer instead
bool _aliased;
Variable(Interpreter* interpreter, Val domain, int ident);
Variable(Interpreter* interpreter, Val domain, bool binding, int ident, Val ann);
static Variable* createRoot(Interpreter* interpreter, Val domain, int ident) {
Variable* v = static_cast<Variable*>(::malloc(sizeof(Variable)));
return new (v) Variable(interpreter, domain, ident);
}
public:
bool aliased(void) const { return _aliased; }
Vec* domain(void) const {
assert(!aliased());
return _domain.toVec();
}
Val lb() const {
assert(!aliased());
assert(_domain[0].isInt());
return _domain[0];
}
Val ub() const {
assert(!aliased());
assert(_domain[_domain.size() - 1].isInt());
return _domain[_domain.size() - 1];
}
bool isBounded() const { return lb().isFinite() && ub().isFinite(); }
/// Set new minimum value included in the domain
bool setMin(Interpreter* interpreter, Val i, bool binding = true);
/// Set new maximum value included in the domain
bool setMax(Interpreter* interpreter, Val i, bool binding = true);
/// Restrict domain to a single value
bool setVal(Interpreter* interpreter, Val i, bool binding = true);
/// Intersect current domain with given domain
bool intersectDom(Interpreter* interpreter, const std::vector<Val>& dom, bool binding = true);
bool intersectDom(Interpreter* interpreter, Val dom, bool binding = true);
/// Set domain to \a newDomain, schedule propagators
void domain(Interpreter* interpreter, const Val& newDomain, bool binding);
/// Set domain to \a newDomain, schedule propagators
void domain(Interpreter* interpreter, const std::vector<Val>& newDomain, bool binding);
Val ann(void) const { return _ann; }
Constraint* defined_by() { return (_definitions.size() == 1) ? _definitions[0] : nullptr; }
const std::vector<Constraint*>& definitions(void) const { return _definitions; }
void addDefinition(Interpreter* interpreter, Constraint* c);
static Variable* a(Interpreter* interpreter, Val domain, bool binding, int ident, Val ann = 0) {
Variable* v = static_cast<Variable*>(::malloc(sizeof(Variable)));
return new (v) Variable(interpreter, domain, binding, ident, ann);
}
static void free(Variable* var) {
// INVARIANT: var->destroy() must be called before free(var);
assert(var->_model_ref_count == 0 && var->_memory_ref_count == 0);
for (auto c : var->_definitions) {
::free(c);
}
::free(var);
}
~Variable(void) = delete;
/// Destroy and unlink this variable
void destroy(Interpreter* interpreter);
void reconstruct(Interpreter* interpreter);
void alias(Interpreter* interpreter, Val v);
void unalias(Interpreter* interpreter, Val dom);
Val alias(void) {
assert(aliased());
return _domain;
};
Variable* prev(void) const { return _prev; }
Variable* next(void) const { return _next; }
static void dump(Variable* d, const std::vector<BytecodeProc>& bs, std::ostream& os);
// Propagation interface
/// Flag whether definition's domain is binding
bool binding(void) const { return _binding == 1; }
/// Set flag whether definition's domain is binding
void binding(Interpreter* interpreter, bool f);
/// Add \a c to set of subscribed constraints
void subscribe(Constraint* d, const SubscriptionEventSet& events);
/// Remove \a c from set of subscribed constraints
void unsubscribe(Constraint* c);
};
} // namespace MiniZinc