Introduction
Painless is built around five main interfaces that you can extend to create new components:
1. Implementing SolverInterface
SolverInterface is the base class for implementing SAT solvers. With specialized interfaces SolverCdclInterface and LocalSearchInterface.
Required Functions
You must override these pure virtual functions:
virtual unsigned int getVariablesCount() = 0;
virtual int getDivisionVariable() = 0;
virtual void setSolverInterrupt() = 0;
virtual void unsetSolverInterrupt() = 0;
virtual SatResult solve(
const std::vector<int>& cube) = 0;
virtual void addClause(ClauseExchangePtr clause) = 0;
virtual void addClauses(const std::vector<ClauseExchangePtr>& clauses) = 0;
virtual void addInitialClauses(const std::vector<simpleClause>& clauses,
unsigned int nbVars) = 0;
virtual void loadFormula(const char* filename) = 0;
virtual std::vector<int> getModel() = 0;
virtual void diversify(const SeedGenerator& getSeed) = 0;
SatResult
Enumeration for SAT solver results.
Definition SolverInterface.hpp:39
The interface provides default implementations for:
printWinningLog()
- Prints solver type info
printStatistics()
- Prints warning that stats aren't implemented
printParameters()
- Prints warning that parameters aren't implemented
- Note
- Use
initializeTypeId<Derived>()
function in most derived class' constructors to set up type IDs
- The solver type is set via the constructor using
SolverAlgorithmType
CDCL Solver Interface
The SolverCdclInterface extends SolverInterface for CDCL (Conflict-Driven Clause Learning) solvers with these additional virtual functions:
virtual void setPhase(const unsigned int var, const bool phase) = 0;
virtual void bumpVariableActivity(const int var, const int times) = 0;
virtual std::vector<int> getFinalAnalysis() = 0;
virtual std::vector<int> getSatAssumptions() = 0;
2. Implementing SharingEntity
SharingEntity is the base class for components that can exchange clauses. It defines a subscription behavior, where clients subscribes to a producer that exports clauses for them to import.
Required Functions
virtual bool importClause(const ClauseExchangePtr& clause) = 0;
virtual void importClauses(const std::vector<ClauseExchangePtr>& clauses) = 0;
Default Behaviors
The class provides default implementations for:
addClient()
- Adds a sharing entity as a client
removeClient()
- Removes a client
clearClients()
- Removes all clients
exportClauseToClient()
- Basic clause export to a single client
exportClause()
- Exports clause to all clients
exportClauses()
- Exports multiple clauses to all clients
std::enable_shared_from_this
is used, thus objects must be managed by std::shared_ptr
- Client management uses mutex protection
- Automatic sharing ID assignment
- Default clause export can be modified by overriding
exportClauseToClient()
3. Implementing SharingStrategy
SharingStrategy inherits from SharingEntity and manages clause distribution.
Required Functions
virtual bool doSharing() = 0;
Default Behaviors
Provides default implementations for:
getSleepingTime()
- Returns configured sharing sleep time via the option shr-sleep
printStats()
- Prints sharing statistics
- Producer/consumer management functions
Implementation Notes
- Overrides
exportClauseToClient()
to not export a clause to its producer
- Uses a clause database (
m_clauseDB
) for storing shared clauses
- Producer list management uses mutex protection
- Returns true from
doSharing()
when sharing should end (see Sharer)
GlobalSharingStrategy Interface
GlobalSharingStrategy specializes SharingStrategy to enable distributed clause sharing through MPI (Message Passing Interface) across multiple processes.
GlobalSharingStrategy adds two functions to the SharingStrategy interface:
virtual void initMpiVariable() = 0;
virtual void joinProcess() = 0;
initMpiVariable()
sets up the MPI related variables for distributed communication.
joinProcess()
provides synchronization mechanisms for process termination and resource cleanup.
It also overrides doSharing()
to execute a periodic end detection algorithm. It returns true when the sharing process should terminate based on global consensus. Thus GlobalSharingStrategy::doSharing()
can be used in derived classes for termination detection.
4. Implementing ClauseDatabase
ClauseDatabase is the base class for clause storage implementations. The ClauseBuffer class presented in Clause Management can be used as a basis for an hypothetical implementation.
Required Functions
virtual bool addClause(ClauseExchangePtr clause) = 0;
virtual size_t giveSelection(std::vector<ClauseExchangePtr>& selectedCls,
unsigned int literalCountLimit) = 0;
virtual void getClauses(std::vector<ClauseExchangePtr>& v_cls) = 0;
virtual bool getOneClause(ClauseExchangePtr& cls) = 0;
virtual size_t getSize() const = 0;
virtual size_t shrinkDatabase() = 0;
virtual void clearDatabase() = 0;
5. Implementing WorkingStrategy
WorkingStrategy defines how solvers are executed. Currently, it is the component where all the other components are to be managed in order to achieve the needed parallelization or distributed strategy.
Required Functions
virtual void solve(const std::vector<int>& cube) = 0;
const std::vector<int>& model) = 0;
virtual void setSolverInterrupt() = 0;
virtual void unsetSolverInterrupt() = 0;
virtual void waitInterrupt() = 0;
Base Interface for Working Strategies.
Definition WorkingStrategy.hpp:18
Default Behaviors
Provides:
addSlave()
- Adds a child working strategy
Implementation Notes
- Uses parent-child relationships
- Implements solver execution patterns
- Launched from main() in painless.cpp
- Controls solver lifecycle
Launching Working Strategies
In painless.cpp
, working strategies are initialized and launched:
if (__globalParameters__.test)
working = new Test();
else if (__globalParameters__.simple)
else
std::vector<int> cube;
std::thread mainWorker(&WorkingStrategy::solve, working, std::ref(cube));
An Implementation of WorkingStrategy that mimics the strategy used in the PRS-Distributed solver from...
Definition PortfolioPRS.hpp:35
A Simple Implementation of WorkingStrategy for the portfolio parallel strategy This strategy uses the...
Definition PortfolioSimple.hpp:24
Implementation Guidelines
- Reference existing implementations in
src/solvers/PortfolioSimple.cpp
, src/solvers/AllgatherSharing.cpp
, ...
- Implement synchronization for thread safety
- Follow shared pointer memory management patterns
- Include logging for debugging
- Test with different SAT instances