SPUR - Satisfying Perfectly Uniform Random Assignment Sampler¶
Library API¶
Class Hierarchy¶
-
- Struct SolverConfiguration
- Struct Variable
- Class AltComponentAnalyzer
- Class Antecedent
- Class BasePackedComponent
- Template Class BitStuffer
- Class CachedAssignment
- Class ClauseHeader
- Class Component
- Class ComponentArchetype
- Class ComponentCache
- Class ComponentManager
- Class DataAndStatistics
- Class DecisionStack
- Class DifferencePackedComponent
- Template Class GenericCacheableComponent
- Class Instance
- Class Literal
- Class LiteralID
- Template Class LiteralIndexedVector
- Class Random
- Class Random::Mpz
- Class SampleAssignment
- Class SamplesManager
- Class Solver
- Class StackLevel
- Class StopWatch
- Enum AssignmentEncoding
- Enum PrintColor
- Enum SolverExitState
- Enum SolverNextAction
- Enum TopTreeNodeType
File Hierarchy¶
-
- Directory src
- Directory types
- File alt_component_analyzer.cpp
- File alt_component_analyzer.h
- File cached_assignment.h
- File component_cache.cpp
- File component_cache.h
- File component_cache.inc
- File component_management.cpp
- File component_management.h
- File containers.h
- File instance.cpp
- File instance.h
- File main.cpp
- File model_sampler.cpp
- File model_sampler.h
- File primitive_types.h
- File rand_distributions.cpp
- File rand_distributions.h
- File sampler_tools.h
- File solver.cpp
- File solver.h
- File solver_config.h
- File stack.cpp
- File stack.h
- File statistics.cpp
- File statistics.h
- File structures.h
- Directory src
Full API¶
Classes and Structs¶
Struct SolverConfiguration¶
- Defined in File solver_config.h
Struct Documentation¶
-
struct
SolverConfiguration
¶ solver_config.h
Purpose: Defines the SolverConfiguration() class stores the state of the sampler and counter.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley. Singleton object used for storing the configuration settings for the current execution.
Public Functions
-
bool
store_sampled_models
()¶ When random sampling is enabled, this flag indicates whether the models should currently be stored or other processing is occurring.
- Return
- True if sample models should be stored.
-
bool
perform_sample_caching
()¶ Cache Sampling State Accessor
Returns whether the cache currently supports sampling.
- Return
- true if samples are being stored in the cache.
-
void
EnableSampleCaching
()¶ Sample Caching Enabler
This enables storing of samples in the cache. It can only be enabled. It can never be disabled by design since once the caching stage has been enabled, it can never be disabled.
Public Members
-
bool
perform_component_caching
= true¶ Support to modify the default state of this feature is disabled in the sampler.
Forces variable backtracking in the case of a conflict being founded. Support to modify the default state of this feature is disabled in the sampler.
-
bool
perform_failed_lit_test
= true¶ Support to modify the default state of this feature is disabled in the sampler.
-
bool
perform_pre_processing
= true¶ Support to modify the default state of this feature is disabled in the sampler.
-
bool
perform_random_sampling_
= true¶ Rather than performing standard model counting, sample satisfying models uniformly at random.
-
bool
perform_top_tree_sampling
= false¶ Performs sampling of the top of the tree.
-
bool
disable_samples_write_
= false¶ Disable writing the samples file.
-
std::string
samples_output_file
= ""¶ Location to write the output sample and sampler information.
-
bool
debug_mode
= false¶ Debug mode has special settings to make debugging the program easier.
-
uint64_t
time_bound_seconds
= UINT64_MAX¶ Stores the maximum execution time of the sampler.
Default is approximately 27 hours.
-
bool
verbose
= false¶ Controls whether verbose state tracking is enabled. When verbose is enabled, a basic trace printing is also enabled.
In some versions of the console, this verbose printing may be multicolored for easier visual tracking.
-
bool
quiet
= false¶ Prevents printing to the console.
Cannot be true if verbose is true.
-
bool
perform_two_pass_sampling_
= false¶ Forces two pass sample construction. This applies only to the case where the number of samples requested is 1.
-
unsigned
num_samples_to_cache_
= 1¶ Number of samples that will be cached at once.
-
bool
skip_partial_assignment_fill
= false¶ DEBUG_ONLY MODE - This is an unsupported feature used for debug and development purposes only. Almost no one should use it beyond the core development team.
-
SampleSize
num_samples_
= 0¶ Number of satisfying assignments to randomly sample. This is a command line parameter.
-
TreeNodeIndex
max_top_tree_depth_
= 25¶ When trimming the top of the tree, this represents the maximum branch variable depth before sample building stops.
-
SampleSize
max_top_tree_leaf_sample_count
= 50¶ Maximum number of samples that can come from a single top tree node.
-
std::string
top_tree_samples_output_file_
= “.” “/”
“__final_top_tree_samples.txt”
¶ Location to write the top tree samples.
Struct Variable¶
- Defined in File structures.h
Class AltComponentAnalyzer¶
- Defined in File alt_component_analyzer.h
Class Documentation¶
-
class
AltComponentAnalyzer
¶ alt_component_analyzer.h
Purpose: Defines the AltComponentAnalyzer() class that analyzes a Boolean formula for connected components.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Public Functions
-
AltComponentAnalyzer
(DataAndStatistics &statistics, LiteralIndexedVector<TriValue> &lit_values)¶
-
const unsigned
scoreOf
(VariableIndex v) const¶
-
ComponentArchetype &
current_archetype
()¶
-
void
initialize
(LiteralIndexedVector<Literal> &literals, std::vector<LiteralID> &lit_pool)¶ alt_component_analyzer.cpp
Purpose: Defines the methods for the AltComponentAnalyzer() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
bool
isUnseenAndActive
(VariableIndex v)¶
-
void
setSeenAndStoreInSearchStack
(VariableIndex v)¶
-
void
setupAnalysisContext
(StackLevel &top, Component &super_comp)¶
-
bool
exploreRemainingCompOf
(VariableIndex v)¶
-
unsigned
max_clause_id
()¶ Maximum clause ID number.
This is used to determine the packing size (m).
- Return
- Maximum clause identification number
-
unsigned
max_variable_id
()¶ Maximum variable ID number.
This is used to determine the packing size (n).
- Return
- Maximum variable identification number
-
ComponentArchetype &
getArchetype
()¶
Class Antecedent¶
- Defined in File structures.h
Class Documentation¶
-
class
Antecedent
¶ Antecedent can be either a clause or a literal.
Public Functions
-
Antecedent
()¶ Creates an empty antecedent clause with ID zero.
-
Antecedent
(const ClauseOfs cl_ofs)¶ Shifts the clause offset by 1 to the left and then adds 1.
- Parameters
cl_ofs
: Clause offset.
-
bool
isAClause
() const¶ Checks if the antecendent is a clause. This is done by checking if the least significant bit is a 0b0 or a 0b1.
- Return
- True if the antecedent is a clause. False if it is a literal.
-
ClauseOfs
asCl
() const¶ Returns the antecedent information formatted as a clause
- Return
- Antecedent clause
-
LiteralID
asLit
()¶ Returns the antecedent information formatted as a literal.
- Return
- Antecedent literal
-
bool
isAnt
() const¶ MT - A NON-Antecedent will only be A NOT_A_CLAUSE Clause Id
Checks whether this is an actual antecedent.
- Return
- true if the this is not a true antecendent (i.e., the value equals 1).
-
Class BasePackedComponent¶
- Defined in File base_packed_component.h
Inheritance Relationships¶
public DifferencePackedComponent
(Class DifferencePackedComponent)
Class Documentation¶
-
class
BasePackedComponent
¶ Stores the specifications for package cache components including the number of bits in a variable, clause, and other information.
Subclassed by DifferencePackedComponent
Public Functions
-
BasePackedComponent
()¶
-
BasePackedComponent
(unsigned creation_time)¶ Creates a packed component and records with it the creation time.
- Parameters
creation_time
:
-
~BasePackedComponent
()¶
-
unsigned
creation_time
()¶
-
const mpz_class &
model_count
() const¶
-
unsigned
alloc_of_model_count
() const¶
-
void
set_creation_time
(unsigned time)¶
-
void
set_model_count
(const mpz_class &rn, unsigned time)¶
-
unsigned
hashkey
() const¶
-
bool
modelCountFound
()¶
-
bool
isDeletable
() const¶ Determines if a cache entry is deletable. This entails that the entry is not connected to an active component in the component stack.
- Return
- true if the cache entry is disconnected from an active component and can be deleted.
-
void
set_deletable
()¶ Mark the packed cache entry as deletable.
-
void
clear
()¶ Free the memory associated with the packed cache entry’s data.
Public Static Functions
-
static unsigned
bits_per_variable
()¶ Accessor to get n := {lg |var(F)|}, i.e., the number of bits that represent a VARIABLE.
- Return
- Number of bits to store a VARIABLE
-
static unsigned
variable_mask
()¶
-
static unsigned
bits_per_clause
()¶ Accessor to get m := {lg |cl(F)|}, i.e., the number of bits that represent a CLAUSE.
- Return
- Number of bits to store a CLAUSE.
-
static unsigned
bits_per_block
()¶
-
static unsigned
bits_of_data_size
()¶
-
void
adjustPackSize
(unsigned int maxVarId, unsigned int maxClId)¶ Configures that variables that define the packing size variables.
- Parameters
maxVarId
: Maximum ID number for a variablemaxClId
: Maximum ID number for a clause
-
static void
outbit
(unsigned v)¶ Prints a bit string to the console. The MSB is printed first and the LSB last.
- Parameters
v
: Value to be printed by bit to the console.
-
static unsigned
log2
(unsigned v)¶
Public Static Attributes
-
unsigned
_debug_static_val
= 0¶
Protected Attributes
-
unsigned *
data_
= nullptr¶ Packed data array to be stored in memory,
data_ contains in packed form the variable indices and clause indices of the component ordered structure is
var var … clause clause …
clauses begin at clauses_ofs_
-
unsigned
hashkey_
= 0¶
-
mpz_class
model_count_
¶
-
unsigned
creation_time_
= 1¶
-
unsigned
length_solution_period_and_flags_
= 0¶
Protected Static Attributes
-
unsigned
_bits_per_clause
= 0¶ In the sharpSAT paper, bits per clause (m) is defined as:
m := {lg |cl(F)|}
It is the minimum number of bits per clause when packing is enabled.
The implementation is slightly different in the code. It is defined as:
m := {lg |cl(F)| + 1}
base_packed_component.cpp
Purpose: Defines the static variables and methods for the BasePackedComponent() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
unsigned
_bits_per_variable
= 0¶ In the sharpSAT paper, bits per variable (n) is defined as:
n := {lg |var(F)|}
It is the minimum number of bits per clause when packing is enabled.
The implementation is slightly different in the code. It is defined as:
n := {lg |var(F)| + 1}
-
unsigned
_bits_of_data_size
= 0¶
-
unsigned
_data_size_mask
= 0¶
-
unsigned
_variable_mask
= 0¶ Bit mask in the form of bits of 0b1 of length “n”
-
unsigned
_clause_mask
= 0¶ Bit mask in the form of bits of 0b1 of length “m”
-
const unsigned
_bits_per_block
= (sizeof(unsigned) << 3)¶ Equals 32 (= 4 * 8 bits)
sizeof(unsigned) = 4 Three left bit shifts equals 8
-
Template Class BitStuffer¶
- Defined in File base_packed_component.h
Class Documentation¶
-
template <class T>
classBitStuffer
¶ base_packed_component.h
Purpose: Defines the classes BitStuffer() and BasePackedComponent().
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley. Manages the data in a byte array. It shift the bits into the array of objects of type T.
- Template Parameters
T
: Generally the “unsigned” type.
Public Functions
-
BitStuffer
(T *data)¶
-
void
stuff
(const unsigned val, const unsigned num_bits_val)¶ Packs the specified signal “val” into the memory.
- Parameters
val
: Binary value to pack into memory.num_bits_val
: The expected bit length of val.
-
void
assert_size
(unsigned size)¶ Verify the specified size matches the actual contents of the BitStuff object.
- Parameters
size
: number of bytes between the data_start_ pointer and the end of the BitStuff managed area.
Class CachedAssignment¶
- Defined in File cached_assignment.h
Class Documentation¶
-
class
CachedAssignment
¶ Public Functions
-
CachedAssignment
()¶
-
void
Sort
()¶ Sort the list of literals for easier management.
-
void
IncreaseSize
(VariableIndex size_adder)¶ Increases the size of the literals list by the specified amount.
- Parameters
size_adder
: The amount the literals list will be increased.
-
const std::vector<VariableIndex>
vars
()¶ Add the specified literal to the list of literals in the cache assignment.
Builds a list of variables in the cached assignment.
- Parameters
lit
: New literal value. Variable List Extractor
- Return
- List of variable numbers in this assignment.
-
const VariableIndex
num_components
() const¶ Stores the total number of components that make up this cached assignment.
- Return
- Number of different components that make up this assignment.
-
const bool
empty
() const¶ An empty assignment has no associated components.
- Return
- true if the assignment is empty.
-
void
ProcessComponent
(const Component *comp, mpz_class model_count_and_assn)¶ Processes a cached component and incorporates its information into the cached assignment.
-
const std::vector<LiteralID> &
literals
() const¶ Accessor for the literals in the cached assignment.
- Return
- List of literals in the cached assignment.
-
const std::vector<VariableIndex> &
emancipated_vars
() const¶ Accessor for get the set of emancipated variabes in this cached assignment.
- Return
- Emancipated variables in the cached assignment.
-
void
clear
()¶ Resets the component and deletes all associated component assignment information including the number of components and the assigned literals.
-
Class ClauseHeader¶
- Defined in File structures.h
Class Component¶
- Defined in File component.h
Class Documentation¶
-
class
Component
¶ cacheable_component.h
Purpose: Defines the Component() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Public Functions
-
void
reserveSpace
(unsigned int num_variables, unsigned int num_clauses)¶ The size is increased by 2 because the objects are surrounded by two since the storage format is:
variables SENTINEL clauses SENTINEL
- Parameters
num_variables
: Number of variables in the componentnum_clauses
: Number of long (i.e., non-unary and non-binary) clauses in the component.
-
void
set_id
(CacheEntryID id)¶ Updates the component ID.
- Parameters
id
: New component ID
-
CacheEntryID
id
() const¶
-
void
addVar
(const VariableIndex var)¶
-
void
closeVariableData
()¶
-
void
addCl
(const ClauseIndex cl)¶
-
void
closeClauseData
()¶
-
std::vector<VariableIndex>::const_iterator
varsBegin
() const¶
-
std::vector<ClauseIndex>::const_iterator
clsBegin
() const¶
-
unsigned
num_variables
() const¶
-
unsigned
numLongClauses
() const¶
-
bool
empty
() const¶ Empty Component Checker
Checks whether this component has any variables or clauses.
- Return
- True if the component has at least one clause or component.
-
void
createAsDummyComponent
(unsigned max_var_id, unsigned max_clause_id)¶
-
void
clear
()¶
-
unsigned
clauses_ofs
() const¶ Accesor the clause offset number.
- Return
- Clause offset number in the data structure.
-
const std::vector<ComponentVarAndCls> &
getData
() const¶ Component Data Accessor
This function exposes the internal “data_” object of the component. It is not a copy so changes to this object would corrupt the component. Care should be taken when using it.
- Return
- Reference to the internal data of the component
Class ComponentArchetype¶
- Defined in File component_archetype.h
Class Documentation¶
-
class
ComponentArchetype
¶ Public Functions
-
ComponentArchetype
()¶
-
ComponentArchetype
(StackLevel &stack_level, Component &super_comp)¶
-
void
reInitialize
(StackLevel &stack_level, Component &super_comp)¶
-
StackLevel &
stack_level
()¶
-
void
setVar_in_sup_comp_unseen
(VariableIndex v)¶
-
void
setClause_in_sup_comp_unseen
(ClauseIndex cl)¶
-
void
setVar_nil
(VariableIndex v)¶
-
void
setClause_nil
(ClauseIndex cl)¶
-
void
setVar_seen
(VariableIndex v)¶
-
void
setClause_seen
(ClauseIndex cl)¶
-
void
setClause_seen
(ClauseIndex cl, bool all_lits_act)¶
-
void
setVar_in_other_comp
(VariableIndex v)¶
-
void
setClause_in_other_comp
(ClauseIndex cl)¶
-
bool
var_seen
(VariableIndex v) const¶
-
bool
clause_seen
(ClauseIndex cl) const¶
-
bool
clause_all_lits_active
(ClauseIndex cl)¶
-
void
setClause_all_lits_active
(ClauseIndex cl) const¶
-
bool
var_nil
(VariableIndex v) const¶
-
bool
clause_nil
(ClauseIndex cl) const¶
-
bool
var_unseen_in_sup_comp
(VariableIndex v) const¶
-
bool
clause_unseen_in_sup_comp
(ClauseIndex cl) const¶
-
bool
var_seen_in_peer_comp
(VariableIndex v) const¶
-
bool
clause_seen_in_peer_comp
(ClauseIndex cl) const¶
-
Class ComponentCache¶
- Defined in File component_cache.h
Class Documentation¶
-
class
ComponentCache
¶ component_cache.h
Purpose: Defines the ComponentCache() class for storing components in the cache.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley. Data structure that is used as the component cache for the number of solutions for different components.
Public Functions
-
ComponentCache
(DataAndStatistics &statistics, SolverConfiguration &config)¶ component_cache.cpp
Purpose: Defines methods for the ComponentCache() class for storing components in the cache.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
~ComponentCache
()¶
-
uint64_t
compute_byte_size_infrastructure
()¶ Rebuild the size of the cache infrastructure (in bytes) from scratch by computing the size of the individual component including:
- Size of the cache entry ID table (based on its capacity
- Size of the cacheable component area.
- Size of the cache entry slots used to store the list of free entries.
It also updates the statistics for the formula including the cache infrastructure bytes usage,
This is called when the cache entries are deleted.
- Return
- Size of the cache infrastructure.
-
const CacheableComponent &
entry_const
(const CacheEntryID id) const¶ Access a reference to an entry in the component cache. If the specified entry ID does not exist, the program will crash. This is the constant version of the function and is safe to use in assert statements.
- Return
- Reference to the specified cache entry ID.
- Parameters
id
: Cache entry identification number
-
CacheableComponent &
entry
(const CacheEntryID id)¶ Access a reference to an entry in the component cache. If the specified entry ID does not exist, the program will crash.
- Return
- Reference to the specified cache entry ID.
- Parameters
id
: Cache entry identification number
-
bool
hasEntry
(CacheEntryID id) const¶ Uses a cached component’s CacheEntryID to extract the components cached information.
- Return
- Cache entry for the specified component. Determines whether the
- Return
- Parameters
comp
: Component to be extracted from the cache.
- Parameters
-
void
removeFromHashTable
(CacheEntryID id)¶ Removes the entry ID from the hash table but not from the entry base.
- Parameters
id
: Identification number of the cache entry.
-
void
cleanPollutionsInvolving
(CacheEntryID id)¶
-
CacheEntryID
storeAsEntry
(CacheableComponent &ccomp, CacheEntryID super_comp_id)¶
-
bool
manageNewComponent
(StackLevel &top, CacheableComponent &packed_comp, Component *unpacked_comp, CachedAssignment &cached_assn, CacheEntryID &cache_entry_id)¶ New Component Cache Checker
MT - Check quickly if the model count of the component is cached. If so, incorporate it into the model count of top If not, store the packed version of it in the entry_base of the cache
- Return
- True if the new component is in cache.
- Parameters
top
: Top of the literal decision stack.packed_comp
: New component to check whether it is in cache.cached_assn
: Cached assignment to be modified
-
void
eraseEntry
(CacheEntryID id)¶
-
void
storeValueOf
(CacheEntryID id, const mpz_class &model_count)¶ Stores the model count of the specified CacheEntryId item in the cache.
If may invoke a cache resize if the new entry cannot fit in the cache.
- Parameters
id
: ID number of the cache entry.model_count
: Number of models for the specified ID.
-
bool
deleteEntries
()¶ Purges old entries from the cache to get the cache size to roughly half of its current size.
It then rehashes the table and updates the cache size information.
- Return
- Always true.
-
void
removeFromDescendantsTree
(CacheEntryID id)¶
-
void
test_descendantstree_consistency
()¶
-
void
debug_dump_data
()¶
Class ComponentManager¶
- Defined in File component_management.h
Class Documentation¶
-
class
ComponentManager
¶ Public Functions
-
ComponentManager
(SolverConfiguration &config, DataAndStatistics &statistics, LiteralIndexedVector<TriValue> &lit_values)¶
-
void
initialize
(LiteralIndexedVector<Literal> &literals, std::vector<LiteralID> &lit_pool, bool quiet = false)¶ Initializes the cache, component stack, and component analyzer.
component_management.cpp
- Parameters
literals
: Set of valid literalslit_pool
:quiet
: Quiet parameter used to set whether console printing is enabled.
Purpose: Defines methods for the ComponentManagement() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
unsigned
scoreOf
(VariableIndex v)¶
-
void
cacheModelCountOf
(VariableIndex stack_comp_id, const mpz_class &value)¶ Cache Model Count Storer
If caching is enabled, this method stores the model count of the component onto the stack.
- Parameters
stack_comp_id
: Component ID of the stack elementvalue
: Model count of the element
-
void
cacheModelCountAndAssignment
(const VariableIndex stack_comp_id, const mpz_class &value, const SampleAssignment &assn, const Component &component)¶ Cache Model Count and Assignment Encoder and Storer
Prepend the component’s MPZ value with the sample assignment.
- Parameters
stack_comp_id
: Component ID of the stack element.value
: Model countassn
: Sample assignment to encode in the cache with the model count.component
: Actual component to get the variables.
-
Component &
superComponentOf
(StackLevel &lev)¶ Gets a pointer to the actual super component that corresponds to passed stack level.
- Return
- Pointer to the super component of the stack item.
- Parameters
lev
: Level in the stack whose super component will be extracted
-
const Component &
super_component
(StackLevel &lev) const¶ Const version of the superComponentOf() method.
- Return
- Pointer to the super component of the stack item.
- Parameters
lev
: Level in the stack whose super component will be extracted
-
VariableIndex
component_stack_size
() const¶ Extracts the number of components currently in the component stack.
- Return
- Number of element in teh component stack.
-
void
cleanRemainingComponentsOf
(StackLevel &top)¶
-
bool
findNextRemainingComponentOf
(StackLevel &top, const std::vector<LiteralID> &literal_stack, SamplesManager &samples)¶ Checks for the next yet to explore remaining component of top returns true if a non-trivial non-cached component has been found and is now stack_.TOS_NextComp() returns false if all components have been processed;
This function has been modified to support sampling. That includes passing the parameter “literal_stack”. This is neeeded to build samples.
- Return
- true if unprocessed components remain.
- Parameters
top
: Top of the decision stack.literal_stack_
: Current assigned literal stack.samples
: Current reservoir sample set.
-
void
recordRemainingCompsFor
(StackLevel &top, const std::vector<LiteralID> &literal_stack)¶ Examines the top of the decision stack. The function will try to decompose the component if applicable. For any new component, the function will check if the new components exists in the cache; if it does, the results are used to update the super component.
Otherwise, the new component is added to the component stack (not the decision stack). The end of unprocessed components is also updated.
Component at the top of the stack is analyzed. If a new and unseen component has never been seen, then the new component is placed on the component stack.
- Parameters
top
: Element at the top of the decision stack.literal_stack
: Current assigned literal stack.
The component stack is then sorted so components with fewer variables are at the top of the stack.
- Parameters
top
: Element at the top of the decision stack.literal_stack_
: Current assigned literal stack.
-
void
buildResidualComponent
(StackLevel &top)¶ Build residual formula component. It uses the contents of the literal stack to decide how to construct remaining components.
- Parameters
top
: Element at the top of the decision stack.
-
Component *
top_stack
()¶ Accessor for the top of the component stack.
- Return
- Pointer to the component on top of the component stack.
-
void
sortComponentStackRange
(unsigned long start, unsigned long end)¶ Sorts the components stack from start (inclusive) to end (exclusive). The components with more variables are placed lower on the stack (i.e., further from the top) and processed later.
- Parameters
start
: Start of component stack to be sorted (inclusive)end
: End of the component stack to sort (exclusive)
-
void
gatherStatistics
()¶
-
void
removeAllCachePollutionsOf
(StackLevel &top)¶
-
std::vector<VariableIndex>
buildFreedVariableList
(const StackLevel &top, const std::vector<LiteralID> &literal_stack)¶ Freed Variable List Builder
When assigning variables in a formula it is common that some variables become free (i.e., no longer appear in any of the clauses). These free variables will not appear on the literal stack but must be tracked to create the sample. This function stores all such freed variables.
- Return
- Vector of the variable indexes of all freed variables
- Parameters
literal_stack
: Current literal stack
-
Class DataAndStatistics¶
- Defined in File statistics.h
Class Documentation¶
-
class
DataAndStatistics
¶ statistics.h
Purpose: Defines the DataAndStatistics() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Public Functions
-
DataAndStatistics
()¶
-
void
UpdateNodeTypeStatistics
(TopTreeNodeType node_type, const mpz_class &num_models)¶ Updates the number of nodes and total model count based on the top tree node type.
- Parameters
node_type
: Type of top tree nodenum_models
: Number of new models for the specified node type.
-
TreeNodeIndex
num_tree_nodes
(TopTreeNodeType node_type)¶ Accesor for the number of top tree nodes of a specified type.
- Return
- Total number of top tree nodes of the specified type.
- Parameters
node_type
: Type of top tree node.
-
mpz_class
num_tree_node_models
(TopTreeNodeType node_type)¶ Accessor for the total number of models associated with a specified type of top tree node.
- Return
- Total number of models associated with the specific top tree node type.
- Parameters
node_type
: Type of top tree node.
-
double
percent_tree_node_models
(TopTreeNodeType node_type)¶ Calculates the percentage of all models that are of a specific type.
- Return
- Percent of all models that fall under the specified node type
- Parameters
node_type
: Type of top tree node (e.g., cylinder, max depth, component split, etc.)
-
void
reset_statistics
()¶
-
bool
cache_full
() const¶ Checks whether the cache is full (i.e., exceeds 100% capacity).
- Return
- true if the cache is full and false otherwise.
-
uint64_t
cache_bytes_memory_usage
() const¶ - Return
- Sum of the infrastructure bytes and the sized of the cached components.
-
uint64_t
overall_cache_bytes_memory_stored
()¶
-
void
incorporate_cache_store
(CacheableComponent &ccomp)¶
-
void
incorporate_cache_erase
(CacheableComponent &ccomp)¶
-
void
incorporate_cache_hit
(CacheableComponent &ccomp)¶
-
unsigned long
cache_MB_memory_usage
()¶
-
double
implicitBCP_miss_rate
()¶
-
unsigned long
num_clauses
() const¶
-
unsigned long
num_conflict_clauses
()¶
-
unsigned long
clause_deletion_interval
()¶
-
void
set_final_solution_count
(const mpz_class &count)¶ Updates the solver field “final_solution_count_” with the solution count multiplied by 2^{#unused variables}. Hence:
final_solution_count_ = count * 2^(num_variables_ - num_used_variables_)
- Parameters
count
: model count.
-
const mpz_class &
final_solution_count
() const¶ Accessor for the final solution count
- Return
- Final solution count.
-
void
printShort
()¶ statistics.cpp
Purpose: Defines methods for the DataAndStatistics() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
void
printShortFormulaInfo
()¶ Prints to the console information about the formula including: number of long, binary, & unit clauses, number of used variables, and total number of variables.
-
unsigned long
getTime
() const¶ Number of decisions (i.e., branch variable selections) made. This is used for determining when to remove components from the cache.
- Return
- Number of branch variable selections
-
long double
getAvgComponentSize
()¶
-
unsigned long
cached_component_count
()¶ Access the number of components in the cache.
- Return
-
unsigned long
cache_hits
()¶ Number of cache look-ups where the component requested was in the cache.
- Return
- Cache look-up count.
-
double
cache_miss_rate
()¶ The rate of cache look-ups where the requested component was not in the cache.
- Return
- 0 if a cache look-up never occurred. Otherwise, it is the number of caches misses divided by the total number of cache look-ups.
-
long double
getAvgCacheHitSize
()¶ The average size of a reused (i.e., hit) components in the cache.
- Return
- 0 if a cache hit has never occurred. Otherwise, it is the average size of cached components that have ever been HIT.
Public Members
-
std::string
input_file_
¶ Path to the file containing the CNF formula used in the current run.
-
time_t
start_time_
¶
-
uint64_t
maximum_cache_size_bytes_
= 0¶
-
SolverExitState
exit_state_
= SolverExitState::NO_STATE¶
-
VariableIndex
num_original_variables_
= 0¶
-
ClauseIndex
num_original_clauses_
= 0¶
-
ClauseIndex
num_original_binary_clauses_
= 0¶
-
ClauseIndex
num_original_unit_clauses_
= 0¶
-
VariableIndex
num_variables_
= 0¶ number of variables remaining
-
VariableIndex
num_used_variables_
= 0¶ Number of variables that actually occurs in clauses
-
VariableIndex
num_free_variables_
= 0¶ Number of variables that do not appear in any clause.
-
VariableIndex
num_indep_support_variables_
= 0¶ Number of variables in the independent support.
-
ClauseIndex
num_long_clauses_
= 0¶ Number of long clauses (i.e., greater than 3 unique literals) after pre-processing.
-
ClauseIndex
num_binary_clauses_
= 0¶ Number of binary clauses after pre-processing.
-
ClauseIndex
num_long_conflict_clauses_
= 0¶
-
ClauseIndex
num_binary_conflict_clauses_
= 0¶
-
ClauseIndex
times_conflict_clauses_cleaned_
= 0¶
-
ClauseIndex
num_unit_clauses_
= 0¶
-
uint64_t
num_decisions_
= 0¶ number of all decisions made - MT
Number of times a branch variable is set. It does not include BCP variable setting.
-
uint64_t
num_failed_literals_detected_
= 0¶ Number of all failed literal detected.
-
uint64_t
num_failed_literal_tests_
= 0¶
-
uint64_t
num_conflicts_
= 0¶ Number of all conflicts encountered.
-
uint64_t
num_clauses_learned_
= 0¶
-
VariableIndex
max_component_split_depth_
= 0¶ Maximum number of embedded components splits.
-
VariableIndex
max_branch_var_depth_
= 0¶ Maximum depth of branch variable setting. This excludes variables implied via UP or implied BCP.
-
TreeNodeIndex
num_top_tree_nodes_
= 0¶ Number of top tree nodes observed.
-
TreeNodeIndex
num_tree_nodes_by_type_
[static_cast<long>(NUM_TREE_NODE_TYPES
)]¶ Number of nodes of each of the top tree node types
-
mpz_class
num_models_by_tree_node_type_
[static_cast<long>(NUM_TREE_NODE_TYPES
)]¶ Number of models for each of the top tree node types.
-
uint64_t
num_cache_hits_
= 0¶
-
uint64_t
num_cache_look_ups_
= 0¶
-
uint64_t
sum_cache_hit_sizes_
= 0¶
-
uint64_t
num_cached_components_
= 0¶
-
uint64_t
sum_size_cached_components_
= 0¶
-
uint64_t
sum_bytes_cached_components_
= 0¶ Number of bytes occupied by all cached components.
-
uint64_t
overall_bytes_components_stored_
= 0¶
-
uint64_t
sum_bytes_pure_cached_component_data_
= 0¶
-
uint64_t
overall_bytes_pure_stored_component_data_
= 0¶
-
uint64_t
sys_overhead_sum_bytes_cached_components_
= 0¶
-
uint64_t
sys_overhead_overall_bytes_components_stored_
= 0¶
-
uint64_t
cache_infrastructure_bytes_memory_usage_
= 0¶
-
uint64_t
overall_num_cache_stores_
= 0¶
-
mpz_class
final_solution_count_
= 0¶
-
double
sampler_time_elapsed_
= DBL_MAX¶ Amount of time required to complete the full sampling.
-
double
sampler_pass_1_time_
= DBL_MAX¶ Amount of time required to complete phase 1 and build all partial assignments (or just the time required to collect a single sample when two pass is disabled).
-
double
sampler_pass_2_time_
= DBL_MAX¶ Time required to convert all partial assignments into complete assignments. This represents “pass 2” of the sampler.
-
std::vector<VariableIndex>
numb_second_pass_vars_
¶ When performing two pass testing, this records the number of variables that remain to be set at the start of the second pass for each sample.
Class DecisionStack¶
- Defined in File stack.h
Class Documentation¶
-
class
DecisionStack
: public std::vector<StackLevel>¶ Vector based decision stack. It is also used during implicit BCP (i.e., failed literal testing).
Public Functions
-
DecisionStack
()¶
-
void
startFailedLitTest
()¶ Sets a flag to begin implicit BCP
-
void
stopFailedLitTest
()¶ Sets a flag to halt implicit BCP.
-
StackLevel &
top
()¶ Accessor for the top of the decision stack.
- Return
- Top of the decision stack.
-
const StackLevel &
top_const
() const¶ Accessor for the top of the decision stack.
- Return
- Top of the decision stack.
-
StackLevel &
on_deck
()¶ Get the element below the top, making it on deck in baseball parlance (i.e., it would be up next after the top).
- Return
- One below the top of the stack.
-
DecisionLevel
get_decision_level
() const¶ Height of the decision stack. This represents “d” in CDCL.
If a failed literal test is underway, a failed literal is pushed onto the stack during testing.
- Return
- Height of the stack.
-
Class DifferencePackedComponent¶
- Defined in File difference_packed_component.h
Inheritance Relationships¶
public BasePackedComponent
(Class BasePackedComponent)
Class Documentation¶
-
class
DifferencePackedComponent
: public BasePackedComponent¶ difference_packed_component.h
Purpose: Defines the class DifferencePackedComponent().
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Template Class GenericCacheableComponent¶
- Defined in File cacheable_component.h
Class Documentation¶
-
template <class T_Component>
classGenericCacheableComponent
: public T_Component¶ Public Functions
-
GenericCacheableComponent
()¶
-
unsigned long
SizeInBytes
() const¶
-
unsigned long
sys_overhead_SizeInBytes
() const¶
-
void
set_father
(CacheEntryID f)¶
-
const CacheEntryID
father
() const¶
-
void
set_next_sibling
(CacheEntryID sibling)¶
-
CacheEntryID
next_sibling
()¶
-
void
set_first_descendant
(CacheEntryID descendant)¶
-
const CacheEntryID
first_descendant
() const¶
-
void
set_next_bucket_element
(CacheEntryID entry)¶
-
CacheEntryID
next_bucket_element
()¶
-
Class Instance¶
- Defined in File instance.h
Inheritance Relationships¶
public Solver
(Class Solver)
Class Documentation¶
-
class
Instance
¶ Subclassed by Solver
Protected Functions
-
Antecedent &
getAntecedent
(LiteralID lit)¶
-
const Antecedent &
antecedent
(LiteralID lit) const¶ Accessor the antecedent object. It is a constant alternative to the method getAntecedent(LiteralID).
-
bool
hasAntecedent
(LiteralID lit) const¶ Checks if the literal has an antecedent clause.
- Return
- True if the literal has an antecedent.
- Parameters
lit
: Literal identification object
-
bool
isolated
(VariableIndex v)¶
-
bool
free
(VariableIndex v)¶
-
bool
deleteConflictClauses
(bool delete_all = false)¶
-
void
compactConflictLiteralPool
()¶
-
void
compactClauses
()¶
-
void
compactVariables
()¶
-
void
cleanClause
(ClauseOfs cl_ofs)¶ instance.cpp
Purpose: Defines the methods for the Instance() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
unsigned long
num_conflict_clauses
() const¶
-
const VariableIndex
num_variables
() const¶ Number of variables in the formula.
- Return
- Size of the variables array
-
bool
createfromFile
(const std::string &file_name)¶ Reads the CNF formula from a file. It does minimal analysis of the clauses. It adds the clauses to the basic clause data structures including the occurence lists.
If there is a self contradictory clause, it may catch that failure but it is not guaranted.
- Return
- ”true” if the file was parsed and the formula properly built.
- Parameters
file_name
: Location of the CNF formula in a file
-
void
decayActivities
()¶ Decay the activity scores of the literal based on a regular decision frequency (128 decisions in the original code).
-
bool
isUnitClause
(const LiteralID lit)¶ Checks whether the specified literal is unit clause.
- Return
- True if the literal is a unit clause.
- Parameters
lit
: Literal identification object.
-
bool
existsUnitClauseOf
(VariableIndex v)¶ Checks whether a unit clause exists for the specified variable.
- Return
- true if the specified variable is in a unit clause.
- Parameters
v
: Variable identification number
-
void
ParseCnfCommentForSupport
(std::ifstream &input_file)¶ Parses a comment line in a DIMACs file to extract the independent support if it is present.
- Parameters
input_file
: Input file stream of a DIMACs file.
-
bool
addUnitClause
(const LiteralID lit)¶ Attempts to add a unit clause literal to the set of unit clauses.
If the unit clause (or its complement) already exists, the function merely returns and does nothing.
- Return
- True if the literal was added or already exists in the unit clause list A return of false implies the formula is UNSAT.
- Parameters
lit
: Unit clause literal
-
long
addClause
(std::vector<LiteralID> &literals)¶ Adds a clause (be it unit, binary, or long) to the set of clauses for the formula.
- Return
- Identification number of the clause. If there is an error adding the clause, it returns “INT_MIN” (i.e., the minimum integer value).
- Parameters
literals
: Set of literals in the clause
-
Antecedent
addUIPConflictClause
(std::vector<LiteralID> &literals)¶
-
Literal &
literal
(LiteralID lit)¶ Accessor to extract the specified literal.
- Return
- Literal with the specified ID
- Parameters
lit
: Identification number for a positive or negative literal.
-
bool
isActive
(LiteralID lit) const¶ - Return
- true if the variable is unset.
- Parameters
lit
: Literal ID number
-
decltype(literal_pool_.begin())
conflict_clauses_begin
()¶
-
ClauseHeader &
getHeaderOf
(ClauseOfs cl_ofs)¶
Protected Attributes
-
DataAndStatistics
statistics_
¶
-
std::vector<LiteralID>
literal_pool_
¶ literal_pool_: the literals of all clauses are stored here INVARIANT: first and last entries of literal_pool_ are a SENTINEL_LIT
Clauses begin with a ClauseHeader structure followed by the literals terminated by SENTINEL_LIT
-
unsigned long
original_lit_pool_size_
¶ this is to determine the starting offset of conflict clauses - MT
This contains the number of unique literals that appear in the original formula. It will be less than or equal to 2 * |variables_|
-
LiteralIndexedVector<Literal>
literals_
¶
-
LiteralIndexedVector<std::vector<ClauseOfs>>
occurrence_lists_
¶ Set of long clauses that the specified literal appears in.
-
LiteralIndexedVector<TriValue>
literal_values_
¶
-
std::vector<VariableIndex>
unused_vars_
¶ Stores the variable identification numbers of any variables that do not appear in a formula at all.
-
bool
has_independent_support_
= false¶ Stores whether the solver has an independent support. This is based on the contents of the CNF file.
-
std::vector<VariableIndex>
independent_support
¶ Variables that represent the independent support.
-
Antecedent &
Class Literal¶
- Defined in File structures.h
Class Documentation¶
-
class
Literal
¶ Reference class storing information on each literal (i.e., both positive and negative0. The primary information this tracks is:
- binary_links_ - Represents variables linked by binary clauses
- Watch List - Clauses associated with the two watch literals principle
Public Functions
-
void
increaseActivity
(unsigned u = 1)¶ Increase the literal’s supplied literals activity score by the specified amount.
- Parameters
u
: Amount to increase the literals activity score by. This should generally be a positive number.
-
void
resetActivity
()¶ Resets the literals activity score which represents how frequently it appears in a clause.
-
void
addWatchLinkTo
(ClauseIndex clause_ofs)¶ Associates the clause to be monitored with this literal.
- Parameters
clause_ofs
: Clause to be monitored
-
void
addBinLinkTo
(LiteralID lit)¶ Creates a link between the implicit literal and the explicitly supplied literal. This implies the two literals are in the same binary clause.
- Parameters
lit
: Other literal to be linked to.
-
void
resetWatchList
()¶ Resets the binary watch list for a literal. It removes all binary links from the literal to all binary clauses.
It does put the sentinel clause onto the stack.
-
bool
hasBinaryLinkTo
(LiteralID lit)¶ Checks if the implicit literal has a link to the explicitly supplied literal.
- Return
- true if the two literals appear in the same binary clause.
- Parameters
lit
: Other literal to check for a binary clause linkage to.
-
bool
hasBinaryLinks
()¶ Checks if the literal is associated with any binary links.
- Return
- True if there is at least one binary link.
Class LiteralID¶
- Defined in File structures.h
Class Documentation¶
-
class
LiteralID
¶ Public Functions
-
LiteralID
()¶ Initializes the literal to negated and ID 0.
-
LiteralID
(int lit)¶ Converts a literal number into a literal ID. The absolute value of the passed literal ID is the variable number. The sign represents whether the literal is negated or non-negated.
- Parameters
lit
: Literal ID with a negative number representing a negated literal
-
LiteralID
(VariableIndex var, bool sign)¶ Build a literal from the variable ID and a sign term.
- Parameters
var
: Variable identification number.sign
: true for a positive literal and false for a negative literal
-
VariableIndex
var
() const¶ Gets the variable identification number associated with the literal. It ignores the literal’s sign (i.e., negation/positive)
- Return
- Variable ID number
-
int
toInt
() const¶ Converts the literal into the form (sign)VariableNumber where sign is +/- depending whether the literal is negated.
- Return
- Signed version of the variable number.
-
void
inc
()¶ Increments the literal ID number. This may cause a negated literal to become positive or cause a positive literal’s ID to become the next negated literal.
-
void
copyRaw
(unsigned int v)¶ Sets the literal ID to the processed value. It does not process its integrity or correctness.
- Parameters
v
: New literal value
-
const bool
sign
() const¶ Returns whether the literal is positive or negated.
- Return
- True if the literal is positive (i.e., unnegated)
-
const LiteralID
neg
() const¶ Creates a literal that has the opposite sign as the current literal. For example, if the implicit literal is negated, this returns a positive/unnegated literal. If it is positive, this function returns a negated literal.
- Return
- LiteralID of this literal just negated.
-
void
print
() const¶
-
unsigned
raw
() const¶ Accesses the raw value of how the literal is stored in the data structure.
- Return
- Unmodified verison of the data structure value
-
Template Class LiteralIndexedVector¶
- Defined in File containers.h
Class Documentation¶
-
template <class _T>
classLiteralIndexedVector
: protected std::vector<_T>¶ containers.h
Purpose: Defines the LiteralIndexVector() class. This stores items and access them via literal identification numbers.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Public Functions
-
LiteralIndexedVector
(VariableIndex size = 0)¶ Creates a vector twice the specified size.
- Parameters
size
: Expected number of variables
-
LiteralIndexedVector
(VariableIndex size, const typename std::vector<_T>::value_type &__value)¶ Create a vector twice the specified size initialized to the specified value.
- Parameters
size
: Expected number of variables.__value
: Value to write into all locations in the vector
-
std::vector<_T>::iterator
begin
()¶ Creates an iterator that points to the first element in the vector.
- Return
- Iterator to first element
-
void
resize
(VariableIndex _size)¶ - Parameters
_size
: Expected number of variables.
-
void
resize
(VariableIndex _size, const typename std::vector<_T>::value_type &_value)¶ Resizes the vector to twice the specified size. If a value is specified, it sets all the elements to the specified value.
- Parameters
_size
:_value
:
-
void
reserve
(VariableIndex _size)¶
Class Random¶
- Defined in File rand_distributions.h
Class Documentation¶
-
class
Random
¶ rand_distributions.h
Purpose: Static class for getting randomly created objects from different distributions and of different types.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Unnamed Group
-
template <typename T>
static Tuniform
(T min, T max)¶ Generates a uniform random integer in the range [min, max].
- Return
- Uniform random integer across the full range of possible values.
- Parameters
min
: Minimum value that can be generated inclusive.max
: Maximum value that can be generated inclusively.
-
static int
uniform
(int min = INT_MIN, int max = INT_MAX)¶ Special int uniform random generator that can optionally avoid reinitialize the uniform int distribution generator.
Public Static Functions
-
static void
init
(SolverConfiguration *config)¶ Random State Initializer
Creates the random state of the program. It also seeds the random number generator.
- Parameters
config
: Solver configuration
-
static SampleSize
binom
(SampleSize n, double p)¶ Creates a random variable sampled from the distribution Binom(n,p)
- Return
- Integer random variable generated according to the binomial distribution.
- Parameters
n
: Number of Bernoulli trials in the binomial distributionp
: Probability of success.
-
template <typename ListType, typename CountType>
static voidDownsampleList
(CountType target_size, std::vector<ListType> &oversampled_vec, bool resize = true)¶ Using a modified version of the Fisher-Yates shuffle, the first
target_size
elements of the vectoroversampled_vec
will be selected uniformly at random. All modifications are done inplace. The running time is O(target_size
).- Template Parameters
ListType
: Type of the object in the oversampled vector.CountType
: Type of object used to store the counts.
- Parameters
oversampled_vec
: Vector with more elements than desired.target_size
elements will be selected in the first [0,target_size
) elements.target_size
: Number of objects to select inoversampled_vec
resize
: True to resizeoversampled_vec
to the sizetarget_count
.
-
template <typename T>
static voidshuffle
(std::vector<T> &vec)¶ Shuffles the specified vector in place uniformly at random.
- Template Parameters
T
: Vector element type
- Parameters
vec
: Vector to be shuffled.
-
static void
SelectRangeInts
(SampleSize max_id, SampleSize num_elements, std::vector<SampleSize> &samples_to_replace)¶ Builds a randomly selected list of integers in the range [0,
max_id
).This is performed WITHOUT replacement. Its running time is Theta(
max_id
)- Parameters
max_id
: Maximum value (exclusive) that any integer in the range can be.num_elements
: Number of elements to be selectedsamples_to_replace
: List of p num_elements randomly selected integers in the range [0,max_id
).
-
template <typename T>
static voidshuffle
(typename std::vector<T>::iterator begin, typename std::vector<T>::iterator end)¶ Shuffles a vector using the standad random device.
- Template Parameters
T
: Type contained in the vector
- Parameters
begin
: Beginning of the vector to shuffle (inclusive)end
: End of the vector to shuffle (exclusive)
-
class
Mpz
¶ Public Static Functions
-
static void
uniform
(mpz_class max_z, mpz_class &rand_val)¶ Generates and returns a random multiprecision integer. This may be used by other classes to consolidate the random MP generation.
- Parameters
max_z
: Maximum integer value. All generated random values will be in the range [0, max_z).rand_val
: Output value where the generated random number will be stored.
-
static SampleSize
binom
(SampleSize n, const mpz_class &t, const mpz_class &a)¶ Selects a binomially distributed random variable from Binom(n, a/t).
It may an approximate or exact version of the distribution depending on the state of the variable Random::Mpz::use_approx_binom_.
- Return
- Integer random variable generated according to the binomial distribution.
- Parameters
n
: Number of Bernoulli trials in the binomial distributiont
: Total weight of all samplesa
: Weight of success.
-
static void
Class Random::Mpz¶
- Defined in File rand_distributions.h
Nested Relationships¶
This class is a nested type of Class Random.
Class Documentation¶
-
class
Mpz
Public Static Functions
-
static void
uniform
(mpz_class max_z, mpz_class &rand_val) Generates and returns a random multiprecision integer. This may be used by other classes to consolidate the random MP generation.
- Parameters
max_z
: Maximum integer value. All generated random values will be in the range [0, max_z).rand_val
: Output value where the generated random number will be stored.
-
static SampleSize
binom
(SampleSize n, const mpz_class &t, const mpz_class &a) Selects a binomially distributed random variable from Binom(n, a/t).
It may an approximate or exact version of the distribution depending on the state of the variable Random::Mpz::use_approx_binom_.
- Return
- Integer random variable generated according to the binomial distribution.
- Parameters
n
: Number of Bernoulli trials in the binomial distributiont
: Total weight of all samplesa
: Weight of success.
-
static void
Class SampleAssignment¶
- Defined in File model_sampler.h
Class Documentation¶
-
class
SampleAssignment
¶ Public Functions
-
SampleAssignment
(SampleSize sample_count)¶ Creates a blank assignment with all variables unset.
- Parameters
sample_count
: Number of samples this sample will represent.
-
SampleAssignment
()¶ Empty constructor with zero samples. It is not valid for general use.
-
std::string
ToString
() const¶ Converts the sample to a string,
- Return
- String representation of the sample.
-
const AssignmentEncoding
var_assignment
(const VariableIndex &var) const¶ Variable Assignment Accessor.
Extracts the value of a single variable from the partial assignment
- Return
- Value of the specified value number
- Parameters
var
: Identification number of the variable from 1 to num_var
-
void
GetPartialAssignment
(PartialAssignment &all_vars) const¶ Extracts the current assignment in vector form.
- Return
- Assignment as a vector
-
void
setVarAssignment
(const VariableIndex var, const AssignmentEncoding &val)¶ Variable Value Setter
Modifies the bit values for a specific variable.
-
const bool
IsComplete
() const¶ Complete Assignment Checker
Determines whether the sample model is partial or complete.
- Return
- true if the sample model is a complete assignment.
-
const SampleSize
sample_count
() const¶ Complete Assignment Checker
Determines whether the sample model is partial or complete.
- Return
- true if the sample model is a complete assignment. Accessor for the number of cached component IDs in this object.
- Return
- Number of cached component IDs in this object Accessor for the number of samples in this object.
- Return
- Number of samples represented by the object.
-
const VariableIndex
num_set_vars
()¶ Accesor for the number of variables set in this assignment. Note that this does not include any emancipated variables since those are free and not set.
- Return
- Number of variables set in this assignment.
-
const VariableIndex
num_set_vars_const
() const¶ Accessor for the number of variables set in this assignment. Note that this does not include any emancipated variables since those are free and not set.
- Return
- Number of variables set in this assignment.
-
const VariableIndex
num_unset_vars
()¶ Updates the assignment of the implicit assignment with that of the specified one. It does NOT update the sample count
- Return
- Number of unset unemancipated variables.
- Parameters
other
: Another SampleAssignment. Gets the number of remaining variables that are unset. This does NOT include emancipated variables.
-
const bool
IsVarEmancipated
(VariableIndex var) const¶ Builds and returns the set of unconstrained variables in this sample.
- Return
- Identification number of the unset variables. Checks if the specified variable is emancipated.
- Return
- True if the variable is emancipated.
- Parameters
var
: Variable identification number
-
const std::vector<CacheEntryID> &
cache_comp_ids
() const¶ Cached component ID accessor.
- Return
- All cached components identification numbers in this object.
-
void
clear_cache_comp_ids
()¶ Clears all stored cached component IDs. There is generally not a reason to call this function outside of when filling a partial assignment. Care should be taken when using this function.
Public Static Functions
-
static void
set_num_var
(const VariableIndex num_var)¶ Defines the number of variables in the Boolean formula. This is used to encode the recipe.
The number of variables dictates the size of the
- Parameters
num_var
: Number of variables in the equation.
-
Class SamplesManager¶
- Defined in File model_sampler.h
Class Documentation¶
-
class
SamplesManager
¶ Public Functions
-
SamplesManager
(SampleSize num_samples, SolverConfiguration &config)¶ Initialize the sample manager. It creates complete blank samples.
-
void
exportFinal
(std::ostream &out, const DataAndStatistics &statistics, const SolverConfiguration &config)¶ Copy constructor. Equality operator.
Exports the set of samples to an output stream. This can be either a file or to the console.
- Return
- Reference to the new SamplesManager created. This allows for chaining equality operators. Sample Exporter
- Parameters
other
: Object to which the implicit object will be set.
- Parameters
output_file_path
: Path for export filestatistics
: CNF and runtime statistics structure.config
: Solver configuration
-
void
reservoirSample
(const Component *active_comp, const std::vector<LiteralID> &literal_stack, const mpz_class &solution_weight, const mpz_class &weight_multiplier, const AltComponentAnalyzer &ana, VariableIndex literal_stack_ofs, const std::vector<VariableIndex> &freed_vars, const std::vector<CacheEntryID> &cached_comp_ids, const CachedAssignment &cached_assn, SampleAssignment &cached_sample)¶ Performs reservoir sampling
- Parameters
active_comp
: Currently active component.literal_stack
: Current assigned literal stacksample_weight
: Weight of the current set of samples to assign.
-
void
GenerateSamplesToReplace
(const mpz_class &new_sample_weight, std::vector<SampleSize> &samples_to_replace) const¶ Sample Replacement List Generator
Builds a list of the samples that will be replaced from the assignment collection. The selection of whether a sample will be replaced is based off their relative weighting of their sample counts.
- Parameters
new_sample_weight
: Model count weight for the new samples.samples_to_replace
: Contains the indices of the samples in the list that will be replaced.
-
void
stitch
(SamplesManager &other)¶ Sample Variable Assignment Accessor
Gets the value of the variable assignment for a specific sample in the list of samples
Debug function.
Stitches together to sample managers. This is used when combining the results after a component split.
- Return
- Variable’s assigned value. Samples Manager Stitcher
- Parameters
sample_num
: Sample number between 0 (inclusive) and num_samples (exclusive)var
: Variable number
- Parameters
other
: Component split to be merged with.
-
void
StitchShuffledArray
(SamplesManager &other)¶ Perform stitching permutation generation by creating a vector of size tot_num_samples_ (|S|) and shuffling it via a Fisher-Yates shuffle which has running time Theta(|S|).
- Parameters
other
: SamplesManager that will be stitched to the implicit SamplesManager.
-
void
SplitAndStitch
(ListOfSamples::iterator &this_itr, ListOfSamples::iterator &other_itr, SampleSize &num_new_samples)¶ Splits the sample point to by
this_itr
. The new split sample hasnum_new_samples
. This new sample is then stitched with the sample pointed to byother_itr
. After performing the stitching, the sample count ofother_itr
is decreased bynum_new_samples
.Note: that if
num_new_samples
and the sample count ofthis_itr
are equal, the sample pointed to by this_itr is not split. All other steps proceed normally.- Parameters
this_itr
: Sample to be split and then merged.other_itr
: Object that will be stitched with the new split sample.num_new_samples
: Sample size for the new stitched object. It must be greater than zero and less than or equal to the sample count ofthis_itr
.
-
const bool
verifyPostStitchingCorrectness
(SamplesManager &other) const¶ Debug helper function to verify that post stitching, the number of samples is correct.
- Return
- True if the stitching appears correct.
- Parameters
other
: Set of samples that there were stitched to the implicit sample set.
-
void
merge
(SamplesManager &other, const mpz_class &other_multiplier, const std::vector<VariableIndex> &freed_vars, const std::vector<CacheEntryID> &cached_comp_ids, const CachedAssignment &cached_assn, SampleAssignment &cached_sample)¶ Samples Manager Merger
After a component split, a new descendant SamplesManager is created. This function will merge the existing SamplesManager with the original one before the component split.
- See
- other model count.
- Parameters
other
: Sample manager created for the descendants of the component split.other_multiplier
: Used to scale the model count of the
- Parameters
freed_vars
: List of emanicipated variables that can be set to either true or false.cached_assn
: Assignment stored in the cached that is used when storing samples in cache.cached_sample
: Sample output when performing sample caching. This will be used to update the top of the decision stack.
-
bool
VerifySolutions
(const std::string &input_file_path, bool skip_unassigned = false) const¶ Sample Verifier
Verifies that all samples generated by the program are valid and actually satisfies the input file. This is mostly for debug and should NEVER return false. If false is ever returned, something is wrong.
- Return
- true if all samples are valid.
- Parameters
input_file_path
: Path to a file in CNF formulaskip_unassigned
: If true, skip verification of all clauses with an unassigned literal.
-
const mpz_class &
model_count
() const¶ Model Count Extractor
Gets the current number of solutions tracked by the manager object
- Return
- Model count for the samples manager object
-
void
AddEmancipatedVars
(const std::vector<VariableIndex> &emancipated_vars)¶ Emancipated and Unused Variable Adder
Unused variables are any variables that do not appear at all in a given formula. This sets them at the end of the countSAT execution.
- Parameters
emancipated_vars
: List of the IDs of unused variables.
-
void
AddCachedCompIds
(const std::vector<CacheEntryID> &cached_comp_ids)¶ Adds the specified cached component identification numbers to all samples in the collection.
- Parameters
cached_comp_ids
: Cached component identification numbers for all samples.
-
void
TransferVariableAssignments
(ListOfSamples &others)¶ Transfers the variable assignments from a previous sampler run and uses them to update the implicit sample manager. This is done when filling a partial assignment since multiple samples with the same cached component are run together even if the rest of their partial assignment is different.
- Parameters
others
: Existing samples from a previous solver run.
-
ListOfSamples &
samples
()¶ Solver Configuration Storer
This function is used to store a reference to the solver’s configuration. This is useful in case any of the run parameters are used.
- Return
- Reference to the sample managers recipe assignments.
- Parameters
config
: Solver’s configuration. Accessor to a sample manager’s variable assignment.
-
bool
IsComplete
() const¶ Sample Setter
This function replaces the sample (based off the specified number) with the new model passed to the function.
- * Extracts a reference to the specified sample from the manager.
- *
- Parameters
sample_num
: Number of the sample to access - base 0
- *
- Return
- Sample at the specified number Checks whether all the samples in the set are complete.
- Return
- true if all contained samples are complete.
- Parameters
sample_num
: Sample number to be setnew_model
: New sample model to be stored Sample Accessor
-
void
append
(SamplesManager &other)¶ Adds the samples from one SamplesManager() to that of annother. This is different from merging and stitching as the implicit SamplesManager()’s samples remain unchanged. The only difference is the samples from
other
are appended to the collections of samples in the implicit parameter.- Parameters
other
: Another SampleManager() object whose samples will be copied to the implicit parameter.
-
void
append
(ListOfSamples &other)¶ Adds the samples from one SamplesManager() to that of annother. This is different from merging and stitching as the implicit SamplesManager()’s samples remain unchanged. The only difference is the samples from
other
are appended to the collections of samples in the implicit parameter.- Parameters
other
: A list of samples to add.
-
const SampleSize
num_samples
() const¶ Accessor for the number of samples actually stored by the SamplesManager() object.
- Return
- Number of samples actually stored by the SamplesManager().
-
void
RemoveSamples
(std::vector<SampleSize> &samples_to_remove)¶ Removes the samples specified at the indices in the
samples_to_remove
input.- Parameters
samples_to_remove
: Identification numbers of the samples to remove.
-
void
KeepSamples
(std::vector<SampleSize> &samples_to_keep)¶ Specifies which samples from this SampleManager should be kept. All others are discarded. This is used as a compliment to the RemoveSamples() function since when there is a merge, one set keeps samples and the other discards them.
- Parameters
samples_to_keep
: Identification number of the samples that will be kept.
-
const bool
verifySampleCount
() const¶ Verifies that the SampleManager actually has the number of samples it is supposed to.
- Return
- True if the sample count is correct.
-
const SampleSize
GetActualSampleCount
() const¶ Gets the actual number of samples that are contained in this manager. In MOST (but not all) cases, this should equal the expected number of samples. However, that is not necessarily the case in some rare but useful exceptions.
- Return
- Actual number of samples contained in this object.
-
void
clear
()¶ Eliminate all existing samples.
-
Class Solver¶
- Defined in File solver.h
Inheritance Relationships¶
public Instance
(Class Instance)
Class Documentation¶
-
class
Solver
: public Instance¶ Main object managing the execution of both the sampler and sharpSAT.
Public Functions
-
Solver
(int argc, char *argv[])¶ Constructs a Solver object from command line input arguments.
- Parameters
argc
: Number of arguments in the argv arrayargv
: Set of input arguments
-
Solver
(SolverConfiguration &config, DataAndStatistics &statistics, SampleSize num_samples = 0, bool two_pass = true)¶
-
Solver
(const Solver &other)¶ Copy constructor
- Parameters
other
: Another solver used as the basic of this solver.
-
void
solve
(const PartialAssignment &partial_assn = PartialAssignment())¶ Performs the main solver execution.
Additional features include printing timing and other notes during execution. Also writes the final results to an output
This solve method can override the stored input file with a custom specified one.
- Parameters
partial_assn
: Initial partial assignment.results_output_file
: Output file to write the results
-
void
sample_models
()¶ Selects uniformly at random a set of satisfying models from the satisfying set for the implicit Boolean formula.
-
const SolverConfiguration &
config
()¶ Accessor for the Solver’s configuration.
- Return
- Reference to the solver’s internal configuration object.
-
void
DisableTopTreeSampling
()¶ Modify the Solver()’s configuration to no longer perform top tree sampling.
-
const DataAndStatistics &
statistics
()¶ Accessor for the Solver()’s statistics information.
- Return
- Solver()’s statistics information.
-
void
PushNewSamplesManagerOnStack
()¶ Creates a new (i.e., empty) SamplesManager for the solver and pushes it onto the stack.
-
Class StackLevel¶
- Defined in File stack.h
Class Documentation¶
-
class
StackLevel
¶ stack.h
Purpose: Defines the StackLevel() class that encapsulates a single level in the decision stack. The decision stack itself is stored in the DecisionStack() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley. Represents a single level in the decision stack.
Public Functions
-
bool
hasUnprocessedComponents
() const¶
-
void
nextUnprocessedComponent
()¶ Mark the current unprocessed component as processed.
It does verify that at least one unprocessed component exists at this decision level.
This function does not return anything. Rather, the other code operates directly on the component stack and accesses the top of it via the
- See
- StackLevel:top() method.
-
void
resetRemainingComps
()¶ Mark all components in this decision level as processed.
-
const VariableIndex
super_component
() const¶
-
const VariableIndex
remaining_components_ofs
() const¶ MT - the start offset in the component stack for the remaining components in this decision level all remaining components can hence be found in
[remaining_components_ofs_, “nextLevel”.remaining_components_begin_)
- Return
- Level in the component stack of the first component for this decision level.
-
const VariableIndex
unprocessed_components_end
() const¶ One greater than the location in the component stack of unprocess components for the current decision level.
- Return
- One greater than the location in the component stack for unprocessed components for teh current point in the decision stack.
-
void
set_unprocessed_components_end
(VariableIndex end)¶ Update the location of the unprocessed component reference for this decision level.
- Parameters
end
: New location of the set of unprocessed components for this decision level.
-
StackLevel
()¶
-
StackLevel
(VariableIndex super_comp, VariableIndex lit_stack_ofs, ClauseOfs comp_stack_ofs)¶
-
VariableIndex
currentRemainingComponent
()¶ Access for the total number of remaining components across all decision levels not just the current one.
- Return
- Total number of remaining components
-
bool
isSecondBranch
()¶ Checks if the second (i.e., “true”) branch is now active.
- Return
- true if the second (“true”) branch is active.
-
void
changeBranch
()¶ Set the active branch (i.e., the one being searched to the positive branch.
-
bool
anotherCompProcessible
()¶ Checks if there is another processible component left. Lack of processible components could be due to either the branch being unsatisfiable or there being no processible components left
- Return
- true if a processible component remains.
-
VariableIndex
literal_stack_ofs
() const¶
-
void
includeSolution
(const mpz_class &solutions)¶ Updates the solution count. If no solution have been found, then the increase is additive. If at least one solution has already been found then the increase is multiplicative.
- Parameters
solutions
: Number of solutions to increase by.
-
void
includeSolutionSampleMultiplier
(const mpz_class &solutions)¶ Updates the multiplier for when doing solution sampling.
- Parameters
solutions
: Number of solutions to increase by.
-
void
includeSolution
(unsigned solutions)¶ Updates the solution count. If no solution have been found, then the increase is additive. If at least one solution has already been found then the increase is multiplicative.
- Parameters
solutions
: Number of solutions to increase by.
-
void
configureNewLevel
(const StackLevel &top, const DecisionLevel decision_level)¶ When variables become free in a residual formula (i.e., they no longer appear in any clauses), the solution count multiplier is stored. This needs to be pushed down the stack to ensure that the sample weights are correct.
This function pushes the current scalar multiplier down the stack.
- Parameters
top
: Current top of the decision stack.decision_level
: Number of branch variables already assigned. This does not include any implicit partial assignment.
-
void
addFreeVariables
(const std::vector<VariableIndex> &freed_vars)¶ Freed Variables Adder
When performing variable assignments, it is common that variables will become free (i.e., no longer appear in any clauses). Those variables will not appear in the literal stack since they are not set. However, they must be assigned as part of the sample generator. This function stores those freed variables.
- Parameters
freed_vars
: Newly freed variables
-
void
addCachedCompIds
(const std::vector<CacheEntryID> &ids)¶ Store the component IDs for the cached components.
- Parameters
ids
: List of cached entry identification numbers
-
bool
branch_found_unsat
() const¶ Checks if the currently active branch variable has been determined to be unsatisfiable.
- Return
- true if the currently active branch is unsatisfiable.
-
void
mark_branch_unsat
()¶ Sets the currently active branch to being unsatisfiable.
-
const mpz_class
getTotalModelCount
() const¶ Total number (i.e., sum of false and true) branches of this literal decision in the subtree.
- Return
- Total model count for both the positive and negative subtrees.
-
const mpz_class &
getActiveModelCount
() const¶ Gets the model count for the active branch. If the active branch is false, it will return the model count for negated version of the literal. Otherwise, it return the positive (unnegated) model count.
- Return
- Model count for the currently active literal state.
-
const mpz_class &
getSamplerSolutionMultiplier
() const¶ Gets the multiplier count for when running the solution sampler. It is used for the case when variables become free due to the residual formula no longer containing them.
- Return
- Solution count multiplier for the sampler.
-
const bool
HasNoDescendentModels
()¶ Calculates the total descendent model count for this stack level. It is equal to:
FalseModelCount * FalseCountMultiplier + TrueModelCount * TrueCountMultiplier
- Return
- Total descendent model count. Checks whether the associated decision level has any descendent models.
- Return
- True if both the true and false descendents are UNSAT.
-
const std::vector<VariableIndex> &
emancipated_vars
() const¶ Emancipated Variable List Accessor
This function is used to access the freed variable list for a specific variable branch. This is used for variable assignments.
- Return
- List of freed variables for the specified active branch.
-
const std::vector<CacheEntryID> &
cached_comp_ids
() const¶ Cached Component ID List Accessor
This function accesses the cached entry identification numbers for this stack level.
- Return
- Cached component IDs
-
const bool
isComponentSplit
() const¶ Component Split State Accessor
Accessor for whether this stack level corresponds with a component split.
It only applies when performing random sampling. Otherwise, it merely returns false.
- Return
- True if component split and random sampling is running.
-
void
setAsComponentSplit
()¶ Marks the decision level as a component split.
It only applies when performing random sampling.
-
void
unsetAsComponentSplit
()¶ Unmarks the decision level as a component split.
This function only has an effect when performing random sampling.
-
const bool
isFirstComponent
() const¶ Returns whether the first component in a component split has been processed. This is only relevant when performing random sampling.
- Return
- true if the first component has not been processed
-
void
markFirstComponentComplete
()¶ This is used for marking when the first component has been completed. We use this for sample stitching.
-
void
set_cached_assn
(CachedAssignment &cached_assn)¶ Cached Assignment Updater
Updates the cached assignment associated with this stack level.
- Parameters
cached_assn
: Updates the cached assignment information for this StackLevel.
-
const CachedAssignment &
cached_assn
() const¶
-
void
ClearCachedAssn
()¶ Removes all information associated with the cached assignment including the number of components it contains as well as the assignment itself.
-
void
set_cache_sample
(const SampleAssignment &cache_sample)¶ Store the cache sample assignment. It will be automatically associated with the right active branch.
- Parameters
cache_sample
: Sample that will be used for caching this sample.
-
SampleAssignment
random_cache_sample
() const¶ Randomly select the cache sample between the two branches.
- Return
- A sample that can be stored in the cache for this stack level.
Public Static Functions
-
static VariableIndex
componentSplitDepth
()¶ Component Split Depth Accessor
Accesses the global component split depth information.
- Return
- Current component split depth.
-
static void
set_solver_config_and_statistics
(SolverConfiguration &config, DataAndStatistics &statistics)¶ Configuration Updater
Stores the solver configuration. This is used so that global configuration settings (e.g., verbose) can be used for printing.
- Parameters
config
: Solver configuration
Class StopWatch¶
- Defined in File solver.h
Class Documentation¶
-
class
StopWatch
¶ solver.h
Purpose: Primary function is to define the Solver() class which is what runs for the entire program. It also
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Public Functions
-
StopWatch
()¶ Used to track time events in the execution of the solver.
Built using the internal C++ timer (i.e., timeval()). Resolution down to microseconds via the “tv_usec” property.
solver.cpp
- See
- timeval
Purpose: Defines the methods for the Solver() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
-
bool
timeBoundBroken
()¶ Checks whether the time bound has been exceeded.
- Return
- true if the time bound has been exceeded.
-
bool
start
()¶
-
bool
stop
()¶ Records and saves the stop time independent of the time zone.
- Return
- 0 for success, or -1 for failure (in which case errno is set appropriately).
-
double
getElapsedSeconds
()¶
-
bool
interval_tick
()¶
-
void
setTimeBound
(uint64_t seconds)¶ Updates the stopwatch’s time bound.
- Parameters
seconds
: New time bound.
Enums¶
Enum SolverExitState¶
- Defined in File primitive_types.h
Enum Documentation¶
-
enum
SolverExitState
¶ Enumerated class the stores the result of a solver execution. It is returned by the Solver::countSAT method. It is also stored as part of the run statistics in
- See
- DataAndStatistics#
Values:
-
NO_STATE
¶
-
SUCCESS
¶
Enum SolverNextAction¶
- Defined in File primitive_types.h
Functions¶
Function ExitInvalidParam¶
- Defined in File sampler_tools.h
Function ExitWithError¶
- Defined in File sampler_tools.h
Function FileExists¶
- Defined in File sampler_tools.h
Function main¶
- Defined in File main.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “main” in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml
Function NOT_A_CLAUSE¶
- Defined in File primitive_types.h
Function Documentation¶
-
static const ClauseIndex NOT_A_CLAUSE(0)
Function NOT_A_LIT¶
- Defined in File structures.h
Function Documentation¶
-
static const LiteralID NOT_A_LIT(0, false)
Function PrintError()¶
- Defined in File sampler_tools.h
Function Documentation¶
Warning
doxygenfunction: Unable to resolve multiple matches for function “PrintError” with arguments () in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml. Potential matches:
- void PrintError(const std::string&)
- void PrintError(const std::stringstream&)
Function PrintError()¶
- Defined in File sampler_tools.h
Function Documentation¶
Warning
doxygenfunction: Unable to resolve multiple matches for function “PrintError” with arguments () in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml. Potential matches:
- void PrintError(const std::string&)
- void PrintError(const std::stringstream&)
Function PrintInColor()¶
- Defined in File sampler_tools.h
Function Documentation¶
Warning
doxygenfunction: Unable to resolve multiple matches for function “PrintInColor” with arguments () in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml. Potential matches:
- void PrintInColor(const std::string&, PrintColor, bool)
- void PrintInColor(const std::stringstream&, PrintColor, bool)
- void PrintInColor(std::ostream&, const std::string&, const PrintColor, bool)
- void PrintInColor(std::ostream&, const std::stringstream&, const PrintColor, bool)
Function PrintInColor()¶
- Defined in File sampler_tools.h
Function Documentation¶
Warning
doxygenfunction: Unable to resolve multiple matches for function “PrintInColor” with arguments () in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml. Potential matches:
- void PrintInColor(const std::string&, PrintColor, bool)
- void PrintInColor(const std::stringstream&, PrintColor, bool)
- void PrintInColor(std::ostream&, const std::string&, const PrintColor, bool)
- void PrintInColor(std::ostream&, const std::stringstream&, const PrintColor, bool)
Function PrintInColor()¶
- Defined in File sampler_tools.h
Function Documentation¶
Warning
doxygenfunction: Unable to resolve multiple matches for function “PrintInColor” with arguments () in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml. Potential matches:
- void PrintInColor(const std::string&, PrintColor, bool)
- void PrintInColor(const std::stringstream&, PrintColor, bool)
- void PrintInColor(std::ostream&, const std::string&, const PrintColor, bool)
- void PrintInColor(std::ostream&, const std::stringstream&, const PrintColor, bool)
Function PrintInColor()¶
- Defined in File sampler_tools.h
Function Documentation¶
Warning
doxygenfunction: Unable to resolve multiple matches for function “PrintInColor” with arguments () in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml. Potential matches:
- void PrintInColor(const std::string&, PrintColor, bool)
- void PrintInColor(const std::stringstream&, PrintColor, bool)
- void PrintInColor(std::ostream&, const std::string&, const PrintColor, bool)
- void PrintInColor(std::ostream&, const std::stringstream&, const PrintColor, bool)
Function printInputArgumentDescription¶
- Defined in File main.cpp
Function Documentation¶
Warning
doxygenfunction: Cannot find function “printInputArgumentDescription” in doxygen xml output for project “SPUR” from directory: ./doxyoutput/xml
Function PrintWarning¶
- Defined in File sampler_tools.h
Function UpdateVarDescedantsList(const std::vector<ComponentVarAndCls>&, VariableIndex, std::vector<bool>&, std::vector<ComponentVarAndCls>, VariableIndex)¶
- Defined in File component_management.cpp
Function Documentation¶
-
VariableIndex
UpdateVarDescedantsList
(const std::vector<ComponentVarAndCls> &ref_vars, VariableIndex ref_num_vars, std::vector<bool> &varInDescendants, std::vector<ComponentVarAndCls> descendant_vars, VariableIndex desc_num_vars)¶ Helper function for determining freed variables.
It goes through a list of variables and marks any that appears in the descendant list. If it is appears, then it is by definition not free.
- See
- ref_vars (exclusive)
- See
- ref_vars. This is a set of non-free vars.
- See
- descendant_vars (exclusive)
- Return
- Number of descendant elements marked as present
- Parameters
ref_vars
: Superset list of reference variables.ref_num_vars
: Number of variables in
- Parameters
varInDescendants
: One to one mapping of variables currently or previous marked as non-free. A variable should only ever be marked as non-free (i.e., true).descendant_vars
: Subset of
- Parameters
desc_num_vars
: Number of variables in
Function UpdateVarDescedantsList(const std::vector<ComponentVarAndCls>&, VariableIndex, std::vector<bool>&, std::vector<ComponentVarAndCls>, VariableIndex)¶
- Defined in File component_management.h
Function Documentation¶
-
VariableIndex
UpdateVarDescedantsList
(const std::vector<ComponentVarAndCls> &ref_vars, VariableIndex ref_num_vars, std::vector<bool> &varInDescendants, std::vector<ComponentVarAndCls> descendant_vars, VariableIndex desc_num_vars) Helper function for determining freed variables.
It goes through a list of variables and marks any that appears in the descendant list. If it is appears, then it is by definition not free.
- See
- ref_vars (exclusive)
- See
- ref_vars. This is a set of non-free vars.
- See
- descendant_vars (exclusive)
- Return
- Number of descendant elements marked as present
- Parameters
ref_vars
: Superset list of reference variables.ref_num_vars
: Number of variables in
- Parameters
varInDescendants
: One to one mapping of variables currently or previous marked as non-free. A variable should only ever be marked as non-free (i.e., true).descendant_vars
: Subset of
- Parameters
desc_num_vars
: Number of variables in
Defines¶
Define CA_CL_ALL_LITS_ACTIVE¶
- Defined in File component_archetype.h
Define CA_CL_IN_OTHER_COMP¶
- Defined in File component_archetype.h
Define CA_CL_IN_SUP_COMP_UNSEEN¶
- Defined in File component_archetype.h
Define CA_VAR_IN_OTHER_COMP¶
- Defined in File component_archetype.h
Define CA_VAR_IN_SUP_COMP_UNSEEN¶
- Defined in File component_archetype.h
Define CACHED_VARIABLE_LEN¶
- Defined in File cached_assignment.h
Define Documentation¶
-
CACHED_VARIABLE_LEN
¶ cached_assignment.h
Purpose: Stores a variable assignment retrieved from the cache.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Define CLAUSE_ADDING_ERROR¶
- Defined in File instance.h
Define Documentation¶
-
CLAUSE_ADDING_ERROR
¶ instance.h
Purpose: Defines the “Instance()” class that is the superclass of the main “Solver()” class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Define ESCAPE_CHAR¶
- Defined in File sampler_tools.h
Define Documentation¶
-
ESCAPE_CHAR
¶ sampler_tools.h
Purpose: Contains generic helper functions used by the solver.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Define F_TRI¶
- Defined in File structures.h
Define FILE_PATH_SEPARATOR¶
- Defined in File sampler_tools.h
Define INVALID_DL¶
- Defined in File structures.h
Define Documentation¶
-
INVALID_DL
¶ structures.h
Purpose: Defines a set of classes originally created by Marc Thurley include LiteralID, Literal, Antecedent, Variable, and ClauseHeader.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Define RESET_CONSOLE_COLOR¶
- Defined in File sampler_tools.h
Define T_TRI¶
- Defined in File structures.h
Define varsSENTINEL¶
- Defined in File primitive_types.h
Define Documentation¶
-
varsSENTINEL
¶ primitive_type.h
Purpose: Base class and type definitions used throughout this project.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Define X_TRI¶
- Defined in File structures.h
Typedefs¶
Typedef AssignmentContainer¶
- Defined in File model_sampler.h
Typedef Documentation¶
-
typedef std::vector<uint32_t>
AssignmentContainer
¶ model_sampler.h
Purpose: Classes for storing and managing partial and complete SAT assignments.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley. Defines the encoding for variable states in the assignment.
Typedef CA_SearchState¶
- Defined in File component_archetype.h
Typedef Documentation¶
-
typedef unsigned char
CA_SearchState
¶ component_archetype.h
Purpose: Defines the ComponentArchetype() class.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Typedef CacheableComponent¶
- Defined in File cacheable_component.h
Typedef Documentation¶
-
typedef GenericCacheableComponent<DifferencePackedComponent>
CacheableComponent
¶
Typedef CacheEntryID¶
- Defined in File primitive_types.h
Typedef ClauseIndex¶
- Defined in File primitive_types.h
Typedef Documentation¶
-
typedef VariableIndex
ClauseIndex
¶ Identification number for clauses.
Typedef ClauseOfs¶
- Defined in File primitive_types.h
Typedef Documentation¶
-
typedef VariableIndex
ClauseOfs
¶ Unsigned Int.
Typedef ComponentAnalyzer¶
- Defined in File component_management.h
Typedef Documentation¶
-
typedef AltComponentAnalyzer
ComponentAnalyzer
¶ component_management.h
Purpose: Defines the ComponentManager() class for managing the Boolean formula components.
Copyright (C) 2018 Zayd Hammoudeh. All rights reserved.
- Author
- Zayd Hammoudeh zayd@ucsc.edu
- Version
- 0.00.00
This software may be modified and distributed under the terms of the MIT license. See the LICENSE file for details.
Original Author: Marc Thurley.
Typedef ComponentVarAndCls¶
- Defined in File primitive_types.h
Typedef Documentation¶
-
typedef VariableIndex
ComponentVarAndCls
¶
Typedef DecisionLevel¶
- Defined in File primitive_types.h
Typedef ListOfSamples¶
- Defined in File model_sampler.h
Typedef Documentation¶
-
typedef std::list<SampleAssignment>
ListOfSamples
¶
Typedef PartialAssignment¶
- Defined in File primitive_types.h
Typedef Documentation¶
-
typedef std::vector<AssignmentEncoding>
PartialAssignment
¶
Typedef SampleSize¶
- Defined in File primitive_types.h
Typedef TopTreeLiteral¶
- Defined in File primitive_types.h
Typedef TreeNodeIndex¶
- Defined in File primitive_types.h
Typedef TriValue¶
- Defined in File structures.h
Typedef VariableIndex¶
- Defined in File primitive_types.h
Directories¶
Directory src¶
Directory path: src
Subdirectories¶
Files¶
- File alt_component_analyzer.cpp
- File alt_component_analyzer.h
- File cached_assignment.h
- File component_cache.cpp
- File component_cache.h
- File component_cache.inc
- File component_management.cpp
- File component_management.h
- File containers.h
- File instance.cpp
- File instance.h
- File main.cpp
- File model_sampler.cpp
- File model_sampler.h
- File primitive_types.h
- File rand_distributions.cpp
- File rand_distributions.h
- File sampler_tools.h
- File solver.cpp
- File solver.h
- File solver_config.h
- File stack.cpp
- File stack.h
- File statistics.cpp
- File statistics.h
- File structures.h
Files¶
File alt_component_analyzer.cpp¶
↰ Parent directory (src
)
Definition (src/alt_component_analyzer.cpp
)¶
↰ Return to documentation for file (src/alt_component_analyzer.cpp
)
#include "stack.h"
#include "alt_component_analyzer.h"
void AltComponentAnalyzer::initialize(LiteralIndexedVector<Literal> & literals,
std::vector<LiteralID> &lit_pool) {
max_variable_id_ = literals.end_lit().var() - 1;
search_stack_.reserve(max_variable_id_ + 1);
var_frequency_scores_.resize(max_variable_id_ + 1, 0);
variable_occurrence_lists_pool_.clear();
variable_link_list_offsets_.clear();
variable_link_list_offsets_.resize(max_variable_id_ + 1, 0);
std::vector<std::vector<ClauseOfs> > occs(max_variable_id_ + 1);
std::vector<std::vector<unsigned> > occ_long_clauses(max_variable_id_ + 1);
std::vector<std::vector<unsigned> > occ_ternary_clauses(max_variable_id_ + 1);
std::vector<unsigned> tmp;
max_clause_id_ = 0;
unsigned curr_clause_length = 0;
auto it_curr_cl_st = lit_pool.begin();
for (auto it_lit = lit_pool.begin(); it_lit < lit_pool.end(); it_lit++) {
if (*it_lit == SENTINEL_LIT) {
if (it_lit + 1 == lit_pool.end())
break;
max_clause_id_++;
it_lit += ClauseHeader::overheadInLits();
it_curr_cl_st = it_lit + 1;
curr_clause_length = 0;
} else {
assert(it_lit->var() <= max_variable_id_);
curr_clause_length++;
getClause(tmp, it_curr_cl_st, *it_lit);
assert(tmp.size() > 1);
if (tmp.size() == 2) {
// if (false) {
occ_ternary_clauses[it_lit->var()].push_back(max_clause_id_);
occ_ternary_clauses[it_lit->var()].insert(occ_ternary_clauses[it_lit->var()].end(),
tmp.begin(), tmp.end());
} else {
occs[it_lit->var()].push_back(max_clause_id_);
occs[it_lit->var()].push_back(occ_long_clauses[it_lit->var()].size());
occ_long_clauses[it_lit->var()].insert(occ_long_clauses[it_lit->var()].end(),
tmp.begin(), tmp.end());
occ_long_clauses[it_lit->var()].push_back(SENTINEL_LIT.raw());
}
}
}
ComponentArchetype::initArrays(max_variable_id_, max_clause_id_);
// the unified link list
unified_variable_links_lists_pool_.clear();
unified_variable_links_lists_pool_.push_back(0);
unified_variable_links_lists_pool_.push_back(0);
for (unsigned v = 1; v < occs.size(); v++) {
// BEGIN data for binary clauses
variable_link_list_offsets_[v] = unified_variable_links_lists_pool_.size();
for (auto l : literals[LiteralID(v, false)].binary_links_)
if (l != SENTINEL_LIT)
unified_variable_links_lists_pool_.push_back(l.var());
for (auto l : literals[LiteralID(v, true)].binary_links_)
if (l != SENTINEL_LIT)
unified_variable_links_lists_pool_.push_back(l.var());
unified_variable_links_lists_pool_.push_back(0);
// BEGIN data for ternary clauses
unified_variable_links_lists_pool_.insert(
unified_variable_links_lists_pool_.end(),
occ_ternary_clauses[v].begin(),
occ_ternary_clauses[v].end());
unified_variable_links_lists_pool_.push_back(0);
// BEGIN data for long clauses
for (auto it = occs[v].begin(); it != occs[v].end(); it+=2) {
unified_variable_links_lists_pool_.push_back(*it);
unified_variable_links_lists_pool_.push_back(*(it + 1) +(occs[v].end() - it));
}
unified_variable_links_lists_pool_.push_back(0);
unified_variable_links_lists_pool_.insert(
unified_variable_links_lists_pool_.end(),
occ_long_clauses[v].begin(),
occ_long_clauses[v].end());
}
}
//void AltComponentAnalyzer::recordComponentOf(const VariableIndex var) {
//
// search_stack_.clear();
// setSeenAndStoreInSearchStack(var);
//
// for (auto vt = search_stack_.begin(); vt != search_stack_.end(); vt++) {
// //BEGIN traverse binary clauses
// assert(isActive(*vt));
// unsigned *p = beginOfLinkList(*vt);
// for (; *p; p++) {
// if (isUnseenAndActive(*p)) {
// setSeenAndStoreInSearchStack(*p);
// var_frequency_scores_[*p]++;
// var_frequency_scores_[*vt]++;
// }
// }
// //END traverse binary clauses
// auto s = p;
// for ( p++; *p ; p+=3) {
// }
// //END traverse ternary clauses
//
// for (p++; *p ; p +=2) {
// if (archetype_.clause_unseen_in_sup_comp(*p)) {
// LiteralID * pstart_cls = reinterpret_cast<LiteralID *>(p + 1 + *(p+1));
// searchClause(*vt,*p, pstart_cls);
// }
// }
//
// for ( s++; *s ; s+=3) {
// if (archetype_.clause_unseen_in_sup_comp(*s)) {
// LiteralID * pstart_cls = reinterpret_cast<LiteralID *>(s + 1);
// searchThreeClause(*vt,*s, pstart_cls);
// }
// }
// }
//}
void AltComponentAnalyzer::recordComponentOf(const VariableIndex var) {
search_stack_.clear();
setSeenAndStoreInSearchStack(var);
for (auto vt = search_stack_.begin(); vt != search_stack_.end(); vt++) {
// BEGIN traverse binary clauses
assert(isActive(*vt));
unsigned *p = beginOfLinkList(*vt);
for (; *p; p++) {
if (manageSearchOccurrenceOf(LiteralID(*p, true))) {
var_frequency_scores_[*p]++;
var_frequency_scores_[*vt]++;
}
}
// END traverse binary clauses
for (p++; *p ; p+=3) {
if (archetype_.clause_unseen_in_sup_comp(*p)) {
LiteralID litA = *reinterpret_cast<const LiteralID *>(p + 1);
LiteralID litB = *(reinterpret_cast<const LiteralID *>(p + 1) + 1);
if (isSatisfied(litA) || isSatisfied(litB)) {
archetype_.setClause_nil(*p);
} else {
var_frequency_scores_[*vt]++;
manageSearchOccurrenceAndScoreOf(litA);
manageSearchOccurrenceAndScoreOf(litB);
archetype_.setClause_seen(*p, isActive(litA) &
isActive(litB));
}
}
}
// END traverse ternary clauses
for (p++; *p ; p +=2)
if (archetype_.clause_unseen_in_sup_comp(*p))
searchClause(*vt, *p, reinterpret_cast<LiteralID *>(p + 1 + *(p+1)));
}
}
bool AltComponentAnalyzer::exploreRemainingCompOf(VariableIndex v) {
assert(archetype_.var_unseen_in_sup_comp(v));
recordComponentOf(v);
if (search_stack_.size() == 1) {
archetype_.stack_level().includeSolution(2);
archetype_.setVar_in_other_comp(v);
return false;
}
return true;
}
Includes¶
alt_component_analyzer.h
(File alt_component_analyzer.h)stack.h
(File stack.h)
File alt_component_analyzer.h¶
↰ Parent directory (src
)
Definition (src/alt_component_analyzer.h
)¶
↰ Return to documentation for file (src/alt_component_analyzer.h
)
#ifndef ALT_COMPONENT_ANALYZER_H_
#define ALT_COMPONENT_ANALYZER_H_
#include <gmpxx.h>
#include <vector>
#include <cmath>
#include "statistics.h"
#include "component_types/component.h"
#include "component_types/base_packed_component.h"
#include "component_types/component_archetype.h"
#include "containers.h"
class AltComponentAnalyzer {
public:
AltComponentAnalyzer(DataAndStatistics &statistics,
LiteralIndexedVector<TriValue> & lit_values) :
literal_values_(lit_values) {
}
const unsigned scoreOf(VariableIndex v) const {
return var_frequency_scores_[v];
}
ComponentArchetype ¤t_archetype() {
return archetype_;
}
void initialize(LiteralIndexedVector<Literal> & literals,
std::vector<LiteralID> &lit_pool);
bool isUnseenAndActive(VariableIndex v) {
assert(v <= max_variable_id_);
return archetype_.var_unseen_in_sup_comp(v);
}
// manages the literal whenever it occurs in component analysis
// returns true iff the underlying variable was unseen before
//
bool manageSearchOccurrenceOf(LiteralID lit) {
if (archetype_.var_unseen_in_sup_comp(lit.var())) {
search_stack_.push_back(lit.var());
archetype_.setVar_seen(lit.var());
return true;
}
return false;
}
bool manageSearchOccurrenceAndScoreOf(LiteralID lit) {
var_frequency_scores_[lit.var()]+= isActive(lit);
return manageSearchOccurrenceOf(lit);
}
void setSeenAndStoreInSearchStack(VariableIndex v) {
assert(isActive(v));
search_stack_.push_back(v);
archetype_.setVar_seen(v);
}
void setupAnalysisContext(StackLevel &top, Component & super_comp) {
archetype_.reInitialize(top, super_comp);
for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++)
if (isActive(*vt)) {
archetype_.setVar_in_sup_comp_unseen(*vt);
var_frequency_scores_[*vt] = 0;
}
for (auto itCl = super_comp.clsBegin(); *itCl != clsSENTINEL; itCl++)
archetype_.setClause_in_sup_comp_unseen(*itCl);
}
// returns true, iff the component found is non-trivial
bool exploreRemainingCompOf(VariableIndex v);
inline Component *makeComponentFromArcheType() {
return archetype_.makeComponentFromState(search_stack_.size());
}
unsigned max_clause_id() {
return max_clause_id_;
}
unsigned max_variable_id() {
return max_variable_id_;
}
ComponentArchetype &getArchetype() {
return archetype_;
}
private:
// /**
// * statistics_ object is not used. It is left for backward compatibility.
// *
// * ZH - Pragma added to prevent compiler warnings.
// */
// DataAndStatistics &statistics_;
// the id of the last clause
// note that clause ID is the clause number,
// different from the offset of the clause in the literal pool
unsigned max_clause_id_ = 0;
unsigned max_variable_id_ = 0;
// this contains clause offsets of the clauses
// where each variable occurs in;
std::vector<ClauseOfs> variable_occurrence_lists_pool_;
std::vector<unsigned> unified_variable_links_lists_pool_;
std::vector<unsigned> variable_link_list_offsets_;
LiteralIndexedVector<TriValue> & literal_values_;
std::vector<unsigned> var_frequency_scores_;
ComponentArchetype archetype_;
std::vector<VariableIndex> search_stack_;
bool isResolved(const LiteralID lit) const {
return literal_values_[lit] == F_TRI;
}
bool isSatisfied(const LiteralID lit) const {
return literal_values_[lit] == T_TRI;
}
bool isActive(const LiteralID lit) const {
return literal_values_[lit] == X_TRI;
}
bool isActive(const VariableIndex v) const {
return literal_values_[LiteralID(v, true)] == X_TRI;
}
unsigned *beginOfLinkList(VariableIndex v) {
return &unified_variable_links_lists_pool_[variable_link_list_offsets_[v]];
}
// stores all information about the component of var
// in variables_seen_, clauses_seen_ and
// component_search_stack
// we have an isolated variable iff
// after execution component_search_stack.size()==1
void recordComponentOf(VariableIndex var);
void getClause(std::vector<unsigned> &tmp,
std::vector<LiteralID>::iterator & it_start_of_cl,
LiteralID & omitLit) {
tmp.clear();
for (auto it_lit = it_start_of_cl; *it_lit != SENTINEL_LIT; it_lit++) {
if (it_lit->var() != omitLit.var())
tmp.push_back(it_lit->raw());
}
}
void searchClause(VariableIndex vt, ClauseIndex clID, LiteralID * pstart_cls) {
auto itVEnd = search_stack_.end();
bool all_lits_active = true;
for (auto itL = pstart_cls; *itL != SENTINEL_LIT; itL++) {
assert(itL->var() <= max_variable_id_);
if (!archetype_.var_nil(itL->var())) {
manageSearchOccurrenceAndScoreOf(*itL);
} else {
assert(!isActive(*itL));
all_lits_active = false;
if (isResolved(*itL))
continue;
//BEGIN accidentally entered a satisfied clause: undo the search process
while (search_stack_.end() != itVEnd) {
assert(search_stack_.back() <= max_variable_id_);
archetype_.setVar_in_sup_comp_unseen(search_stack_.back());
search_stack_.pop_back();
}
archetype_.setClause_nil(clID);
while (*itL != SENTINEL_LIT)
if (isActive(*(--itL)))
var_frequency_scores_[itL->var()]--;
//END accidentally entered a satisfied clause: undo the search process
break;
}
}
if (!archetype_.clause_nil(clID)) {
var_frequency_scores_[vt]++;
archetype_.setClause_seen(clID, all_lits_active);
}
}
// void searchThreeClause(VariableIndex vt, ClauseIndex clID, LiteralID * pstart_cls) {
// auto itVEnd = search_stack_.end();
// bool all_lits_active = true;
// // LiteralID * pstart_cls = reinterpret_cast<LiteralID *>(p + 1 + *(p+1));
// for (auto itL = pstart_cls; itL != pstart_cls+2; itL++) {
// assert(itL->var() <= max_variable_id_);
// if (archetype_.var_nil(itL->var())) {
// assert(!isActive(*itL));
// all_lits_active = false;
// if (isResolved(*itL))
// continue;
// //BEGIN accidentally entered a satisfied clause: undo the search process
// while (search_stack_.end() != itVEnd) {
// assert(search_stack_.back() <= max_variable_id_);
// archetype_.setVar_in_sup_comp_unseen(search_stack_.back());
// search_stack_.pop_back();
// }
// archetype_.setClause_nil(clID);
// while (itL != pstart_cls - 1)
// if (isActive(*(--itL)))
// var_frequency_scores_[itL->var()]--;
// //END accidentally entered a satisfied clause: undo the search process
// break;
// } else {
// assert(isActive(*itL));
// var_frequency_scores_[itL->var()]++;
// if (isUnseenAndActive(itL->var()))
// setSeenAndStoreInSearchStack(itL->var());
// }
// }
//
// if (!archetype_.clause_nil(clID)) {
// var_frequency_scores_[vt]++;
// archetype_.setClause_seen(clID,all_lits_active);
// }
// }
};
#endif // ALT_COMPONENT_ANALYZER_H_
Includes¶
cmath
component_types/base_packed_component.h
(File base_packed_component.h)component_types/component.h
(File component.h)component_types/component_archetype.h
(File component_archetype.h)containers.h
(File containers.h)gmpxx.h
statistics.h
(File statistics.h)vector
Classes¶
File base_packed_component.cpp¶
↰ Parent directory (src/component_types
)
Definition (src/component_types/base_packed_component.cpp
)¶
↰ Return to documentation for file (src/component_types/base_packed_component.cpp
)
#include "base_packed_component.h"
#include <math.h> // Needed since taking log based 2.
#include <iostream>
unsigned BasePackedComponent::_bits_per_clause = 0;
unsigned BasePackedComponent::_bits_per_variable = 0; // bitsperentry
unsigned BasePackedComponent::_variable_mask = 0;
unsigned BasePackedComponent::_clause_mask = 0; // bitsperentry
unsigned BasePackedComponent::_debug_static_val = 0;
unsigned BasePackedComponent::_bits_of_data_size = 0;
unsigned BasePackedComponent::_data_size_mask = 0;
void BasePackedComponent::adjustPackSize(unsigned int maxVarId, unsigned int maxClId) {
_bits_per_variable = log2(maxVarId) + 1;
_bits_per_clause = log2(maxClId) + 1;
_bits_of_data_size = log2(maxVarId + maxClId) + 1;
_variable_mask = _clause_mask = _data_size_mask = 0;
// Iteratively bit shift to create the mask variable
for (unsigned int i = 0; i < _bits_per_variable; i++)
_variable_mask = (_variable_mask << 1) + 1;
for (unsigned int i = 0; i < _bits_per_clause; i++)
_clause_mask = (_clause_mask << 1) + 1;
for (unsigned int i = 0; i < _bits_of_data_size; i++)
_data_size_mask = (_data_size_mask << 1) + 1;
}
Includes¶
base_packed_component.h
(File base_packed_component.h)iostream
math.h
File base_packed_component.h¶
↰ Parent directory (src/component_types
)
Contents
Definition (src/component_types/base_packed_component.h
)¶
↰ Return to documentation for file (src/component_types/base_packed_component.h
)
#ifndef BASE_PACKED_COMPONENT_H_
#define BASE_PACKED_COMPONENT_H_
#include <assert.h>
#include <gmpxx.h>
#include <iostream>
//using namespace std;
template <class T> class BitStuffer {
public:
explicit BitStuffer(T *data) : data_start_(data), p(data) {
*p = 0;
}
void stuff(const unsigned val, const unsigned num_bits_val) {
assert(num_bits_val > 0); // Verify a number of bits is specified
assert((val >> num_bits_val) == 0); // Verify no hanging over bits in the passed in value
// Clear the memory at the specified location to make sure it is empty
if (end_of_bits_ == 0)
*p = 0;
// Ensure there are no 1 bits after the end_of_bits_ bit location.
assert((*p >> end_of_bits_) == 0);
// Insert val into the memory location pointed to by p.
*p |= val << end_of_bits_;
// Shift the bit location by the number of bits in the vlue
end_of_bits_ += num_bits_val;
if (end_of_bits_ > _bits_per_block) {
//assert(*p);
// Roll over the bit count
end_of_bits_ -= _bits_per_block;
*(++p) = val >> (num_bits_val - end_of_bits_);
assert(end_of_bits_ != 0 || (*p == 0));
} else if (end_of_bits_ == _bits_per_block) {
end_of_bits_ -= _bits_per_block;
p++;
}
}
void assert_size(unsigned size) {
if (end_of_bits_ == 0)
p--;
assert(p - data_start_ == size - 1);
}
private:
T *data_start_ = nullptr;
T *p = nullptr;
unsigned end_of_bits_ = 0;
static const unsigned _bits_per_block = (sizeof(T) << 3);
};
class BasePackedComponent {
public:
static unsigned bits_per_variable() {
return _bits_per_variable;
}
static unsigned variable_mask() {
return _variable_mask;
}
static unsigned bits_per_clause() {
return _bits_per_clause;
}
static unsigned bits_per_block() {
return _bits_per_block;
}
static unsigned bits_of_data_size() {
return _bits_of_data_size;
}
static void adjustPackSize(unsigned int maxVarId, unsigned int maxClId);
BasePackedComponent() = default;
explicit BasePackedComponent(unsigned creation_time) : creation_time_(creation_time) {}
~BasePackedComponent() {
// if (data_) // Deleting nullptr has no effect so no need for if
// delete data_;
delete data_;
}
static void outbit(unsigned v) {
for (auto i=0; i < 32; i++) {
std::cout << ((v&2147483648)?"1":"0"); // 2147483648 == 2^31
v&=2147483648-1;
v <<= 1;
}
}
static unsigned log2(unsigned v) {
// taken from
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
static const char LogTable256[256] = {
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
unsigned r; // r will be lg(v)
unsigned int t, tt; // temporaries
if ((tt = (v >> 16))) {
r = (t = (tt >> 8)) ? 24 + LogTable256[t] : 16 + LogTable256[tt];
} else {
r = (t = (v >> 8)) ? 8 + LogTable256[t] : LogTable256[v];
}
return r;
}
unsigned creation_time() {
return creation_time_;
}
const mpz_class &model_count() const {
return model_count_;
}
unsigned alloc_of_model_count() const {
return sizeof(mpz_class) + model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t);
}
void set_creation_time(unsigned time) {
creation_time_ = time;
}
void set_model_count(const mpz_class &rn, unsigned time) {
model_count_ = rn;
length_solution_period_and_flags_ = (time - creation_time_)
| (length_solution_period_and_flags_ & 1);
}
unsigned hashkey() const {
return hashkey_;
}
bool modelCountFound() {
return (length_solution_period_and_flags_ >> 1);
}
bool isDeletable() const {
return length_solution_period_and_flags_ & 1;
}
void set_deletable() {
length_solution_period_and_flags_ |= 1;
}
void clear() {
// before deleting the contents of this component,
// we should make sure that this component is not present in the component stack anymore!
assert(isDeletable());
// if (data_) // If statement unnecessary as deleting nullptr as no effect
// delete data_;
delete data_;
data_ = nullptr;
}
static unsigned _debug_static_val;
protected:
unsigned* data_ = nullptr;
unsigned hashkey_ = 0;
mpz_class model_count_;
unsigned creation_time_ = 1;
// this is: length_solution_period = length_solution_period_and_flags_ >> 1
// length_solution_period == 0 means unsolved
// and the first bit is "delete_permitted"
unsigned length_solution_period_and_flags_ = 0;
// deletion is permitted only after
// the copy of this component in the stack
// does not exist anymore
protected:
static unsigned _bits_per_clause;
static unsigned _bits_per_variable; // bitsperentry
static unsigned _bits_of_data_size; // number of bits needed to store the data size.
static unsigned _data_size_mask;
static unsigned _variable_mask;
static unsigned _clause_mask;
static const unsigned _bits_per_block = (sizeof(unsigned) << 3);
};
#endif /* BASE_PACKED_COMPONENT_H_ */
Includes¶
assert.h
gmpxx.h
iostream
Included By¶
File cacheable_component.h¶
↰ Parent directory (src/component_types
)
Contents
Definition (src/component_types/cacheable_component.h
)¶
↰ Return to documentation for file (src/component_types/cacheable_component.h
)
/*
* cacheable_component.h
*
* Created on: Feb 21, 2013
* Author: mthurley
*/
#ifndef CACHEABLE_COMPONENT_H_
#define CACHEABLE_COMPONENT_H_
#include <assert.h>
#include <vector>
#include "../primitive_types.h"
#include "difference_packed_component.h"
//#include "simple_unpacked_component.h"
//using namespace std;
#define NIL_ENTRY 0
class Component;
class ComponentArchetype;
// GenericCacheableComponent Adds Structure to PackedComponent that is
// necessary to store it in the cache
// namely, the descendant tree structure that
// allows for the removal of cache pollutions
template< class T_Component>
class GenericCacheableComponent: public T_Component {
public:
GenericCacheableComponent() = default;
explicit GenericCacheableComponent(Component &comp) :
T_Component(comp) {
}
unsigned long SizeInBytes() const {
return sizeof(GenericCacheableComponent<T_Component>) + T_Component::raw_data_byte_size();
}
// the 48 = 16*3 in overhead stems from the three parts of the component
// being dynamically allocated (i.e. the GenericCacheableComponent itself,
// the data_ and the model_count data
unsigned long sys_overhead_SizeInBytes() const {
return sizeof(GenericCacheableComponent<T_Component>)
+ T_Component::sys_overhead_raw_data_byte_size()
// + 24;
+48;
}
// BEGIN Cache Pollution Management
void set_father(CacheEntryID f) {
father_ = f;
}
const CacheEntryID father() const {
return father_;
}
void set_next_sibling(CacheEntryID sibling) {
next_sibling_ = sibling;
}
CacheEntryID next_sibling() {
return next_sibling_;
}
void set_first_descendant(CacheEntryID descendant) {
first_descendant_ = descendant;
}
const CacheEntryID first_descendant() const {
return first_descendant_;
}
void set_next_bucket_element(CacheEntryID entry) {
next_bucket_element_ = entry;
}
CacheEntryID next_bucket_element() {
return next_bucket_element_;
}
private:
CacheEntryID next_bucket_element_ = 0;
// theFather and theDescendants:
// each CCacheEntry is a Node in a tree which represents the relationship
// of the components stored
CacheEntryID father_ = 0;
CacheEntryID first_descendant_ = 0;
CacheEntryID next_sibling_ = 0;
};
typedef GenericCacheableComponent<DifferencePackedComponent> CacheableComponent;
//typedef GenericCacheableComponent<SimplePackedComponent> CacheableComponent;
#endif /* CACHEABLE_COMPONENT_H_ */
Includes¶
../primitive_types.h
assert.h
difference_packed_component.h
(File difference_packed_component.h)vector
Defines¶
Typedefs¶
File cached_assignment.h¶
↰ Parent directory (src
)
Definition (src/cached_assignment.h
)¶
↰ Return to documentation for file (src/cached_assignment.h
)
#ifndef SHARPSAT_CACHED_ASSIGNMENT_H
#define SHARPSAT_CACHED_ASSIGNMENT_H
#include <algorithm>
#include <vector>
#include "structures.h"
#define CACHED_VARIABLE_LEN 2 // In Bits
class CachedAssignment{
public:
CachedAssignment() {
assigned_literals_.reserve(1);
emancipated_vars_.reserve(1);
}
inline void Sort() {
std::sort(assigned_literals_.begin(), assigned_literals_.end());
std::sort(emancipated_vars_.begin(), emancipated_vars_.begin());
}
inline void IncreaseSize(VariableIndex size_adder) {
VariableIndex new_size = assigned_literals_.capacity() + size_adder;
assigned_literals_.reserve(new_size);
}
// /**
// * Add the specified literal to the list of literals in the cache
// * assignment.
// *
// * @param lit New literal value.
// */
// inline void AddLiteral(LiteralID lit) {assigned_literals_.push_back(lit);}
const std::vector<VariableIndex> vars() {
std::vector<VariableIndex> cached_vars;
cached_vars.reserve(assigned_literals_.size());
for (auto lit : assigned_literals_)
cached_vars.push_back(lit.var());
cached_vars.insert(cached_vars.end(), emancipated_vars_.begin(), emancipated_vars_.end());
return cached_vars;
}
const VariableIndex num_components() const { return num_cached_components; }
const bool empty() const {return num_cached_components == 0; }
void ProcessComponent(const Component * comp, mpz_class model_count_and_assn) {
// Nothing to store in the UNSAT case
if (model_count_and_assn == 0)
return;
IncreaseSize(comp->num_variables()); // Increase the capacity
// Extract the literal assignments from the MPZ object
std::vector<ComponentVarAndCls> comp_data = comp->getData();
for (VariableIndex i = 0; i < comp->num_variables(); i++) {
VariableIndex bit_index = CACHED_VARIABLE_LEN * i;
// Check if the variable is emancipated
if (mpz_tstbit(model_count_and_assn.get_mpz_t(), bit_index + 1) == 1) {
emancipated_vars_.emplace_back(comp_data[i]);
} else {
bool sign = (mpz_tstbit(model_count_and_assn.get_mpz_t(), bit_index) == 1);
assigned_literals_.emplace_back(LiteralID(comp_data[i], sign));
}
}
num_cached_components++;
}
const std::vector<LiteralID>& literals() const { return assigned_literals_; }
const std::vector<VariableIndex>& emancipated_vars() const { return emancipated_vars_; }
void clear() {
assigned_literals_.clear();
emancipated_vars_.clear();
num_cached_components = 0;
}
// /**
// * Component Split Accessor
// *
// * Accessor for whether this cached assignment corresponds with a component
// * split.
// *
// * @return true if this cached assignment corresponds to a component split.
// */
// const bool is_component_split() const { return is_component_split_;}
private:
std::vector<VariableIndex> emancipated_vars_;
std::vector<LiteralID> assigned_literals_;
unsigned long num_cached_components = 0;
};
#endif // SHARPSAT_CACHED_ASSIGNMENT_H
Includes¶
algorithm
structures.h
(File structures.h)vector
Classes¶
Defines¶
File component.h¶
↰ Parent directory (src/component_types
)
Definition (src/component_types/component.h
)¶
↰ Return to documentation for file (src/component_types/component.h
)
#ifndef COMPONENT_H_
#define COMPONENT_H_
#include <assert.h>
#include <vector>
#include "../primitive_types.h"
//using namespace std;
class Component {
public:
void reserveSpace(unsigned int num_variables, unsigned int num_clauses) {
data_.reserve(num_variables + num_clauses + 2);
}
void set_id(CacheEntryID id) {
id_ = id;
}
CacheEntryID id() const {
return id_;
}
void addVar(const VariableIndex var) {
// the only time a varsSENTINEL is added should be in a
// call to closeVariableData(..)
assert(var != varsSENTINEL);
data_.push_back(var);
}
void closeVariableData() {
data_.push_back(varsSENTINEL);
clauses_ofs_ = (unsigned) data_.size();
}
void addCl(const ClauseIndex cl) {
// the only time a clsSENTINEL is added should be in a
// call to closeClauseData(..)
assert(cl != clsSENTINEL);
data_.push_back(cl);
}
void closeClauseData() {
data_.push_back(clsSENTINEL);
assert(*(clsBegin()-1) == 0);
}
std::vector<VariableIndex>::const_iterator varsBegin() const {
return data_.begin();
}
std::vector<ClauseIndex>::const_iterator clsBegin() const {
return data_.begin() + clauses_ofs_;
}
unsigned num_variables() const {
return clauses_ofs_ - 1;
}
unsigned numLongClauses() const {
return (unsigned) data_.size() - clauses_ofs_ - 1;
}
bool empty() const {
return data_.empty();
}
void createAsDummyComponent(unsigned max_var_id, unsigned max_clause_id) {
data_.clear();
clauses_ofs_ = 1;
for (unsigned idvar = 1; idvar <= max_var_id; idvar++)
addVar(idvar);
closeVariableData();
if (max_clause_id > 0) {
for (unsigned idcl = 1; idcl <= max_clause_id; idcl++)
addCl(idcl);
}
closeClauseData();
}
void clear() {
clauses_ofs_ = 0;
data_.clear();
}
unsigned clauses_ofs() const {
return clauses_ofs_;
}
const std::vector<ComponentVarAndCls >& getData() const { return data_; }
private:
// data_ stores the component data:
// for better cache performance the
// clause and variable data are stored in
// a contiguous piece of memory
// variables SENTINEL clauses SENTINEL
// this order has to be taken care of on filling
// in the data!
std::vector<ComponentVarAndCls> data_;
unsigned clauses_ofs_ = 0;
// id_ will identify denote the entry in the cacheable component database,
// where a Packed version of this component is stored
// yet this does not imply that the model count of this component is already known
// once the model count is known, a link to the packed component will be stored
// in the hash table
CacheEntryID id_ = 0;
};
#endif /* COMPONENT_H_ */
Includes¶
../primitive_types.h
assert.h
vector
Included By¶
Classes¶
File component_archetype.cpp¶
↰ Parent directory (src/component_types
)
Definition (src/component_types/component_archetype.cpp
)¶
↰ Return to documentation for file (src/component_types/component_archetype.cpp
)
#include "component_archetype.h"
CA_SearchState *ComponentArchetype::seen_ = nullptr;
unsigned ComponentArchetype::seen_byte_size_ = 0;
Includes¶
component_archetype.h
(File component_archetype.h)
File component_archetype.h¶
↰ Parent directory (src/component_types
)
Contents
Definition (src/component_types/component_archetype.h
)¶
↰ Return to documentation for file (src/component_types/component_archetype.h
)
#ifndef COMPONENT_ARCHETYPE_H_
#define COMPONENT_ARCHETYPE_H_
#include <cstring>
#include <algorithm>
#include <iostream>
#include "../primitive_types.h"
#include "component.h"
#include "cacheable_component.h"
// State values for variables found during component
// analysis (CA)
typedef unsigned char CA_SearchState;
#define CA_NIL 0
#define CA_VAR_IN_SUP_COMP_UNSEEN 1
#define CA_VAR_SEEN 2
#define CA_VAR_IN_OTHER_COMP 4
#define CA_VAR_MASK 7
#define CA_CL_IN_SUP_COMP_UNSEEN 8
#define CA_CL_SEEN 16
#define CA_CL_IN_OTHER_COMP 32
#define CA_CL_ALL_LITS_ACTIVE 64
#define CA_CL_MASK 120
class StackLevel;
class ComponentArchetype {
public:
ComponentArchetype() = default;
ComponentArchetype(StackLevel &stack_level, Component &super_comp) :
p_super_comp_(&super_comp), p_stack_level_(&stack_level) {
}
void reInitialize(StackLevel &stack_level, Component &super_comp) {
p_super_comp_ = &super_comp;
p_stack_level_ = &stack_level;
clearArrays();
current_comp_for_caching_.reserveSpace(super_comp.num_variables(), super_comp.numLongClauses());
}
Component &super_comp() {
return *p_super_comp_;
}
StackLevel & stack_level() {
return *p_stack_level_;
}
void setVar_in_sup_comp_unseen(VariableIndex v) {
seen_[v] = CA_VAR_IN_SUP_COMP_UNSEEN | (seen_[v] & CA_CL_MASK);
}
void setClause_in_sup_comp_unseen(ClauseIndex cl) {
seen_[cl] = CA_CL_IN_SUP_COMP_UNSEEN | (seen_[cl] & CA_VAR_MASK);
}
void setVar_nil(VariableIndex v) {
seen_[v] &= CA_CL_MASK;
}
void setClause_nil(ClauseIndex cl) {
seen_[cl] &= CA_VAR_MASK;
}
void setVar_seen(VariableIndex v) {
seen_[v] = CA_VAR_SEEN | (seen_[v] & CA_CL_MASK);
}
void setClause_seen(ClauseIndex cl) {
setClause_nil(cl);
seen_[cl] = CA_CL_SEEN | (seen_[cl] & CA_VAR_MASK);
}
void setClause_seen(ClauseIndex cl, bool all_lits_act) {
setClause_nil(cl);
seen_[cl] = CA_CL_SEEN | (all_lits_act ? CA_CL_ALL_LITS_ACTIVE : 0) | (seen_[cl] & CA_VAR_MASK);
}
void setVar_in_other_comp(VariableIndex v) {
seen_[v] = CA_VAR_IN_OTHER_COMP | (seen_[v] & CA_CL_MASK);
}
void setClause_in_other_comp(ClauseIndex cl) {
seen_[cl] = CA_CL_IN_OTHER_COMP | (seen_[cl] & CA_VAR_MASK);
}
bool var_seen(VariableIndex v) const {
return seen_[v] & CA_VAR_SEEN;
}
bool clause_seen(ClauseIndex cl) const {
return seen_[cl] & CA_CL_SEEN;
}
bool clause_all_lits_active(ClauseIndex cl) {
return seen_[cl] & CA_CL_ALL_LITS_ACTIVE;
}
void setClause_all_lits_active(ClauseIndex cl) const {
seen_[cl] |= CA_CL_ALL_LITS_ACTIVE;
}
bool var_nil(VariableIndex v) const {
return (seen_[v] & CA_VAR_MASK) == 0;
}
bool clause_nil(ClauseIndex cl) const {
return (seen_[cl] & CA_CL_MASK) == 0;
}
bool var_unseen_in_sup_comp(VariableIndex v) const {
return seen_[v] & CA_VAR_IN_SUP_COMP_UNSEEN;
}
bool clause_unseen_in_sup_comp(ClauseIndex cl) const {
return seen_[cl] & CA_CL_IN_SUP_COMP_UNSEEN;
}
bool var_seen_in_peer_comp(VariableIndex v) const {
return seen_[v] & CA_VAR_IN_OTHER_COMP;
}
bool clause_seen_in_peer_comp(ClauseIndex cl) const {
return seen_[cl] & CA_CL_IN_OTHER_COMP;
}
static void initArrays(unsigned max_variable_id, unsigned max_clause_id) {
unsigned seen_size = std::max(max_variable_id, max_clause_id) + 1;
seen_ = new CA_SearchState[seen_size];
seen_byte_size_ = sizeof(CA_SearchState) * (seen_size);
clearArrays();
}
static void clearArrays() {
memset(seen_, CA_NIL, seen_byte_size_);
}
Component *makeComponentFromState(unsigned long stack_size) {
Component *p_new_comp = new Component();
p_new_comp->reserveSpace(stack_size, super_comp().numLongClauses());
current_comp_for_caching_.clear();
for (auto v_it = super_comp().varsBegin(); *v_it != varsSENTINEL; v_it++)
if (var_seen(*v_it)) { //we have to put a var into our component
p_new_comp->addVar(*v_it);
current_comp_for_caching_.addVar(*v_it);
setVar_in_other_comp(*v_it);
}
p_new_comp->closeVariableData();
current_comp_for_caching_.closeVariableData();
for (auto it_cl = super_comp().clsBegin(); *it_cl != clsSENTINEL; it_cl++)
if (clause_seen(*it_cl)) {
p_new_comp->addCl(*it_cl);
if (!clause_all_lits_active(*it_cl))
current_comp_for_caching_.addCl(*it_cl);
setClause_in_other_comp(*it_cl);
}
p_new_comp->closeClauseData();
current_comp_for_caching_.closeClauseData();
return p_new_comp;
}
// Component *makeComponentFromState(unsigned stack_size) {
// Component *p_new_comp = new Component();
// p_new_comp->reserveSpace(stack_size, super_comp().numLongClauses());
//
// for (auto v_it = super_comp().varsBegin(); *v_it != varsSENTINEL; v_it++)
// if (var_seen(*v_it)) { //we have to put a var into our component
// p_new_comp->addVar(*v_it);
// setVar_in_other_comp(*v_it);
// }
// p_new_comp->closeVariableData();
//
// for (auto it_cl = super_comp().clsBegin(); *it_cl != clsSENTINEL; it_cl++)
// if (clause_seen(*it_cl)) {
// p_new_comp->addCl(*it_cl);
// setClause_in_other_comp(*it_cl);
// }
// p_new_comp->closeClauseData();
// return p_new_comp;
// }
// inline void createComponents(Component &ret_comp, CacheableComponent ret_cache_comp,
// unsigned stack_size);
Component current_comp_for_caching_;
private:
Component *p_super_comp_;
StackLevel *p_stack_level_;
static CA_SearchState *seen_;
static unsigned seen_byte_size_;
};
//void ComponentArchetype::createComponents(Component &ret_comp,
// CacheableComponent ret_cache_comp, unsigned stack_size) {
//}
#endif /* COMPONENT_ARCHETYPE_H_ */
Includes¶
../primitive_types.h
algorithm
cacheable_component.h
(File cacheable_component.h)component.h
(File base_packed_component.h)cstring
iostream
Classes¶
Defines¶
Typedefs¶
File component_cache.cpp¶
↰ Parent directory (src
)
Definition (src/component_cache.cpp
)¶
↰ Return to documentation for file (src/component_cache.cpp
)
#include <algorithm>
#include <vector>
#include "component_cache.h"
#include "sampler_tools.h"
#ifdef __linux__
#include <sys/sysinfo.h>
#include <cstdint>
uint64_t freeram() {
struct sysinfo info;
sysinfo(&info);
return info.freeram *(uint64_t) info.mem_unit;
}
#elif __APPLE__ && __MACH__
#include <sys/sysctl.h>
uint64_t freeram() {
int mib[2];
int64_t physical_memory;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
size_t length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);
return physical_memory;
}
#else
#endif
ComponentCache::ComponentCache(DataAndStatistics &statistics, SolverConfiguration &config) :
statistics_(statistics), config_(config) {
}
void ComponentCache::init(Component &super_comp, bool quiet) {
if (!quiet) {
std::cout << "Initialize cache\n"
<< "Size of Cacheable Component:\t" << sizeof(CacheableComponent) << "\n"
<< "Size of MPZ Class:\t" << sizeof(mpz_class) << std::endl;
}
CacheableComponent &packed_super_comp = *new CacheableComponent(super_comp);
my_time_ = 1;
entry_base_.clear();
entry_base_.reserve(2000000);
entry_base_.push_back(new CacheableComponent()); // dummy Element
table_.clear();
table_.resize(1024*1024, 0);
table_size_mask_ = table_.size() - 1;
free_entry_base_slots_.clear();
free_entry_base_slots_.reserve(10000);
uint64_t free_ram = freeram();
uint64_t max_cache_bound = 95 * (free_ram / 100);
if (statistics_.maximum_cache_size_bytes_ == 0) {
statistics_.maximum_cache_size_bytes_ = max_cache_bound;
}
if (!quiet) {
if (statistics_.maximum_cache_size_bytes_ > free_ram) {
std::cout << "\n";
//PrintWarning("Maximum cache size larger than free RAM available");
std::cout << " Free RAM " << free_ram / 1000000 << "MB\n";
}
std::cout << "Maximum cache size:\t"
<< statistics_.maximum_cache_size_bytes_ / 1000000 << " MB\n"
<< std::endl;
}
assert(!statistics_.cache_full());
if (entry_base_.capacity() == entry_base_.size())
entry_base_.reserve(2 * entry_base_.size());
entry_base_.push_back(&packed_super_comp);
statistics_.incorporate_cache_store(packed_super_comp);
super_comp.set_id(1);
}
void ComponentCache::test_descendantstree_consistency() {
for (unsigned id = 2; id < entry_base_.size(); id++)
if (entry_base_[id] != nullptr) {
CacheEntryID act_child = entry(id).first_descendant();
while (act_child) {
CacheEntryID next_child = entry(act_child).next_sibling();
assert(entry(act_child).father() == id);
act_child = next_child;
}
CacheEntryID father = entry(id).father();
CacheEntryID act_sib = entry(father).first_descendant();
bool found = false;
while (act_sib && !found) {
CacheEntryID next_sib = entry(act_sib).next_sibling();
if (act_sib == id)
found = true;
act_sib = next_sib;
}
assert(found);
}
}
bool ComponentCache::deleteEntries() {
assert(statistics_.cache_full());
// Build a list of all the scores, sorts the list, then delete all
// entries with a score below the median.
std::vector<double> scores;
for (auto it = entry_base_.begin() + 1; it != entry_base_.end(); it++)
if (*it != nullptr && (*it)->isDeletable()) {
scores.push_back(static_cast<double>((*it)->creation_time()));
}
std::sort(scores.begin(), scores.end());
double cutoff = scores[scores.size() / 2];
//std::cout << "cutoff" << cutoff << " entries: "<< entry_base_.size()<< std::endl;
// first : go through the EntryBase and mark the entries to be deleted as deleted (i.e. EMPTY
// note we start at index 2,
// since index 1 is the whole formula,
// should always stay here!
for (unsigned id = 2; id < entry_base_.size(); id++)
if (entry_base_[id] != nullptr &&
entry_base_[id]->isDeletable() &&
static_cast<double>(entry_base_[id]->creation_time()) <= cutoff) {
removeFromDescendantsTree(id);
eraseEntry(id);
}
// then go through the Hash Table and erase all Links to empty entries
#ifdef DEBUG
test_descendantstree_consistency();
#endif
reHashTable(table_.size());
statistics_.sum_size_cached_components_ = 0;
statistics_.sum_bytes_cached_components_ = 0;
statistics_.sys_overhead_sum_bytes_cached_components_ = 0;
statistics_.sum_bytes_pure_cached_component_data_ = 0;
for (unsigned id = 2; id < entry_base_.size(); id++)
if (entry_base_[id] != nullptr) {
statistics_.sum_size_cached_components_ +=
entry_base_[id]->num_variables();
statistics_.sum_bytes_cached_components_ +=
entry_base_[id]->SizeInBytes();
statistics_.sum_bytes_pure_cached_component_data_ +=
entry_base_[id]->data_only_byte_size();
statistics_.sys_overhead_sum_bytes_cached_components_ +=
entry_base_[id]->sys_overhead_SizeInBytes();
}
statistics_.num_cached_components_ = entry_base_.size();
compute_byte_size_infrastructure();
//std::cout << " \t entries: "<< entry_base_.size() - free_entry_base_slots_.size()<< std::endl;
return true;
}
uint64_t ComponentCache::compute_byte_size_infrastructure() {
statistics_.cache_infrastructure_bytes_memory_usage_ =
sizeof(ComponentCache)
+ sizeof(CacheEntryID)* table_.capacity()
+ sizeof(CacheableComponent *)* entry_base_.capacity()
+ sizeof(CacheEntryID) * free_entry_base_slots_.capacity();
return statistics_.cache_infrastructure_bytes_memory_usage_;
}
void ComponentCache::debug_dump_data() {
std::cout << "sizeof (CacheableComponent *, CacheEntryID) "
<< sizeof(CacheableComponent *) << ", "
<< sizeof(CacheEntryID) << std::endl;
std::cout << "table (size/capacity) " << table_.size()
<< "/" << table_.capacity() << std::endl;
std::cout << "entry_base_ (size/capacity) " << entry_base_.size()
<< "/" << entry_base_.capacity() << std::endl;
std::cout << "free_entry_base_slots_ (size/capacity) " << free_entry_base_slots_.size()
<< "/" << free_entry_base_slots_.capacity() << std::endl;
// uint64_t size_model_counts = 0;
uint64_t alloc_model_counts = 0;
for (auto &pentry : entry_base_)
if (pentry != nullptr) {
// size_model_counts += pentry->size_of_model_count();
alloc_model_counts += pentry->alloc_of_model_count();
}
std::cout << "model counts size " << alloc_model_counts << std::endl;
}
Includes¶
algorithm
component_cache.h
(File component_cache.h)sampler_tools.h
(File sampler_tools.h)vector
File component_cache.h¶
↰ Parent directory (src
)
Definition (src/component_cache.h
)¶
↰ Return to documentation for file (src/component_cache.h
)
#ifndef COMPONENT_CACHE_H_
#define COMPONENT_CACHE_H_
#include <gmpxx.h>
#include <vector>
#include <sstream>
#include "component_types/cacheable_component.h"
#include "statistics.h"
#include "component_types/component.h"
#include "stack.h"
#include "solver_config.h"
#include "cached_assignment.h"
class ComponentCache {
public:
ComponentCache(DataAndStatistics &statistics, SolverConfiguration &config);
~ComponentCache() {
// debug_dump_data();
for (auto &pentry : entry_base_) {
// if (pentry != nullptr)
// delete pentry;
delete pentry; // Do NOT need the check as deleting nullptr has no effect
}
}
void init(Component &super_comp, bool quiet = false);
// compute the size in bytes of the component cache from scratch
// the value is stored in bytes_memory_usage_
uint64_t compute_byte_size_infrastructure();
const CacheableComponent &entry_const(const CacheEntryID id) const {
assert(entry_base_.size() > id); // Verify the ID is value for the size.
assert(entry_base_[id] != nullptr);
return *entry_base_[id];
}
CacheableComponent &entry(const CacheEntryID id) {
return const_cast<CacheableComponent&>(entry_const(id));
}
// /**
// * Uses a cached component's CacheEntryID to extract the components
// * cached information.
// *
// * @param comp Component to be extracted from the cache.
// * @return Cache entry for the specified component.
// */
// CacheableComponent &entry(const Component& comp) {
// return entry(comp.id());
// }
bool hasEntry(CacheEntryID id) const {
assert(entry_base_.size() > id);
return static_cast<bool>(entry_base_[id]);
}
inline void removeFromHashTable(CacheEntryID id);
// we delete the Component with ID id
// and all its descendants from the cache
inline void cleanPollutionsInvolving(CacheEntryID id);
// creates a CCacheEntry in the entry base
// which contains a packed copy of comp
// returns the id of the entry created
// stores in the entry the position of
// comp which is a part of the component stack
inline CacheEntryID storeAsEntry(CacheableComponent &ccomp,
CacheEntryID super_comp_id);
bool manageNewComponent(StackLevel &top, CacheableComponent &packed_comp,
Component * unpacked_comp, CachedAssignment &cached_assn,
CacheEntryID &cache_entry_id) {
statistics_.num_cache_look_ups_++;
unsigned table_ofs = packed_comp.hashkey() & table_size_mask_;
CacheEntryID act_id = table_[table_ofs];
while (act_id) {
if (entry(act_id).equals(packed_comp)) {
if (config_.verbose) {
std::stringstream ss;
ss << "\tCache hit for component #" << top.super_component() << " with model count "
<< entry(act_id).model_count() << " for cache ID #" << act_id;
PrintInColor(ss, COLOR_YELLOW);
}
// if (config_.perform_random_sampling_ && config_.perform_sample_caching()) {
if (config_.perform_sample_caching()) {
// ToDo Add support for multiple samples in cache.
assert(config_.num_samples_to_cache_ == 1);
VariableIndex num_vars = unpacked_comp->num_variables();
VariableIndex bit_shift = CACHED_VARIABLE_LEN * num_vars;
mpz_class actual_model_count = entry(act_id).model_count() >> bit_shift;
top.includeSolution(actual_model_count);
cached_assn.ProcessComponent(unpacked_comp, entry(act_id).model_count());
} else {
top.includeSolution(entry(act_id).model_count());
}
cache_entry_id = act_id; // Store the cache ID
statistics_.incorporate_cache_hit(packed_comp);
return true;
}
act_id = entry(act_id).next_bucket_element();
}
return false;
}
// unchecked erase of an entry from entry_base_
void eraseEntry(CacheEntryID id) {
statistics_.incorporate_cache_erase(*entry_base_[id]);
delete entry_base_[id];
entry_base_[id] = nullptr;
free_entry_base_slots_.push_back(id);
}
// store the number in model_count as the model count of CacheEntryID id
inline void storeValueOf(CacheEntryID id, const mpz_class &model_count);
bool deleteEntries();
// delete entries, keeping the descendants tree consistent
inline void removeFromDescendantsTree(CacheEntryID id);
// test function to ensure consistency of the descendant tree
inline void test_descendantstree_consistency();
void debug_dump_data();
private:
void considerCacheResize() {
if (entry_base_.size() > table_.size()) {
reHashTable(2*table_.size());
}
}
void reHashTable(unsigned long size) {
table_.clear();
table_.resize(size, 0);
// we assert that table size is a power of 2
// otherwise the table_size_mask_ doesn't work
assert((table_.size() & (table_.size() - 1)) == 0);
table_size_mask_ = table_.size() - 1;
std::cout << "ZH - Rehash the table.\n";
std::cout << "ts " << table_.size() << " " << table_size_mask_ << std::endl;
unsigned collisions = 0;
for (unsigned id = 2; id < entry_base_.size(); id++) {
if (entry_base_[id] != nullptr) {
entry_base_[id]->set_next_bucket_element(0);
if (entry_base_[id]->modelCountFound()) {
unsigned table_ofs = tableEntry(id);
collisions += (table_[table_ofs] > 0 ? 1 : 0);
entry_base_[id]->set_next_bucket_element(table_[table_ofs]);
table_[table_ofs] = id;
}
}
}
std::cout << "ZH - Number of collisions.\n" << "coll " << collisions << std::endl;
}
unsigned tableEntry(CacheEntryID id) {
return entry(id).hashkey() & table_size_mask_;
}
void add_descendant(CacheEntryID compid, CacheEntryID descendantid) {
assert(descendantid != entry_const(compid).first_descendant());
entry(descendantid).set_next_sibling(entry_const(compid).first_descendant());
entry(compid).set_first_descendant(descendantid);
}
void remove_firstdescendantOf(CacheEntryID compid) {
CacheEntryID desc = entry(compid).first_descendant();
if (desc != 0)
entry(compid).set_first_descendant(entry(desc).next_sibling());
}
std::vector<CacheableComponent *> entry_base_;
std::vector<CacheEntryID> free_entry_base_slots_;
// the actual hash table
// by means of which the cache is accessed
std::vector<CacheEntryID> table_;
unsigned table_size_mask_ = INT_MAX;
DataAndStatistics &statistics_;
unsigned long my_time_ = 0;
SolverConfiguration &config_;
};
#include "component_cache.inc"
#endif /* COMPONENT_CACHE_H_ */
Includes¶
cached_assignment.h
(File cached_assignment.h)component_cache.inc
(File component_cache.inc)component_types/cacheable_component.h
(File cacheable_component.h)component_types/component.h
(File component.h)gmpxx.h
solver_config.h
(File solver_config.h)sstream
stack.h
(File stack.h)statistics.h
(File statistics.h)vector
Included By¶
Classes¶
File component_cache.inc¶
↰ Parent directory (src
)
Definition (src/component_cache.inc
)¶
↰ Return to documentation for file (src/component_cache.inc
)
#ifndef COMPONENT_CACHE_INL_H_
#define COMPONENT_CACHE_INL_H_
CacheEntryID ComponentCache::storeAsEntry(CacheableComponent &ccomp, CacheEntryID super_comp_id) {
CacheEntryID id;
if (statistics_.cache_full())
deleteEntries();
assert(!statistics_.cache_full());
ccomp.set_creation_time(my_time_++);
if (free_entry_base_slots_.empty()) {
if (entry_base_.capacity() == entry_base_.size()) {
entry_base_.reserve(2 * entry_base_.size());
}
entry_base_.push_back(&ccomp);
id = entry_base_.size() - 1;
} else {
id = free_entry_base_slots_.back();
assert(id < entry_base_.size());
assert(entry_base_[id] == nullptr);
free_entry_base_slots_.pop_back();
entry_base_[id] = &ccomp;
}
entry(id).set_father(super_comp_id);
add_descendant(super_comp_id, id);
assert(hasEntry(id));
assert(hasEntry(super_comp_id));
statistics_.incorporate_cache_store(ccomp);
#ifdef DEBUG
for (unsigned u = 2; u < entry_base_.size(); u++)
if (entry_base_[u] != nullptr) {
assert(entry_base_[u]->father() != id);
assert(entry_base_[u]->first_descendant() != id);
assert(entry_base_[u]->next_sibling() != id);
}
#endif
return id;
}
void ComponentCache::cleanPollutionsInvolving(CacheEntryID id) {
CacheEntryID father = entry(id).father();
if (entry(father).first_descendant() == id) {
entry(father).set_first_descendant(entry(id).next_sibling());
} else {
CacheEntryID act_sibl = entry(father).first_descendant();
while (act_sibl) {
CacheEntryID next_sibl = entry(act_sibl).next_sibling();
if (next_sibl == id) {
entry(act_sibl).set_next_sibling(entry(next_sibl).next_sibling());
break;
}
act_sibl = next_sibl;
}
}
CacheEntryID next_child = entry(id).first_descendant();
entry(id).set_first_descendant(0);
while (next_child) {
CacheEntryID act_child = next_child;
next_child = entry(act_child).next_sibling();
cleanPollutionsInvolving(act_child);
}
removeFromHashTable(id);
eraseEntry(id);
}
void ComponentCache::removeFromHashTable(CacheEntryID id) {
//assert(false);
unsigned act_id = table_[tableEntry(id)];
if (act_id == id) {
table_[tableEntry(id)] = entry(act_id).next_bucket_element();
} else {
while (act_id) {
CacheEntryID next_id = entry(act_id).next_bucket_element();
if (next_id == id) {
entry(act_id).set_next_bucket_element(entry(next_id).next_bucket_element());
break;
}
act_id = next_id;
}
}
// CacheBucket *p_bucket = bucketOf(entry(id));
// if (p_bucket)
// for (auto it = p_bucket->begin(); it != p_bucket->end(); it++)
// if (*it == id) {
// *it = p_bucket->back();
// p_bucket->pop_back();
// break;
// }
}
void ComponentCache::removeFromDescendantsTree(CacheEntryID id) {
assert(hasEntry(id));
// we need a father for this all to work
assert(entry(id).father());
assert(hasEntry(entry(id).father()));
// two steps
// 1. remove id from the siblings list
CacheEntryID father = entry(id).father();
if (entry(father).first_descendant() == id) {
entry(father).set_first_descendant(entry(id).next_sibling());
} else {
CacheEntryID act_sibl = entry(father).first_descendant();
while (act_sibl) {
CacheEntryID next_sibl = entry(act_sibl).next_sibling();
if (next_sibl == id) {
entry(act_sibl).set_next_sibling(entry(next_sibl).next_sibling());
break;
}
act_sibl = next_sibl;
}
}
// 2. add the children of this one as
// siblings to the current siblings
CacheEntryID act_child = entry(id).first_descendant();
while (act_child) {
CacheEntryID next_child = entry(act_child).next_sibling();
entry(act_child).set_father(father);
entry(act_child).set_next_sibling(entry(father).first_descendant());
entry(father).set_first_descendant(act_child);
act_child = next_child;
}
}
void ComponentCache::storeValueOf(CacheEntryID id, const mpz_class &model_count) {
considerCacheResize();
unsigned table_ofs = tableEntry(id);
// when storing the new model count the size of the model count
// and hence that of the component will change
statistics_.sum_bytes_cached_components_ -= entry(id).SizeInBytes();
statistics_.overall_bytes_components_stored_ -= entry(id).SizeInBytes();
statistics_.sys_overhead_sum_bytes_cached_components_ -= entry(id).sys_overhead_SizeInBytes();
statistics_.sys_overhead_overall_bytes_components_stored_ -= entry(id).sys_overhead_SizeInBytes();
entry(id).set_model_count(model_count, my_time_);
entry(id).set_creation_time(my_time_);
entry(id).set_next_bucket_element(table_[table_ofs]);
table_[table_ofs] = id;
statistics_.sum_bytes_cached_components_ += entry(id).SizeInBytes();
statistics_.overall_bytes_components_stored_ += entry(id).SizeInBytes();
statistics_.sys_overhead_sum_bytes_cached_components_ += entry(id).sys_overhead_SizeInBytes();
statistics_.sys_overhead_overall_bytes_components_stored_ += entry(id).sys_overhead_SizeInBytes();
}
#endif /* COMPONENT_CACHE_INL_H_ */
Included By¶
File component_management.cpp¶
↰ Parent directory (src
)
Definition (src/component_management.cpp
)¶
↰ Return to documentation for file (src/component_management.cpp
)
#include <algorithm>
#include "component_management.h"
void ComponentManager::initialize(LiteralIndexedVector<Literal> & literals,
std::vector<LiteralID> &lit_pool, bool quiet) {
ana_.initialize(literals, lit_pool);
// BEGIN CACHE INIT
CacheableComponent::adjustPackSize(ana_.max_variable_id(), ana_.max_clause_id());
// Prevent a memory leak
for (auto &i : component_stack_)
delete i;
component_stack_.clear();
component_stack_.reserve(ana_.max_variable_id() + 2);
component_stack_.push_back(new Component());
component_stack_.push_back(new Component());
assert(component_stack_.size() == 2);
component_stack_.back()->createAsDummyComponent(ana_.max_variable_id(),
ana_.max_clause_id());
if (config_.perform_random_sampling_)
cached_vars_.clear();
cache_.init(*component_stack_.back(), quiet);
}
void ComponentManager::removeAllCachePollutionsOf(StackLevel &top) {
// all processed components are found in
// [top.currentRemainingComponent(), component_stack_.size())
// first, remove the list of descendants from the father
assert(top.remaining_components_ofs() <= component_stack_.size());
assert(top.super_component() != 0);
assert(cache_.hasEntry(super_component(top).id()));
if (top.remaining_components_ofs() == component_stack_.size())
return;
for (unsigned u = top.remaining_components_ofs(); u < component_stack_.size();
u++) {
assert(cache_.hasEntry(component_stack_[u]->id()));
cache_.cleanPollutionsInvolving(component_stack_[u]->id());
}
#ifdef DEBUG
cache_.test_descendantstree_consistency();
#endif
}
std::vector<VariableIndex> ComponentManager::buildFreedVariableList(const StackLevel & top,
const std::vector<LiteralID> &literal_stack) {
Component * descendant_comp, *ref_comp = component_stack_[top.super_component()];
const VariableIndex original_var_count = ref_comp->num_variables();
VariableIndex num_unused_vars = original_var_count;
std::vector<bool> var_in_descendants(original_var_count, false);
std::vector<ComponentVarAndCls> descendant_vars, ref_vars = ref_comp->getData();
for (unsigned comp_id=top.remaining_components_ofs();
comp_id < top.unprocessed_components_end(); comp_id++) {
descendant_comp = component_stack_[comp_id];
descendant_vars = descendant_comp->getData();
UpdateVarDescedantsList(ref_vars, ref_comp->num_variables(), var_in_descendants,
descendant_vars, descendant_comp->num_variables());
num_unused_vars -= descendant_comp->num_variables();
}
// Build a list of all literals assigned in the last round
const long list_stack_ofs = top.literal_stack_ofs();
VariableIndex num_lits_assigned = literal_stack.size() - list_stack_ofs;
std::vector<ComponentVarAndCls> assigned_stack_vars;
assigned_stack_vars.reserve(num_lits_assigned);
for (VariableIndex stack_i = 0; stack_i < num_lits_assigned; stack_i++)
assigned_stack_vars.push_back(literal_stack[list_stack_ofs + stack_i].var());
// Sort the vector and exclude the assigned literals
sort(assigned_stack_vars.begin(), assigned_stack_vars.end());
num_unused_vars -= UpdateVarDescedantsList(ref_vars, ref_comp->num_variables(),
var_in_descendants, assigned_stack_vars,
num_lits_assigned);
// Skip the cached variables
num_unused_vars -= UpdateVarDescedantsList(ref_vars, ref_comp->num_variables(),
var_in_descendants,
cached_vars_, cached_vars_.size());
// If a variable does not appear in the descendant nor in the cache and is not on
// top of the literal stack, it was freed.
std::vector<VariableIndex> freed_vars;
freed_vars.reserve(num_unused_vars);
for (VariableIndex ref_i = 0; ref_i < ref_comp->num_variables(); ref_i++) {
if (!var_in_descendants[ref_i])
freed_vars.push_back(ref_vars[ref_i]);
}
assert(num_unused_vars == freed_vars.size());
return freed_vars;
}
VariableIndex UpdateVarDescedantsList(const std::vector<ComponentVarAndCls> &ref_vars,
VariableIndex ref_num_vars,
std::vector<bool> &varInDescendants,
std::vector<ComponentVarAndCls> descendant_vars,
VariableIndex desc_num_vars) {
if (desc_num_vars == 0)
return 0;
VariableIndex varsRemoved = 0;
VariableIndex ref_i, desc_i = 0;
for (ref_i = 0; ref_i < ref_num_vars; ref_i++) {
// Reference list is always a superset and since both are sorted, go to the next
if (ref_vars[ref_i] < descendant_vars[desc_i])
continue;
if (ref_vars[ref_i] > descendant_vars[desc_i])
desc_i++;
if (desc_i >= desc_num_vars)
break;
// If the descendant and reference match, the var is present
if (ref_vars[ref_i] == descendant_vars[desc_i]) {
// DebugZH - A variable should only be in a single descedent
assert(!varInDescendants[ref_i]);
varInDescendants[ref_i] = true;
varsRemoved++;
}
}
return varsRemoved;
}
Includes¶
algorithm
component_management.h
(File component_management.h)
File component_management.h¶
↰ Parent directory (src
)
Definition (src/component_management.h
)¶
↰ Return to documentation for file (src/component_management.h
)
#ifndef COMPONENT_MANAGEMENT_H_
#define COMPONENT_MANAGEMENT_H_
#include <gmpxx.h>
#include <utility>
#include <algorithm>
#include <string>
#include <vector>
#include "component_types/component.h"
#include "component_cache.h"
#include "alt_component_analyzer.h"
#include "containers.h"
#include "stack.h"
#include "solver_config.h"
#include "model_sampler.h"
//#include "top_tree_sampler.h"
typedef AltComponentAnalyzer ComponentAnalyzer;
class ComponentManager {
public:
ComponentManager(SolverConfiguration &config, DataAndStatistics &statistics,
LiteralIndexedVector<TriValue> & lit_values) :
config_(config), /*statistics_(statistics),*/ cache_(statistics, config),
ana_(statistics, lit_values) {
}
void initialize(LiteralIndexedVector<Literal> & literals,
std::vector<LiteralID> &lit_pool, bool quiet = false);
unsigned scoreOf(VariableIndex v) {
return ana_.scoreOf(v);
}
void cacheModelCountOf(VariableIndex stack_comp_id, const mpz_class &value) {
if (config_.perform_component_caching)
cache_.storeValueOf(component_stack_[stack_comp_id]->id(), value);
}
void cacheModelCountAndAssignment(const VariableIndex stack_comp_id, const mpz_class &value,
const SampleAssignment &assn, const Component &component) {
mpz_class combined_value = 0;
mpz_class temp_value = 0;
// If the component is UNSAT do not push any assignment
if (value > 0) {
VariableIndex last_shift_len = 0, offset_amount = 0;
uint64_t cached_word = 0;
const VariableIndex MAX_OFFSET_AMOUNT = 28;
std::vector<ComponentVarAndCls> comp_data = component.getData();
for (VariableIndex i = 0; i < component.num_variables(); i++) {
AssignmentEncoding var_assn = assn.var_assignment(comp_data[i]);
// Make sure the assignment is valid
assert((var_assn != ASSN_U && !assn.IsVarEmancipated(comp_data[i]))
|| (var_assn == ASSN_U && assn.IsVarEmancipated(comp_data[i])));
cached_word += var_assn << (offset_amount);
if (offset_amount == MAX_OFFSET_AMOUNT) {
mpz_import(temp_value.get_mpz_t(), 1, 1, sizeof(cached_word), 0, 0, &cached_word);
combined_value += temp_value << last_shift_len;
last_shift_len = CACHED_VARIABLE_LEN * (i + 1);
offset_amount = 0;
cached_word = 0;
} else {
offset_amount += CACHED_VARIABLE_LEN;
}
}
if (offset_amount > 0) {
mpz_import(temp_value.get_mpz_t(), 1, 1, sizeof(cached_word), 0, 0, &cached_word);
combined_value += temp_value << last_shift_len;
}
combined_value += value << (CACHED_VARIABLE_LEN * component.num_variables());
}
cacheModelCountOf(stack_comp_id, combined_value);
}
Component & superComponentOf(StackLevel &lev) {
assert(component_stack_.size() > lev.super_component());
return *component_stack_[lev.super_component()];
}
const Component & super_component(StackLevel &lev) const {
assert(component_stack_.size() > lev.super_component());
return *component_stack_[lev.super_component()];
}
VariableIndex component_stack_size() const {
return static_cast<VariableIndex>(component_stack_.size());
}
void cleanRemainingComponentsOf(StackLevel &top) {
while (component_stack_.size() > top.remaining_components_ofs()) {
if (cache_.hasEntry(component_stack_.back()->id()))
cache_.entry(component_stack_.back()->id()).set_deletable();
delete component_stack_.back();
component_stack_.pop_back();
}
assert(top.remaining_components_ofs() <= component_stack_.size());
}
inline const Component &component(unsigned long comp_idx) const {
return *component_stack_[comp_idx];
}
// Component & currentRemainingComponentOf(StackLevel &top) {
// assert(component_stack_.size() > top.currentRemainingComponent());
// return *component_stack_[top.currentRemainingComponent()];
// }
inline bool findNextRemainingComponentOf(StackLevel &top,
const std::vector<LiteralID> &literal_stack,
SamplesManager &samples);
inline void recordRemainingCompsFor(StackLevel &top,
const std::vector<LiteralID> &literal_stack);
inline void buildResidualComponent(StackLevel &top);
inline Component* top_stack() {
return component_stack_.back();
}
inline void sortComponentStackRange(unsigned long start, unsigned long end);
void gatherStatistics() {
// statistics_.cache_bytes_memory_usage_ =
// cache_.recompute_bytes_memory_usage();
cache_.compute_byte_size_infrastructure();
}
void removeAllCachePollutionsOf(StackLevel &top);
std::vector<VariableIndex> buildFreedVariableList(const StackLevel & top,
const std::vector<LiteralID> &literal_stack);
private:
std::vector<VariableIndex> cached_vars_;
std::vector<CacheEntryID> cached_comp_ids_;
SolverConfiguration &config_;
// DataAndStatistics &statistics_;
std::vector<Component *> component_stack_;
ComponentCache cache_;
ComponentAnalyzer ana_;
};
void ComponentManager::sortComponentStackRange(unsigned long start, unsigned long end) {
assert(start <= end);
// sort the remaining components for processing
for (unsigned long i = start; i < end; i++)
for (unsigned long j = i + 1; j < end; j++) {
if (component_stack_[i]->num_variables()
< component_stack_[j]->num_variables())
std::swap(component_stack_[i], component_stack_[j]);
}
}
bool ComponentManager::findNextRemainingComponentOf(StackLevel &top,
const std::vector<LiteralID> &literal_stack,
SamplesManager &samples) {
// record Remaining Components if there are none!
if (component_stack_.size() <= top.remaining_components_ofs())
recordRemainingCompsFor(top, literal_stack);
assert(!top.branch_found_unsat());
if (top.hasUnprocessedComponents()) {
// Perform reservoir sampling if the model count is greater than zero
if (config_.perform_random_sampling_ && top.getActiveModelCount() > 0) {
if (!top.isComponentSplit() || top.isFirstComponent()) {
top.includeSolutionSampleMultiplier(top.getActiveModelCount());
std::vector<VariableIndex> freed_vars = buildFreedVariableList(top, literal_stack);
top.addFreeVariables(freed_vars);
top.addCachedCompIds(cached_comp_ids_);
}
}
return true;
}
// if no component remains
// make sure, at least that the current branch is considered SAT
top.includeSolution(1);
// Perform reservoir sampling if the model count is greater than zero
if (config_.store_sampled_models()) {
if (config_.verbose) {
std::cout << "\t# Solutions Found: " << top.getActiveModelCount()
<< ". Total multiplied weight is "
<< top.getActiveModelCount() * top.getSamplerSolutionMultiplier()
<< std::endl;
}
SampleAssignment cached_sample(config_.num_samples_to_cache_);
if (!top.cached_comp_ids().empty())
cached_comp_ids_.insert(cached_comp_ids_.end(), top.cached_comp_ids().begin(),
top.cached_comp_ids().end());
samples.reservoirSample(component_stack_[top.super_component()], literal_stack,
top.getActiveModelCount(), top.getSamplerSolutionMultiplier(),
ana_, top.literal_stack_ofs(), top.emancipated_vars(),
cached_comp_ids_, top.cached_assn(), cached_sample);
if (config_.perform_sample_caching()) {
top.ClearCachedAssn();
top.set_cache_sample(cached_sample);
}
// DebugZH
// assert(samples.VerifySolutions(statistics_.input_file_, true));
}
return false;
}
void ComponentManager::recordRemainingCompsFor(StackLevel &top,
const std::vector<LiteralID> &literal_stack) {
Component & super_comp = superComponentOf(top);
VariableIndex new_comps_start_ofs = component_stack_.size(); // Location to store new comp if any
// Clear the variables considered cached.
cached_vars_.clear();
cached_comp_ids_.clear();
CachedAssignment cached_assn;
// Initialize data structures for the component analyzer
ana_.setupAnalysisContext(top, super_comp);
// Go through each variable and checks its component to see if cached or new
for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) {
if (ana_.isUnseenAndActive(*vt) && ana_.exploreRemainingCompOf(*vt)) {
Component *p_new_comp = ana_.makeComponentFromArcheType();
auto *packed_comp = new CacheableComponent(ana_.getArchetype().current_comp_for_caching_);
CacheEntryID cache_entry_id;
if (!cache_.manageNewComponent(top, *packed_comp, p_new_comp, cached_assn, cache_entry_id)) {
component_stack_.push_back(p_new_comp);
p_new_comp->set_id(cache_.storeAsEntry(*packed_comp, super_comp.id()));
} else {
if (config_.perform_random_sampling_) {
// Store any cached vars in case of a split.
std::vector<ComponentVarAndCls> cached_comp_data = p_new_comp->getData();
VariableIndex comp_i = 0;
// Store the variables in the component for proper processing of emancipated variables
while (cached_comp_data[comp_i] != varsSENTINEL) {
cached_vars_.push_back(cached_comp_data[comp_i]);
comp_i++;
}
cached_comp_ids_.push_back(cache_entry_id);
}
// Delete component as it was found in the cache
delete packed_comp;
delete p_new_comp;
}
}
}
top.set_unprocessed_components_end(component_stack_.size());
sortComponentStackRange(new_comps_start_ofs, component_stack_.size());
if (config_.perform_random_sampling_) {
long split_width = component_stack_.size() - new_comps_start_ofs;
if (split_width > 1 || (split_width == 1 && !cached_assn.empty())) {
top.setAsComponentSplit();
if (config_.verbose) {
std::stringstream ss;
ss << "Component #" << (new_comps_start_ofs - 1) << " split into " << (split_width)
<< " pieces at depth " << StackLevel::componentSplitDepth() << ".";
PrintInColor(ss, COLOR_CYAN);
}
}
if (!cached_assn.empty())
top.set_cached_assn(cached_assn);
}
// For simplicity, sort the cached variable list
if (cached_vars_.size() > 1) {
sort(cached_vars_.begin(), cached_vars_.end());
sort(cached_comp_ids_.begin(), cached_comp_ids_.end());
}
}
void ComponentManager::buildResidualComponent(StackLevel &top) {
Component & super_comp = superComponentOf(top);
std::vector<VariableIndex> comp_vars;
std::vector<ClauseIndex> comp_cls;
// Initialize data structures for the component analyzer
ana_.setupAnalysisContext(top, super_comp);
// Go through all components to be spawned and build a list of vars and comp
for (auto vt = super_comp.varsBegin(); *vt != varsSENTINEL; vt++) {
if (ana_.isUnseenAndActive(*vt) && ana_.exploreRemainingCompOf(*vt)) {
Component *p_new_comp = ana_.makeComponentFromArcheType();
auto comp_data = p_new_comp->getData();
for (VariableIndex i = 0; i < p_new_comp->num_variables(); i++)
comp_vars.push_back(comp_data[i]);
for (ClauseIndex i = 0; i < p_new_comp->numLongClauses(); i++) {
ClauseIndex cls = comp_data[p_new_comp->clauses_ofs() + i];
comp_cls.push_back(cls);
}
delete p_new_comp;
}
}
delete component_stack_.back();
component_stack_.pop_back();
// Sort the lists as components are build from only sorted lists
std::sort(comp_vars.begin(), comp_vars.end());
std::sort(comp_cls.begin(), comp_cls.end());
auto * initial_component = new Component();
for (auto var : comp_vars)
initial_component->addVar(var);
initial_component->closeVariableData();
for (auto cls : comp_cls)
initial_component->addCl(cls);
initial_component->closeClauseData();
component_stack_.push_back(initial_component);
}
VariableIndex UpdateVarDescedantsList(const std::vector<ComponentVarAndCls> &ref_vars,
VariableIndex ref_num_vars,
std::vector<bool> &varInDescendants,
std::vector<ComponentVarAndCls> descendant_vars,
VariableIndex desc_num_vars);
//bool varInVector(long var_num, std::vector<unsigned int> vec);
#endif /* COMPONENT_MANAGEMENT_H_ */
Includes¶
algorithm
alt_component_analyzer.h
(File alt_component_analyzer.h)component_cache.h
(File component_cache.h)component_types/component.h
(File component.h)containers.h
(File containers.h)gmpxx.h
model_sampler.h
(File model_sampler.h)solver_config.h
(File solver_config.h)stack.h
(File stack.h)string
utility
vector
Included By¶
Classes¶
Functions¶
Typedefs¶
File containers.h¶
↰ Parent directory (src
)
Definition (src/containers.h
)¶
↰ Return to documentation for file (src/containers.h
)
#ifndef CONTAINERS_H_
#define CONTAINERS_H_
#include <vector>
#include "structures.h"
template<class _T>
/***
* @tparam _T Type of element to store in the vector.
*/
class LiteralIndexedVector: protected std::vector<_T> {
public:
explicit LiteralIndexedVector(VariableIndex size = 0) :
std::vector<_T>(size * 2) {
}
LiteralIndexedVector(VariableIndex size, const typename std::vector<_T>::value_type& __value)
: std::vector<_T>(size * 2, __value) {
}
inline _T &operator[](const LiteralID lit) {
return *(std::vector<_T>::begin() + lit.raw());
}
inline const _T &operator[](const LiteralID &lit) const {
return *(std::vector<_T>::begin() + lit.raw());
}
inline typename std::vector<_T>::iterator begin() {
return std::vector<_T>::begin() + 2;
}
void resize(VariableIndex _size) {
std::vector<_T>::resize(_size * 2);
}
void resize(VariableIndex _size, const typename std::vector<_T>::value_type& _value) {
std::vector<_T>::resize(_size * 2, _value);
}
void reserve(VariableIndex _size) {
std::vector<_T>::reserve(_size * 2);
}
LiteralID end_lit() {
return LiteralID(size() / 2, false);
}
// Methods reused from the imported class
using std::vector<_T>::end;
using std::vector<_T>::size;
using std::vector<_T>::clear;
using std::vector<_T>::push_back;
};
#endif /* CONTAINERS_H_ */
Includes¶
structures.h
(File structures.h)vector
File difference_packed_component.h¶
↰ Parent directory (src/component_types
)
Contents
Definition (src/component_types/difference_packed_component.h
)¶
↰ Return to documentation for file (src/component_types/difference_packed_component.h
)
#ifndef DIFFERENCE_PACKED_COMPONENT_H_
#define DIFFERENCE_PACKED_COMPONENT_H_
#include <math.h>
#include "base_packed_component.h"
#include "component.h"
class DifferencePackedComponent:public BasePackedComponent {
public:
DifferencePackedComponent() = default;
inline explicit DifferencePackedComponent(Component &rComp);
unsigned num_variables() const {
uint64_t *p = reinterpret_cast<uint64_t *>(data_);
// ToDo Thurley is doing something suspect here - Types dont have any casting
return (*p >> bits_of_data_size()) & (uint64_t) variable_mask();
}
unsigned data_size() const {
return *data_ & _data_size_mask;
}
unsigned data_only_byte_size() const {
return data_size()* sizeof(unsigned);
}
unsigned raw_data_byte_size() const {
return data_size()* sizeof(unsigned) + model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t);
}
// raw data size with the overhead
// for the supposed 16byte alignment of malloc
unsigned sys_overhead_raw_data_byte_size() const {
unsigned ds = data_size()* sizeof(unsigned);
unsigned ms = model_count_.get_mpz_t()->_mp_alloc * sizeof(mp_limb_t);
// unsigned mask = 0xfffffff8;
// return (ds & mask) + ((ds & 7)?8:0)
// +(ms & mask) + ((ms & 7)?8:0);
unsigned mask = 0xfffffff0;
return (ds & mask) + ((ds & 15)?16:0) +(ms & mask) + ((ms & 15)?16:0);
}
bool equals(const DifferencePackedComponent &comp) const {
if (hashkey_ != comp.hashkey())
return false;
unsigned* p = data_;
unsigned* r = comp.data_;
while (p != data_ + data_size()) {
if (*(p++) != *(r++))
return false;
}
return true;
}
private:
};
DifferencePackedComponent::DifferencePackedComponent(Component &rComp) {
unsigned max_var_diff = 0;
unsigned hashkey_vars = *rComp.varsBegin();
for (auto it = rComp.varsBegin() + 1; *it != varsSENTINEL; it++) {
hashkey_vars = (hashkey_vars * 3) + *it;
if ((*it - *(it - 1)) - 1 > max_var_diff)
max_var_diff = (*it - *(it - 1)) - 1;
}
unsigned hashkey_clauses = *rComp.clsBegin();
unsigned max_clause_diff = 0;
if (*rComp.clsBegin()) {
for (auto jt = rComp.clsBegin() + 1; *jt != clsSENTINEL; jt++) {
hashkey_clauses = hashkey_clauses*3 + *jt;
if (*jt - *(jt - 1) - 1 > max_clause_diff)
max_clause_diff = *jt - *(jt - 1) - 1;
}
}
hashkey_ = hashkey_vars + (hashkey_clauses << 11) + (hashkey_clauses >> 23);
//VERIFIED the definition of bits_per_var_diff and bits_per_clause_diff
unsigned bits_per_var_diff = log2(max_var_diff) + 1;
unsigned bits_per_clause_diff = log2(max_clause_diff) + 1;
assert(bits_per_var_diff <= 31);
assert(bits_per_clause_diff <= 31);
unsigned data_size_vars = bits_of_data_size() + 2*bits_per_variable() + 5;
data_size_vars += (rComp.num_variables() - 1) * bits_per_var_diff;
unsigned data_size_clauses = 0;
if (*rComp.clsBegin())
data_size_clauses += bits_per_clause() + 5
+ (rComp.numLongClauses() - 1) * bits_per_clause_diff;
unsigned data_size = (data_size_vars + data_size_clauses)/bits_per_block();
data_size+= ((data_size_vars + data_size_clauses) % bits_per_block())? 1 : 0;
data_ = new unsigned[data_size];
assert((data_size >> bits_of_data_size()) == 0);
BitStuffer<unsigned> bs(data_);
bs.stuff(data_size, bits_of_data_size());
bs.stuff(rComp.num_variables(), bits_per_variable());
bs.stuff(bits_per_var_diff, 5);
bs.stuff(*rComp.varsBegin(), bits_per_variable());
if (bits_per_var_diff) {
for (auto it = rComp.varsBegin() + 1; *it != varsSENTINEL; it++)
bs.stuff(*it - *(it - 1) - 1, bits_per_var_diff);
}
if (*rComp.clsBegin()) {
bs.stuff(bits_per_clause_diff, 5);
bs.stuff(*rComp.clsBegin(), bits_per_clause());
if (bits_per_clause_diff) {
for (auto jt = rComp.clsBegin() + 1; *jt != clsSENTINEL; jt++)
bs.stuff(*jt - *(jt - 1) - 1, bits_per_clause_diff);
}
}
// to check wheter the "END" block of bits_per_clause()
// many zeros fits into the current
// bs.end_check(bits_per_clause());
// this will tell us if we computed the data_size
// correctly
bs.assert_size(data_size);
}
#endif /* DIFFERENCE_PACKED_COMPONENT_H_ */
Includes¶
base_packed_component.h
(File base_packed_component.h)component.h
(File base_packed_component.h)math.h
Included By¶
Classes¶
File instance.cpp¶
↰ Parent directory (src
)
Contents
Definition (src/instance.cpp
)¶
↰ Return to documentation for file (src/instance.cpp
)
#include <sys/stat.h>
#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include "instance.h"
#include "model_sampler.h"
void Instance::cleanClause(ClauseOfs cl_ofs) {
bool satisfied = false;
for (auto it = beginOf(cl_ofs); *it != SENTINEL_LIT; it++)
if (isSatisfied(*it)) {
satisfied = true;
break;
}
// mark the clause as empty if satisfied
if (satisfied) {
*beginOf(cl_ofs) = SENTINEL_LIT;
return;
}
auto jt = beginOf(cl_ofs);
auto it = beginOf(cl_ofs);
// from now, all inactive literals are resolved
for (; *it != SENTINEL_LIT; it++, jt++) {
while (*jt != SENTINEL_LIT && !isActive(*jt))
jt++;
*it = *jt;
if (*jt == SENTINEL_LIT)
break;
}
unsigned length = it - beginOf(cl_ofs);
// if it has become a unit clause, it should have already been asserted
if (length == 1) {
*beginOf(cl_ofs) = SENTINEL_LIT;
// if it has become binary, transform it to binary and delete it
} else if (length == 2) {
addBinaryClause(*beginOf(cl_ofs), *(beginOf(cl_ofs) + 1));
*beginOf(cl_ofs) = SENTINEL_LIT;
}
}
void Instance::compactClauses() {
std::vector<ClauseOfs> clause_ofs;
clause_ofs.reserve(statistics_.num_long_clauses_);
// clear watch links and occurrence lists
for (auto it_lit = literal_pool_.begin(); it_lit != literal_pool_.end();
it_lit++) {
if (*it_lit == SENTINEL_LIT) {
if (it_lit + 1 == literal_pool_.end())
break;
it_lit += ClauseHeader::overheadInLits();
clause_ofs.push_back(1 + it_lit - literal_pool_.begin());
}
}
for (auto ofs : clause_ofs)
cleanClause(ofs);
for (auto &l : literals_)
l.resetWatchList();
occurrence_lists_.clear();
occurrence_lists_.resize(variables_.size());
std::vector<LiteralID> tmp_pool = literal_pool_;
literal_pool_.clear();
literal_pool_.push_back(SENTINEL_LIT);
ClauseOfs new_ofs;
unsigned num_clauses = 0;
for (auto ofs : clause_ofs) {
auto it = (tmp_pool.begin() + ofs);
if (*it != SENTINEL_LIT) {
for (unsigned i = 0; i < ClauseHeader::overheadInLits(); i++)
literal_pool_.emplace_back(0);
new_ofs = literal_pool_.size();
literal(*it).addWatchLinkTo(new_ofs);
literal(*(it + 1)).addWatchLinkTo(new_ofs);
num_clauses++;
for (; *it != SENTINEL_LIT; it++) {
literal_pool_.push_back(*it);
occurrence_lists_[*it].push_back(new_ofs);
}
literal_pool_.push_back(SENTINEL_LIT);
}
}
std::vector<LiteralID> tmp_bin;
unsigned bin_links = 0;
for (auto &l : literals_) {
tmp_bin.clear();
for (auto it = l.binary_links_.begin(); *it != SENTINEL_LIT; it++)
if (isActive(*it))
tmp_bin.push_back(*it);
bin_links += tmp_bin.size();
tmp_bin.push_back(SENTINEL_LIT);
l.binary_links_ = tmp_bin;
}
statistics_.num_long_clauses_ = num_clauses;
statistics_.num_binary_clauses_ = bin_links >> 1;
}
void Instance::compactVariables() {
std::vector<unsigned> var_map(variables_.size(), 0);
unsigned last_ofs = 0;
unsigned num_isolated = 0; // Emancipated/freed variables no longer in any clause
LiteralIndexedVector<std::vector<LiteralID> > _tmp_bin_links(1);
LiteralIndexedVector<TriValue> _tmp_values = literal_values_;
for (auto l : literals_)
_tmp_bin_links.push_back(l.binary_links_);
assert(_tmp_bin_links.size() == literals_.size());
for (unsigned v = 1; v < variables_.size(); v++)
if (isActive(v)) {
if (isolated(v)) {
std::cout << "Variable " << v << " is isolated." << std::endl;
num_isolated++;
continue;
}
last_ofs++;
var_map[v] = last_ofs;
}
variables_.clear();
variables_.resize(last_ofs + 1);
occurrence_lists_.clear();
occurrence_lists_.resize(variables_.size());
literals_.clear();
literals_.resize(variables_.size());
literal_values_.clear();
literal_values_.resize(variables_.size(), X_TRI);
unsigned bin_links = 0;
LiteralID newlit;
for (auto l = LiteralID(0, false); l != _tmp_bin_links.end_lit(); l.inc()) {
if (var_map[l.var()] != 0) {
newlit = LiteralID(var_map[l.var()], l.sign());
for (auto it = _tmp_bin_links[l].begin(); *it != SENTINEL_LIT; it++) {
assert(var_map[it->var()] != 0);
literals_[newlit].addBinLinkTo(
LiteralID(var_map[it->var()], it->sign()));
}
bin_links += literals_[newlit].binary_links_.size() - 1;
}
}
std::vector<ClauseOfs> clause_ofs;
clause_ofs.reserve(statistics_.num_long_clauses_);
// clear watch links and occurrence lists
for (auto it_lit = literal_pool_.begin(); it_lit != literal_pool_.end();
it_lit++) {
if (*it_lit == SENTINEL_LIT) {
if (it_lit + 1 == literal_pool_.end())
break;
it_lit += ClauseHeader::overheadInLits();
clause_ofs.push_back(1 + it_lit - literal_pool_.begin());
}
}
for (auto ofs : clause_ofs) {
literal(LiteralID(var_map[beginOf(ofs)->var()], beginOf(ofs)->sign())).addWatchLinkTo(
ofs);
literal(LiteralID(var_map[(beginOf(ofs) + 1)->var()],
(beginOf(ofs) + 1)->sign())).addWatchLinkTo(ofs);
for (auto it_lit = beginOf(ofs); *it_lit != SENTINEL_LIT; it_lit++) {
*it_lit = LiteralID(var_map[it_lit->var()], it_lit->sign());
occurrence_lists_[*it_lit].push_back(ofs);
}
}
literal_values_.clear();
literal_values_.resize(variables_.size(), X_TRI);
unit_clauses_.clear();
statistics_.num_variables_ = variables_.size() - 1 + num_isolated;
statistics_.num_used_variables_ = num_variables();
statistics_.num_free_variables_ = num_isolated;
}
void Instance::compactConflictLiteralPool() {
auto write_pos = conflict_clauses_begin();
std::vector<ClauseOfs> tmp_conflict_clauses = conflict_clauses_;
conflict_clauses_.clear();
for (auto clause_ofs : tmp_conflict_clauses) {
auto read_pos = beginOf(clause_ofs) - ClauseHeader::overheadInLits();
for (unsigned i = 0; i < ClauseHeader::overheadInLits(); i++)
*(write_pos++) = *(read_pos++);
ClauseOfs new_ofs = write_pos - literal_pool_.begin();
conflict_clauses_.push_back(new_ofs);
// first substitute antecedent if clause_ofs implied something
if (isAntecedentOf(clause_ofs, *beginOf(clause_ofs)))
var(*beginOf(clause_ofs)).ante = Antecedent(new_ofs);
// now redo the watches
literal(*beginOf(clause_ofs)).replaceWatchLinkTo(clause_ofs, new_ofs);
literal(*(beginOf(clause_ofs)+1)).replaceWatchLinkTo(clause_ofs, new_ofs);
// next, copy clause data
assert(read_pos == beginOf(clause_ofs));
while (*read_pos != SENTINEL_LIT)
*(write_pos++) = *(read_pos++);
*(write_pos++) = SENTINEL_LIT;
}
literal_pool_.erase(write_pos, literal_pool_.end());
}
//bool Instance::deleteConflictClauses() {
// statistics_.times_conflict_clauses_cleaned_++;
// std::vector<ClauseOfs> tmp_conflict_clauses = conflict_clauses_;
// conflict_clauses_.clear();
// std::vector<double> tmp_ratios;
// double score, lifetime;
// for (auto clause_ofs: tmp_conflict_clauses) {
// score = getHeaderOf(clause_ofs).score();
// lifetime = statistics_.num_conflicts_ - getHeaderOf(clause_ofs).creation_time();
// tmp_ratios.push_back(score/lifetime/(getHeaderOf(clause_ofs).length()));
// }
// std::vector<double> tmp_ratiosB = tmp_ratios;
//
// sort(tmp_ratiosB.begin(), tmp_ratiosB.end());
//
// double cutoff = tmp_ratiosB[tmp_ratiosB.size()/2];
//
// for (unsigned i = 0; i < tmp_conflict_clauses.size(); i++) {
// if (tmp_ratios[i] < cutoff) {
// if (!markClauseDeleted(tmp_conflict_clauses[i]))
// conflict_clauses_.push_back(tmp_conflict_clauses[i]);
// } else
// conflict_clauses_.push_back(tmp_conflict_clauses[i]);
// }
// return true;
//}
bool Instance::deleteConflictClauses(bool delete_all) {
statistics_.times_conflict_clauses_cleaned_++;
std::vector<ClauseOfs> tmp_conflict_clauses = conflict_clauses_;
conflict_clauses_.clear();
std::vector<double> tmp_ratios;
for (auto clause_ofs : tmp_conflict_clauses) {
double score = getHeaderOf(clause_ofs).score();
// lifetime = statistics_.num_conflicts_ - getHeaderOf(clause_ofs).creation_time();
// tmp_ratios.push_back(score/lifetime);
tmp_ratios.push_back(score);
}
std::vector<double> tmp_ratiosB = tmp_ratios;
sort(tmp_ratiosB.begin(), tmp_ratiosB.end());
double cutoff = -1;
if (!tmp_ratiosB.empty())
cutoff = tmp_ratiosB[tmp_ratiosB.size()/2];
for (unsigned i = 0; i < tmp_conflict_clauses.size(); i++) {
if (delete_all) {
markClauseDeleted(tmp_conflict_clauses[i]);
continue;
}
if (tmp_ratios[i] < cutoff) {
if (!markClauseDeleted(tmp_conflict_clauses[i]))
conflict_clauses_.push_back(tmp_conflict_clauses[i]);
} else {
conflict_clauses_.push_back(tmp_conflict_clauses[i]);
}
}
return true;
}
bool Instance::markClauseDeleted(ClauseOfs cl_ofs) {
// only first literal may possibly have cl_ofs as antecedent
if (isAntecedentOf(cl_ofs, *beginOf(cl_ofs)))
return false;
literal(*beginOf(cl_ofs)).removeWatchLinkTo(cl_ofs);
literal(*(beginOf(cl_ofs)+1)).removeWatchLinkTo(cl_ofs);
return true;
}
bool Instance::createfromFile(const std::string &file_name) {
if (!file_name.empty())
statistics_.input_file_ = file_name;
unsigned max_ignore = 1000000; // Max number of characters on line to ignore.
// Initialize the literal pool
literal_pool_.clear();
literal_pool_.push_back(SENTINEL_LIT);
// Builds the list
variables_.clear();
variables_.emplace_back(); //initializing the Sentinel
literal_values_.clear();
unit_clauses_.clear();
unused_vars_.clear();
// BEGIN File input
std::ifstream input_file(statistics_.input_file_);
if (!input_file)
ExitWithError("Cannot open file: " + statistics_.input_file_, EX_IOERR);
char c;
while ((input_file >> c) && c != 'p')
ParseCnfCommentForSupport(input_file);
std::string idstring;
long nVars = -1, nCls = -1;
if (!((input_file >> idstring) && idstring == "cnf" && (input_file >> nVars)
&& (input_file >> nCls)))
ExitWithError("Invalid CNF file", EX_PROTOCOL);
else if (nVars <= 0)
ExitWithError("Invalid variable count. At least one variable is required.", EX_PROTOCOL);
else if (nCls < 0)
ExitWithError("Invalid clause count. A negative clause count is invalid.", EX_PROTOCOL);
variables_.resize(nVars + FIRST_VAR);
literal_values_.resize(nVars + FIRST_VAR, X_TRI);
struct stat file_status;
stat(statistics_.input_file_ .c_str(), &file_status);
literal_pool_.reserve(file_status.st_size);
conflict_clauses_.reserve(2 * nCls);
occurrence_lists_.clear();
occurrence_lists_.resize(nVars + FIRST_VAR);
std::vector<LiteralID> literals;
literals_.clear();
literals_.resize(nVars + FIRST_VAR);
std::vector<bool> var_used(nVars + FIRST_VAR, false);
// Analyze each clause and add literals/variables as appropriate.
unsigned clauses_added = 0;
while ((input_file >> c) && clauses_added < nCls) {
input_file.unget(); // extracted a nonspace character to determine if
// we have a clause, so put it back
if ((c == '-') || isdigit(c)) {
literals.clear(); // Empty the literal set in the clause
bool skip_clause = false;
long lit;
while ((input_file >> lit) && lit != 0) {
var_used[abs(lit)] = true; // Mark the variable as used.
bool duplicate_literal = false;
for (auto i : literals) {
// Checks if same literal already in the clause
if (i.toInt() == lit) {
duplicate_literal = true;
break;
}
// Checks if a clause has a literal and its complement in the same clause.
if (i.toInt() == -lit) {
skip_clause = true;
break;
}
}
if (!duplicate_literal)
literals.emplace_back(lit);
}
if (!skip_clause) {
assert(!literals.empty()); // May report a fail in an UNSAT file.
clauses_added++;
statistics_.incorporateClauseData(literals);
long cl_ofs = addClause(literals);
if (cl_ofs == CLAUSE_ADDING_ERROR)
return false;
// If the clause is non-binary and non-unit, then
// Add to the occurrence list for the literal.
if (literals.size() >= 3)
for (auto l : literals)
occurrence_lists_[l].push_back(cl_ofs);
}
} else if (c == 'c') {
input_file >> c;
ParseCnfCommentForSupport(input_file);
continue;
}
input_file.ignore(max_ignore, '\n');
}
// END NEW
input_file.close();
// /// END FILE input
statistics_.num_variables_ = statistics_.num_original_variables_ = (VariableIndex)nVars;
statistics_.num_used_variables_ = num_variables();
statistics_.num_indep_support_variables_ = independent_support.size();
// statistics_.num_free_variables_ = nVars - num_variables(); // This line seems not to work right
if (!independent_support.empty()) {
has_independent_support_ = true;
std::sort(independent_support.begin(), independent_support.end());
}
// Get a list of unused variables.
statistics_.num_free_variables_ = 0;
for (VariableIndex i = 1; i < var_used.size(); i++) {
if (!var_used[i]) {
statistics_.num_free_variables_++;
// unused_vars_.push_back(i); // Done instead at the top of var stack
}
}
statistics_.num_original_clauses_ = static_cast<ClauseIndex>(nCls);
statistics_.num_original_binary_clauses_ = statistics_.num_binary_clauses_;
statistics_.num_original_unit_clauses_ = statistics_.num_unit_clauses_ = unit_clauses_.size();
original_lit_pool_size_ = literal_pool_.size();
return true;
}
void Instance::ParseCnfCommentForSupport(std::ifstream &input_file) {
std::string ind_str, line;
std::istringstream iss;
// Check if the comment line contains an independent support
std::getline(input_file, line);
iss.str(line);
iss.clear();
iss >> ind_str;
if (ind_str != "ind")
return;
VariableIndex support_var;
while ((iss >> support_var) && support_var != 0)
independent_support.emplace_back(support_var);
}
Includes¶
algorithm
fstream
instance.h
(File instance.h)model_sampler.h
(File model_sampler.h)string
sys/stat.h
vector
File instance.h¶
↰ Parent directory (src
)
Definition (src/instance.h
)¶
↰ Return to documentation for file (src/instance.h
)
#ifndef INSTANCE_H_
#define INSTANCE_H_
#include <sysexits.h>
#include <limits.h>
#include <cassert>
#include <string>
#include <vector>
#include "statistics.h"
#include "structures.h"
#include "containers.h"
#define CLAUSE_ADDING_ERROR INT_MIN
class Instance {
protected:
void unSet(LiteralID lit) {
var(lit).ante = Antecedent(NOT_A_CLAUSE);
var(lit).decision_level = INVALID_DL;
literal_values_[lit] = X_TRI;
literal_values_[lit.neg()] = X_TRI;
}
Antecedent & getAntecedent(LiteralID lit) {
return variables_[lit.var()].ante;
}
const Antecedent & antecedent(LiteralID lit) const {
return variables_[lit.var()].ante;
}
bool hasAntecedent(LiteralID lit) const {
return variables_[lit.var()].ante.isAnt();
}
bool isAntecedentOf(ClauseOfs ante_cl, LiteralID lit) {
return var(lit).ante.isAClause() && (var(lit).ante.asCl() == ante_cl);
}
bool isolated(VariableIndex v) {
LiteralID lit(v, false);
return (literal(lit).binary_links_.size() <= 1)
& occurrence_lists_[lit].empty()
& (literal(lit.neg()).binary_links_.size() <= 1)
& occurrence_lists_[lit.neg()].empty();
}
bool free(VariableIndex v) {
return isolated(v) & isActive(v);
}
bool deleteConflictClauses(bool delete_all = false);
bool markClauseDeleted(ClauseOfs cl_ofs);
// Compact the literal pool erasing all the clause
// information from deleted clauses
void compactConflictLiteralPool();
// we assert that the formula is consistent
// and has not been found UNSAT yet
// hard wires all assertions in the literal stack into the formula
// removes all set variables and essentially reinitiallizes all
// further data
void compactClauses();
void compactVariables();
void cleanClause(ClauseOfs cl_ofs);
// END access to variables and literals
unsigned long num_conflict_clauses() const {
return conflict_clauses_.size();
}
const VariableIndex num_variables() const {
return (VariableIndex)variables_.size() - 1;
}
bool createfromFile(const std::string &file_name);
DataAndStatistics statistics_;
std::vector<LiteralID> literal_pool_;
unsigned long original_lit_pool_size_;
LiteralIndexedVector<Literal> literals_;
LiteralIndexedVector<std::vector<ClauseOfs>> occurrence_lists_;
std::vector<ClauseOfs> conflict_clauses_;
std::vector<LiteralID> unit_clauses_;
std::vector<Variable> variables_;
LiteralIndexedVector<TriValue> literal_values_;
/*-------------------------------------------
-- Begin Sampler Objects --
-------------------------------------------*/
std::vector<VariableIndex> unused_vars_;
/*-------------------------------------------
-- End Sampler Objects --
-------------------------------------------*/
void decayActivities() {
for (auto l_it = literals_.begin(); l_it != literals_.end(); l_it++)
l_it->activity_score_ *= 0.5;
for (auto clause_ofs : conflict_clauses_)
getHeaderOf(clause_ofs).decayScore();
}
void updateActivities(ClauseOfs clause_ofs) {
getHeaderOf(clause_ofs).increaseScore();
for (auto it = beginOf(clause_ofs); *it != SENTINEL_LIT; it++) {
literal(*it).increaseActivity();
}
}
bool isUnitClause(const LiteralID lit) {
for (auto l : unit_clauses_)
if (l == lit)
return true;
return false;
}
bool existsUnitClauseOf(VariableIndex v) {
for (auto l : unit_clauses_)
// Extract the unit clause's variable number
if (l.var() == v)
return true;
return false;
}
void ParseCnfCommentForSupport(std::ifstream &input_file);
// addUnitClause checks whether lit or lit.neg() is already a
// unit clause
// a negative return value implied that the Instance is UNSAT
bool addUnitClause(const LiteralID lit) {
for (auto l : unit_clauses_) {
if (l == lit)
return true;
if (l == lit.neg())
return false;
}
unit_clauses_.push_back(lit);
return true;
}
inline long addClause(std::vector<LiteralID> &literals);
// adds a UIP Conflict Clause
// and returns it as an Antecedent to the first
// literal stored in literals
inline Antecedent addUIPConflictClause(std::vector<LiteralID> &literals);
inline bool addBinaryClause(LiteralID litA, LiteralID litB);
// BEGIN access to variables, literals, clauses
inline Variable& var(const LiteralID lit) {
//return variables_[lit.var()];
return const_cast<Variable&>(var_const(lit));
}
inline const Variable& var_const(const LiteralID lit) const {
return variables_[lit.var()];
}
Literal & literal(LiteralID lit) {
return literals_[lit];
}
inline bool isSatisfied(const LiteralID &lit) const {
return literal_values_[lit] == T_TRI;
}
bool isResolved(LiteralID lit) {
return literal_values_[lit] == F_TRI;
}
bool isActive(LiteralID lit) const {
return literal_values_[lit] == X_TRI;
}
std::vector<LiteralID>::const_iterator beginOf(ClauseOfs cl_ofs) const {
return literal_pool_.begin() + cl_ofs;
}
std::vector<LiteralID>::iterator beginOf(ClauseOfs cl_ofs) {
return literal_pool_.begin() + cl_ofs;
}
decltype(literal_pool_.begin()) conflict_clauses_begin() {
return literal_pool_.begin() + original_lit_pool_size_;
}
ClauseHeader &getHeaderOf(ClauseOfs cl_ofs) {
return *reinterpret_cast<ClauseHeader *>(&literal_pool_[cl_ofs
- ClauseHeader::overheadInLits()]);
}
bool isSatisfied(ClauseOfs cl_ofs) {
for (auto lt = beginOf(cl_ofs); *lt != SENTINEL_LIT; lt++)
if (isSatisfied(*lt))
return true;
return false;
}
bool has_independent_support_ = false;
std::vector<VariableIndex> independent_support;
};
long Instance::addClause(std::vector<LiteralID> &literals) {
if (literals.size() == 1) {
// MT_TODO Deal properly with the situation that opposing unit clauses are learned
// assert(!isUnitClause(literals[0].neg()));
if (isUnitClause(literals[0].neg()))
return CLAUSE_ADDING_ERROR;
unit_clauses_.push_back(literals[0]);
return 0;
}
if (literals.size() == 2) {
addBinaryClause(literals[0], literals[1]);
return 0;
}
for (unsigned i = 0; i < ClauseHeader::overheadInLits(); i++)
literal_pool_.emplace_back(0);
ClauseOfs cl_ofs = literal_pool_.size();
for (auto l : literals) {
literal_pool_.push_back(l);
literal(l).increaseActivity(1);
}
// make an end: SENTINEL_LIT
literal_pool_.push_back(SENTINEL_LIT);
literal(literals[0]).addWatchLinkTo(cl_ofs);
literal(literals[1]).addWatchLinkTo(cl_ofs);
getHeaderOf(cl_ofs).set_creation_time(statistics_.num_conflicts_);
return cl_ofs;
}
Antecedent Instance::addUIPConflictClause(std::vector<LiteralID> &literals) {
Antecedent ante(NOT_A_CLAUSE);
statistics_.num_clauses_learned_++;
ClauseOfs cl_ofs = addClause(literals);
if (cl_ofs != 0) {
conflict_clauses_.push_back(cl_ofs);
getHeaderOf(cl_ofs).set_length(literals.size());
ante = Antecedent(cl_ofs);
} else if (literals.size() == 2) {
ante = Antecedent(literals.back());
statistics_.num_binary_conflict_clauses_++;
} else if (literals.size() == 1) {
statistics_.num_unit_clauses_++;
}
return ante;
}
bool Instance::addBinaryClause(LiteralID litA, LiteralID litB) {
if (literal(litA).hasBinaryLinkTo(litB))
return false;
literal(litA).addBinLinkTo(litB);
literal(litB).addBinLinkTo(litA);
literal(litA).increaseActivity();
literal(litB).increaseActivity();
return true;
}
#endif /* INSTANCE_H_ */
Includes¶
cassert
containers.h
(File containers.h)limits.h
statistics.h
(File statistics.h)string
structures.h
(File structures.h)sysexits.h
vector
Included By¶
Classes¶
Defines¶
File main.cpp¶
↰ Parent directory (src
)
Contents
Definition (src/main.cpp
)¶
↰ Return to documentation for file (src/main.cpp
)
#include "sysexits.h"
#include <vector>
#include <iostream>
#include "solver.h"
int printInputArgumentDescription();
int main(int argc, char *argv[]) {
if (argc == 1 || (argc == 2 && strcmp(argv[0], "-h") == 0))
printInputArgumentDescription();
Solver theSolver(argc, argv);
if (theSolver.config().perform_random_sampling_)
theSolver.sample_models();
else
theSolver.solve();
return EXIT_SUCCESS;
}
int printInputArgumentDescription() {
std::cout << "Usage: spur [settings]\n"
<< "\t -cnf [cnf_file] Path to the CNF file\n"
<< "\t -s [s] \t Number of models \"s\" to sample uniformly at random\n"
<< "\t -tp \t Forces two-pass sampling. (Only applicable when s=1)\n"
<< "\t -out [out_file] Path to write the specified samples\n"
<< "\t -no-sample-write Disable writing the final samples to a file.\n"
<< "\t -count-only\t Perform only model counting. Disable sampling.\n"
<< "\t -q \t Quiet mode\n"
<< "\t -v \t Verbose and trace mode\n"
<< "\t -d \t Debug mode\n"
<< "\t -t [s] \t Set time bound to s seconds\n"
<< "\t -cs [n]\t Set max cache size to n MB\n"
<< std::flush;
exit(EX_USAGE);
}
Includes¶
iostream
solver.h
(File solver.h)sysexits.h
vector
File model_sampler.cpp¶
↰ Parent directory (src
)
Definition (src/model_sampler.cpp
)¶
↰ Return to documentation for file (src/model_sampler.cpp
)
#include <gmpxx.h>
#include <fstream>
// Used for precision string printing
#include <iomanip>
#include <sstream>
#include <algorithm>
#include "stack.h"
#include "model_sampler.h"
//#include "top_tree_sampler.h"
// Satisfy the linker by initializing the static variables
VariableIndex SampleAssignment::num_var_ = 0;
VariableIndex SampleAssignment::var_vec_len_ = 0;
void SamplesManager::exportFinal(std::ostream &out,
const DataAndStatistics& statistics,
const SolverConfiguration& config) {
time_t ltime = time(<ime);
tm cur_time;
localtime_r(<ime, &cur_time);
// Create the output file header
char buf[50];
out << "#START_HEADER" << "\n"
<< "start_time," << asctime_r(&cur_time, buf) // Implicit new line.
<< "formula_file," << statistics.input_file_ << "\n"
<< "num_vars," << statistics.num_variables_ << "\n"
<< "independent_support_size," << statistics.num_indep_support_variables_ << "\n"
<< "num_clauses," << statistics.num_clauses() << "\n"
<< "tot_num_models," << statistics.final_solution_count().get_str() << "\n"
<< "max_component_split_depth," << statistics.max_component_split_depth_ << "\n"
<< "max_branch_var_depth," << statistics.max_branch_var_depth_ << "\n"
<< "num_samples," << config.num_samples_ << "\n"
<< "num_second_pass_groups," << statistics.numb_second_pass_vars_.size() << "\n"
<< "num_second_pass_vars";
VariableIndex average_rem_var_cnt = 0;
for (auto rem_var_cnt : statistics.numb_second_pass_vars_) {
out << "," << rem_var_cnt;
average_rem_var_cnt += rem_var_cnt;
}
std::stringstream stream;
stream << std::fixed << std::setprecision(2)
<< static_cast<double>(average_rem_var_cnt)/statistics.numb_second_pass_vars_.size();
out << "\n";
// TopTreeSampler::printTreeSolverStatistics(out);
out << "avg_second_pass_var," << stream.str() << "\n"
<< "execution_time," << statistics.sampler_time_elapsed_ << "\n"
<< "pass1_time," << statistics.sampler_pass_1_time_ << "\n"
<< "pass2_time," << statistics.sampler_pass_2_time_ << "\n"
<< "#END_HEADER\n";
// Do not write the solutions to the console.
if (&out == &std::cout || config.disable_samples_write_)
return;
// Write the samples (if any
out << "\n\n#START_SAMPLES\n";
if (statistics.final_solution_count_ > 0) {
for (const auto &sample : samples_)
out << sample.sample_count() << "," << sample.ToString() << "\n";
} else {
out << "UNSAT\n";
}
out << "#END_SAMPLES" << std::endl;
}
void SamplesManager::reservoirSample(const Component * active_comp,
const std::vector<LiteralID> &literal_stack,
const mpz_class &solution_weight,
const mpz_class &weight_multiplier,
const AltComponentAnalyzer &ana,
const VariableIndex literal_stack_ofs,
const std::vector<VariableIndex> &freed_vars,
const std::vector<CacheEntryID> &cached_comp_ids,
const CachedAssignment &cached_assn,
SampleAssignment& cached_sample) {
assert(num_samples() > 0);
if (solution_weight == 0)
return; // UNSAT so move along.
mpz_class sample_weight = solution_weight;
if (weight_multiplier != 1)
sample_weight *= weight_multiplier;
solution_count_ += sample_weight;
SampleSize num_samples_to_replace;
if (solution_count_ == sample_weight) {
// First solution always gets weight equivalent to the number of samples.
assert(samples_.empty());
num_samples_to_replace = num_samples();
if (config_->verbose) {
std::stringstream ss;
ss << "\t\tInitial sample auto-selected.";
PrintInColor(ss, COLOR_GREEN);
}
} else {
// Use a binomial random variable to determine how many samples to replace.
std::vector<SampleSize> samples_to_replace;
GenerateSamplesToReplace(sample_weight, samples_to_replace);
num_samples_to_replace = static_cast<SampleSize>(samples_to_replace.size());
// Nothing to replace in this case.
if (num_samples_to_replace == 0) {
if (config_->perform_sample_caching()) {
BuildSample(cached_sample, active_comp, literal_stack,
literal_stack_ofs, ana, freed_vars, cached_comp_ids);
cached_sample.IncorporateCachedAssignment(cached_assn);
assert(cached_sample.VerifyEmancipatedVars());
}
return;
}
RemoveSamples(samples_to_replace);
if (config_->verbose) {
std::stringstream ss;
ss << "\t\tReservoir sampling accepted " << samples_to_replace.size() << " samples.";
PrintInColor(ss, COLOR_GREEN);
}
}
samples_.emplace_back(SampleAssignment(num_samples_to_replace));
BuildSample(samples_.back(), active_comp, literal_stack,
literal_stack_ofs, ana, freed_vars, cached_comp_ids);
// Handle the special requirements of sample caching.
if (config_->perform_sample_caching()) {
samples_.back().IncorporateCachedAssignment(cached_assn);
cached_sample = SampleAssignment(config_->num_samples_to_cache_, samples_.back());
assert(cached_sample.VerifyEmancipatedVars());
assert(num_samples() == cached_sample.sample_count());
}
}
void SamplesManager::GenerateSamplesToReplace(const mpz_class &new_sample_weight,
std::vector<SampleSize> &samples_to_replace) const {
assert(new_sample_weight <= solution_count_);
SampleSize num_samples_to_replace = Random::Mpz::binom(num_samples(), solution_count_,
new_sample_weight);
samples_to_replace.clear();
if (num_samples_to_replace == 0)
return;
Random::SelectRangeInts(num_samples(), num_samples_to_replace, samples_to_replace);
// This sorts in DESCENDING ORDER. Hence, it would be <5, 4, 3, 2, 1>. This is for
// Simplified removal later.
std::sort(samples_to_replace.rbegin(), samples_to_replace.rend());
}
bool SamplesManager::VerifySolutions(const std::string &input_file_path,
const bool skip_unassigned) const {
std::vector<std::vector<signed long>> clauses;
buildCnfClauseLiterals(input_file_path, clauses);
bool cls_sat;
for (const auto &sample : samples_) {
for (SampleSize i = 0; i < sample.sample_count(); i++) {
PartialAssignment assn;
sample.BuildRandomizedPartialAssignment(assn);
for (auto cls : clauses) {
cls_sat = false;
for (auto lit : cls) {
// Any unassigned literals automatically fail.
if (assn[abs(lit)] == ASSN_U) {
if (skip_unassigned) {// If true, ignore all clauses with unassigned variables
cls_sat = true;
break;
}
std::cerr << "Error: Variable #" << abs(lit) << " Unassigned bit in final sample\n";
return false;
}
// One true literal satisfies the clause so we can break
if ((lit < 0 && assn[abs(lit)] == ASSN_F)
|| (lit > 0 && assn[abs(lit)] == ASSN_T)) {
cls_sat = true;
break;
}
}
if (cls_sat)
continue;
std::stringstream ss;
ss << "Assignment is invalid. Clause is ";
for (auto lit : cls)
ss << lit << ", ";
PrintError(ss);
return false;
}
}
}
return true;
}
void SamplesManager::BuildSample(SampleAssignment &new_sample,
const Component *active_comp,
const std::vector<LiteralID> &literal_stack,
const VariableIndex last_branch_lit,
const AltComponentAnalyzer &ana,
const std::vector<VariableIndex> &freed_vars,
const std::vector<CacheEntryID> &cached_comp_ids) {
assert(last_branch_lit < literal_stack.size() || literal_stack.empty());
assert(new_sample.num_set_vars() == 0);
// Literal stack values are constrained so explicitly set them
for (auto lit : literal_stack)
new_sample.setVarAssignment(lit.var(), lit.sign() ? ASSN_T : ASSN_F);
new_sample.addEmancipatedVars(freed_vars);
new_sample.addCachedCompIds(cached_comp_ids);
// Get all the free/unassigned variables
std::vector<VariableIndex> new_free_vars;
VariableIndex i = 0;
const auto &component_data = active_comp->getData();
// Run to the end of the variables
while (component_data[i] != varsSENTINEL) {
VariableIndex var_num = component_data[i];
i++;
// Ignore all non-free variables.
// Sometimes variables set in the last or in BCP may appear free but are not
if (ana.scoreOf(var_num) > 0)
continue;
if (SamplesManager::isVarInLitStack(var_num, literal_stack, last_branch_lit))
continue;
new_free_vars.push_back(var_num);
// DebugZH - Make sure literal was not missed in the literal stack.
assert(!SamplesManager::isVarInLitStack(var_num, literal_stack));
}
new_sample.addEmancipatedVars(new_free_vars);
}
void SamplesManager::buildCnfClauseLiterals(const std::string &input_file_path,
std::vector<std::vector<signed long>> &clauses) {
// BEGIN File input
std::ifstream input_file(input_file_path);
if (!input_file)
ExitWithError("Cannot open file " + input_file_path + " Solution validation failed.", EX_IOERR);
// Remove the comments header
VariableIndex nVars;
ClauseIndex nCls;
const uint64_t max_ignore = UINT64_MAX; // Max number of characters on line to ignore.
std::string idstring;
char c;
while (input_file >> c && c != 'p')
input_file.ignore(max_ignore, '\n');
if (!(input_file >> idstring && idstring == "cnf" && input_file >> nVars && input_file >> nCls))
ExitWithError("Invalid CNF file\n" "Solution validation failed.", EX_DATAERR);
// Analyze each clause and add literals/variables as appropriate.
long lit;
clauses.clear();
while ((input_file >> c) && clauses.size() < nCls) {
// Ignore comment inline
if (c == 'c') {
input_file.ignore(max_ignore, '\n');
continue;
}
clauses.emplace_back(); // Create a new clause
input_file.unget(); // Extracted a non-space character to determine if a clause, so put it back
if ((c == '-') || isdigit(c)) {
while ((input_file >> lit) && lit != 0) {
clauses.back().push_back(lit);
}
}
input_file.ignore(max_ignore, '\n');
if (clauses.back().empty())
clauses.pop_back();
}
input_file.close();
assert(clauses.size() == nCls);
}
void SamplesManager::merge(SamplesManager &other, const mpz_class &other_multiplier,
const std::vector<VariableIndex> &freed_vars,
const std::vector<CacheEntryID> &cached_comp_ids,
const CachedAssignment & cached_assn,
SampleAssignment& cached_sample) {
// No solutions in the component split so move on.
if (other.solution_count_ == 0 || other_multiplier == 0)
return;
// Determine which samples to take from the other component split.
mpz_class other_weighted = other.solution_count_;
if (other_multiplier > 1)
other_weighted *= other_multiplier;
solution_count_ += other_weighted;
other.AddEmancipatedVars(freed_vars);
other.AddCachedCompIds(cached_comp_ids);
// Handle the case of sample caching.
if (config_->perform_sample_caching()) {
assert(config_->num_samples_to_cache_ == 1);
other.samples_.front().IncorporateCachedAssignment(cached_assn);
cached_sample = other.samples_.front();
}
std::vector<SampleSize> samples_to_replace;
GenerateSamplesToReplace(other_weighted, samples_to_replace);
if (samples_to_replace.empty())
return;
RemoveSamples(samples_to_replace);
// What is removed from the existing set is what is kept from the other set.
other.KeepSamples(samples_to_replace);
if (config_->verbose) {
std::stringstream ss;
ss << "\t\tMerged " << samples_to_replace.size() << " samples from the component branches.";
PrintInColor(ss, COLOR_GREEN);
}
append(other);
assert(GetActualSampleCount() == num_samples());
}
//bool IsVarInLiteralStack(const std::vector<LiteralID> &literal_stack, VariableIndex var) {
// for (unsigned i = 0; i < literal_stack.size(); i++)
// if (literal_stack[i].var() == var) {
// std::stringstream ss;
// ss << "Var #" << var << " is in the literal stack at level " << i << " with val "
// << (literal_stack[i].sign());
// PrintInColor(std::cerr, ss.str(), COLOR_RED);
// return true;
// }
// return false;
//}
Includes¶
algorithm
fstream
gmpxx.h
iomanip
model_sampler.h
(File model_sampler.h)sstream
stack.h
(File stack.h)
File model_sampler.h¶
↰ Parent directory (src
)
Definition (src/model_sampler.h
)¶
↰ Return to documentation for file (src/model_sampler.h
)
#ifndef SHARPSAT_SOLUTION_RECIPE_H
#define SHARPSAT_SOLUTION_RECIPE_H
#include <gmpxx.h>
#include <random>
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include "structures.h"
#include "component_types/component.h"
#include "statistics.h"
#include "alt_component_analyzer.h"
#include "solver_config.h"
#include "cached_assignment.h"
#include "rand_distributions.h"
typedef std::vector<uint32_t> AssignmentContainer;
class SampleAssignment {
friend class SamplesManager;
private:
explicit SampleAssignment(SampleSize sample_count, const SampleAssignment &other) :
sample_count_(sample_count), assn_(other.assn_), num_vars_set_(other.num_vars_set_),
emancipated_vars_(other.emancipated_vars_), cache_comp_ids_(other.cache_comp_ids_) { }
SampleSize sample_count_;
AssignmentContainer assn_;
VariableIndex num_vars_set_ = 0;
std::vector<VariableIndex> remaining_vars_;
std::vector<VariableIndex> emancipated_vars_;
std::vector<CacheEntryID> cache_comp_ids_;
std::string comp_cache_key_;
static VariableIndex num_var_;
static VariableIndex var_vec_len_;
static const unsigned int size_of_word_ = sizeof(typename AssignmentContainer::value_type)
* BITS_PER_BYTE;
static const VariableIndex bits_per_var_ = 2;
static const AssignmentContainer::value_type var_mask_ = 0x3;
bool VerifyStitchingCompatibility(const SampleAssignment &other) const {
assert(assn_.size() == other.assn_.size());
assert(sample_count_ <= other.sample_count_); // Less than or equal for simplified code
// when stitching the SamplesManager objects
AssignmentEncoding this_val, other_val;
for (VariableIndex i = FIRST_VAR; i <= num_var_; i++) {
this_val = this->var_assignment(i);
other_val = other.var_assignment(i);
if (this_val != other_val && this_val != ASSN_U && other_val != ASSN_U) {
std::cerr << "Stitching error on variable #" << i << std::endl
<< "Implicit Value = " << this_val << ". Other Value = "
<< other_val << std::endl;
return false;
}
}
return true;
}
inline static void calculateWordAndBitNumbers(const VariableIndex &var_num,
VariableIndex &word_num, VariableIndex &bit_num) {
assert(var_num >= FIRST_VAR && var_num <= num_var_);
word_num = (var_num * bits_per_var_) / size_of_word_;
assert(word_num >= 0 && word_num < var_vec_len_);
bit_num = (var_num * bits_per_var_) % size_of_word_;
}
const bool VerifyEmancipatedVars() const {
if (emancipated_vars_.empty())
return true;
std::vector<VariableIndex> all_vars = emancipated_vars_;
std::sort(all_vars.begin(), all_vars.end());
if (var_assignment(all_vars[0]) != ASSN_U)
return false;
for (VariableIndex i = 1; i < all_vars.size(); i++) {
if (all_vars[i] == all_vars[i-1] || var_assignment(all_vars[i]) != ASSN_U)
return false;
}
return true;
}
template <typename T>
static const bool VerifyNoDuplicates(const std::vector<T> &vec) {
if (vec.empty())
return true;
std::vector<T> vec_copy = vec;
std::sort(vec_copy.begin(), vec_copy.end());
for (VariableIndex i = 1; i < vec_copy.size(); i++) {
if (vec_copy[i] == vec_copy[i-1])
return false;
}
return true;
}
const std::vector<VariableIndex>& emancipated_vars() const { return emancipated_vars_; }
void DeleteEmancipatedVars(const std::vector<VariableIndex> &vars_to_delete) {
for (auto &var_id : vars_to_delete) {
auto itr = std::find(emancipated_vars_.begin(), emancipated_vars_.end(), var_id);
emancipated_vars_.erase(itr);
}
}
void addEmancipatedVars(const std::vector<VariableIndex> &new_emancipated_vars) {
if (new_emancipated_vars.empty())
return;
emancipated_vars_.insert(emancipated_vars_.end(), new_emancipated_vars.begin(),
new_emancipated_vars.end());
// for (auto var_id : new_emancipated_vars) {
// if (!IsVarEmancipated(var_id))
// emancipated_vars_.push_back(var_id);
// }
assert(VerifyEmancipatedVars());
}
void addCachedCompIds(const std::vector<CacheEntryID> &cache_comp_ids) {
comp_cache_key_.clear();
cache_comp_ids_.insert(cache_comp_ids_.end(), cache_comp_ids.begin(), cache_comp_ids.end());
assert(VerifyNoDuplicates<CacheEntryID>(cache_comp_ids_));
}
void DecreaseSampleCount(SampleSize dec_sample_count) {
assert(dec_sample_count > 0 && dec_sample_count < sample_count_);
sample_count_ -= dec_sample_count;
}
void zeroSampleCount() { sample_count_ = 0; }
inline const VariableIndex num_var() const { return num_var_; }
void IncorporateCachedAssignment(const CachedAssignment & cached_assn) {
for (auto lit : cached_assn.literals()) {
assert(var_assignment(lit.var()) == ASSN_U); // Only assign to unassigned variables
setVarAssignment(lit.var(), lit.sign() ? ASSN_T : ASSN_F);
}
if (!cached_assn.emancipated_vars().empty())
emancipated_vars_.insert(emancipated_vars_.end(), cached_assn.emancipated_vars().begin(),
cached_assn.emancipated_vars().end());
assert(VerifyEmancipatedVars());
}
inline void stitch(const SampleAssignment &other) {
assert(VerifyStitchingCompatibility(other));
for (VariableIndex i = 0; i < assn_.size(); i++)
assn_[i] &= other.assn_[i];
addEmancipatedVars(other.emancipated_vars_);
addCachedCompIds(other.cache_comp_ids_);
num_vars_set_ += other.num_vars_set_;
remaining_vars_.clear();
// Make sure no variables miraculously materialized.
assert(num_set_vars_const() + emancipated_vars_.size() <= num_var());
}
inline SampleAssignment split(SampleSize new_assn_sample_count) {
DecreaseSampleCount(new_assn_sample_count);
return SampleAssignment(new_assn_sample_count, *this);
}
inline void set_sample_count(SampleSize new_sample_count) { sample_count_ = new_sample_count; }
inline void BuildRandomizedPartialAssignment(PartialAssignment &all_vars) const {
GetPartialAssignment(all_vars);
for (auto var : emancipated_vars_)
all_vars[var] = (Random::uniform(0, 1)) ? ASSN_F : ASSN_T;
}
static SampleAssignment buildUnsetterAssignment(std::vector<VariableIndex> vars_to_keep) {
SampleAssignment new_assn;
for (auto &var : vars_to_keep)
new_assn.setVarAssignment(var, ASSN_F);
return new_assn;
}
void unsetVariableAssignments(SampleAssignment &unsetter) {
assert(assn_.size() == unsetter.assn_.size());
for (VariableIndex i = 0; i < assn_.size(); i++)
assn_[i] |= unsetter.assn_[i];
}
std::vector<VariableIndex> GetRemainingVariables() {
if (remaining_vars_.empty())
num_set_vars(); // Builds the unset variables list.
return remaining_vars_;
}
public:
explicit SampleAssignment(SampleSize sample_count) : sample_count_(sample_count) {
assn_.resize(var_vec_len_, static_cast<typename AssignmentContainer::value_type>(-1));
}
SampleAssignment() : SampleAssignment(0) {}
inline std::string ToString() const {
std::stringstream ss;
for (VariableIndex i = FIRST_VAR; i <= num_var(); i++) {
AssignmentEncoding var_val = var_assignment(i);
switch (var_val) {
case ASSN_F: ss << '0'; break;
case ASSN_T: ss << '1'; break;
case ASSN_U: ss << '*'; break;
}
}
return ss.str();
}
inline const AssignmentEncoding var_assignment(const VariableIndex &var) const {
VariableIndex word_num, bit_num;
calculateWordAndBitNumbers(var, word_num, bit_num);
return (AssignmentEncoding) ((assn_[word_num] >> bit_num) & var_mask_);
}
inline void GetPartialAssignment(PartialAssignment &all_vars) const {
all_vars.clear();
all_vars.resize(num_var_ + FIRST_VAR);
for (VariableIndex i = FIRST_VAR; i <= num_var_; i++)
all_vars[i] = var_assignment(i);
}
inline void setVarAssignment(const VariableIndex var, const AssignmentEncoding &val) {
assert((val == ASSN_F || val == ASSN_T) && var_assignment(var) == ASSN_U);
VariableIndex word_num, bit_num;
calculateWordAndBitNumbers(var, word_num, bit_num);
// Updates the bits of interest only by masking then setting them.
assn_[word_num] = (assn_[word_num] & ~(var_mask_ << bit_num)) | (val << bit_num);
num_vars_set_++;
remaining_vars_.clear();
}
static void set_num_var(const VariableIndex num_var) {
assert(num_var_ == 0); // This function should onyl be called once.
num_var_ = num_var;
var_vec_len_ = ((num_var + 1) * bits_per_var_ / size_of_word_)+ 1;
}
const bool IsComplete() const {
// return cache_comp_ids().empty();
return num_set_vars_const() + emancipated_vars_.size() == num_var_;
}
// /**
// * Complete Assignment Checker
// *
// * Determines whether the sample model is partial or complete.
// *
// * @return true if the sample model is a complete assignment.
// */
// bool IsComplete() const {
// return num_set_vars_const() + emancipated_vars_.size() == num_var_;
// }
// /**
// * Accessor for the number of cached component IDs in this object.
// * @return Number of cached component IDs in this object
// */
// inline const uint64_t cached_comp_count() const { return cache_comp_ids_.size(); }
const SampleSize sample_count() const { return sample_count_; }
const VariableIndex num_set_vars() {
if (!remaining_vars_.empty())
return num_vars_set_;
// ToDo once variable setting is efficient, just return the set variable count
num_vars_set_ = 0;
for (VariableIndex i = FIRST_VAR; i <= num_var(); i++) {
if (var_assignment(i) != ASSN_U) {
num_vars_set_++;
} else if (!IsVarEmancipated(i)) {
remaining_vars_.emplace_back(i);
}
}
return num_vars_set_;
}
const VariableIndex num_set_vars_const() const {
// ToDo once variable setting is efficient, just return the set variable count
SampleSize num_vars_set = 0;
for (VariableIndex i = FIRST_VAR; i <= num_var(); i++)
if (var_assignment(i) != ASSN_U)
num_vars_set++;
return num_vars_set;
}
// /**
// * Updates the assignment of the implicit assignment with that of the specified one. It does
// * NOT update the sample count
// *
// * @param other Another SampleAssignment.
// */
// void updateAssignmentOnly(const SampleAssignment &other) {
// this->assn_ = other.assn_;
// this->emancipated_vars_ = other.emancipated_vars_;
// }
const VariableIndex num_unset_vars() {
return num_var_ - num_set_vars() - emancipated_vars_.size();
}
// /**
// * Builds and returns the set of unconstrained variables in this sample.
// *
// * @return Identification number of the unset variables.
// */
// const std::vector<VariableIndex> GetUnsetConstrainedVars() const {
// std::vector<VariableIndex> unset_vars;
// for (VariableIndex i = FIRST_VAR; i <= num_var(); i++)
// if (var_assignment(i) == ASSN_U && !IsVarEmancipated(i))
// unset_vars.push_back(i);
// return unset_vars;
// }
const bool IsVarEmancipated(VariableIndex var) const {
return std::find(emancipated_vars_.begin(), emancipated_vars_.end(), var)
!= emancipated_vars_.end();
}
const std::vector<CacheEntryID>& cache_comp_ids() const {
return cache_comp_ids_;
}
void clear_cache_comp_ids() {
cache_comp_ids_.clear();
}
// /**
// * Generate a unique key for the cached components in the sample assignment.
// *
// * @return Key string for the cached components.
// */
// std::string GetCachedCompKey() {
// if (!comp_cache_key_.empty())
// return comp_cache_key_;
// std::sort(cache_comp_ids_.begin(), cache_comp_ids_.end());
// std::stringstream ss;
// for (auto cached_comp : cache_comp_ids_) {
// if (cached_comp != cache_comp_ids_[0])
// ss << ",";
// ss << cached_comp;
// }
// comp_cache_key_ = ss.str();
// return comp_cache_key_;
// }
};
typedef std::list<SampleAssignment> ListOfSamples;
class SamplesManager {
private:
mpz_class solution_count_ = 0;
ListOfSamples samples_;
// /**
// * Stores the final expected number of samples to be returned at the
// * end of sampling.
// */
// static SampleSize final_num_samples_;
// /**
// * Stores the current number of samples being built by the sampler.
// */
// static SampleSize samples_manager_vector_size_;
SampleSize tot_num_samples_;
SolverConfiguration *config_;
// /**
// * Used in the random number generator. Stores the random bits
// * to be extracted.
// */
// static int random_bits_;
// /**
// * Next random bit to be used. It is between [0,NUM_INT_BITS-1).
// */
// static int next_rand_bit_;
// static const int NUM_INT_BITS_;
static void BuildSample(SampleAssignment &new_sample,
const Component *active_comp,
const std::vector<LiteralID> &literal_stack,
VariableIndex last_branch_lit,
const AltComponentAnalyzer &ana,
const std::vector<VariableIndex> &freed_vars,
const std::vector<CacheEntryID> &cached_comp_ids);
static bool isVarInLitStack(const VariableIndex var_num,
const std::vector<LiteralID> &literal_stack,
const VariableIndex start_ofs = 0) {
for (auto itr = literal_stack.begin() + start_ofs; itr != literal_stack.end(); itr++)
if ((*itr).var() == var_num)
return true;
return false;
}
static void buildCnfClauseLiterals(const std::string &input_file_path,
std::vector<std::vector<signed long>> &clauses);
void splitSampleAndInsert(std::list<SampleAssignment>::iterator &itr,
const SampleSize &new_assn_sample_count) {
assert(new_assn_sample_count > 0 && new_assn_sample_count < itr->sample_count());
// Need to increment then decrement since this method inserts the new element before itr
SampleAssignment new_node = itr->split(new_assn_sample_count);
samples_.insert(itr, new_node);
--itr;
}
public:
SamplesManager(SampleSize num_samples, SolverConfiguration &config) : config_(&config) {
tot_num_samples_ = num_samples;
}
// /**
// * Copy constructor.
// */
// SamplesManager(const SamplesManager &other)
// : SamplesManager(other.num_samples(), *other.config_) {}
// /**
// * Equality operator.
// *
// * @param other Object to which the implicit object will be set.
// * @return Reference to the new SamplesManager created. This allows for chaining equality
// * operators.
// */
// SamplesManager& operator=(const SamplesManager &other) {
// this->tot_num_samples_ = other.tot_num_samples_;
// this->samples_ = other.samples_;
// this->config_ = other.config_;
// return *this;
// }
void exportFinal(std::ostream &out, const DataAndStatistics &statistics,
const SolverConfiguration& config);
void reservoirSample(const Component * active_comp,
const std::vector<LiteralID> & literal_stack,
const mpz_class &solution_weight,
const mpz_class &weight_multiplier,
const AltComponentAnalyzer &ana,
VariableIndex literal_stack_ofs,
const std::vector<VariableIndex>& freed_vars,
const std::vector<CacheEntryID> &cached_comp_ids,
const CachedAssignment& cached_assn,
SampleAssignment& cached_sample);
inline void GenerateSamplesToReplace(const mpz_class &new_sample_weight,
std::vector<SampleSize> &samples_to_replace) const;
// /**
// * Sample Variable Assignment Accessor
// *
// * Gets the value of the variable assignment for a specific sample in the list of samples
// *
// * Debug function.
// *
// * @param sample_num Sample number between 0 (inclusive) and num_samples (exclusive)
// * @param var Variable number
// *
// * @return Variable's assigned value.
// */
// AssignmentEncoding sample_var_val(const SampleSize sample_num, const VariableIndex var) const {
// assert(var >= FIRST_VAR && var <= samples_[sample_num].num_var());
// return samples_[sample_num].var_assignment(var);
// }
inline void stitch(SamplesManager &other) {
assert(this->tot_num_samples_ == other.tot_num_samples_);
if (solution_count_ == 0) {
this->samples_ = other.samples_;
solution_count_ = other.solution_count_;
return;
} else {
solution_count_ *= other.solution_count_;
}
// Handle the UNSAT case
if (other.solution_count_ == 0) {
this->samples_.clear();
return;
}
// Depending on the number of sample objects, different stitching approaches are faster
StitchShuffledArray(other);
// After the size normalization, perform the stitching sample by sample.
assert(verifyPostStitchingCorrectness(other));
}
inline void StitchShuffledArray(SamplesManager &other) {
assert(this->GetActualSampleCount() == other.GetActualSampleCount());
std::vector<ListOfSamples::iterator> other_samples_itrs;
other_samples_itrs.reserve(other.samples_.size());
std::vector<SampleSize> other_sample_order;
other_sample_order.reserve(other.tot_num_samples_);
// Store a reference to each element in other's samples
// These will be used for simplifying the stitching look-up.
SampleSize i = 0;
for (auto other_itr = other.samples_.begin(); other_itr != other.samples_.end(); ++other_itr) {
other_samples_itrs.emplace_back(other_itr);
for (SampleSize j=0; j < other_itr->sample_count(); j++)
other_sample_order.emplace_back(i);
++i;
}
Random::shuffle<SampleSize>(other_sample_order.begin(), other_sample_order.end());
// Split and merge to create the permutations
SampleSize sample_offset = 0;
for (auto this_itr = samples_.begin(); this_itr != samples_.end(); ) {
SampleSize sample_end = sample_offset + this_itr->sample_count();
std::vector<SampleSize> samples_per_element(other_sample_order.size(), 0);
for (SampleSize sample_cnt = sample_offset; sample_cnt < sample_end; ++sample_cnt)
samples_per_element[other_sample_order[sample_cnt]]++;
// Indices from the same "other" sample are grouped together so split and stitch.
for (SampleSize other_cnt = 0; other_cnt < samples_per_element.size(); ++other_cnt) {
if (samples_per_element[other_cnt] == 0)
continue;
SplitAndStitch(this_itr, other_samples_itrs[other_cnt], samples_per_element[other_cnt]);
}
// Update all pointer
sample_offset = sample_end;
}
}
void SplitAndStitch(ListOfSamples::iterator &this_itr, ListOfSamples::iterator &other_itr,
SampleSize &num_new_samples) {
assert(num_new_samples > 0 && num_new_samples <= this_itr->sample_count()
&& num_new_samples <= other_itr->sample_count());
// If applicable add a new node
if (num_new_samples != this_itr->sample_count())
splitSampleAndInsert(this_itr, num_new_samples);
this_itr->stitch(*other_itr);
++this_itr;
if (other_itr->sample_count() == num_new_samples)
other_itr->zeroSampleCount();
else
other_itr->DecreaseSampleCount(num_new_samples);
}
const bool verifyPostStitchingCorrectness(SamplesManager &other) const {
for (auto &sample : other.samples_) {
if (sample.sample_count() != 0) {
PrintInColor("An other_sample had non-zero size.", PrintColor::COLOR_RED);
return false;
}
}
if (!this->verifySampleCount()) {
PrintInColor("The sample count of the stitched object is incorrect.", PrintColor::COLOR_RED);
return false;
}
return true;
}
void merge(SamplesManager &other, const mpz_class &other_multiplier,
const std::vector<VariableIndex> &freed_vars,
const std::vector<CacheEntryID> &cached_comp_ids,
const CachedAssignment & cached_assn,
SampleAssignment& cached_sample);
bool VerifySolutions(const std::string &input_file_path,
bool skip_unassigned = false) const;
const mpz_class &model_count() const { return solution_count_; }
void AddEmancipatedVars(const std::vector<VariableIndex> &emancipated_vars) {
for (auto &sample : samples_)
sample.addEmancipatedVars(emancipated_vars);
// Multiply by 2^num_unused_vars since those represent a parallel cylinder
mpz_mul_2exp(solution_count_.get_mpz_t(), solution_count_.get_mpz_t(),
emancipated_vars.size());
}
void AddCachedCompIds(const std::vector<CacheEntryID> &cached_comp_ids) {
for (auto &sample : samples_)
sample.addCachedCompIds(cached_comp_ids);
}
void TransferVariableAssignments(ListOfSamples &others) {
std::vector<VariableIndex> unset_vars = others.front().GetRemainingVariables();
assert(!unset_vars.empty());
auto unsetter = SampleAssignment::buildUnsetterAssignment(unset_vars);
// Delete redundant emancipated variables.
for (auto &sample : samples_) {
sample.unsetVariableAssignments(unsetter);
sample.DeleteEmancipatedVars(others.front().emancipated_vars());
}
SampleSize sample_count = 0;
for (auto &other : others) {
sample_count += other.sample_count();
other.clear_cache_comp_ids(); // Out of data cache ids from previous run.
}
assert(sample_count == this->num_samples());
SamplesManager others_manager(sample_count, *config_);
others_manager.solution_count_ = 1;
others_manager.samples_ = others;
this->stitch(others_manager);
}
// /**
// * Solver Configuration Storer
// *
// * This function is used to store a reference to the solver's configuration.
// * This is useful in case any of the run parameters are used.
// * @param config Solver's configuration.
// */
// static void set_solver_config(SolverConfiguration &config) { config_ = &config; }
ListOfSamples &samples() { return samples_; }
// /**
// * Sample Setter
// *
// * This function replaces the sample (based off the specified number)
// * with the new model passed to the function.
// *
// * @param sample_num Sample number to be set
// * @param new_model New sample model to be stored
// */
// inline void set_sample(SampleSize sample_num,
// const SampleAssignment &new_model) {
// assert(sample_num >= 0 && sample_num < samples_.size());
// samples_[sample_num] = new_model;
// }
// /**
// * Sample Accessor
// *
// + * Extracts a reference to the specified sample from the manager.
// *
// + * @param sample_num Number of the sample to access - base 0
// *
// + * @return Sample at the specified number
// */
// inline const SampleAssignment &sample(SampleSize sample_num) const {
// assert(sample_num >= 0 && sample_num < samples_.size());
// return samples_[sample_num];
// }
inline bool IsComplete() const {
for (const auto &sample : samples_)
if (!sample.IsComplete())
return false;
return true;
}
inline void append(SamplesManager &other) {
append(other.samples_);
}
inline void append(ListOfSamples &other) {
samples_.splice(samples_.end(), other);
assert(GetActualSampleCount() <= tot_num_samples_);
}
inline const SampleSize num_samples() const {
// assert(verifySampleCount());
return tot_num_samples_;
}
void RemoveSamples(std::vector<SampleSize> &samples_to_remove) {
if (samples_to_remove.empty())
return;
if (num_samples() == samples_to_remove.size()) {
samples_.clear();
return;
}
// Delete from back to front to prevent deletion affecting counts.
assert(!samples_.empty());
auto sample_itr = --(samples_.end());
SampleSize cur_sample_start_count = num_samples() - sample_itr->sample_count();
SampleSize num_to_remove = 0;
for (auto &sample_to_remove : samples_to_remove) {
assert(sample_to_remove >= 0 && sample_to_remove < num_samples());
// Skip to the next sample to remove.
while (sample_to_remove < cur_sample_start_count) {
if (num_to_remove > 0) {
if (sample_itr->sample_count() == num_to_remove)
// If no samples are left then remove the object
sample_itr = samples_.erase(sample_itr);
else
sample_itr->DecreaseSampleCount(num_to_remove);
num_to_remove = 0;
}
--sample_itr;
cur_sample_start_count -= sample_itr->sample_count();
}
num_to_remove++;
}
// Handle the last element that requires removal
if (sample_itr->sample_count() == num_to_remove)
sample_itr = samples_.erase(sample_itr);
else
sample_itr->DecreaseSampleCount(num_to_remove);
assert(GetActualSampleCount() == tot_num_samples_ - samples_to_remove.size());
}
void KeepSamples(std::vector<SampleSize> &samples_to_keep) {
if (samples_to_keep.empty()) {
samples_.clear();
return;
}
if (num_samples() == samples_to_keep.size())
return;
// Delete from back to front to prevent deletion affecting counts.
assert(!samples_.empty());
auto sample_itr = --(samples_.end());
SampleSize cur_sample_start_count = num_samples() - sample_itr->sample_count();
SampleSize num_to_keep = 0;
for (auto &sample_to_keep : samples_to_keep) {
assert(sample_to_keep >= 0 && sample_to_keep < num_samples());
// Skip to the next sample to check
while (sample_to_keep < cur_sample_start_count) {
if (num_to_keep > 0) {
sample_itr->set_sample_count(num_to_keep);
num_to_keep = 0;
} else {
sample_itr = samples_.erase(sample_itr);
}
--sample_itr;
cur_sample_start_count -= sample_itr->sample_count();
}
num_to_keep++;
}
// Handle the last node to keep
sample_itr->set_sample_count(num_to_keep);
// Any nodes never encountered have to be removed.
if (sample_itr != samples_.begin())
samples_.erase(samples_.begin(), sample_itr);
assert(GetActualSampleCount() == samples_to_keep.size());
}
const bool verifySampleCount() const {
return GetActualSampleCount() == tot_num_samples_;
}
const SampleSize GetActualSampleCount() const {
SampleSize actual_sample_count = 0;
for (auto &sample : samples_) {
assert(sample.sample_count() > 0); // Make sure no dead samples
actual_sample_count += sample.sample_count();
}
return actual_sample_count;
}
void clear() { samples_.clear(); }
};
// * Recipe Structure Initializer
// *
// * Initializes recipe static structures. This requires a dedicated function
// * because of the scope requirements of static objects.
// *
// * @param num_var Number of variables in the Boolean formula.
// */
//void InitializeSamplerStructures(VariableIndex num_var);
// * Sample Size Initializer
// *
// * Initializes the number of samples to by collected by the algorithm.
// *
// * @param sample_count Number of samples
// */
//void InitializeSampleCount(SampleSize sample_count);
//
//
//bool IsVarInLiteralStack(const std::vector<LiteralID> &literal_stack, VariableIndex var);
#endif //SHARPSAT_SOLUTION_RECIPE_H
Includes¶
algorithm
alt_component_analyzer.h
(File alt_component_analyzer.h)cached_assignment.h
(File cached_assignment.h)component_types/component.h
(File component.h)fstream
gmpxx.h
list
rand_distributions.h
(File rand_distributions.h)random
solver_config.h
(File solver_config.h)statistics.h
(File statistics.h)string
structures.h
(File structures.h)vector
Included By¶
File primitive_types.h¶
↰ Parent directory (src
)
Definition (src/primitive_types.h
)¶
↰ Return to documentation for file (src/primitive_types.h
)
#include <vector>
#ifndef PRIMITIVE_TYPES_H_
#define PRIMITIVE_TYPES_H_
#define varsSENTINEL 0
#define clsSENTINEL NOT_A_CLAUSE
#define EXIT_TIMEOUT 128
typedef uint64_t VariableIndex;
typedef VariableIndex ClauseIndex;
typedef VariableIndex ClauseOfs;
typedef VariableIndex ComponentVarAndCls;
typedef unsigned CacheEntryID;
typedef int64_t DecisionLevel;
static const ClauseIndex NOT_A_CLAUSE(0);
#define SENTINEL_CL NOT_A_CLAUSE
#define BITS_PER_BYTE 8
#define FIRST_VAR 1
enum class SolverExitState {
NO_STATE, SUCCESS//, TIMEOUT, ABORTED
};
enum class SolverNextAction {
EXIT, RESOLVED, PROCESS_COMPONENT, BACKTRACK
};
#ifdef DEBUG
#define toDEBUGOUT(X) std::cout << X;
#else
#define toDEBUGOUT(X)
#endif
enum AssignmentEncoding{
ASSN_F = 0x0, ASSN_T = 0x1, ASSN_U = 0x3,
};
typedef std::vector<AssignmentEncoding> PartialAssignment;
typedef uint32_t SampleSize;
typedef int32_t TopTreeLiteral;
typedef uint64_t TreeNodeIndex;
enum class TopTreeNodeType {
MAX_DEPTH,
CYLINDER,
COMPONENT_SPLIT,
NUM_TREE_NODE_TYPES // Always be last
};
#endif /* PRIMITIVE_TYPES_H_ */
Includes¶
vector
Included By¶
Functions¶
Defines¶
File rand_distributions.cpp¶
↰ Parent directory (src
)
Definition (src/rand_distributions.cpp
)¶
↰ Return to documentation for file (src/rand_distributions.cpp
)
#include <cstdlib>
#include "rand_distributions.h"
// Satisfy the linker by initializing the static variables
SolverConfiguration * Random::master_config_;
std::random_device Random::rd_; // only used once to initialise (seed) engine
std::mt19937 Random::rng_; // random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> Random::uni_(INT_MIN, INT_MAX);
bool Random::Mpz::use_approx_binom_ = true;
gmp_randstate_t Random::Mpz::rand_state_;
Includes¶
cstdlib
rand_distributions.h
(File rand_distributions.h)
File rand_distributions.h¶
↰ Parent directory (src
)
Definition (src/rand_distributions.h
)¶
↰ Return to documentation for file (src/rand_distributions.h
)
#ifndef PROJECT_RANDOM_H
#define PROJECT_RANDOM_H
#include <gmpxx.h>
#include <chrono> // NOLINT (build/c++11)
#include <cstdlib>
#include <iostream>
#include <random>
#include <vector>
#include "solver_config.h"
#include "primitive_types.h"
#include "sampler_tools.h"
class Random{
public:
static void init(SolverConfiguration * config) {
master_config_ = config;
gmp_randinit_mt(Random::Mpz::rand_state_);
// create the generator seed for the random engine to reference
long long int seed;
if (master_config_->debug_mode) {
if (!master_config_->quiet)
std::cout << "WARNING: Debug mode has a fixed seed for the MPZ class.\n";
seed = 0;
} else {
seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
}
mpz_class rand_seed;
mpz_import(rand_seed.get_mpz_t(), 1, -1, sizeof(seed), 0, 0, &seed);
gmp_randseed(Random::Mpz::rand_state_, rand_seed.get_mpz_t());
if (master_config_->debug_mode) {
if (!master_config_->quiet)
std::cout << "WARNING: Debug mode uses a fixed random number seed." << std::endl;
} else {
Random::rng_ = std::mt19937(Random::rd_());
}
}
template <typename T> inline static T uniform(T min, T max) {
std::uniform_int_distribution<T> distribution(min, max);
return distribution(rng_);
}
inline static int uniform(int min = INT_MIN, int max = INT_MAX) {
if (min == INT_MIN && max == INT_MAX) {
return uni_(rng_);
} else {
std::uniform_int_distribution<int> distribution(min, max);
return distribution(rng_);
}
}
static SampleSize binom(SampleSize n, double p) {
std::binomial_distribution<> d(n, p);
return static_cast<SampleSize>(d(rng_));
}
template<typename ListType, typename CountType>
static void DownsampleList(CountType target_size, std::vector<ListType> &oversampled_vec,
bool resize = true) {
assert(oversampled_vec.size() >= target_size);
CountType end_point = oversampled_vec.size() - 1;
while (end_point > target_size) {
auto id_loc = Random::uniform<CountType>(0, end_point);
oversampled_vec[id_loc] = oversampled_vec[end_point]; // Copy back & overwrite the used value
end_point--;
}
if (resize)
oversampled_vec.resize(target_size);
}
template<typename T>
static void shuffle(std::vector<T> &vec) {
std::shuffle(vec.begin(), vec.end(), rng_);
}
class Mpz {
// Allow the Random class to access this class' private methods/fields
friend class Random;
public:
inline static void uniform(mpz_class max_z, mpz_class &rand_val) {
mpz_urandomm(rand_val.get_mpz_t(), Random::Mpz::rand_state_, max_z.get_mpz_t());
}
inline static SampleSize binom(SampleSize n, const mpz_class &t,
const mpz_class &a) {
assert(t > 0 && t >= a);
// Handle the edge cases
if (a == 0)
return 0;
else if (a == t)
return n;
if (use_approx_binom_)
return Random::Mpz::binom_approx(n, t, a);
else
return Random::Mpz::binom_exact(n, t, a);
}
private:
static bool use_approx_binom_;
static gmp_randstate_t rand_state_;
inline static SampleSize binom_approx(SampleSize n, const mpz_class &t,
const mpz_class &a) {
mpf_class a_mpf = a, t_mpf = t;
mpf_class p_mpf = a_mpf / t_mpf;
return Random::binom(n, p_mpf.get_d());
// double p = mpz_get_d(a.get_mpz_t()) / mpz_get_d(t.get_mpz_t());
// return Random::binom(n,p);
}
inline static SampleSize binom_exact(SampleSize n, const mpz_class &t,
const mpz_class &a) {
mpz_class rand_mpz = 0;
SampleSize num_success = 0;
for (SampleSize i = 0; i < n; i++) {
Random::Mpz::uniform(t, rand_mpz);
if (rand_mpz < a)
num_success++;
}
return num_success;
}
};
static void SelectRangeInts(SampleSize max_id, SampleSize num_elements,
std::vector<SampleSize> &samples_to_replace) {
assert(max_id >= num_elements);
samples_to_replace.clear();
samples_to_replace.reserve(max_id);
for (SampleSize i = 0; i < max_id; i++)
samples_to_replace.emplace_back(i);
//ToDo Modify this function to only ever do a maximum of max_id/2 random numbers
Random::DownsampleList<SampleSize, SampleSize>(num_elements, samples_to_replace);
}
template<typename T>
static void shuffle(typename std::vector<T>::iterator begin, // Dependent types so add the
typename std::vector<T>::iterator end) { // "typename" keyword.
std::shuffle(begin, end, rng_);
}
private:
Random() = default;
static std::uniform_int_distribution<int> uni_;
static SolverConfiguration * master_config_;
static std::random_device rd_;
static std::mt19937 rng_;
};
#endif //PROJECT_RANDOM_H
Includes¶
chrono
cstdlib
gmpxx.h
iostream
primitive_types.h
(File primitive_types.h)random
sampler_tools.h
(File sampler_tools.h)solver_config.h
(File solver_config.h)vector
Included By¶
Classes¶
File sampler_tools.h¶
↰ Parent directory (src
)
Definition (src/sampler_tools.h
)¶
↰ Return to documentation for file (src/sampler_tools.h
)
#ifndef SAMPLER_TOOLS_
#define SAMPLER_TOOLS_
#define ESCAPE_CHAR "\033["
#define PRINT_BOLD "1"
#define ITEM_SEP ";"
#define END_ESCAPE "m"
#define RESET_CONSOLE_COLOR (ESCAPE_CHAR "0" END_ESCAPE)
#include <sysexits.h>
#include <sys/stat.h>
#include <iostream>
#include <string>
#include <sstream>
#include "solver_config.h"
#include "statistics.h"
#define STR_DECIMAL_BASE 10
#if defined(WIN32) || defined(_WIN32)
#define FILE_PATH_SEPARATOR "\\"
#else
#define FILE_PATH_SEPARATOR "/"
#endif
enum PrintColor {
// INVERT_COLORS = 7,
COLOR_BLACK = 30,
COLOR_RED = 31,
COLOR_GREEN = 32,
COLOR_YELLOW = 33,
COLOR_BLUE = 34,
COLOR_MAGENTA = 35,
COLOR_CYAN = 36,
// COLOR_WHITE = 37
};
inline void PrintInColor(std::ostream &out, const std::string &msg,
const PrintColor color = COLOR_BLACK, bool bold = true) {
out << ESCAPE_CHAR;
if (bold)
out << PRINT_BOLD ITEM_SEP;
out << color;
out << END_ESCAPE << msg << RESET_CONSOLE_COLOR << std::endl;
}
inline void PrintInColor(const std::string &msg,
PrintColor color = COLOR_BLACK, bool bold = true) {
PrintInColor(std::cout, msg, color, bold);
}
inline void PrintInColor(std::ostream &out, const std::stringstream &msg,
const PrintColor color = COLOR_BLACK, bool bold = true) {
PrintInColor(out, msg.str(), color, bold);
}
inline void PrintInColor(const std::stringstream &msg,
PrintColor color = COLOR_BLACK, bool bold = true) {
PrintInColor(std::cout, msg.str(), color, bold);
}
inline void PrintWarning(const std::string &msg) {
PrintInColor(std::cout, "WARNING: " + msg, COLOR_YELLOW);
}
inline void PrintError(const std::string &msg) {
PrintInColor(std::cerr, "ERROR: " + msg, COLOR_RED);
}
inline void PrintError(const std::stringstream &msg) { PrintError(msg.str()); }
inline void ExitWithError(const std::string &msg, const int err_code=EXIT_FAILURE) {
PrintError(msg);
exit(err_code);
}
inline void ExitInvalidParam(const std::string &msg) {
ExitWithError(msg, EX_DATAERR);
}
inline const bool FileExists(const std::string &file_path) {
struct stat buffer;
return (stat(file_path.c_str(), &buffer) == 0);
}
#endif // SAMPLER_TOOLS_
Includes¶
iostream
solver_config.h
(File solver_config.h)sstream
statistics.h
(File statistics.h)string
sys/stat.h
sysexits.h
Included By¶
Enums¶
Functions¶
File solver.cpp¶
↰ Parent directory (src
)
Contents
Definition (src/solver.cpp
)¶
↰ Return to documentation for file (src/solver.cpp
)
#include <deque>
#include <string>
#include <utility>
#include <vector>
#include <sstream>
#include <unordered_map>
#include "primitive_types.h"
#include "solver.h"
//#include "top_tree_sampler.h"
#include "solver_config.h"
#include "sampler_tools.h"
StopWatch::StopWatch() {
interval_length_.tv_sec = 60;
gettimeofday(&last_interval_start_, nullptr);
start_time_ = stop_time_ = last_interval_start_;
}
timeval StopWatch::getElapsedTime() {
timeval other_time = stop_time_;
if (stop_time_.tv_sec == start_time_.tv_sec
&& stop_time_.tv_usec == start_time_.tv_usec)
gettimeofday(&other_time, nullptr);
long int ad = 0;
unsigned int bd = 0;
if (other_time.tv_usec < start_time_.tv_usec) {
ad = 1;
bd = 1000000;
}
timeval r = (struct timeval) {0};
r.tv_sec = other_time.tv_sec - ad - start_time_.tv_sec;
r.tv_usec = other_time.tv_usec + bd - start_time_.tv_usec;
return r;
}
bool Solver::simplePreProcess() {
if (!config_.perform_pre_processing)
return true;
assert(literal_stack_.empty());
// BEGIN process unit clauses
for (auto lit : unit_clauses_)
setLiteralIfFree(lit);
// END process unit clauses
VariableIndex start_ofs = 0;
bool succeeded = BCP(start_ofs);
if (succeeded)
succeeded &= prepFailedLiteralTest();
// ToDo major slowdown possible without HardWireAndCompact. Need to make a different version.
// if (succeeded)
// HardWireAndCompact();
return succeeded;
}
bool Solver::prepFailedLiteralTest() {
unsigned long last_size;
do {
last_size = literal_stack_.size();
for (unsigned v = 1; v < variables_.size(); v++) {
if (isActive(v)) {
unsigned long sz = literal_stack_.size();
setLiteralIfFree(LiteralID(v, true));
bool res = BCP(sz);
while (literal_stack_.size() > sz) {
unSet(literal_stack_.back());
literal_stack_.pop_back();
}
if (!res) {
sz = literal_stack_.size();
setLiteralIfFree(LiteralID(v, false));
if (!BCP(sz))
return false;
} else {
sz = literal_stack_.size();
setLiteralIfFree(LiteralID(v, false));
bool resb = BCP(sz);
while (literal_stack_.size() > sz) {
unSet(literal_stack_.back());
literal_stack_.pop_back();
}
if (!resb) {
sz = literal_stack_.size();
setLiteralIfFree(LiteralID(v, true));
if (!BCP(sz))
return false;
}
}
}
}
} while (literal_stack_.size() > last_size);
return true;
}
//void Solver::HardWireAndCompact() {
// compactClauses();
// compactVariables();
// literal_stack_.clear();
//
// for (auto l = LiteralID(1, false); l != literals_.end_lit(); l.inc()) {
// literal(l).activity_score_ = literal(l).binary_links_.size() - 1;
// literal(l).activity_score_ += occurrence_lists_[l].size();
// }
//
// statistics_.num_unit_clauses_ = unit_clauses_.size();
//
// statistics_.num_original_binary_clauses_ = statistics_.num_binary_clauses_;
// statistics_.num_original_unit_clauses_ = statistics_.num_unit_clauses_ = unit_clauses_.size();
// initStack(num_variables());
// original_lit_pool_size_ = literal_pool_.size();
//}
void Solver::sample_models() {
if (!createfromFile(statistics_.input_file_)) {
PrintFinalSamplerResults();
return;
}
SampleAssignment::set_num_var(statistics_.num_variables_);
Solver temp_solver(config_, statistics_);
temp_solver.createfromFile(statistics_.input_file_);
LinkConfigAndStatistics();
reservoir_sample_models(PartialAssignment(), temp_solver);
ReportSharpSatResults();
PrintFinalSamplerResults();
}
void Solver::reservoir_sample_models(const PartialAssignment &partial_assn, Solver &temp_solver) {
if (!InitializeSolverAndPreprocess(partial_assn))
return;
PerformInitialSampling();
statistics_.sampler_pass_1_time_ = sampler_stopwatch_.getElapsedSeconds();
// The UNSAT case can be reached in two different ways either by the
// preprocessor or by running sharpSAT's main flow.
if (statistics_.final_solution_count_ > 0 && config_.perform_two_pass_sampling_)
FillPartialAssignments(temp_solver);
// Print the final results after all sampling then quit.
sampler_stopwatch_.stop();
statistics_.sampler_time_elapsed_ = sampler_stopwatch_.getElapsedSeconds();
statistics_.sampler_pass_2_time_ = statistics_.sampler_time_elapsed_
- statistics_.sampler_pass_1_time_;
}
void Solver::PrintFinalSamplerResults() {
if (!config_.quiet)
std::cout << "\nTotal Sampler Execution Time: " << statistics_.sampler_time_elapsed_ << "s\n\n";
// Print any helper messages
if (!config_.quiet && statistics_.final_solution_count_ < config_.num_samples_) {
std::stringstream ss;
ss << "Only " << statistics_.final_solution_count_ << " models exist but "
<< config_.num_samples_ << " samples were requested." << std::endl;
PrintWarning(ss.str());
}
// Export to a file and the console.
if (!config_.quiet)
final_samples_.exportFinal(std::cout, statistics_, config_);
if (!config_.samples_output_file.empty()) {
std::ofstream samples_file(config_.samples_output_file);
final_samples_.exportFinal(samples_file, statistics_, config_);
samples_file.close();
}
// // ToDo Remove Debug Verification
// bool valid_samples = final_samples_.VerifySolutions(statistics_.input_file_,
// config_.skip_partial_assignment_fill);
// if (!valid_samples)
// ExitWithError("INVALID SAMPLES", EX_SOFTWARE);
// if (!final_samples_.IsComplete())
// ExitWithError("INCOMPLETE SAMPLES", EX_SOFTWARE);
}
void Solver::PerformInitialSampling() {
if (!config_.perform_two_pass_sampling_)
config_.EnableSampleCaching();
if (!config_.quiet) {
if (config_.perform_two_pass_sampling_)
std::cout << "STAGE #1: ";
std::cout << "Build the initial partial assignments" << std::endl;
}
// If the solver has not been shown to be UNSAT by the preprocess,
// run the basic sampler and model count
statistics_.exit_state_ = countSAT();
unused_vars_ = stack_.top().emancipated_vars();
statistics_.set_final_solution_count(stack_.top().getTotalModelCount());
statistics_.num_long_conflict_clauses_ = num_conflict_clauses();
// Clean up the component so it is not an issue during pass two
if (stack_.back().isComponentSplit())
stack_.back().unsetAsComponentSplit();
// If UNSAT, report it and exit.
if (statistics_.final_solution_count_ == 0)
return;
if (unused_vars_.empty()) {
if (config_.verbose)
std::cout << "No unused variables. Continuing..." << std::endl;
} else {
if (config_.verbose)
std::cout << "Number of unused variables: " << unused_vars_.size() << std::endl;
samples_stack_.back().AddEmancipatedVars(unused_vars_);
}
final_samples_ = samples_stack_.back();
assert(IsEndSamplesStackSizeValid());
assert(final_samples_.model_count() == statistics_.final_solution_count_);
if (!config_.quiet) {
if (config_.perform_two_pass_sampling_)
std::cout << "STAGE #1: ";
std::cout << "COMPLETED building initial partial assignments" << std::endl;
}
}
inline void Solver::FillPartialAssignments(Solver &temp_solver) {
if (config_.skip_partial_assignment_fill)
return;
if (!config_.quiet)
std::cout << "STAGE #2 - Filling in partial assignments..." << std::endl;
SamplesManager updated_samples = SamplesManager(config_.num_samples_, config_);
// Free the memory to be used by the descendant solver's cache
// unit_clauses_.clear();
comp_manager_.initialize(literals_, literal_pool_, config_.quiet);
deleteConflictClauses(true);
// Group the samples so that same cache ids are tested together
std::vector<std::pair<std::vector<CacheEntryID>, long>> grouped_samples;
std::vector<ListOfSamples> list_elements;
for (auto &sample : final_samples_.samples()) {
auto new_key = sample.cache_comp_ids();
SampleSize i = 0;
for (i = 0; i < grouped_samples.size(); i++)
if (grouped_samples[i].first == new_key)
break;
if (i < grouped_samples.size()) {
grouped_samples[i].second += sample.sample_count();
list_elements[i].emplace_back(sample);
} else {
grouped_samples.emplace_back(std::pair<std::vector<CacheEntryID>, long>(new_key,
sample.sample_count()));
list_elements.emplace_back();
list_elements.back().emplace_back(sample);
}
}
SampleSize group_cnt = 0, tot_count = 0;
ListOfSamples * samples_list;
auto sample_itr = final_samples_.samples().begin();
while (sample_itr != final_samples_.samples().end()) {
auto key = sample_itr->cache_comp_ids();
long new_sample_count = 0;
SampleSize group_idx;
for (group_idx = 0; group_idx < grouped_samples.size(); group_idx++) {
if (grouped_samples[group_idx].first == key) {
new_sample_count = grouped_samples[group_idx].second;
samples_list = &list_elements[group_idx];
break;
}
}
if (new_sample_count < 0) {
if (sample_itr->cache_comp_ids().empty())
++sample_itr;
else
sample_itr = final_samples_.samples().erase(sample_itr);
continue;
}
grouped_samples[group_idx].second = -new_sample_count;
tot_count += new_sample_count;
++group_cnt;
if (sample_itr->IsComplete()) {
++sample_itr;
statistics_.numb_second_pass_vars_.push_back(0);
if (!config_.quiet)
std::cout << "Sample #" << group_cnt << " of " << grouped_samples.size()
<< " is already a complete assignment. Continuing..." << std::endl;
continue;
}
// If the assignment is complete, then go to next sample
VariableIndex num_unset_vars = sample_itr->num_unset_vars();
statistics_.numb_second_pass_vars_.push_back(num_unset_vars);
assert(num_unset_vars < statistics_.num_variables_);
if (!config_.quiet)
std::cout << "Completing sample #" << group_cnt << " of " << grouped_samples.size()
<< " which has " << num_unset_vars << " variable"
<< ((num_unset_vars == 1) ? "" : "s") << " unset and " << new_sample_count
<< " sample" << ((new_sample_count == 1) ? "" : "s") << "." << std::endl;
// Build an intermediary solver
Solver new_solver = temp_solver;
new_solver.config_.quiet = new_solver.config_.quiet || !config_.verbose;
PartialAssignment partial_assn;
sample_itr->GetPartialAssignment(partial_assn);
new_solver.config_.num_samples_ = static_cast<SampleSize>(new_sample_count);
if (new_solver.config_.num_samples_ == 1)
new_solver.config_.EnableSampleCaching();
new_solver.reservoir_sample_models(partial_assn, temp_solver);
assert(new_solver.IsEndSamplesStackSizeValid());
assert(new_solver.stack_.top_const().getTotalModelCount()
== new_solver.final_samples_.model_count());
assert(new_solver.stack_.top_const().getTotalModelCount() > 0);
assert(new_solver.final_samples_.IsComplete());
// Take the updated sample and store it.
if (samples_list->size() > 1)
new_solver.final_samples_.TransferVariableAssignments(*samples_list);
// Insert the new elements into the samples and delete the old one.
final_samples_.samples().splice(sample_itr, new_solver.final_samples_.samples());
sample_itr = final_samples_.samples().erase(sample_itr);
}
if (tot_count != config_.num_samples_)
ExitWithError("Not all samples tested", EX_SOFTWARE);
if (!config_.quiet)
std::cout << "STAGE #2 - COMPLETE" << std::endl;
// Relink the configuration and statistics objects which may have been unlinked during the
// dependent tasks.
LinkConfigAndStatistics();
}
bool Solver::InitializeSolverAndPreprocess(const PartialAssignment &partial_assn) {
statistics_.set_final_solution_count(0); // Zero out initial model count
applyPartialAssignment(partial_assn);
initStack(num_variables());
if (!config_.quiet) {
if (!config_.perform_random_sampling_)
std::cout << "Performing Exact Model Counting..." << std::endl;
else
std::cout << "Performing Uniform Model Sampling..." << std::endl;
std::cout << "Input File: " << statistics_.input_file_ << std::endl;
if (config_.perform_random_sampling_)
std::cout << "Output File: " << config_.samples_output_file << std::endl;
}
if (!config_.quiet)
std::cout << "\nPreprocessing ..." << std::flush;
bool notfoundUNSAT = simplePreProcess();
if (!config_.quiet)
std::cout << " DONE" << std::endl;
if (!notfoundUNSAT) {
statistics_.exit_state_ = SolverExitState::SUCCESS;
statistics_.final_solution_count_ = 0;
if (!config_.quiet)
std::cout << "\nFOUND UNSAT DURING PREPROCESSING " << std::endl;
return notfoundUNSAT;
}
// If preprocessor did not find the formula to be unsatisfiable, then
// get ready for model counting
if (!config_.quiet)
statistics_.printShortFormulaInfo();
last_ccl_deletion_time_ = last_ccl_cleanup_time_ = statistics_.getTime();
violated_clause.reserve(num_variables());
comp_manager_.initialize(literals_, literal_pool_, config_.quiet);
return notfoundUNSAT;
}
void Solver::applyPartialAssignment(const PartialAssignment &partial_assn) {
// Optionally constrain the solution with unit clauses that match the partial assignment
if (partial_assn.empty())
return;
assert(partial_assn.size() == num_variables() + FIRST_VAR);
std::vector<LiteralID> literals;
literals.emplace_back();
for (VariableIndex var_num = FIRST_VAR; var_num <= num_variables(); var_num++) {
AssignmentEncoding var_assn = partial_assn[var_num];
if (var_assn != ASSN_U) {
literals[0] = LiteralID((var_assn == ASSN_F) ? (-1 * static_cast<int>(var_num))
: static_cast<int>(var_num));
statistics_.incorporateClauseData(literals);
addClause(literals);
}
}
statistics_.num_original_unit_clauses_ = statistics_.num_unit_clauses_ = unit_clauses_.size();
}
void Solver::solve(const PartialAssignment &partial_assn) {
if (createfromFile(this->statistics_.input_file_)) {
bool notfoundUNSAT = InitializeSolverAndPreprocess(partial_assn);
if (notfoundUNSAT) {
statistics_.exit_state_ = countSAT();
statistics_.set_final_solution_count(stack_.top().getTotalModelCount());
statistics_.num_long_conflict_clauses_ = num_conflict_clauses();
}
}
ReportSharpSatResults();
}
void Solver::ReportSharpSatResults() {
statistics_.sampler_time_elapsed_ = sampler_stopwatch_.getElapsedSeconds();
comp_manager_.gatherStatistics();
// if (!results_output_file.empty())
// statistics_.writeToFile(results_output_file);
if (!config_.quiet)
statistics_.printShort();
}
SolverExitState Solver::countSAT() {
SolverNextAction state = SolverNextAction::RESOLVED;
// Put the initial item on the top of the samples stack
PushNewSamplesManagerOnStack();
while (true) {
while (comp_manager_.findNextRemainingComponentOf(stack_.top(), literal_stack_,
samples_stack_.back())) {
decideLiteral();
if (sampler_stopwatch_.timeBoundBroken()) {
if (!config_.quiet)
PrintError("TIMEOUT");
exit(EXIT_TIMEOUT);
}
if (sampler_stopwatch_.interval_tick())
printOnlineStats();
while (!bcp()) {
state = resolveConflict();
if (state == SolverNextAction::BACKTRACK)
break;
}
if (state == SolverNextAction::BACKTRACK)
break;
}
state = backtrack();
if (state == SolverNextAction::EXIT)
return SolverExitState::SUCCESS;
while (state != SolverNextAction::PROCESS_COMPONENT && !bcp()) {
state = resolveConflict();
if (state == SolverNextAction::BACKTRACK) {
state = backtrack();
if (state == SolverNextAction::EXIT)
return SolverExitState::SUCCESS;
}
}
}
}
void Solver::decideLiteral() {
// Store the decision level info for determining what to do with the samples
StackLevel *prev_top = &stack_.top();
// establish another decision stack level
StackLevel newLevel = StackLevel(stack_.top().currentRemainingComponent(),
literal_stack_.size(),
comp_manager_.component_stack_size());
if (config_.perform_random_sampling_ && !stack_.top().isComponentSplit())
newLevel.configureNewLevel(stack_.top(), stack_.get_decision_level());
stack_.push_back(newLevel);
// Manage the passing of the samples
if (config_.perform_random_sampling_) {
// Each component splits necessitate formula merging so create blanks
if (prev_top->isComponentSplit()) {
if (prev_top->isFirstComponent()) {
PushNewSamplesManagerOnStack();
prev_top->markFirstComponentComplete();
}
PushNewSamplesManagerOnStack();
}
}
float max_score = -1;
VariableIndex max_score_var = 0;
// Select the variable with the highest score as the branch variable
for (auto it = comp_manager_.superComponentOf(stack_.top()).varsBegin();
*it != varsSENTINEL; it++) {
float score = scoreOf(*it);
if (score > max_score) {
max_score = score;
max_score_var = *it;
}
}
// this assert should always hold,
// if not then there is a bug in the logic of countSAT();
assert(max_score_var != 0);
// Create the literal to assign
// Select either the negated or unnegated literal depending on
// which form of the literal is most active.
LiteralID theLit(max_score_var,
literal(LiteralID(max_score_var, true)).activity_score_
> literal(LiteralID(max_score_var, false)).activity_score_);
setLiteralIfFree(theLit);
statistics_.num_decisions_++;
set_variable_depth_++;
if (set_variable_depth_ > statistics_.max_branch_var_depth_)
statistics_.max_branch_var_depth_ = set_variable_depth_;
if (statistics_.num_decisions_ % 128 == 0)
// if (statistics_.num_conflicts_ % 128 == 0)
decayActivities();
// decayActivitiesOf(comp_manager_.superComponentOf(stack_.top()));
if (config_.verbose)
std::cout << "Literal Stack Location #" << literal_stack_.size() - 1 << ": Variable #"
<< literal_stack_.back().var() << " assigned to "
<< ((literal_stack_.back().sign()) ? "TRUE" : "FALSE") << std::endl;
assert(stack_.top_const().remaining_components_ofs() <= comp_manager_.component_stack_size());
}
SolverNextAction Solver::backtrack() {
assert(stack_.top_const().remaining_components_ofs() <= comp_manager_.component_stack_size());
do {
if (stack_.top().branch_found_unsat())
comp_manager_.removeAllCachePollutionsOf(stack_.top());
else if (stack_.top().anotherCompProcessible())
return SolverNextAction::PROCESS_COMPONENT;
if (!stack_.top().isSecondBranch()) {
LiteralID aLit = TOS_decLit();
assert(stack_.get_decision_level() > 0);
if (stack_.top().isComponentSplit())
ProcessSampleComponentSplitBacktrack();
// Must close branch after processing backtracking as it will affect the flow otherwise
stack_.top().changeBranch();
reactivateTOS();
setLiteralIfFree(aLit.neg(), Antecedent(NOT_A_CLAUSE));
if (config_.verbose)
std::cout << "Literal Stack Location #" << literal_stack_.size() - 1 << ": Variable #"
<< literal_stack_.back().var() << " switched to "
<< (literal_stack_.back().sign() ? "TRUE" : "FALSE") << std::endl;
return SolverNextAction::RESOLVED;
}
if (stack_.get_decision_level() <= 0)
break; // Bottomed out the decision stack so program execution is complete.
reactivateTOS();
assert(stack_.size() >= 2);
// Merge the solution count up the stack.
(stack_.end() - 2)->includeSolution(stack_.top().getTotalModelCount());
if (config_.perform_random_sampling_)
ProcessSampleComponentSplitBacktrack();
// OTHERWISE: backtrack further
// Store the model count AND POTENTIALLY the assignment in cache.
ProcessCacheStore();
// Process top-tree sampling for max depth.
// Must be after processing component splits to ensure that an immediately dependent
// component split is cleared.
if (config_.perform_top_tree_sampling && set_variable_depth_ == config_.max_top_tree_depth_) {
// if (!stack_.top().HasNoDescendentModels() && HasNoUpperComponentSplit()) {
if (!stack_.top().HasNoDescendentModels()) {
mpz_class multiplier;
if (stack_.on_deck().isComponentSplit())
multiplier = 1;
else
multiplier = stack_.on_deck().getSamplerSolutionMultiplier();
}
}
set_variable_depth_--;
assert(set_variable_depth_ >= 0 && set_variable_depth_ <= literal_stack_.size());
stack_.pop_back();
// step to the next component not yet processed
stack_.top().nextUnprocessedComponent();
assert(stack_.top_const().remaining_components_ofs() < comp_manager_.component_stack_size()+1);
} while (stack_.get_decision_level() >= 0);
return SolverNextAction::EXIT;
}
void Solver::ProcessCacheStore() {
if (stack_.size() == 1 || stack_.top().getTotalModelCount() == 0
|| !config_.perform_sample_caching()) {
// Just store the model count as normal
comp_manager_.cacheModelCountOf(stack_.top().super_component(),
stack_.top().getTotalModelCount());
} else {
// Bundle the model count with a partial assignment
StackLevel top = stack_.top();
Component top_comp = comp_manager_.component(top.super_component());
SampleAssignment cache_sample = top.random_cache_sample();
comp_manager_.cacheModelCountAndAssignment(top.super_component(), top.getTotalModelCount(),
cache_sample, top_comp);
stack_.on_deck().set_cache_sample(cache_sample);
}
}
void Solver::ProcessSampleComponentSplitBacktrack() {
// Combine the results of a component split
if (stack_.top().isComponentSplit()) {
// Merge the component split with its parent
if (config_.verbose) {
std::stringstream ss;
ss << "Component " << stack_.top().super_component() << " merging component split "
<< "at depth " << StackLevel::componentSplitDepth() << ".";
PrintInColor(ss, COLOR_MAGENTA);
}
if (config_.store_sampled_models()) {
SampleAssignment cached_sample;
VariableIndex on_deck = samples_stack_.size() - 2;
samples_stack_[on_deck].merge(samples_stack_.back(),
stack_.top().getSamplerSolutionMultiplier(),
stack_.top().emancipated_vars(),
stack_.top().cached_comp_ids(),
stack_.top().cached_assn(), cached_sample);
samples_stack_.pop_back();
if (config_.perform_sample_caching()) {
// ToDo modify to support multiple sample caching
stack_.top().ClearCachedAssn();
stack_.top().set_cache_sample(cached_sample);
}
// assert(samples_stack_.back().VerifySolutions(statistics_.input_file_, true)); // DebugZH
}
stack_.top().unsetAsComponentSplit();
}
// Only close a component branch after testing both true and false paths.
// If there is a back to back component split, may need to close both the component
// split and the branch in a single round.
if (stack_.size() <= 1)
return;
if (stack_.top().isSecondBranch() && stack_.on_deck().isComponentSplit()) {
if (config_.verbose) {
std::stringstream ss;
ss << "Component branch #" << stack_.top().super_component() << " split end reached at depth "
<< StackLevel::componentSplitDepth() << ". Stitching the sample.";
PrintInColor(ss, COLOR_BLUE);
}
if (config_.store_sampled_models()) {
samples_stack_[samples_stack_.size() - 2].stitch(samples_stack_.back());
samples_stack_.pop_back();
// assert(samples_stack_.back().VerifySolutions(statistics_.input_file_, true)); // DebugZH
}
}
}
SolverNextAction Solver::resolveConflict() {
recordLastUIPCauses();
if (statistics_.num_clauses_learned_ - last_ccl_deletion_time_
> statistics_.clause_deletion_interval()) {
deleteConflictClauses();
last_ccl_deletion_time_ = statistics_.num_clauses_learned_;
}
if (statistics_.num_clauses_learned_ - last_ccl_cleanup_time_ > 100000) {
compactConflictLiteralPool();
last_ccl_cleanup_time_ = statistics_.num_clauses_learned_;
}
statistics_.num_conflicts_++;
assert(stack_.top_const().remaining_components_ofs() <= comp_manager_.component_stack_size());
assert(uip_clauses_.size() == 1);
// DEBUG
if (uip_clauses_.back().empty() && !config_.quiet)
std::cerr << "EMPTY CLAUSE FOUND" << std::endl;
// END DEBUG
stack_.top().mark_branch_unsat();
// BEGIN Backtracking
// maybe the other branch had some solutions
if (stack_.top().isSecondBranch()) {
return SolverNextAction::BACKTRACK;
}
Antecedent ant(NOT_A_CLAUSE);
// this has to be checked since using implicit BCP
// and checking literals there not exhaustively
// we cannot guarantee that uip_clauses_.back().front() == TOS_decLit().neg()
// this is because we might have checked a literal
// during implict BCP which has been a failed literal
// due only to assignments made at lower decision levels
if (uip_clauses_.back().front() == TOS_decLit().neg()) {
assert(TOS_decLit().neg() == uip_clauses_.back()[0]);
var(TOS_decLit().neg()).ante = addUIPConflictClause(
uip_clauses_.back());
ant = var(TOS_decLit()).ante;
}
// // RRR
// else if (var(uip_clauses_.back().front()).decision_level
// < stack_.get_decision_level()
// && assertion_level_ < stack_.get_decision_level()) {
// stack_.top().set_both_branches_unsat();
// return BACKTRACK;
// }
//
//
// // RRR
assert(stack_.get_decision_level() > 0);
assert(stack_.top_const().branch_found_unsat());
// we do not have to remove pollutions here,
// since conflicts only arise directly before
// remaining components are stored
// hence
assert(
stack_.top_const().remaining_components_ofs() == comp_manager_.component_stack_size());
stack_.top().changeBranch();
LiteralID lit = TOS_decLit();
reactivateTOS();
setLiteralIfFree(lit.neg(), ant);
// END Backtracking
return SolverNextAction::RESOLVED;
}
bool Solver::bcp() {
// the asserted literal has been set, so we start
// bcp on that literal
VariableIndex start_ofs = literal_stack_.size() - 1;
// BEGIN process unit clauses
for (auto lit : unit_clauses_)
setLiteralIfFree(lit);
// END process unit clauses
bool bSucceeded = BCP(start_ofs);
if (config_.perform_failed_lit_test && bSucceeded) {
bSucceeded = implicitBCP();
}
return bSucceeded;
}
bool Solver::BCP(VariableIndex start_at_stack_ofs) {
for (VariableIndex i = start_at_stack_ofs; i < literal_stack_.size(); i++) {
LiteralID unLit = literal_stack_[i].neg();
// BEGIN Propagate Bin Clauses
for (auto bt = literal(unLit).binary_links_.begin();
*bt != SENTINEL_LIT; bt++) {
if (isResolved(*bt)) {
setConflictState(unLit, *bt);
return false;
}
setLiteralIfFree(*bt, Antecedent(unLit));
}
// END Propagate Bin Clauses
for (auto itcl = literal(unLit).watch_list_.rbegin();
*itcl != SENTINEL_CL; itcl++) {
bool isLitA = (*beginOf(*itcl) == unLit);
auto p_watchLit = beginOf(*itcl) + 1 - isLitA;
auto p_otherLit = beginOf(*itcl) + isLitA;
if (isSatisfied(*p_otherLit))
continue;
auto itL = beginOf(*itcl) + 2;
while (isResolved(*itL))
itL++;
// either we found a free or satisfied lit
if (*itL != SENTINEL_LIT) {
literal(*itL).addWatchLinkTo(*itcl);
std::swap(*itL, *p_watchLit);
*itcl = literal(unLit).watch_list_.back();
literal(unLit).watch_list_.pop_back();
} else {
// or p_unLit stays resolved
// and we have hence no free literal left
// for p_otherLit remain poss: Active or Resolved
if (setLiteralIfFree(*p_otherLit, Antecedent(*itcl))) { // implication
if (isLitA)
std::swap(*p_otherLit, *p_watchLit);
} else {
setConflictState(*itcl);
return false;
}
}
}
}
return true;
}
//bool Solver::implicitBCP() {
// static std::vector<LiteralID> test_lits(num_variables());
// static LiteralIndexedVector<unsigned char> viewed_lits(num_variables() + 1,
// 0);
//
// unsigned stack_ofs = stack_.top().literal_stack_ofs();
// while (stack_ofs < literal_stack_.size()) {
// test_lits.clear();
// for (auto it = literal_stack_.begin() + stack_ofs;
// it != literal_stack_.end(); it++) {
// for (auto cl_ofs : occurrence_lists_[it->neg()])
// if (!isSatisfied(cl_ofs)) {
// for (auto lt = beginOf(cl_ofs); *lt != SENTINEL_LIT; lt++)
// if (isActive(*lt) && !viewed_lits[lt->neg()]) {
// test_lits.push_back(lt->neg());
// viewed_lits[lt->neg()] = true;
//
// }
// }
// }
//
// stack_ofs = literal_stack_.size();
// for (auto jt = test_lits.begin(); jt != test_lits.end(); jt++)
// viewed_lits[*jt] = false;
//
// statistics_.num_failed_literal_tests_ += test_lits.size();
//
// for (auto lit : test_lits)
// if (isActive(lit)) {
// unsigned sz = literal_stack_.size();
// // we increase the decLev artificially
// // s.t. after the tentative BCP call, we can learn a conflict clause
// // relative to the assn_ of *jt
// stack_.startFailedLitTest();
// setLiteralIfFree(lit);
//
// assert(!hasAntecedent(lit));
//
// bool bSucceeded = BCP(sz);
// if (!bSucceeded)
// recordAllUIPCauses();
//
// stack_.stopFailedLitTest();
//
// while (literal_stack_.size() > sz) {
// unSet(literal_stack_.back());
// literal_stack_.pop_back();
// }
//
// if (!bSucceeded) {
// statistics_.num_failed_literals_detected_++;
// sz = literal_stack_.size();
// for (auto it = uip_clauses_.rbegin(); it != uip_clauses_.rend();
// it++) {
// setLiteralIfFree(it->front(), addUIPConflictClause(*it));
// }
// if (!BCP(sz))
// return false;
// }
// }
// }
// return true;
//}
// this is IBCP 30.08
bool Solver::implicitBCP() {
static std::vector<LiteralID> test_lits(num_variables());
static LiteralIndexedVector<unsigned char> viewed_lits(num_variables() + 1, 0);
VariableIndex stack_ofs = stack_.top().literal_stack_ofs();
while (stack_ofs < literal_stack_.size()) {
test_lits.clear();
for (auto it = literal_stack_.begin() + stack_ofs;
it != literal_stack_.end(); it++) {
for (auto cl_ofs : occurrence_lists_[it->neg()])
if (!isSatisfied(cl_ofs)) {
for (auto lt = beginOf(cl_ofs); *lt != SENTINEL_LIT; lt++)
if (isActive(*lt) && !viewed_lits[lt->neg()]) {
test_lits.push_back(lt->neg());
viewed_lits[lt->neg()] = true;
}
}
}
VariableIndex num_curr_lits = literal_stack_.size() - stack_ofs;
stack_ofs = literal_stack_.size();
for (auto jt = test_lits.begin(); jt != test_lits.end(); jt++)
viewed_lits[*jt] = false;
std::vector<float> scores;
scores.clear();
for (auto &test_lit : test_lits) {
scores.push_back(literal(test_lit).activity_score_);
}
sort(scores.begin(), scores.end());
num_curr_lits = 10 + num_curr_lits / 20;
float threshold = 0.0;
if (scores.size() > num_curr_lits) {
threshold = scores[scores.size() - num_curr_lits];
}
statistics_.num_failed_literal_tests_ += test_lits.size();
for (auto lit : test_lits)
if (isActive(lit) && threshold <= literal(lit).activity_score_) {
VariableIndex sz = literal_stack_.size();
// we increase the decLev artificially
// s.t. after the tentative BCP call, we can learn a conflict clause
// relative to the assn_ of *jt
stack_.startFailedLitTest();
setLiteralIfFree(lit);
assert(!hasAntecedent(lit));
bool bSucceeded = BCP(sz);
if (!bSucceeded)
recordAllUIPCauses();
stack_.stopFailedLitTest();
while (literal_stack_.size() > sz) {
unSet(literal_stack_.back());
literal_stack_.pop_back();
}
if (!bSucceeded) {
statistics_.num_failed_literals_detected_++;
sz = literal_stack_.size();
for (auto it = uip_clauses_.rbegin();
it != uip_clauses_.rend(); it++) {
// DEBUG
if (it->empty() && !config_.quiet)
PrintError("EMPTY CLAUSE FOUND");
// END DEBUG
setLiteralIfFree(it->front(), addUIPConflictClause(*it));
}
if (!BCP(sz))
return false;
}
}
}
// BEGIN TEST
// float max_score = -1;
// float score;
// unsigned max_score_var = 0;
// for (auto it =
// component_analyzer_.superComponentOf(stack_.top()).varsBegin();
// *it != varsSENTINEL; it++)
// if (isActive(*it)) {
// score = scoreOf(*it);
// if (score > max_score) {
// max_score = score;
// max_score_var = *it;
// }
// }
// LiteralID theLit(max_score_var,
// literal(LiteralID(max_score_var, true)).activity_score_
// > literal(LiteralID(max_score_var, false)).activity_score_);
// if (!fail_test(theLit.neg())) {
// std::cout << ".";
//
// statistics_.num_failed_literals_detected_++;
// unsigned sz = literal_stack_.size();
// for (auto it = uip_clauses_.rbegin(); it != uip_clauses_.rend(); it++) {
// setLiteralIfFree(it->front(), addUIPConflictClause(*it));
// }
// if (!BCP(sz))
// return false;
//
// }
// END
return true;
}
// BEGIN module conflictAnalyzer
void Solver::minimizeAndStoreUIPClause(LiteralID uipLit,
std::vector<LiteralID> &tmp_clause,
const bool seen[]) {
static std::deque<LiteralID> clause;
clause.clear();
assertion_level_ = 0;
for (auto lit : tmp_clause) {
if (existsUnitClauseOf(lit.var()))
continue;
bool resolve_out = false;
if (hasAntecedent(lit)) {
resolve_out = true;
if (getAntecedent(lit).isAClause()) {
for (auto it = beginOf(getAntecedent(lit).asCl()) + 1;
*it != SENTINEL_CL; it++)
if (!seen[it->var()]) {
resolve_out = false;
break;
}
} else if (!seen[getAntecedent(lit).asLit().var()]) {
resolve_out = false;
}
}
if (!resolve_out) {
// uipLit should be the sole literal of this Decision Level
if (var(lit).decision_level >= assertion_level_) {
assertion_level_ = var(lit).decision_level;
clause.push_front(lit);
} else {
clause.push_back(lit);
}
}
}
if (uipLit.var())
assert(var_const(uipLit).decision_level == stack_.get_decision_level());
// assert(uipLit.var() != 0);
if (uipLit.var() != 0)
clause.push_front(uipLit);
uip_clauses_.emplace_back(std::vector<LiteralID>(clause.begin(), clause.end()));
}
void Solver::recordLastUIPCauses() {
// note:
// variables of lower dl: if seen we dont work with them anymore
// variables of this dl: if seen we incorporate their
// antecedent and set to unseen
bool seen[num_variables() + 1];
memset(seen, false, sizeof(bool) * (num_variables() + 1));
static std::vector<LiteralID> tmp_clause;
tmp_clause.clear();
assertion_level_ = 0;
uip_clauses_.clear();
unsigned long lit_stack_ofs = literal_stack_.size();
long DL = stack_.get_decision_level();
unsigned lits_at_current_dl = 0;
for (auto l : violated_clause) {
if (var(l).decision_level == 0 || existsUnitClauseOf(l.var()))
continue;
if (var(l).decision_level < DL)
tmp_clause.push_back(l);
else
lits_at_current_dl++;
literal(l).increaseActivity();
seen[l.var()] = true;
}
LiteralID curr_lit;
while (lits_at_current_dl) {
assert(lit_stack_ofs != 0);
curr_lit = literal_stack_[--lit_stack_ofs];
if (!seen[curr_lit.var()])
continue;
seen[curr_lit.var()] = false;
if (lits_at_current_dl-- == 1) {
// perform UIP stuff
if (!hasAntecedent(curr_lit)) {
// this should be the decision literal when in first branch
// or it is a literal decided to explore in failed literal testing
// assert(stack_.TOS_decLit() == curr_lit);
// std::cout << "R" << curr_lit.toInt() << "S"
// << var(curr_lit).ante.isAnt() << " " << std::endl;
break;
}
}
assert(hasAntecedent(curr_lit));
// std::cout << "{" << curr_lit.toInt() << "}";
if (getAntecedent(curr_lit).isAClause()) {
updateActivities(getAntecedent(curr_lit).asCl());
assert(curr_lit == *beginOf(antecedent(curr_lit).asCl()));
for (auto it = beginOf(getAntecedent(curr_lit).asCl()) + 1;
*it != SENTINEL_CL; it++) {
if (seen[it->var()] || (var(*it).decision_level == 0)
|| existsUnitClauseOf(it->var()))
continue;
if (var(*it).decision_level < DL)
tmp_clause.push_back(*it);
else
lits_at_current_dl++;
seen[it->var()] = true;
}
} else {
LiteralID alit = getAntecedent(curr_lit).asLit();
literal(alit).increaseActivity();
literal(curr_lit).increaseActivity();
if (!seen[alit.var()] && var(alit).decision_level != 0
&& !existsUnitClauseOf(alit.var())) {
if (var(alit).decision_level < DL)
tmp_clause.push_back(alit);
else
lits_at_current_dl++;
seen[alit.var()] = true;
}
}
curr_lit = NOT_A_LIT;
}
// std::cout << "T" << curr_lit.toInt() << "U "
// << var(curr_lit).decision_level << ", " << stack_.get_decision_level()
// << "\n"
// << "V" << var(curr_lit).ante.isAnt() << " " << std::endl;
minimizeAndStoreUIPClause(curr_lit.neg(), tmp_clause, seen);
// if (var(curr_lit).decision_level > assertion_level_)
// assertion_level_ = var(curr_lit).decision_level;
}
void Solver::recordAllUIPCauses() {
// note:
// variables of lower dl: if seen we dont work with them anymore
// variables of this dl: if seen we incorporate their
// antecedent and set to unseen
bool seen[num_variables() + 1];
memset(seen, false, sizeof(bool) * (num_variables() + 1));
static std::vector<LiteralID> tmp_clause;
tmp_clause.clear();
assertion_level_ = 0;
uip_clauses_.clear();
unsigned long lit_stack_ofs = literal_stack_.size();
long DL = stack_.get_decision_level();
unsigned lits_at_current_dl = 0;
for (auto l : violated_clause) {
if (var(l).decision_level == 0 || existsUnitClauseOf(l.var()))
continue;
if (var(l).decision_level < DL)
tmp_clause.push_back(l);
else
lits_at_current_dl++;
literal(l).increaseActivity();
seen[l.var()] = true;
}
unsigned n = 0;
LiteralID curr_lit;
while (lits_at_current_dl) {
assert(lit_stack_ofs != 0);
curr_lit = literal_stack_[--lit_stack_ofs];
if (!seen[curr_lit.var()])
continue;
seen[curr_lit.var()] = false;
if (lits_at_current_dl-- == 1) {
n++;
if (!hasAntecedent(curr_lit)) {
// this should be the decision literal when in first branch
// or it is a literal decided to explore in failed literal testing
//assert(stack_.TOS_decLit() == curr_lit);
break;
}
// perform UIP stuff
minimizeAndStoreUIPClause(curr_lit.neg(), tmp_clause, seen);
}
assert(hasAntecedent(curr_lit));
if (getAntecedent(curr_lit).isAClause()) {
updateActivities(getAntecedent(curr_lit).asCl());
assert(curr_lit == *beginOf(getAntecedent(curr_lit).asCl()));
for (auto it = beginOf(getAntecedent(curr_lit).asCl()) + 1;
*it != SENTINEL_CL; it++) {
if (seen[it->var()] || (var(*it).decision_level == 0)
|| existsUnitClauseOf(it->var()))
continue;
if (var(*it).decision_level < DL)
tmp_clause.push_back(*it);
else
lits_at_current_dl++;
seen[it->var()] = true;
}
} else {
LiteralID alit = getAntecedent(curr_lit).asLit();
literal(alit).increaseActivity();
literal(curr_lit).increaseActivity();
if (!seen[alit.var()] && var(alit).decision_level != 0
&& !existsUnitClauseOf(alit.var())) {
if (var(alit).decision_level < DL)
tmp_clause.push_back(alit);
else
lits_at_current_dl++;
seen[alit.var()] = true;
}
}
}
if (!hasAntecedent(curr_lit)) {
minimizeAndStoreUIPClause(curr_lit.neg(), tmp_clause, seen);
}
// if (var(curr_lit).decision_level > assertion_level_)
// assertion_level_ = var(curr_lit).decision_level;
}
void Solver::printOnlineStats() {
if (config_.quiet)
return;
std::cout << "\ntime elapsed: " << sampler_stopwatch_.getElapsedSeconds() << "s" << std::endl;
if (config_.verbose) {
std::cout << "conflict clauses (all / bin / unit) \t"
<< num_conflict_clauses()
<< "/" << statistics_.num_binary_conflict_clauses_ << "/"
<< unit_clauses_.size() << "\n"
<< "failed literals found by implicit BCP \t "
<< statistics_.num_failed_literals_detected_ << "\n";
std::cout << "implicit BCP miss rate \t "
<< statistics_.implicitBCP_miss_rate() * 100 << "%\n";
comp_manager_.gatherStatistics();
std::cout << "cache size " << statistics_.cache_MB_memory_usage() << "MB" << "\n"
<< "components (stored / hits) \t\t"
<< statistics_.cached_component_count() << "/"
<< statistics_.cache_hits() << "\n"
<< "avg. variable count (stored / hits) \t"
<< statistics_.getAvgComponentSize() << "/"
<< statistics_.getAvgCacheHitSize() << "\n"
<< "cache miss rate " << statistics_.cache_miss_rate() * 100 << "%"
<< std::endl;
}
}
//bool Solver::IsVarInLiteralStack(const VariableIndex var) {
// for (VariableIndex i = 0; i < literal_stack_.size(); i++) {
// if (literal_stack_[i].var() == var) {
// std::stringstream ss;
// ss << "Var #" << var << " is in the literal stack at level " << i
// << " with val " << literal_stack_[i].sign();
// PrintError(ss);
// return true;
// }
// }
// return false;
//}
//
//
//void Solver::PrintLiteralStackLocation(VariableIndex var) {
// for (VariableIndex i = 0; i < literal_stack_.size(); i++) {
// if (literal_stack_[i].var() == var) {
// std::stringstream ss;
// ss << "Var #" << var << " is located in slot " << i << " and has sign "
// << (literal_stack_[i].sign() ? "POS" : "NEG");
// PrintError(ss);
// }
// }
//}
Solver::Solver(int argc, char *argv[]) : final_samples_(0, config_) {
// Store the configuration for visibility by the stack.
LinkConfigAndStatistics();
time(&statistics_.start_time_);
config_.num_samples_ = 0; // By default initialize the model count to zero
for (int i = 1; i < argc; i++) {
// if (strcmp(argv[i], "-noCC") == 0)
// config_.perform_component_caching = false;
// else if (strcmp(argv[i], "-noIBCP") == 0)
// config_.perform_failed_lit_test = false;
// else if (strcmp(argv[i], "-noPP") == 0)
// config_.perform_pre_processing = false;
// else if (strcmp(argv[i], "-q") == 0)
if (strcmp(argv[i], "-q") == 0) {
config_.quiet = true;
} else if (strcmp(argv[i], "-v") == 0) {
config_.verbose = true;
} else if (strcmp(argv[i], "-d") == 0) {
config_.debug_mode = true;
} else if (strcmp(argv[i], "-tp") == 0) {
config_.perform_two_pass_sampling_ = true;
} else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-out") == 0) {
if (argc <= i + 1 || !config_.perform_random_sampling_)
ExitInvalidParam("Invalid parameters for sampling");
if (strcmp(argv[i], "-s") == 0) {
long num_samples = strtoul(argv[++i], nullptr, STR_DECIMAL_BASE);
config_.num_samples_ = static_cast<SampleSize>(num_samples);
if (config_.num_samples_ < 1)
ExitInvalidParam("Must sample at least one model");
} else {
config_.samples_output_file = argv[++i];
}
} else if (strcmp(argv[i], "-no-sample-write") == 0) {
config_.disable_samples_write_ = true;
} else if (strcmp(argv[i], "-count-only") == 0) {
config_.perform_random_sampling_ = false;
if (config_.num_samples_ > 0 || !config_.samples_output_file.empty())
ExitInvalidParam("Invalid parameters for counting and sampling");
} else if (strcmp(argv[i], "-t") == 0) {
if (argc <= i + 1)
ExitInvalidParam("Time bound missing");
config_.time_bound_seconds = strtoul(argv[++i], nullptr, STR_DECIMAL_BASE);
} else if (strcmp(argv[i], "-cs") == 0) {
if (argc <= i + 1)
ExitInvalidParam("No cache size specified");
statistics_.maximum_cache_size_bytes_ = strtoul(argv[++i], nullptr, STR_DECIMAL_BASE)
* (uint64_t) 1000000;
} else if (strcmp(argv[i], "-cnf") == 0) {
if (argc <= i + 1)
ExitInvalidParam("No CNF file specified");
statistics_.input_file_ = argv[++i];
} else if (strcmp(argv[i], "-no-partial-fill") == 0) {
// This is a debug only feature. Functionality is not guaranteed.
config_.skip_partial_assignment_fill = true;
} else if (strcmp(argv[i], "-top-tree") == 0) {
config_.perform_top_tree_sampling = true;
} else if (strcmp(argv[i], "-top-tree-depth") == 0) {
long top_tree_depth = strtoul(argv[++i], nullptr, STR_DECIMAL_BASE);
if (top_tree_depth <= 1)
ExitInvalidParam("The top tree depth must be greater than 1.");
config_.max_top_tree_depth_ = static_cast<TreeNodeIndex>(top_tree_depth);
} else if (strcmp(argv[i], "-max-leaf-size") == 0) {
long max_leaf_size = strtoul(argv[++i], nullptr, STR_DECIMAL_BASE);
if (max_leaf_size <= 1)
ExitInvalidParam("The top tree leaf size must be greater than 1.");
config_.max_top_tree_leaf_sample_count = static_cast<SampleSize>(max_leaf_size);
} else {
ExitInvalidParam(static_cast<std::string>("Unknown parameter found \"") + argv[i] + "\"");
}
}
// Perform additional cross-checking of input parameters
if (config_.quiet && config_.verbose)
ExitInvalidParam("Invalid combination of verbose and quiet");
if (config_.num_samples_ < 1 && config_.perform_random_sampling_)
ExitInvalidParam("If sampling is enabled, a sample count greater than or equal \n"
"to 1 must be specified.");
if (config_.perform_two_pass_sampling_ && !config_.perform_random_sampling_)
ExitInvalidParam("The two pass sampling flag is only applicable when sampling is enabled.\n");
if (config_.perform_top_tree_sampling && !config_.perform_random_sampling_)
ExitInvalidParam("Top tree sampling cannot be enabled if random sampling is disabled.");
if (config_.disable_samples_write_ && !config_.perform_random_sampling_)
ExitInvalidParam("Disabling sample write cannot be selected if sampling is disabled.");
if (config_.samples_output_file.empty() && config_.perform_random_sampling_) {
std::string input_file = statistics_.input_file_;
uint64_t os_sep_loc = input_file.rfind('\\');
os_sep_loc = (os_sep_loc != std::string::npos) ? os_sep_loc : input_file.rfind('/');
std::string out_file;
if (os_sep_loc != std::string::npos)
out_file = statistics_.input_file_.substr(0, os_sep_loc + 1);
// Prepend "results_" to the samples filename
out_file += "samples_";
// Append the filename and change extension to ".txt"
uint64_t filename_start_loc = os_sep_loc + 1;
uint64_t file_ext_start = input_file.rfind('.');
if (file_ext_start <= filename_start_loc || file_ext_start == std::string::npos)
file_ext_start = statistics_.input_file_.size();
uint64_t filename_len = file_ext_start - filename_start_loc;
out_file += statistics_.input_file_.substr(filename_start_loc, filename_len);
out_file += ".txt";
config_.samples_output_file = out_file;
if (!config_.quiet)
PrintWarning(static_cast<std::string>("No sample results file specified.\n")
+ "Using default filename: \"" + out_file + "\"");
}
if (config_.perform_two_pass_sampling_ && config_.num_samples_ > 1 && !config_.quiet)
PrintWarning("The two pass sampling flag only has an effect\n"
"when the number of samples equals 1. Ignoring...");
// Initialize the time bound.
sampler_stopwatch_.setTimeBound(config_.time_bound_seconds);
// Any time the same count is larger than one, always do two pass sampling
if (config_.num_samples_ > 1)
config_.perform_two_pass_sampling_ = true;
// Must parse at the end in case debug mode is selected.
Random::init(&config_);
}
Includes¶
deque
primitive_types.h
(File primitive_types.h)sampler_tools.h
(File sampler_tools.h)solver.h
(File solver.h)solver_config.h
(File solver_config.h)sstream
string
unordered_map
utility
vector
File solver.h¶
↰ Parent directory (src
)
Definition (src/solver.h
)¶
↰ Return to documentation for file (src/solver.h
)
#ifndef SOLVER_H_
#define SOLVER_H_
#include <sys/time.h>
#include <algorithm>
#include <utility>
#include <vector>
#include <string>
#include "statistics.h"
#include "instance.h"
#include "component_management.h"
#include "solver_config.h"
#include "model_sampler.h"
#include "cached_assignment.h"
//#include "top_tree_sampler.h"
class StopWatch {
public:
StopWatch();
bool timeBoundBroken() {
timeval actual_time = (struct timeval) {0};
gettimeofday(&actual_time, nullptr);
return actual_time.tv_sec - start_time_.tv_sec > time_bound_;
}
bool start() {
auto ret = static_cast<bool>(gettimeofday(&last_interval_start_, nullptr));
start_time_ = stop_time_ = last_interval_start_;
return !ret;
}
bool stop() {
return gettimeofday(&stop_time_, nullptr) == 0;
}
double getElapsedSeconds() {
timeval r = getElapsedTime();
return r.tv_sec + static_cast<double>(r.tv_usec) / 1000000;
}
bool interval_tick() {
timeval actual_time = (struct timeval) {0};
gettimeofday(&actual_time, nullptr);
if (actual_time.tv_sec - last_interval_start_.tv_sec
> interval_length_.tv_sec) {
gettimeofday(&last_interval_start_, nullptr);
return true;
}
return false;
}
void setTimeBound(uint64_t seconds) {
time_bound_ = seconds;
}
// ZH Appears to neither be implemented or used.
//long int getTimeBound();
private:
timeval start_time_;
timeval stop_time_;
uint64_t time_bound_ = UINT64_MAX;
timeval interval_length_;
timeval last_interval_start_;
timeval getElapsedTime();
};
class Solver: public Instance {
public:
Solver(int argc, char *argv[]);
Solver(SolverConfiguration &config, DataAndStatistics &statistics,
SampleSize num_samples = 0, bool two_pass = true)
: config_(config), final_samples_(num_samples, config_) {
LinkConfigAndStatistics();
statistics_.input_file_ = statistics.input_file_;
// ToDo modify to support caching multiple samples
//config_.num_samples_to_cache_ = num_samples;
config_.num_samples_to_cache_ = 1;
sampler_stopwatch_.setTimeBound(config_.time_bound_seconds); // Initialize the time bound.
config_.samples_output_file = "";
config_.disable_samples_write_ = true;
config_.num_samples_ = num_samples;
time(&statistics_.start_time_);
config_.perform_two_pass_sampling_ = two_pass;
}
Solver(const Solver &other)
: config_(other.config_), final_samples_(other.final_samples_.num_samples(), config_) {
// Bring over the configuration and statistics
statistics_ = other.statistics_;
LinkConfigAndStatistics();
config_.num_samples_to_cache_ = 1;
config_.disable_samples_write_ = true;
// Data structures used in the createFromFile Function
literal_pool_ = other.literal_pool_;
variables_ = other.variables_;
literal_values_ = other.literal_values_;
unit_clauses_ = other.unit_clauses_;
unused_vars_ = other.unused_vars_;
independent_support = other.independent_support;
has_independent_support_ = other.has_independent_support_;
conflict_clauses_ = other.conflict_clauses_;
occurrence_lists_ = other.occurrence_lists_;
literals_ = other.literals_;
// Initialize other variables as needed
statistics_.start_time_ = other.statistics_.start_time_; // Needed to ensure timeout
sampler_stopwatch_.setTimeBound(config_.time_bound_seconds); // Initialize the time bound.
original_lit_pool_size_ = other.original_lit_pool_size_;
}
void solve(const PartialAssignment &partial_assn = PartialAssignment());
void sample_models();
const SolverConfiguration &config() {
return config_;
}
void DisableTopTreeSampling() {
assert(config_.perform_top_tree_sampling);
config_.perform_top_tree_sampling = false;
}
const DataAndStatistics &statistics() {
return statistics_;
}
void PushNewSamplesManagerOnStack() {
if (config_.store_sampled_models())
samples_stack_.emplace_back(SamplesManager(config_.num_samples_, config_));
}
// /**
// * Literal Stack Location Printer
// *
// * Debug only tool. Often, a CNF formula has hundreds of thousands
// * of variables on the literal stack. Finding where a specific variable
// * is on the stack (if at all) can be time consuming. This function
// * prints whether the specified variable is on the stack.
// *
// * @param var Variable number of interest.
// */
// void PrintLiteralStackLocation(VariableIndex var);
// End Sampler Objects
private:
SolverConfiguration config_;
DecisionStack stack_;
std::vector<LiteralID> literal_stack_;
ComponentManager comp_manager_ = ComponentManager(config_, statistics_, literal_values_);
StopWatch sampler_stopwatch_;
uint64_t last_ccl_deletion_time_ = 0;
uint64_t last_ccl_cleanup_time_ = 0;
std::vector<SamplesManager> samples_stack_;
SamplesManager final_samples_;
bool simplePreProcess();
bool prepFailedLiteralTest();
void reservoir_sample_models(const PartialAssignment &partial_assn, Solver &temp_solver);
// /**
// * MT - we assert that the formula is consistent and has not been
// * found UNSAT yet hard wires all assertions in the literal stack
// * into the formula removes all set variables and essentially
// * reinitializes all further data.
// */
// void HardWireAndCompact();
SolverExitState countSAT();
void decideLiteral();
bool bcp();
void decayActivitiesOf(Component & comp) {
for (auto it = comp.varsBegin(); *it != varsSENTINEL; it++) {
literal(LiteralID(*it, true)).activity_score_ *=0.5;
literal(LiteralID(*it, false)).activity_score_ *=0.5;
}
}
bool implicitBCP();
bool BCP(VariableIndex start_at_stack_ofs);
SolverNextAction backtrack();
void ProcessCacheStore();
void ProcessSampleComponentSplitBacktrack();
SolverNextAction resolveConflict();
void PrintFinalSamplerResults();
// BEGIN small helper functions
float scoreOf(VariableIndex v) {
float score = comp_manager_.scoreOf(v);
score += 10.0 * literal(LiteralID(v, true)).activity_score_;
score += 10.0 * literal(LiteralID(v, false)).activity_score_;
// score += (10*stack_.get_decision_level()) * literal(LiteralID(v, true)).activity_score_;
// score += (10*stack_.get_decision_level()) * literal(LiteralID(v, false)).activity_score_;
return score;
}
bool setLiteralIfFree(LiteralID lit, Antecedent ant = Antecedent(NOT_A_CLAUSE)) {
if (literal_values_[lit] != X_TRI)
return false;
var(lit).decision_level = stack_.get_decision_level();
var(lit).ante = ant;
literal_stack_.push_back(lit);
if (ant.isAClause() && ant.asCl() != NOT_A_CLAUSE)
getHeaderOf(ant.asCl()).increaseScore();
literal_values_[lit] = T_TRI;
literal_values_[lit.neg()] = F_TRI;
return true;
}
void printOnlineStats();
// /**
// * Literal Stack Contents Checker
// *
// * Checks whether the specified variable is in the literal stack.
// *
// * @param var Variable of interest
// * @return true if the specified variable @see var is in the literal stack.
// */
// bool IsVarInLiteralStack(VariableIndex var);
void setConflictState(LiteralID litA, LiteralID litB) {
violated_clause.clear();
violated_clause.push_back(litA);
violated_clause.push_back(litB);
}
void setConflictState(ClauseOfs cl_ofs) {
getHeaderOf(cl_ofs).increaseScore();
violated_clause.clear();
for (auto it = beginOf(cl_ofs); *it != SENTINEL_LIT; it++)
violated_clause.push_back(*it);
}
std::vector<LiteralID>::const_iterator TOSLiteralsBegin() {
return literal_stack_.begin() + stack_.top().literal_stack_ofs();
}
void initStack(unsigned long resSize = 0) {
stack_.clear();
if (resSize != 0)
stack_.reserve(resSize);
literal_stack_.clear();
if (resSize != 0)
literal_stack_.reserve(resSize);
// initialize the stack to contain at least level zero
stack_.push_back(StackLevel(1, 0, 2));
stack_.back().changeBranch();
// Reset the samples stack.
if (config_.store_sampled_models()) {
samples_stack_.clear();
samples_stack_.reserve(30);
}
set_variable_depth_ = 0;
statistics_.max_component_split_depth_ = 0;
}
const LiteralID &TOS_decLit() const {
assert(stack_.top_const().literal_stack_ofs() < literal_stack_.size());
return literal_stack_[stack_.top_const().literal_stack_ofs()];
}
void reactivateTOS() {
for (auto it = TOSLiteralsBegin(); it != literal_stack_.end(); it++)
unSet(*it);
comp_manager_.cleanRemainingComponentsOf(stack_.top());
literal_stack_.resize(stack_.top().literal_stack_ofs());
stack_.top().resetRemainingComps();
}
bool fail_test(LiteralID lit) {
VariableIndex sz = literal_stack_.size();
// we increase the decLev artificially
// s.t. after the tentative BCP call, we can learn a conflict clause
// relative to the assn_ of *jt
stack_.startFailedLitTest();
setLiteralIfFree(lit);
assert(!hasAntecedent(lit));
bool bSucceeded = BCP(sz);
if (!bSucceeded)
recordAllUIPCauses();
stack_.stopFailedLitTest();
while (literal_stack_.size() > sz) {
unSet(literal_stack_.back());
literal_stack_.pop_back();
}
return bSucceeded;
}
// BEGIN conflict analysis
// if the state name is CONFLICT,
// then violated_clause contains the clause determining the conflict;
std::vector<LiteralID> violated_clause;
// this is an array of all the clauses found
// during the most recent conflict analysis
// it might contain more than 2 clauses
// but always will have:
// uip_clauses_.front() the 1UIP clause found
// uip_clauses_.back() the lastUIP clause found
// possible clauses in between will be other UIP clauses
std::vector<std::vector<LiteralID>> uip_clauses_;
// the assertion level of uip_clauses_.back()
// or (if the decision variable did not have an antecedent
// before) then assertionLevel_ == DL;
int64_t assertion_level_ = 0;
// build conflict clauses from most recent conflict
// as stored in state_.violated_clause
// solver state must be CONFLICT to work;
// this first method record only the last UIP clause
// so as to create clause that asserts the current decision
// literal
void recordLastUIPCauses();
void recordAllUIPCauses();
void minimizeAndStoreUIPClause(LiteralID uipLit,
std::vector<LiteralID> & tmp_clause,
const bool seen[]);
// Commented out by ZH as not implemented
// void storeUIPClause(LiteralID uipLit, std::vector<LiteralID> & tmp_clause);
// int getAssertionLevel() const {
// return assertion_level_;
// }
// END conflict analysis
VariableIndex set_variable_depth_ = 0;
bool InitializeSolverAndPreprocess(const PartialAssignment &partial_assn);
void applyPartialAssignment(const PartialAssignment &partial_assn);
void ReportSharpSatResults();
void PerformInitialSampling();
inline void FillPartialAssignments(Solver &temp_solver);
inline bool IsEndSamplesStackSizeValid() const {
return samples_stack_.size() == 1
|| (samples_stack_.size() == 2 && samples_stack_[0].model_count() == 0);
}
// /**
// * Checks whether the current point in the solver execution is valid for storing a top
// * tree sample.
// *
// * @return true If there none of the current literal assignments led to a component split,
// * the current depth is below the maximum and top tree mode is enabled.
// */
// inline bool IsValidTopTreeNodeStorePoint() {
// return config_.perform_top_tree_sampling && set_variable_depth_ < config_.max_top_tree_depth_;
// }
inline void LinkConfigAndStatistics() {
// ToDo If the solver is multithreaded, static for config and statistics will need to change.
StackLevel::set_solver_config_and_statistics(config_, statistics_);
// SamplesManager::set_solver_config(config_);
}
};
#endif // SOLVER_H_
Includes¶
algorithm
cached_assignment.h
(File cached_assignment.h)component_management.h
(File component_management.h)instance.h
(File instance.h)model_sampler.h
(File model_sampler.h)solver_config.h
(File solver_config.h)statistics.h
(File statistics.h)string
sys/time.h
utility
vector
Included By¶
Classes¶
File solver_config.h¶
↰ Parent directory (src
)
Definition (src/solver_config.h
)¶
↰ Return to documentation for file (src/solver_config.h
)
#ifndef SOLVER_CONFIG_H_
#define SOLVER_CONFIG_H_
#include <cstdlib>
#include <cassert>
#include <string>
#include "primitive_types.h"
#include "sampler_tools.h"
struct SolverConfiguration {
// Support for these features is removed in the sampler.
// /**
// * Support to modify the default state of this feature is
// * disabled in the sampler.
// *
// * Forces variable backtracking in the case of a conflict
// * being founded.
// */
// bool perform_non_chron_back_track = true;
bool perform_component_caching = true;
bool perform_failed_lit_test = true;
bool perform_pre_processing = true;
bool perform_random_sampling_ = true;
bool perform_top_tree_sampling = false;
bool disable_samples_write_ = false;
bool store_sampled_models() {
return perform_random_sampling_ && !perform_top_tree_sampling;
}
std::string samples_output_file = "";
bool debug_mode = false;
uint64_t time_bound_seconds = UINT64_MAX;
bool verbose = false;
bool quiet = false;
bool perform_sample_caching() {
assert(perform_random_sampling_ || !perform_sample_caching_);
// return perform_random_sampling_ && perform_sample_caching_;
return perform_sample_caching_;
}
void EnableSampleCaching() {
assert(perform_random_sampling_);
perform_sample_caching_ = true;
}
bool perform_two_pass_sampling_ = false;
unsigned num_samples_to_cache_ = 1;
bool skip_partial_assignment_fill = false;
SampleSize num_samples_ = 0;
TreeNodeIndex max_top_tree_depth_ = 25;
SampleSize max_top_tree_leaf_sample_count = 50;
std::string top_tree_samples_output_file_ = "." FILE_PATH_SEPARATOR
"__final_top_tree_samples.txt";
private:
bool perform_sample_caching_ = false;
};
#endif /* SOLVER_CONFIG_H_ */
Includes¶
cassert
cstdlib
primitive_types.h
(File primitive_types.h)sampler_tools.h
(File sampler_tools.h)string
Included By¶
Classes¶
File stack.cpp¶
↰ Parent directory (src
)
Contents
Definition (src/stack.cpp
)¶
↰ Return to documentation for file (src/stack.cpp
)
#include <string>
#include "stack.h"
SolverConfiguration* StackLevel::config_ = nullptr;
DataAndStatistics* StackLevel::statistics_ = nullptr;
VariableIndex StackLevel::component_split_depth_ = 0;
void StackLevel::includeSolutionVar(const mpz_class &solutions, mpz_class solution_var[],
const std::string &name_var) {
if (branch_found_unsat_[active_branch_]) {
assert(solution_var[active_branch_] == 0);
return;
}
if (solutions == 0)
branch_found_unsat_[active_branch_] = true;
if (solution_var[active_branch_] == 0) {
solution_var[active_branch_] = solutions;
if (config_->verbose && solutions > 0)
std::cout << "\t" << name_var << ": Solution count MPZ set to " << solutions << std::endl;
} else {
solution_var[active_branch_] *= solutions;
if (config_->verbose)
std::cout << "\t" << name_var << ": Solution count MPZ multiplied by "
<< solutions << " for a product of " << solution_var[active_branch_] << std::endl;
}
}
SampleAssignment StackLevel::random_cache_sample() const {
// Only get the sample after both branches explored.
assert(active_branch_);
// Must have at least one valid sample to have a random sample.
assert(branch_model_count_[0] > 0 || branch_model_count_[1] > 0);
// If either side is UNSAT, make the easy choice
if (branch_model_count_[0] == 0)
return cache_sample_[1];
if (branch_model_count_[1] == 0)
return cache_sample_[0];
// Randomly select either the positive or negative side.
mpz_class rand_mpz, total_count = branch_model_count_[0] + branch_model_count_[1];
// SamplesManager::get_rand_mpz(total_count, uniform_mpz);
Random::Mpz::uniform(total_count, rand_mpz);
if (rand_mpz < branch_model_count_[0])
return cache_sample_[0];
else
return cache_sample_[1];
}
void StackLevel::includeSolution(unsigned solutions) {
if (branch_found_unsat_[active_branch_]) {
assert(branch_model_count_[active_branch_] == 0);
return;
}
if (solutions == 0)
branch_found_unsat_[active_branch_] = true;
if (branch_model_count_[active_branch_] == 0) {
branch_model_count_[active_branch_] = solutions;
if (config_->verbose) {
std::cout << "\tSolution count set to " << solutions << std::endl;
}
} else {
branch_model_count_[active_branch_] *= solutions;
if (config_->verbose) {
std::cout << "\tSolution count multiplied by " << solutions << " for a product of "
<< branch_model_count_[active_branch_] << std::endl;
}
}
}
Includes¶
stack.h
(File stack.h)string
File stack.h¶
↰ Parent directory (src
)
Definition (src/stack.h
)¶
↰ Return to documentation for file (src/stack.h
)
#ifndef STACK_H_
#define STACK_H_
#include <gmpxx.h>
#include <cassert>
#include <vector>
#include <string>
#include "model_sampler.h"
#include "cached_assignment.h"
#include "solver_config.h"
class StackLevel {
const VariableIndex super_component_ = 0;
bool active_branch_ = false;
const VariableIndex literal_stack_ofs_ = 0;
bool is_component_split_ = false;
bool first_component_ = false;
SampleAssignment cache_sample_[2];
mpz_class branch_model_count_[2] = {0, 0};
bool branch_found_unsat_[2] = {false, false};
void includeSolutionVar(const mpz_class &solutions, mpz_class solution_var[],
const std::string &name_var);
const VariableIndex remaining_components_ofs_ = 0;
VariableIndex unprocessed_components_end_ = 0;
static VariableIndex component_split_depth_;
/*---------------------------------------*
* Begin Sampler Variables *
*---------------------------------------*/
mpz_class stack_solution_count_multiplier_[2] = {1, 1};
std::vector<std::vector<VariableIndex>> stack_emancipated_vars_;
std::vector<CacheEntryID> cache_comp_ids_[2];
static SolverConfiguration* config_;
static DataAndStatistics* statistics_;
CachedAssignment cached_assn_;
public:
bool hasUnprocessedComponents() const {
assert(unprocessed_components_end_ >= remaining_components_ofs_);
return unprocessed_components_end_ > remaining_components_ofs_;
}
void nextUnprocessedComponent() {
assert(unprocessed_components_end_ > remaining_components_ofs_);
unprocessed_components_end_--;
}
void resetRemainingComps() {
unprocessed_components_end_ = remaining_components_ofs_;
}
const VariableIndex super_component() const {
return super_component_;
}
const VariableIndex remaining_components_ofs() const {
return remaining_components_ofs_;
}
const VariableIndex unprocessed_components_end() const {
return unprocessed_components_end_;
}
void set_unprocessed_components_end(VariableIndex end) {
unprocessed_components_end_ = end;
assert(remaining_components_ofs_ <= unprocessed_components_end_);
}
StackLevel() {
stack_emancipated_vars_.resize(2);
}
StackLevel(VariableIndex super_comp, VariableIndex lit_stack_ofs,
ClauseOfs comp_stack_ofs) :
super_component_(super_comp),
literal_stack_ofs_(lit_stack_ofs),
remaining_components_ofs_(comp_stack_ofs),
unprocessed_components_end_(comp_stack_ofs) {
assert(super_comp < comp_stack_ofs);
stack_emancipated_vars_.resize(2);
}
VariableIndex currentRemainingComponent() {
assert(remaining_components_ofs_ <= unprocessed_components_end_ - 1);
return unprocessed_components_end_ - 1;
}
bool isSecondBranch() {
return active_branch_;
}
void changeBranch() {
active_branch_ = true;
}
bool anotherCompProcessible() {
return (!branch_found_unsat()) && hasUnprocessedComponents();
}
VariableIndex literal_stack_ofs() const {
return literal_stack_ofs_;
}
void includeSolution(const mpz_class &solutions) {
includeSolutionVar(solutions, branch_model_count_, "branch_model_count");
}
void includeSolutionSampleMultiplier(const mpz_class &solutions) {
includeSolutionVar(solutions, stack_solution_count_multiplier_,
"sampler_solution_multiplier");
}
void includeSolution(unsigned solutions);
void configureNewLevel(const StackLevel &top, const DecisionLevel decision_level) {
// Do not push down any counts at the top of the decision stack when doing reservoir sampling
// This is required in some cases in top tree sampling since the solution count at each leaf
// is required while traversing the tree.
if (decision_level == 0 && !(config_->perform_top_tree_sampling && !top.isComponentSplit()))
return;
// Push down the solution multiplier and freed variable list
// Make sure to only use the active branch.
for (auto &multiplier : stack_solution_count_multiplier_)
multiplier = top.getSamplerSolutionMultiplier();
for (auto &freed_variables : stack_emancipated_vars_)
freed_variables = top.emancipated_vars();
for (auto &cache_comp_ids : cache_comp_ids_)
cache_comp_ids = top.cached_comp_ids();
}
void addFreeVariables(const std::vector<VariableIndex> &freed_vars) {
int idx = (active_branch_) ? 1 : 0;
stack_emancipated_vars_[idx].insert(stack_emancipated_vars_[idx].end(),
freed_vars.begin(), freed_vars.end());
}
void addCachedCompIds(const std::vector<CacheEntryID> &ids) {
int idx = (active_branch_) ? 1 : 0;
// assert(cached_comp_ids_.empty());
if (ids.empty())
return;
cache_comp_ids_[idx].insert(cache_comp_ids_[idx].end(), ids.begin(), ids.end());
}
inline bool branch_found_unsat() const {
return branch_found_unsat_[active_branch_];
}
inline void mark_branch_unsat() {
branch_found_unsat_[active_branch_] = true;
}
const mpz_class getTotalModelCount() const {
return branch_model_count_[0] + branch_model_count_[1];
}
const mpz_class& getActiveModelCount() const {
if (!active_branch_)
return branch_model_count_[0];
else
return branch_model_count_[1];
}
const mpz_class& getSamplerSolutionMultiplier() const {
if (!active_branch_)
return stack_solution_count_multiplier_[0];
else
return stack_solution_count_multiplier_[1];
}
// /**
// * Calculates the total descendent model count for this stack level. It is equal to:
// *
// * FalseModelCount * FalseCountMultiplier + TrueModelCount * TrueCountMultiplier
// *
// * @return Total descendent model count.
// */
// const mpz_class GetDescendentModelCount() const {
// mpz_class total_model_count = 0;
// for (int i = 0; i < 2; i++) {
// if (stack_solution_count_multiplier_[i] == 1)
// total_model_count += branch_model_count_[i];
// else
// total_model_count += branch_model_count_[i] * stack_solution_count_multiplier_[i];
// }
// return total_model_count;
// }
const bool HasNoDescendentModels() {
return branch_found_unsat_[0] && branch_found_unsat_[1];
}
inline const std::vector<VariableIndex> &emancipated_vars() const {
if (!active_branch_)
return stack_emancipated_vars_[0];
else
return stack_emancipated_vars_[1];
}
inline const std::vector<CacheEntryID> &cached_comp_ids() const {
if (!active_branch_)
return cache_comp_ids_[0];
else
return cache_comp_ids_[1];
}
inline const bool isComponentSplit() const {
return is_component_split_ && config_->perform_random_sampling_;
}
inline void setAsComponentSplit() {
if (!config_->perform_random_sampling_)
return;
if (!is_component_split_) {
component_split_depth_++;
if (component_split_depth_ > statistics_->max_component_split_depth_)
statistics_->max_component_split_depth_ = component_split_depth_;
}
is_component_split_ = true;
first_component_ = true;
}
inline void unsetAsComponentSplit() {
if (!config_->perform_random_sampling_)
return;
if (is_component_split_)
component_split_depth_--;
assert(component_split_depth_>= 0);
is_component_split_ = false;
first_component_ = false;
}
inline static VariableIndex componentSplitDepth() {
return component_split_depth_;
}
inline const bool isFirstComponent() const {
assert(is_component_split_);
return first_component_ && config_->perform_random_sampling_;
}
inline void markFirstComponentComplete() {
assert(is_component_split_);
first_component_ = false;
}
inline static void set_solver_config_and_statistics(SolverConfiguration &config,
DataAndStatistics &statistics) {
config_ = &config;
statistics_ = &statistics;
}
inline void set_cached_assn(CachedAssignment &cached_assn) {
assert(config_->perform_random_sampling_);
cached_assn_ = cached_assn;
}
inline const CachedAssignment& cached_assn() const { return cached_assn_; }
inline void ClearCachedAssn() { cached_assn_.clear(); }
inline void set_cache_sample(const SampleAssignment & cache_sample) {
if (!active_branch_)
cache_sample_[0] = cache_sample;
else
cache_sample_[1] = cache_sample;
}
SampleAssignment random_cache_sample() const;
};
class DecisionStack: public std::vector<StackLevel> {
VariableIndex failed_literal_test_active = 0;
public:
DecisionStack() : std::vector<StackLevel>() {}
void startFailedLitTest() {
// failed_literal_test_active = true; // Thurley's old code. Relies on casting
failed_literal_test_active = 1;
}
void stopFailedLitTest() {
// failed_literal_test_active = false; // Thurley's old code. Relies on casting
failed_literal_test_active = 0;
}
// end for implicit BCP
StackLevel &top() {
return const_cast<StackLevel&>(top_const()); // Strip off the const
}
const StackLevel &top_const() const {
assert(!empty());
return back();
}
StackLevel &on_deck() {
assert(size() >= 2);
return (*this)[size() - 2];
}
DecisionLevel get_decision_level() const {
assert(!empty());
return size() - 1 + failed_literal_test_active;
} // 0 means pre-1st-decision
};
#endif // STACK_H_
Includes¶
cached_assignment.h
(File cached_assignment.h)cassert
gmpxx.h
model_sampler.h
(File model_sampler.h)solver_config.h
(File solver_config.h)string
vector
Included By¶
Classes¶
File statistics.cpp¶
↰ Parent directory (src
)
Contents
Definition (src/statistics.cpp
)¶
↰ Return to documentation for file (src/statistics.cpp
)
#include <fstream>
#include <string>
#include "statistics.h"
void DataAndStatistics::printShort() {
std::cout << "\n\n"
<< "variables (total / active / free)\t" << num_variables_ << "/"
<< num_used_variables_ << "/" << num_variables_ - num_used_variables_
<< "\n"
<< "clauses (removed) \t\t" << num_original_clauses_ << " ("
<< num_original_clauses_ - num_clauses() << ")" << "\n"
<< "decisions \t\t\t\t" << num_decisions_ << "\n"
<< "conflicts \t\t\t\t" << num_conflicts_ << "\n"
<< "conflict clauses (all/bin/unit) \t"
<< num_conflict_clauses()
<< "/" << num_binary_conflict_clauses_ << "/" << num_unit_clauses_
<< "\n"
<< "failed literals found by implicit BCP \t "
<< num_failed_literals_detected_ << "\n";
std::cout << "implicit BCP miss rate \t" << implicitBCP_miss_rate() * 100 << "%\n"
<< "bytes cache size \t" << cache_bytes_memory_usage() << "\t\n";
std::cout << "bytes cache (overall) \t" << overall_cache_bytes_memory_stored()
<< "\n"
<< "bytes cache (infra / comps) "
<< (cache_infrastructure_bytes_memory_usage_) << "/"
<< sum_bytes_cached_components_ << "\t\n";
std::cout << "bytes pure comp data (curr) "
<< sum_bytes_pure_cached_component_data_ << "\n"
<< "bytes pure comp data (overall) "
<< overall_bytes_pure_stored_component_data_ << "\n";
std::cout << "bytes cache with sysoverh (curr) "
<< sys_overhead_sum_bytes_cached_components_ << "\n"
<< "bytes cache with sysoverh (overall) "
<< sys_overhead_overall_bytes_components_stored_ << "\n";
std::cout << "cache (stores / hits) \t\t\t" << num_cached_components_ << "/"
<< num_cache_hits_ << "\n"
<< "cache miss rate \t\t" << cache_miss_rate() * 100 << "%\n"
<< "avg. variable count (stores / hits) \t" << getAvgComponentSize()
<< "/" << getAvgCacheHitSize() << "\n\n"
<< "\n# solutions " << "\n"
<< final_solution_count_.get_str() << "\n"
<< "\n# END\n\n"
<< "time: " << sampler_time_elapsed_ << "s\n\n";
}
Includes¶
fstream
statistics.h
(File statistics.h)string
File statistics.h¶
↰ Parent directory (src
)
Definition (src/statistics.h
)¶
↰ Return to documentation for file (src/statistics.h
)
#ifndef STATISTICS_H_
#define STATISTICS_H_
#include <gmpxx.h>
#include <string>
#include <cstdint>
#include <vector>
#include <cfloat>
#include "structures.h"
#include "component_types/cacheable_component.h"
#include "primitive_types.h"
#include "solver_config.h"
class DataAndStatistics {
public:
DataAndStatistics() {
time(&start_time_);
for (unsigned i = 0; i < static_cast<unsigned>(TopTreeNodeType::NUM_TREE_NODE_TYPES); i++) {
num_models_by_tree_node_type_[i] = 0;
num_tree_nodes_by_type_[i] = 0;
}
}
std::string input_file_;
//double time_elapsed_ = 0.0;
time_t start_time_;
uint64_t maximum_cache_size_bytes_ = 0;
SolverExitState exit_state_ = SolverExitState::NO_STATE;
// different variable counts
// number of variables and clauses before preprocessing
VariableIndex num_original_variables_ = 0;
ClauseIndex num_original_clauses_ = 0;
ClauseIndex num_original_binary_clauses_ = 0;
ClauseIndex num_original_unit_clauses_ = 0;
VariableIndex num_variables_ = 0;
VariableIndex num_used_variables_ = 0;
VariableIndex num_free_variables_ = 0;
VariableIndex num_indep_support_variables_ = 0;
ClauseIndex num_long_clauses_ = 0;
ClauseIndex num_binary_clauses_ = 0;
ClauseIndex num_long_conflict_clauses_ = 0;
ClauseIndex num_binary_conflict_clauses_ = 0;
ClauseIndex times_conflict_clauses_cleaned_ = 0;
ClauseIndex num_unit_clauses_ = 0;
uint64_t num_decisions_ = 0;
uint64_t num_failed_literals_detected_ = 0;
uint64_t num_failed_literal_tests_ = 0;
uint64_t num_conflicts_ = 0;
// number of clauses overall learned
uint64_t num_clauses_learned_ = 0;
VariableIndex max_component_split_depth_ = 0;
VariableIndex max_branch_var_depth_ = 0;
TreeNodeIndex num_top_tree_nodes_ = 0;
TreeNodeIndex num_tree_nodes_by_type_[static_cast<long>(TopTreeNodeType::NUM_TREE_NODE_TYPES)];
mpz_class num_models_by_tree_node_type_[static_cast<long>(TopTreeNodeType::NUM_TREE_NODE_TYPES)];
void UpdateNodeTypeStatistics(TopTreeNodeType node_type, const mpz_class & num_models) {
auto node_type_id = static_cast<long>(node_type);
num_tree_nodes_by_type_[node_type_id]++;
num_models_by_tree_node_type_[node_type_id] += num_models;
}
TreeNodeIndex num_tree_nodes(TopTreeNodeType node_type) {
auto node_type_id = static_cast<long>(node_type);
return num_tree_nodes_by_type_[node_type_id];
}
mpz_class num_tree_node_models(TopTreeNodeType node_type) {
auto node_type_id = static_cast<long>(node_type);
return num_models_by_tree_node_type_[node_type_id];
}
double percent_tree_node_models(TopTreeNodeType node_type) {
if (final_solution_count_ == 0)
return -1;
mpf_class percent_models = num_tree_node_models(node_type);
percent_models /= static_cast<mpf_class>(final_solution_count_);
return percent_models.get_d();
}
/* cache statistics */
uint64_t num_cache_hits_ = 0;
uint64_t num_cache_look_ups_ = 0;
uint64_t sum_cache_hit_sizes_ = 0;
uint64_t num_cached_components_ = 0;
uint64_t sum_size_cached_components_ = 0;
uint64_t sum_bytes_cached_components_ = 0;
// the same number, summing over all components ever stored
uint64_t overall_bytes_components_stored_ = 0;
// the above numbers, but without any overhead,
// counting only the pure data size of the components - without model counts
uint64_t sum_bytes_pure_cached_component_data_ = 0;
// the same number, summing over all components ever stored
uint64_t overall_bytes_pure_stored_component_data_ = 0;
uint64_t sys_overhead_sum_bytes_cached_components_ = 0;
// the same number, summing over all components ever stored
uint64_t sys_overhead_overall_bytes_components_stored_ = 0;
uint64_t cache_infrastructure_bytes_memory_usage_ = 0;
uint64_t overall_num_cache_stores_ = 0;
/*end statistics */
void reset_statistics() {
// Reset cache statistics
num_cache_hits_ = 0;
num_cache_look_ups_ = 0;
// Reset literal search operations
num_failed_literals_detected_ = 0;
num_failed_literal_tests_ = 0;
num_conflicts_ = 0;
num_decisions_ = 0;
// num_implications_ = 0;
num_unit_clauses_ = 0;
// Reset execution parameters
sampler_time_elapsed_ = 0.0;
exit_state_ = SolverExitState::NO_STATE;
// Reset all sampler only variables
numb_second_pass_vars_.clear();
sampler_time_elapsed_ = DBL_MAX;
sampler_pass_1_time_ = DBL_MAX;
sampler_pass_2_time_ = DBL_MAX;
}
bool cache_full() const {
return cache_bytes_memory_usage() >= maximum_cache_size_bytes_;
}
uint64_t cache_bytes_memory_usage() const {
return cache_infrastructure_bytes_memory_usage_
+ sum_bytes_cached_components_;
}
uint64_t overall_cache_bytes_memory_stored() {
return cache_infrastructure_bytes_memory_usage_
+ overall_bytes_components_stored_;
}
void incorporate_cache_store(CacheableComponent &ccomp) {
sum_bytes_cached_components_ += ccomp.SizeInBytes();
sum_size_cached_components_ += ccomp.num_variables();
num_cached_components_++;
overall_bytes_components_stored_ += ccomp.SizeInBytes();
overall_num_cache_stores_ += ccomp.num_variables();
sys_overhead_sum_bytes_cached_components_ += ccomp.sys_overhead_SizeInBytes();
sys_overhead_overall_bytes_components_stored_ += ccomp.sys_overhead_SizeInBytes();
sum_bytes_pure_cached_component_data_ += ccomp.data_only_byte_size();
overall_bytes_pure_stored_component_data_ += ccomp.data_only_byte_size();
}
void incorporate_cache_erase(CacheableComponent &ccomp) {
sum_bytes_cached_components_ -= ccomp.SizeInBytes();
sum_size_cached_components_ -= ccomp.num_variables();
num_cached_components_--;
sum_bytes_pure_cached_component_data_ -= ccomp.data_only_byte_size();
sys_overhead_sum_bytes_cached_components_ -= ccomp.sys_overhead_SizeInBytes();
}
void incorporate_cache_hit(CacheableComponent &ccomp) {
num_cache_hits_++;
sum_cache_hit_sizes_ += ccomp.num_variables();
}
unsigned long cache_MB_memory_usage() {
return cache_bytes_memory_usage() / 1000000;
}
mpz_class final_solution_count_ = 0;
double implicitBCP_miss_rate() {
if (num_failed_literal_tests_ == 0) return 0.0;
return (num_failed_literal_tests_ - num_failed_literals_detected_)
/ static_cast<double>(num_failed_literal_tests_);
}
unsigned long num_clauses() const {
return num_long_clauses_ + num_binary_clauses_ + num_unit_clauses_;
}
unsigned long num_conflict_clauses() {
return num_long_conflict_clauses_ + num_binary_conflict_clauses_;
}
unsigned long clause_deletion_interval() {
return 10000 + 10 * times_conflict_clauses_cleaned_;
}
void set_final_solution_count(const mpz_class &count) {
// set final_solution_count_ = count * 2^(num_variables_ - num_used_variables_)
mpz_mul_2exp(final_solution_count_.get_mpz_t(), count.get_mpz_t(),
num_variables_ - num_used_variables_);
}
const mpz_class &final_solution_count() const {
return final_solution_count_;
}
// void incorporateConflictClauseData(const std::vector<LiteralID> &clause) {
// if (clause.size() == 1)
// num_unit_clauses_++;
// else if (clause.size() == 2)
// num_binary_conflict_clauses_++;
// num_long_conflict_clauses_++;
// }
void incorporateClauseData(const std::vector<LiteralID> &clause) {
if (clause.size() == 1)
num_unit_clauses_++;
else if (clause.size() == 2)
num_binary_clauses_++;
else
num_long_clauses_++;
}
void printShort();
void printShortFormulaInfo() {
std::cout << "variables (all/used/free): \t"
<< num_variables_ << "/" << num_used_variables_ << "/"
<< num_variables_ - num_used_variables_ << "\n"
<< "independent support size: \t" << num_indep_support_variables_ << "\n";
std::cout << "clauses (all/long/binary/unit): "
<< num_clauses() << "/" << num_long_clauses_
<< "/" << num_binary_clauses_ << "/" << num_unit_clauses_ << std::endl;
}
unsigned long getTime() const {
return num_decisions_;
}
long double getAvgComponentSize() {
return sum_size_cached_components_ / static_cast<long double>(num_cached_components_);
}
unsigned long cached_component_count() {
return num_cached_components_;
}
unsigned long cache_hits() {
return num_cache_hits_;
}
double cache_miss_rate() {
if (num_cache_look_ups_ == 0) return 0.0;
return (num_cache_look_ups_ - num_cache_hits_) / static_cast<double>(num_cache_look_ups_);
}
long double getAvgCacheHitSize() {
if (num_cache_hits_ == 0) return 0.0;
return sum_cache_hit_sizes_ / static_cast<long double>(num_cache_hits_);
}
//-----------------------------------------//
// Sampler Fields and Methods //
//-----------------------------------------//
double sampler_time_elapsed_ = DBL_MAX;
double sampler_pass_1_time_ = DBL_MAX;
double sampler_pass_2_time_ = DBL_MAX;
std::vector<VariableIndex> numb_second_pass_vars_;
};
#endif /* STATISTICS_H_ */
Includes¶
cfloat
component_types/cacheable_component.h
(File cacheable_component.h)cstdint
gmpxx.h
primitive_types.h
(File primitive_types.h)solver_config.h
(File solver_config.h)string
structures.h
(File structures.h)vector
Included By¶
Classes¶
File structures.h¶
↰ Parent directory (src
)
Definition (src/structures.h
)¶
↰ Return to documentation for file (src/structures.h
)
#ifndef STRUCTURES_H_
#define STRUCTURES_H_
#include <assert.h>
#include <vector>
#include <iostream>
#include "primitive_types.h"
#define INVALID_DL -1
typedef unsigned char TriValue;
#define F_TRI 0
#define T_TRI 1
#define X_TRI 2
class LiteralID {
public:
LiteralID() {
value_ = 0;
}
// This code does screwy casting. Cannot use explicit
LiteralID(int lit) { // NOLINT (runtime/explicit)
value_ = (abs(lit) << 1) + static_cast<unsigned>(lit > 0);
}
LiteralID(VariableIndex var, bool sign) {
value_ = (var << 1) + static_cast<unsigned>(sign);
}
VariableIndex var() const {
return (value_ >> 1);
}
int toInt() const {
return (static_cast<int>(value_) >> 1) * ((sign()) ? 1 : -1);
}
void inc() {++value_;}
void copyRaw(unsigned int v) {
value_ = v;
}
const bool sign() const {
return static_cast<bool>(value_ & 0x01);
}
const bool operator!=(const LiteralID &rL2) const {
return value_ != rL2.value_;
}
const bool operator==(const LiteralID &rL2) const {
return value_ == rL2.value_;
}
const bool operator<(const LiteralID &rL2) const {
return value_ < rL2.value_;
}
const LiteralID neg() const {
return LiteralID(var(), !sign());
}
void print() const {
std::cout << (sign() ? " " : "-") << var() << " ";
}
inline unsigned raw() const { return value_;}
private:
unsigned value_;
template <class _T> friend class LiteralIndexedVector;
};
static const LiteralID NOT_A_LIT(0, false);
#define SENTINEL_LIT NOT_A_LIT
class Literal {
public:
std::vector<LiteralID> binary_links_ = std::vector<LiteralID>(1, SENTINEL_LIT);
std::vector<ClauseOfs> watch_list_ = std::vector<ClauseOfs>(1, SENTINEL_CL); // Watch clauses
float activity_score_ = 0.0f;
void increaseActivity(unsigned u = 1) {
activity_score_+= u;
}
void resetActivity() { activity_score_ = 0;}
void removeWatchLinkTo(ClauseOfs clause_ofs) {
for (auto it = watch_list_.begin(); it != watch_list_.end(); it++)
if (*it == clause_ofs) {
*it = watch_list_.back(); // Get last element in vector and replace item to be removed
watch_list_.pop_back(); // Delete the last element
return;
}
}
void replaceWatchLinkTo(ClauseOfs clause_ofs, ClauseOfs replace_ofs) {
for (auto it = watch_list_.begin(); it != watch_list_.end(); it++)
if (*it == clause_ofs) {
*it = replace_ofs;
return;
}
}
void addWatchLinkTo(ClauseIndex clause_ofs) {
watch_list_.push_back(clause_ofs);
}
void addBinLinkTo(LiteralID lit) {
binary_links_.back() = lit;
binary_links_.push_back(SENTINEL_LIT);
}
void resetWatchList() {
watch_list_.clear();
watch_list_.push_back(SENTINEL_CL);
}
bool hasBinaryLinkTo(LiteralID lit) {
for (auto l : binary_links_) {
if (l == lit)
return true;
}
return false;
}
bool hasBinaryLinks() {
return !binary_links_.empty();
}
};
class Antecedent {
unsigned int val_;
public:
Antecedent() {
val_ = 1;
}
explicit Antecedent(const ClauseOfs cl_ofs) {
val_ = (cl_ofs << 1) | 1;
}
explicit Antecedent(const LiteralID idLit) {
val_ = (idLit.raw() << 1);
}
bool isAClause() const {
return val_ & 0x01;
}
ClauseOfs asCl() const {
assert(isAClause()); // ZH - Verify the antecedent actually is a CLAUSE.
return val_ >> 1;
}
LiteralID asLit() {
assert(!isAClause()); // ZH - Verify the antecedent actually is a LITERAL.
LiteralID idLit;
idLit.copyRaw(val_ >> 1);
return idLit;
}
bool isAnt() const {
return val_ != 1; // i.e. NOT a NOT_A_CLAUSE;
}
};
struct Variable {
Antecedent ante;
long decision_level = INVALID_DL;
};
class ClauseHeader {
unsigned creation_time_; // number of conflicts seen at creation time
unsigned score_;
unsigned length_;
public:
void increaseScore() {
score_++;
}
void decayScore() {
score_ >>= 1;
}
unsigned score() const {
return score_;
}
unsigned creation_time() {
return creation_time_;
}
unsigned length() { return length_; }
void set_length(unsigned length) { length_ = length; }
void set_creation_time(unsigned time) {
creation_time_ = time;
}
static unsigned overheadInLits() { return sizeof(ClauseHeader)/sizeof(LiteralID); }
};
#endif /* STRUCTURES_H_ */
Includes¶
assert.h
iostream
primitive_types.h
(File primitive_types.h)vector