diff --git a/Makefile.dep b/Makefile.dep index 1ea49eac45..e6c20d7d10 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -35244,3 +35244,139 @@ test/int/min-distance$(OBJSUFFIX) test/int/min-distance$(SBJSUFFIX): \ ./gecode/support/static-stack.hpp ./gecode/support/thread.hpp ./gecode/support/thread/thread.hpp \ ./gecode/support/timer.hpp ./test/int.hh ./test/int.hpp \ ./test/test.hh ./test/test.hpp +gecode/int/inter-distance$(OBJSUFFIX) gecode/int/inter-distance$(SBJSUFFIX): \ + ./gecode/int.hh ./gecode/int/array-traits.hpp ./gecode/int/array.hpp \ + ./gecode/int/branch.hpp ./gecode/int/branch/action.hpp ./gecode/int/branch/afc.hpp \ + ./gecode/int/branch/assign.hpp ./gecode/int/branch/chb.hpp ./gecode/int/branch/traits.hpp \ + ./gecode/int/branch/val.hpp ./gecode/int/branch/var.hpp ./gecode/int/channel.hpp \ + ./gecode/int/distinct.hh ./gecode/int/distinct/bnd.hpp ./gecode/int/distinct/cbs.hpp \ + ./gecode/int/distinct/dom-ctrl.hpp ./gecode/int/distinct/dom.hpp ./gecode/int/distinct/eqite.hpp \ + ./gecode/int/distinct/graph.hpp ./gecode/int/distinct/ter-dom.hpp ./gecode/int/distinct/val.hpp \ + ./gecode/int/div.hh ./gecode/int/div.hpp ./gecode/int/exception.hpp \ + ./gecode/int/extensional.hpp ./gecode/int/extensional/dfa.hpp ./gecode/int/extensional/tuple-set.hpp \ + ./gecode/int/int-set-1.hpp ./gecode/int/int-set-2.hpp ./gecode/int/inter-distance.hh \ + ./gecode/int/ipl.hpp ./gecode/int/irt.hpp ./gecode/int/limits.hpp \ + ./gecode/int/propagator.hpp ./gecode/int/reify.hpp ./gecode/int/rel.hh \ + ./gecode/int/rel/eq.hpp ./gecode/int/rel/lex.hpp ./gecode/int/rel/lq-le.hpp \ + ./gecode/int/rel/nq.hpp ./gecode/int/trace.hpp ./gecode/int/trace/bool-delta.hpp \ + ./gecode/int/trace/bool-trace-view.hpp ./gecode/int/trace/int-delta.hpp ./gecode/int/trace/int-trace-view.hpp \ + ./gecode/int/trace/traits.hpp ./gecode/int/var-imp.hpp ./gecode/int/var-imp/bool.hpp \ + ./gecode/int/var-imp/delta.hpp ./gecode/int/var-imp/int.hpp ./gecode/int/var/bool.hpp \ + ./gecode/int/var/int.hpp ./gecode/int/var/print.hpp ./gecode/int/view-val-graph.hh \ + ./gecode/int/view-val-graph/bi-link.hpp ./gecode/int/view-val-graph/comb-ptr-flag.hpp ./gecode/int/view-val-graph/edge.hpp \ + ./gecode/int/view-val-graph/graph.hpp ./gecode/int/view-val-graph/iter-prune-val.hpp ./gecode/int/view-val-graph/node.hpp \ + ./gecode/int/view.hpp ./gecode/int/view/bool-test.hpp ./gecode/int/view/bool.hpp \ + ./gecode/int/view/cached.hpp ./gecode/int/view/constint.hpp ./gecode/int/view/int.hpp \ + ./gecode/int/view/iter.hpp ./gecode/int/view/minus.hpp ./gecode/int/view/neg-bool.hpp \ + ./gecode/int/view/offset.hpp ./gecode/int/view/print.hpp ./gecode/int/view/rel-test.hpp \ + ./gecode/int/view/scale.hpp ./gecode/int/view/zero.hpp ./gecode/iter.hh \ + ./gecode/iter/ranges-add.hpp ./gecode/iter/ranges-append.hpp ./gecode/iter/ranges-array.hpp \ + ./gecode/iter/ranges-cache.hpp ./gecode/iter/ranges-compl.hpp ./gecode/iter/ranges-diff.hpp \ + ./gecode/iter/ranges-empty.hpp ./gecode/iter/ranges-inter.hpp ./gecode/iter/ranges-list.hpp \ + ./gecode/iter/ranges-map.hpp ./gecode/iter/ranges-minmax.hpp ./gecode/iter/ranges-minus.hpp \ + ./gecode/iter/ranges-negative.hpp ./gecode/iter/ranges-offset.hpp ./gecode/iter/ranges-operations.hpp \ + ./gecode/iter/ranges-positive.hpp ./gecode/iter/ranges-rangelist.hpp ./gecode/iter/ranges-scale.hpp \ + ./gecode/iter/ranges-singleton-append.hpp ./gecode/iter/ranges-singleton.hpp ./gecode/iter/ranges-size.hpp \ + ./gecode/iter/ranges-union.hpp ./gecode/iter/ranges-values.hpp ./gecode/iter/values-array.hpp \ + ./gecode/iter/values-bitset.hpp ./gecode/iter/values-bitsetoffset.hpp ./gecode/iter/values-inter.hpp \ + ./gecode/iter/values-list.hpp ./gecode/iter/values-map.hpp ./gecode/iter/values-minus.hpp \ + ./gecode/iter/values-negative.hpp ./gecode/iter/values-offset.hpp ./gecode/iter/values-positive.hpp \ + ./gecode/iter/values-ranges.hpp ./gecode/iter/values-singleton.hpp ./gecode/iter/values-union.hpp \ + ./gecode/iter/values-unique.hpp ./gecode/kernel.hh ./gecode/kernel/archive.hpp \ + ./gecode/kernel/branch/action.hpp ./gecode/kernel/branch/afc.hpp ./gecode/kernel/branch/chb.hpp \ + ./gecode/kernel/branch/filter.hpp ./gecode/kernel/branch/merit.hpp ./gecode/kernel/branch/print.hpp \ + ./gecode/kernel/branch/tiebreak.hpp ./gecode/kernel/branch/traits.hpp ./gecode/kernel/branch/val-commit.hpp \ + ./gecode/kernel/branch/val-sel-commit.hpp ./gecode/kernel/branch/val-sel.hpp ./gecode/kernel/branch/val.hpp \ + ./gecode/kernel/branch/var.hpp ./gecode/kernel/branch/view-sel.hpp ./gecode/kernel/branch/view-val.hpp \ + ./gecode/kernel/branch/view.hpp ./gecode/kernel/core.hpp ./gecode/kernel/data/array.hpp \ + ./gecode/kernel/data/rnd.hpp ./gecode/kernel/data/shared-array.hpp ./gecode/kernel/data/shared-data.hpp \ + ./gecode/kernel/exception.hpp ./gecode/kernel/gpi.hpp ./gecode/kernel/macros.hpp \ + ./gecode/kernel/memory/allocators.hpp ./gecode/kernel/memory/config.hpp ./gecode/kernel/memory/manager.hpp \ + ./gecode/kernel/memory/region.hpp ./gecode/kernel/modevent.hpp ./gecode/kernel/propagator/advisor.hpp \ + ./gecode/kernel/propagator/pattern.hpp ./gecode/kernel/propagator/subscribed.hpp ./gecode/kernel/propagator/wait.hpp \ + ./gecode/kernel/range-list.hpp ./gecode/kernel/shared-object.hpp ./gecode/kernel/shared-space-data.hpp \ + ./gecode/kernel/trace/filter.hpp ./gecode/kernel/trace/general.hpp ./gecode/kernel/trace/print.hpp \ + ./gecode/kernel/trace/recorder.hpp ./gecode/kernel/trace/tracer.hpp ./gecode/kernel/trace/traits.hpp \ + ./gecode/kernel/var-imp.hpp ./gecode/kernel/var-type.hpp ./gecode/kernel/var.hpp \ + ./gecode/kernel/view.hpp ./gecode/search.hh ./gecode/search/bab.hpp \ + ./gecode/search/base.hpp ./gecode/search/build.hpp ./gecode/search/cutoff.hpp \ + ./gecode/search/dfs.hpp ./gecode/search/engine.hpp ./gecode/search/exception.hpp \ + ./gecode/search/lds.hpp ./gecode/search/options.hpp ./gecode/search/pbs.hpp \ + ./gecode/search/rbs.hpp ./gecode/search/sebs.hpp ./gecode/search/seq/dead.hh \ + ./gecode/search/statistics.hpp ./gecode/search/stop.hpp ./gecode/search/support.hh \ + ./gecode/search/trace-recorder.hpp ./gecode/search/tracer.hpp ./gecode/search/traits.hpp \ + ./gecode/support.hh ./gecode/support/allocator.hpp ./gecode/support/auto-link.hpp \ + ./gecode/support/bitset-base.hpp ./gecode/support/bitset-offset.hpp ./gecode/support/bitset.hpp \ + ./gecode/support/block-allocator.hpp ./gecode/support/cast.hpp gecode/support/config.hpp \ + ./gecode/support/dynamic-array.hpp ./gecode/support/dynamic-queue.hpp ./gecode/support/dynamic-stack.hpp \ + ./gecode/support/exception.hpp ./gecode/support/failpoint.hpp ./gecode/support/hash.hpp \ + ./gecode/support/heap.hpp ./gecode/support/hw-rnd.hpp ./gecode/support/int-type.hpp \ + ./gecode/support/macros.hpp ./gecode/support/marked-pointer.hpp ./gecode/support/random.hpp \ + ./gecode/support/ref-count.hpp ./gecode/support/run-jobs.hpp ./gecode/support/sort.hpp \ + ./gecode/support/static-stack.hpp ./gecode/support/thread.hpp ./gecode/support/thread/thread.hpp \ + ./gecode/support/timer.hpp +test/int/inter-distance$(OBJSUFFIX) test/int/inter-distance$(SBJSUFFIX): \ + ./gecode/int.hh ./gecode/int/array-traits.hpp ./gecode/int/array.hpp \ + ./gecode/int/branch.hpp ./gecode/int/branch/action.hpp ./gecode/int/branch/afc.hpp \ + ./gecode/int/branch/assign.hpp ./gecode/int/branch/chb.hpp ./gecode/int/branch/traits.hpp \ + ./gecode/int/branch/val.hpp ./gecode/int/branch/var.hpp ./gecode/int/channel.hpp \ + ./gecode/int/div.hh ./gecode/int/div.hpp ./gecode/int/exception.hpp \ + ./gecode/int/extensional.hpp ./gecode/int/extensional/dfa.hpp ./gecode/int/extensional/tuple-set.hpp \ + ./gecode/int/int-set-1.hpp ./gecode/int/int-set-2.hpp ./gecode/int/ipl.hpp \ + ./gecode/int/irt.hpp ./gecode/int/limits.hpp ./gecode/int/propagator.hpp \ + ./gecode/int/reify.hpp ./gecode/int/trace.hpp ./gecode/int/trace/bool-delta.hpp \ + ./gecode/int/trace/bool-trace-view.hpp ./gecode/int/trace/int-delta.hpp ./gecode/int/trace/int-trace-view.hpp \ + ./gecode/int/trace/traits.hpp ./gecode/int/var-imp.hpp ./gecode/int/var-imp/bool.hpp \ + ./gecode/int/var-imp/delta.hpp ./gecode/int/var-imp/int.hpp ./gecode/int/var/bool.hpp \ + ./gecode/int/var/int.hpp ./gecode/int/var/print.hpp ./gecode/int/view.hpp \ + ./gecode/int/view/bool-test.hpp ./gecode/int/view/bool.hpp ./gecode/int/view/cached.hpp \ + ./gecode/int/view/constint.hpp ./gecode/int/view/int.hpp ./gecode/int/view/iter.hpp \ + ./gecode/int/view/minus.hpp ./gecode/int/view/neg-bool.hpp ./gecode/int/view/offset.hpp \ + ./gecode/int/view/print.hpp ./gecode/int/view/rel-test.hpp ./gecode/int/view/scale.hpp \ + ./gecode/int/view/zero.hpp ./gecode/iter.hh ./gecode/iter/ranges-add.hpp \ + ./gecode/iter/ranges-append.hpp ./gecode/iter/ranges-array.hpp ./gecode/iter/ranges-cache.hpp \ + ./gecode/iter/ranges-compl.hpp ./gecode/iter/ranges-diff.hpp ./gecode/iter/ranges-empty.hpp \ + ./gecode/iter/ranges-inter.hpp ./gecode/iter/ranges-list.hpp ./gecode/iter/ranges-map.hpp \ + ./gecode/iter/ranges-minmax.hpp ./gecode/iter/ranges-minus.hpp ./gecode/iter/ranges-negative.hpp \ + ./gecode/iter/ranges-offset.hpp ./gecode/iter/ranges-operations.hpp ./gecode/iter/ranges-positive.hpp \ + ./gecode/iter/ranges-rangelist.hpp ./gecode/iter/ranges-scale.hpp ./gecode/iter/ranges-singleton-append.hpp \ + ./gecode/iter/ranges-singleton.hpp ./gecode/iter/ranges-size.hpp ./gecode/iter/ranges-union.hpp \ + ./gecode/iter/ranges-values.hpp ./gecode/iter/values-array.hpp ./gecode/iter/values-bitset.hpp \ + ./gecode/iter/values-bitsetoffset.hpp ./gecode/iter/values-inter.hpp ./gecode/iter/values-list.hpp \ + ./gecode/iter/values-map.hpp ./gecode/iter/values-minus.hpp ./gecode/iter/values-negative.hpp \ + ./gecode/iter/values-offset.hpp ./gecode/iter/values-positive.hpp ./gecode/iter/values-ranges.hpp \ + ./gecode/iter/values-singleton.hpp ./gecode/iter/values-union.hpp ./gecode/iter/values-unique.hpp \ + ./gecode/kernel.hh ./gecode/kernel/archive.hpp ./gecode/kernel/branch/action.hpp \ + ./gecode/kernel/branch/afc.hpp ./gecode/kernel/branch/chb.hpp ./gecode/kernel/branch/filter.hpp \ + ./gecode/kernel/branch/merit.hpp ./gecode/kernel/branch/print.hpp ./gecode/kernel/branch/tiebreak.hpp \ + ./gecode/kernel/branch/traits.hpp ./gecode/kernel/branch/val-commit.hpp ./gecode/kernel/branch/val-sel-commit.hpp \ + ./gecode/kernel/branch/val-sel.hpp ./gecode/kernel/branch/val.hpp ./gecode/kernel/branch/var.hpp \ + ./gecode/kernel/branch/view-sel.hpp ./gecode/kernel/branch/view-val.hpp ./gecode/kernel/branch/view.hpp \ + ./gecode/kernel/core.hpp ./gecode/kernel/data/array.hpp ./gecode/kernel/data/rnd.hpp \ + ./gecode/kernel/data/shared-array.hpp ./gecode/kernel/data/shared-data.hpp ./gecode/kernel/exception.hpp \ + ./gecode/kernel/gpi.hpp ./gecode/kernel/macros.hpp ./gecode/kernel/memory/allocators.hpp \ + ./gecode/kernel/memory/config.hpp ./gecode/kernel/memory/manager.hpp ./gecode/kernel/memory/region.hpp \ + ./gecode/kernel/modevent.hpp ./gecode/kernel/propagator/advisor.hpp ./gecode/kernel/propagator/pattern.hpp \ + ./gecode/kernel/propagator/subscribed.hpp ./gecode/kernel/propagator/wait.hpp ./gecode/kernel/range-list.hpp \ + ./gecode/kernel/shared-object.hpp ./gecode/kernel/shared-space-data.hpp ./gecode/kernel/trace/filter.hpp \ + ./gecode/kernel/trace/general.hpp ./gecode/kernel/trace/print.hpp ./gecode/kernel/trace/recorder.hpp \ + ./gecode/kernel/trace/tracer.hpp ./gecode/kernel/trace/traits.hpp ./gecode/kernel/var-imp.hpp \ + ./gecode/kernel/var-type.hpp ./gecode/kernel/var.hpp ./gecode/kernel/view.hpp \ + ./gecode/search.hh ./gecode/search/bab.hpp ./gecode/search/base.hpp \ + ./gecode/search/build.hpp ./gecode/search/cutoff.hpp ./gecode/search/dfs.hpp \ + ./gecode/search/engine.hpp ./gecode/search/exception.hpp ./gecode/search/lds.hpp \ + ./gecode/search/options.hpp ./gecode/search/pbs.hpp ./gecode/search/rbs.hpp \ + ./gecode/search/sebs.hpp ./gecode/search/seq/dead.hh ./gecode/search/statistics.hpp \ + ./gecode/search/stop.hpp ./gecode/search/support.hh ./gecode/search/trace-recorder.hpp \ + ./gecode/search/tracer.hpp ./gecode/search/traits.hpp ./gecode/support.hh \ + ./gecode/support/allocator.hpp ./gecode/support/auto-link.hpp ./gecode/support/bitset-base.hpp \ + ./gecode/support/bitset-offset.hpp ./gecode/support/bitset.hpp ./gecode/support/block-allocator.hpp \ + ./gecode/support/cast.hpp gecode/support/config.hpp ./gecode/support/dynamic-array.hpp \ + ./gecode/support/dynamic-queue.hpp ./gecode/support/dynamic-stack.hpp ./gecode/support/exception.hpp \ + ./gecode/support/failpoint.hpp ./gecode/support/hash.hpp ./gecode/support/heap.hpp \ + ./gecode/support/hw-rnd.hpp ./gecode/support/int-type.hpp ./gecode/support/macros.hpp \ + ./gecode/support/marked-pointer.hpp ./gecode/support/random.hpp ./gecode/support/ref-count.hpp \ + ./gecode/support/run-jobs.hpp ./gecode/support/sort.hpp ./gecode/support/static-stack.hpp \ + ./gecode/support/thread.hpp ./gecode/support/thread/thread.hpp ./gecode/support/timer.hpp \ + ./test/int.hh ./test/int.hpp ./test/test.hh \ + ./test/test.hpp diff --git a/Makefile.in b/Makefile.in index 26d8c94e77..8e5d2c625d 100755 --- a/Makefile.in +++ b/Makefile.in @@ -337,7 +337,7 @@ INTSRC0 = \ bin-packing/conflict-graph.cpp \ order.cpp order/propagate.cpp \ unary.cpp cumulative.cpp cumulatives.cpp \ - circuit.cpp no-overlap.cpp nvalues.cpp \ + circuit.cpp no-overlap.cpp inter-distance.cpp nvalues.cpp \ member.cpp min-distance.cpp branch/action.cpp branch/chb.cpp \ arithmetic/mult.cpp \ branch/view-sel.cpp branch/val-sel-commit.cpp \ @@ -428,7 +428,7 @@ INTHDR0 = \ circuit.hh circuit/base.hpp circuit/val.hpp circuit/dom.hpp \ no-overlap.hh no-overlap/dim.hpp no-overlap/box.hpp \ no-overlap/base.hpp no-overlap/man.hpp no-overlap/opt.hpp \ - nvalues.hh nvalues/range-event.hpp \ + inter-distance.hh nvalues.hh nvalues/range-event.hpp \ nvalues/sym-bit-matrix.hpp nvalues/graph.hpp \ nvalues/bool-base.hpp nvalues/bool-eq.hpp \ nvalues/bool-lq.hpp nvalues/bool-gq.hpp \ @@ -1122,7 +1122,7 @@ INTTESTSRC00 = \ rel linear gcc sorted unshare exec sequence \ mm-arithmetic mm-bool mm-lin mm-count mm-rel \ bin-packing order unary cumulative cumulatives circuit \ - no-overlap precede nvalues member min-distance + no-overlap precede inter-distance nvalues member min-distance INTTESTSRC0 = test/int.cpp $(INTTESTSRC00:%=test/int/%.cpp) INTTESTOBJ = $(INTTESTSRC0:%.cpp=%$(OBJSUFFIX)) diff --git a/changelog.in b/changelog.in index 219972aeb1..394b936a5d 100755 --- a/changelog.in +++ b/changelog.in @@ -162,6 +162,21 @@ The propagation algorithms follow: M. Z. Lagerkvist, Propagation Algorithms for the Minimum-Distance Constraint over Selected Points, ModRef 2026. +[ENTRY] +Module: int +What: new +Rank: major +[DESCRIPTION] +Add the inter-distance constraint for fixed and variable separation. Basic +propagation checks feasibility and bounds the distance; advanced propagation +adds staged quadratic bounds filtering. The algorithms are described in: +C.-G. Quimper, A. Lopez-Ortiz, G. Pesant, A Quadratic Propagator for the +Inter-Distance Constraint, AAAI 2006, and Constraint Programming Letters 3 +(2008), 21-35. +M. R. Garey, D. S. Johnson, B. B. Simons, R. E. Tarjan, Scheduling Unit-Time +Tasks with Arbitrary Release Times and Deadlines, SIAM Journal on Computing +10(2) (1981), 256-269. + [RELEASE] Version: 6.4.0 Date: 2026-07-15 diff --git a/cmake/GecodeSources.cmake b/cmake/GecodeSources.cmake index 09b4365587..58a415eb36 100644 --- a/cmake/GecodeSources.cmake +++ b/cmake/GecodeSources.cmake @@ -88,6 +88,7 @@ set(GECODE_INT_SOURCES gecode/int/extensional/tuple-set.cpp gecode/int/gcc.cpp gecode/int/int-set.cpp + gecode/int/inter-distance.cpp gecode/int/ldsb.cpp gecode/int/ldsb/sym-imp.cpp gecode/int/ldsb/sym-obj.cpp @@ -415,6 +416,7 @@ set(GECODE_TEST_SOURCES test/int/exec.cpp test/int/extensional.cpp test/int/gcc.cpp + test/int/inter-distance.cpp test/int/linear.cpp test/int/member.cpp test/int/min-distance.cpp diff --git a/gecode/int.hh b/gecode/int.hh index 7d0e765955..04bfb99d70 100755 --- a/gecode/int.hh +++ b/gecode/int.hh @@ -1748,6 +1748,75 @@ namespace Gecode { //@} + /** + * \defgroup TaskModelIntInterDistance Inter-distance constraint + * \ingroup TaskModelInt + */ + //@{ + /** \brief Post bounds-consistent propagator for \f$|x_i-x_j|\geq p\f$ for all \f$0\leq i\neq j<|x|\f$ + * + * Domains with holes are treated as intervals between their bounds. + * + * - \a IPL_BASIC checks interval feasibility in \f$O(n\log n)\f$ time + * and linear temporary space, where \f$n=|x|\f$. + * - \a IPL_ADVANCED and \a IPL_BASIC_ADVANCED first perform + * the basic check, then schedule quadratic bounds(Z) filtering at + * a higher cost. This filtering uses quadratic temporary space. + * + * The default, \a IPL_DEF, uses both stages. The value/bounds/domain part + * of \a ipl does not affect these algorithms. + * + * A zero distance, or fewer than two variables, imposes no restriction. + * A distance of one is propagated as a bounds-consistent distinct constraint. + * + * The propagator uses algorithms taken from: + * + * Claude-Guy Quimper, Alejandro Lopez-Ortiz, and Gilles Pesant, + * A Quadratic Propagator for the Inter-Distance Constraint, + * AAAI, pages 123-128, 2006. + * + * and + * + * M. R. Garey, D. S. Johnson, B. B. Simons, and R. E. Tarjan, + * Scheduling Unit-Time Tasks with Arbitrary Release Times and Deadlines, + * SIAM Journal on Computing 10(2), pages 256-269, 1981. + * + * Throws Int::OutOfLimits if \a p is negative or exceeds Int::Limits::max. + * Throws Int::ArgumentSame if \a p is positive and \a x contains the same + * unassigned variable multiply. + */ + GECODE_INT_EXPORT void + inter_distance(Home home, const IntVarArgs& x, int p, + IntPropLevel ipl=IPL_DEF); + /** \brief Post inter-distance constraint with variable separation + * + * Constrains \f$p\geq0\f$ and \f$|x_i-x_j|\geq p\f$ for all + * \f$0\leq i\neq j<|x|\f$. + * + * Uses the same algorithm options as the fixed-distance overload. + * The basic stage additionally tightens \a p's upper bound by binary + * search using the linear-space feasibility checker. Its time bound + * is \f$O(n\log n\log(1+\max(p)))\f$. The advanced stage provides + * bounds(Z) consistency for \a x using the minimum of \a p, giving + * bounds(Z) consistency for the whole constraint. + * + * The variable-distance algorithm is taken from: + * + * Claude-Guy Quimper, Alejandro Lopez-Ortiz, and Gilles Pesant, + * A Quadratic Propagator for the Inter-Distance Constraint, + * Constraint Programming Letters 3, pages 21-35, 2008, Section 5. + * + * Fewer than two variables only constrain \a p to be nonnegative. + * With at least two variables, throws Int::ArgumentSame if \a p is the + * same unassigned variable as a member of \a x, or if \a p can be positive + * and \a x contains the same unassigned variable multiply. + */ + GECODE_INT_EXPORT void + inter_distance(Home home, const IntVarArgs& x, IntVar p, + IntPropLevel ipl=IPL_DEF); + //@} + + /** * \defgroup TaskModelIntDistinct Distinct constraints * \ingroup TaskModelInt diff --git a/gecode/int/inter-distance.cpp b/gecode/int/inter-distance.cpp new file mode 100644 index 0000000000..77b39cef20 --- /dev/null +++ b/gecode/int/inter-distance.cpp @@ -0,0 +1,953 @@ +/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* + * Main authors: + * Claude-Guy Quimper + * Mikael Zayenz Lagerkvist + * + * Copyright: + * Claude-Guy Quimper, 2006 + * Mikael Zayenz Lagerkvist, 2026 + * + * This file is part of Gecode, the generic constraint + * development environment: + * http://www.gecode.dev + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include + +#include +#include +#include + +namespace Gecode { namespace Int { namespace InterDistance { + + namespace { + typedef long long int Time; + typedef std::ptrdiff_t RegionIndex; + + /// Task bounds and ranks in their sorted orders + struct Task { + Time min; + Time max; + int minRank; + int maxRank; + }; + + /// Forbidden starting times (inclusive) + struct Forbidden { + Time min; + Time max; + }; + + /// Nonnegative remainder, including for negative deadlines + Time residue(Time t, Time p) { + Time q = t % p; + return (q < 0) ? q+p : q; + } + + /** + * \brief Ordered residue groups with region-backed storage + * + * Group keys are drawn from the original deadline residues. A shift + * merges groups into an existing key, but later deadline activation can + * reinsert a removed key. A Fenwick tree of active-key counts supports + * insertion, removal, and successor queries in O(log n) time. + */ + class ResidueGroups { + Time* keys; + int* groups; + int* counts; + int keyCount; + int activeCount; + int topBit; + + /// Change the active-key count at rank i + void update(int i, int delta) { + for (unsigned int j=static_cast(i)+1; + j<=static_cast(keyCount); j+=j & -j) + counts[j] += delta; + activeCount += delta; + } + + /// First active key at or after rank i, or keyCount + int next_active(int i) const { + int before = 0; + for (unsigned int j=static_cast(i); j; j-=j & -j) + before += counts[j]; + if (before == activeCount) + return keyCount; + + int ordinal = before+1; + int rank = 0; + for (int bit=topBit; bit; bit/=2) + if ((bit <= keyCount-rank) && (counts[rank+bit] < ordinal)) { + rank += bit; + ordinal -= counts[rank]; + } + return rank; + } + public: + /// Allocate once; repeated distance checks reuse these arrays + ResidueGroups(Region& r, int n) + : keys(r.alloc