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
  • 5153fb6
  • /
  • cadical
  • /
  • src
  • /
  • lucky.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:43c96f6a691cc00a6f9267e8cbd607333b14ad7b
origin badgedirectory badge
swh:1:dir:01d80ce94d8f49344a6b25660f682eedd134ff96
origin badgerevision badge
swh:1:rev:3b45819df15225431050eeb48c1a31ffdd580af7
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: 3b45819df15225431050eeb48c1a31ffdd580af7 authored by Daniel Le Berre on 22 June 2023, 20:02:19 UTC
Typo in README
Tip revision: 3b45819
lucky.cpp
#include "internal.hpp"

namespace CaDiCaL {

// It turns out that even in the competition there are formulas which are
// easy to satisfy by either setting all variables to the same truth value
// or by assigning variables to the same value and propagating it.  In the
// latter situation this can be done either in the order of all variables
// (forward or backward) or in the order of all clauses.  These lucky
// assignments can be tested initially in a kind of pre-solving step.

// This function factors out clean up code common among the 'lucky'
// functions for backtracking and resetting a potential conflict.  One could
// also use exceptions here, but there are two different reasons for
// aborting early.  The first kind of aborting is due to asynchronous
// termination and the second kind due to a situation in which it is clear
// that a particular function will not be successful (for instance a
// completely negative clause is found).  The latter situation returns zero
// and will just abort the particular lucky function, while the former will
// abort all (by returning '-1').

int Internal::unlucky (int res) {
  if (level > 0) backtrack ();
  if (conflict) conflict = 0;
  return res;
}

int Internal::trivially_false_satisfiable () {
  LOG ("checking that all clauses contain a negative literal");
  assert (!level);
  assert (assumptions.empty ());
  for (const auto & c : clauses) {
    if (terminated_asynchronously (100)) return unlucky (-1);
    if (c->garbage) continue;
    if (c->redundant) continue;
    bool satisfied = false, found_negative_literal = false;
    for (const auto & lit : *c) {
      const signed char tmp = val (lit);
      if (tmp > 0) { satisfied = true; break; }
      if (tmp < 0) continue;
      if (lit > 0) continue;
      found_negative_literal = true;
      break;
    }
    if (satisfied || found_negative_literal) continue;
    LOG (c, "found purely positively");
    return unlucky (0);
  }
  VERBOSE (1, "all clauses contain a negative literal");
  for (auto idx : vars) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (-idx);
    if (propagate ()) continue;
    assert (level > 0);
    LOG ("propagation failed including redundant clauses");
    return unlucky (0);
  }
  stats.lucky.constant.zero++;
  return 10;
}

int Internal::trivially_true_satisfiable () {
  LOG ("checking that all clauses contain a positive literal");
  assert (!level);
  assert (assumptions.empty ());
  for (const auto & c : clauses) {
    if (terminated_asynchronously (100)) return unlucky (-1);
    if (c->garbage) continue;
    if (c->redundant) continue;
    bool satisfied = false, found_positive_literal = false;
    for (const auto & lit : *c) {
      const signed char tmp = val (lit);
      if (tmp > 0) { satisfied = true; break; }
      if (tmp < 0) continue;
      if (lit < 0) continue;
      found_positive_literal = true;
      break;
    }
    if (satisfied || found_positive_literal) continue;
    LOG (c, "found purely negatively");
    return unlucky (0);
  }
  VERBOSE (1, "all clauses contain a positive literal");
  for (auto idx : vars) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (idx);
    if (propagate ()) continue;
    assert (level > 0);
    LOG ("propagation failed including redundant clauses");
    return unlucky (0);
  }
  stats.lucky.constant.one++;
  return 10;
}

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

int Internal::forward_false_satisfiable () {
  LOG ("checking increasing variable index false assignment");
  assert (!unsat);
  assert (!level);
  assert (assumptions.empty ());
  for (auto idx : vars) {
    if (terminated_asynchronously (100)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (-idx);
    if (!propagate ()) return unlucky (0);
  }
  VERBOSE (1, "forward assuming variables false satisfies formula");
  assert (satisfied ());
  stats.lucky.forward.zero++;
  return 10;
}

int Internal::forward_true_satisfiable () {
  LOG ("checking increasing variable index true assignment");
  assert (!unsat);
  assert (!level);
  assert (assumptions.empty ());
  for (auto idx : vars) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (idx);
    if (!propagate ()) return unlucky (0);
  }
  VERBOSE (1, "forward assuming variables true satisfies formula");
  assert (satisfied ());
  stats.lucky.forward.one++;
  return 10;
}

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

int Internal::backward_false_satisfiable () {
  LOG ("checking decreasing variable index false assignment");
  assert (!unsat);
  assert (!level);
  assert (assumptions.empty ());
  for (int idx = max_var; idx > 0; idx--) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (-idx);
    if (!propagate ()) return unlucky (0);
  }
  VERBOSE (1, "backward assuming variables false satisfies formula");
  assert (satisfied ());
  stats.lucky.backward.zero++;
  return 10;
}

