Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://github.com/TakehideSoh/SAF
18 January 2026, 11:53:51 UTC
  • Code
  • Branches (4)
  • Releases (0)
  • Visits
    • Branches
    • Releases
    • HEAD
    • refs/heads/dev
    • refs/heads/main
    • refs/tags/v1.0-cmsb2023
    • refs/tags/v1.1-CMSB2023
    No releases to show
  • 83aaea6
  • /
  • cadical
  • /
  • src
  • /
  • reduce.cpp
Raw File Download Save again
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
origin badgecontent badge
swh:1:cnt:c7efffe0e7ef289e4410f8ca516b70e37bd471d2
origin badgedirectory badge
swh:1:dir:01d80ce94d8f49344a6b25660f682eedd134ff96
origin badgerevision badge
swh:1:rev:d26cc9f94a4f79c046ee0cdd3a127a44f7b443b6
origin badgesnapshot badge
swh:1:snp:d3fcf0e446f52630e867f11dee4c2c828bf46951

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: d26cc9f94a4f79c046ee0cdd3a127a44f7b443b6 authored by TakehideSoh on 23 June 2023, 07:02:26 UTC
Merge pull request #2 from TakehideSoh/dev
Tip revision: d26cc9f
reduce.cpp
#include "internal.hpp"

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

// Once in a while we reduce, e.g., we remove learned clauses which are
// supposed to be less useful in the future.  This is done in increasing
// intervals, which has the effect of allowing more and more learned clause
// to be kept for a longer period.  The number of learned clauses kept
// in memory corresponds to an upper bound on the 'space' of a resolution
// proof needed to refute a formula in proof complexity sense.

bool Internal::reducing () {
  if (!opts.reduce) return false;
  if (!stats.current.redundant) return false;
  return stats.conflicts >= lim.reduce;
}

/*------------------------------------------------------------------------*/

// Even less regularly we are flushing all redundant clauses.

bool Internal::flushing () {
  if (!opts.flush) return false;
  return stats.conflicts >= lim.flush;
}

/*------------------------------------------------------------------------*/

void Internal::mark_clauses_to_be_flushed () {
  for (const auto & c : clauses) {
    if (!c->redundant) continue; // keep irredundant
    if (c->garbage) continue;    // already marked as garbage
    if (c->reason) continue;     // need to keep reasons
    const unsigned used = c->used;
    if (used) c->used--;
    if (used) continue;          // but keep recently used clauses
    mark_garbage (c);            // flush unused clauses
    if (c->hyper) stats.flush.hyper++;
    else stats.flush.learned++;
  }
  // No change to 'lim.kept{size,glue}'.
}

/*------------------------------------------------------------------------*/

// Clauses of larger glue or larger size are considered less useful.
//
// We also follow the observations made by the Glucose team in their
// IJCAI'09 paper and keep all low glue clauses limited by
// 'options.keepglue' (typically '2').
//
// In earlier versions we pre-computed a 64-bit sort key per clause and
// wrapped a pointer to the clause and the 64-bit sort key into a separate
// data structure for sorting.  This was probably faster but awkward and
// so we moved back to a simpler scheme which also uses 'stable_sort'
// instead of 'rsort' below.  Sorting here is not a hot-spot anyhow.

struct reduce_less_useful {
  bool operator () (const Clause * c, const Clause * d) const {
    if (c->glue > d->glue) return true;
    if (c->glue < d->glue) return false;
    return c->size > d->size;
  }
};

// This function implements the important reduction policy. It determines
// which redundant clauses are considered not useful and thus will be
// collected in a subsequent garbage collection phase.