int Internal::backward_true_satisfiable () {
  LOG ("checking decreasing variable index true assignment");
  assert (!unsat);
  assert (!level);
  assert (assumptions.empty ());
  for (int idx = max_var; idx > 0; idx--) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (idx);
    if (!propagate ()) return unlucky (0);
  }
  VERBOSE (1, "backward assuming variables true satisfies formula");
  assert (satisfied ());
  stats.lucky.backward.one++;
  return 10;
}

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

// The following two functions test if the formula is a satisfiable horn
// formula.  Actually the test is slightly more general.  It goes over all
// clauses and assigns the first positive literal to true and propagates.
// Already satisfied clauses are of course skipped.  A reverse function
// is not implemented yet.

int Internal::positive_horn_satisfiable () {
  LOG ("checking that all clauses are positive horn satisfiable");
  assert (!level);
  assert (assumptions.empty ());
  for (const auto & c : clauses) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (c->garbage) continue;
    if (c->redundant) continue;
    int positive_literal = 0;
    bool satisfied = false;
    for (const auto & lit : *c) {
      const signed char tmp = val (lit);
      if (tmp > 0) { satisfied = true; break; }
      if (tmp < 0) continue;
      if (lit < 0) continue;
      positive_literal = lit;
      break;
    }
    if (satisfied) continue;
    if (!positive_literal) {
      LOG (c, "no positive unassigned literal in");
      return unlucky (0);
    }
    assert (positive_literal > 0);
    LOG (c, "found positive literal %d in", positive_literal);
    search_assume_decision (positive_literal);
    if (propagate ()) continue;
    LOG ("propagation of positive literal %d leads to conflict",
      positive_literal);
    return unlucky (0);
  }
  for (auto idx : vars) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (-idx);
    if (propagate ()) continue;
    LOG ("propagation of remaining literal %d leads to conflict", -idx);
    return unlucky (0);
  }
  VERBOSE (1, "clauses are positive horn satisfied");
  assert (!conflict);
  assert (satisfied ());
  stats.lucky.horn.positive++;
  return 10;
}

int Internal::negative_horn_satisfiable () {
  LOG ("checking that all clauses are negative horn satisfiable");
  assert (!level);
  assert (assumptions.empty ());
  for (const auto & c : clauses) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (c->garbage) continue;
    if (c->redundant) continue;
    int negative_literal = 0;
    bool satisfied = false;
    for (const auto & lit : *c) {
      const signed char tmp = val (lit);
      if (tmp > 0) { satisfied = true; break; }
      if (tmp < 0) continue;
      if (lit > 0) continue;
      negative_literal = lit;
      break;
    }
    if (satisfied) continue;
    if (!negative_literal) {
      if (level > 0) backtrack ();
      LOG (c, "no negative unassigned literal in");
      return unlucky (0);
    }
    assert (negative_literal < 0);
    LOG (c, "found negative literal %d in", negative_literal);
    search_assume_decision (negative_literal);
    if (propagate ()) continue;
    LOG ("propagation of negative literal %d leads to conflict",
      negative_literal);
    return unlucky (0);
  }
  for (auto idx : vars) {
    if (terminated_asynchronously (10)) return unlucky (-1);
    if (val (idx)) continue;
    search_assume_decision (idx);
    if (propagate ()) continue;
    LOG ("propagation of remaining literal %d leads to conflict", idx);
    return unlucky (0);
  }
  VERBOSE (1, "clauses are negative horn satisfied");
  assert (!conflict);
  assert (satisfied ());
  stats.lucky.horn.negative++;
  return 10;
}

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

int Internal::lucky_phases () {
  assert (!level);
  require_mode (SEARCH);
  if (!opts.lucky) return 0;

  // TODO: Some of the lucky assignments can also be found if there are
  // assumptions, but this is not completely implemented nor tested yet.
  // Nothing done for constraint either.
  if (!assumptions.empty () || !constraint.empty ()) return 0;

  START (search);
  START (lucky);
  assert (!searching_lucky_phases);
  searching_lucky_phases = true;
  stats.lucky.tried++;
  int res       = trivially_false_satisfiable ();
  if (!res) res = trivially_true_satisfiable ();
  if (!res) res = forward_true_satisfiable ();
  if (!res) res = forward_false_satisfiable ();
  if (!res) res = backward_false_satisfiable ();
  if (!res) res = backward_true_satisfiable ();
  if (!res) res = positive_horn_satisfiable ();
  if (!res) res = negative_horn_satisfiable ();
  if (res < 0) assert (termination_forced), res = 0;
  if (res == 10) stats.lucky.succeeded++;
  report ('l', !res);
  assert (searching_lucky_phases);
  searching_lucky_phases = false;
  STOP (lucky);
  STOP (search);

  return res;
}

}

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