void Internal::mark_useless_redundant_clauses_as_garbage () {

  // We use a separate stack for sorting candidates for removal.  This uses
  // (slightly) more memory but has the advantage to keep the relative order
  // in 'clauses' intact, which actually due to using stable sorting goes
  // into the candidate selection (more recently learned clauses are kept if
  // they otherwise have the same glue and size).

  vector<Clause *> stack;

  stack.reserve (stats.current.redundant);

  for (const auto & c : clauses) {
    if (!c->redundant) continue;    // Keep irredundant.
    if (c->garbage) continue;       // Skip already marked.
    if (c->reason) continue;        // Need to keep reasons.
    const unsigned used = c->used;
    if (used) c->used--;
    if (c->hyper) {                 // Hyper binary and ternary resolvents
      assert (c->size <= 3);        // are only kept for one reduce round
      if (!used) mark_garbage (c);  // (even if 'c->keep' is true) unless
      continue;                     //  used recently.
    }
    if (used) continue;             // Do keep recently used clauses.
    if (c->keep) continue;          // Forced to keep (see above).

    stack.push_back (c);
  }

  stable_sort (stack.begin (), stack.end (), reduce_less_useful ());

  size_t target = 1e-2 * opts.reducetarget * stack.size ();

  // This is defensive code, which I usually consider a bug, but here I am
  // just not sure that using floating points in the line above is precise
  // in all situations and instead of figuring that out, I just use this.
  //
  if (target > stack.size ()) target = stack.size ();

  PHASE ("reduce", stats.reductions, "reducing %zd clauses %.0f%%",
    target, percent (target, stats.current.redundant));

  auto i = stack.begin ();
  const auto t = i + target;
  while (i != t) {
    Clause * c = *i++;
    LOG (c, "marking useless to be collected");
    mark_garbage (c);
    stats.reduced++;
  }

  lim.keptsize = lim.keptglue = 0;

  const auto end = stack.end ();
  for (i = t; i != end; i++) {
    Clause * c = *i;
    LOG (c, "keeping");
    if (c->size > lim.keptsize) lim.keptsize = c->size;
    if (c->glue > lim.keptglue) lim.keptglue = c->glue;
  }

  erase_vector (stack);

  PHASE ("reduce", stats.reductions,
    "maximum kept size %d glue %d", lim.keptsize, lim.keptglue);
}

/*------------------------------------------------------------------------*/

// If chronological backtracking produces out-of-order assigned units, then
// it is necessary to completely propagate them at the root level in order
// to derive all implied units.  Otherwise the blocking literals in
// 'flush_watches' are messed up and assertion 'FW1' fails.

bool Internal::propagate_out_of_order_units () {
  if (!level) return true;
  int oou = 0;
  for (size_t i = control[1].trail; !oou && i < trail.size (); i++) {
    const int lit = trail[i];
    assert (val (lit) > 0);
    if (var (lit).level) continue;
    LOG ("found out-of-order assigned unit %d", oou);
    oou = lit;
  }
  if (!oou) return true;
  assert (opts.chrono);
  backtrack (0);
  if (propagate ()) return true;
  learn_empty_clause ();
  return false;
}

/*------------------------------------------------------------------------*/

void Internal::reduce () {
  START (reduce);

  stats.reductions++;
  report ('.', 1);

  bool flush = flushing ();
  if (flush) stats.flush.count++;

  if (!propagate_out_of_order_units ()) goto DONE;

  mark_satisfied_clauses_as_garbage ();
  protect_reasons ();
  if (flush) mark_clauses_to_be_flushed ();
  else mark_useless_redundant_clauses_as_garbage ();
  garbage_collection ();

  {
    int64_t delta = opts.reduceint * (stats.reductions + 1);
    if (irredundant () > 1e5) {
      delta *= log (irredundant ()/1e4) / log (10);
      if (delta < 1) delta = 1;
    }
    lim.reduce = stats.conflicts + delta;
    PHASE ("reduce", stats.reductions,
      "new reduce limit %" PRId64 " after %" PRId64 " conflicts",
      lim.reduce, delta);
  }

  if (flush) {
    PHASE ("flush", stats.flush.count,
      "new flush increment %" PRId64 "", inc.flush);
    inc.flush *= opts.flushfactor;
    lim.flush = stats.conflicts + inc.flush;
    PHASE ("flush", stats.flush.count,
      "new flush limit %" PRId64 "", lim.flush);
  }

  last.reduce.conflicts = stats.conflicts;

DONE:

  report (flush ? 'f' : '-');
  STOP (reduce);
}

}

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API