This provides the actual API of the CaDiCaL solver, which is implemented in the class 'Solver' below. Beside its constructor and destructor most  important is the IPASIR part which you can find between 'BEGIN IPASIR'
and 'END IPASIR' comments below. The following '[Example]' below might  also be a good starting point to understand the API.

译文:最重要的是IPASIR部分,你可以在下面的“BEGIN IPASIR”和“END IPASIR”之间找到.

译文:下面的“[示例]”可能也是理解API的一个很好的起点。

   
 

/*========================================================================*/

// [Example]
//
// The internal solver state follows the IPASIR API model used in the incremental track of the SAT competition.
// State transitions are triggered by member function calls, declared and described below.

      译文:状态转换由成员函数调用触发,声明和描述如下。
//
// Consider the following code (from 'test/api/example.cpp') of API usage:
//
// CaDiCaL::Solver * solver = new CaDiCaL::Solver;
//
// // ------------------------------------------------------------------
// // Encode Problem and check without assumptions.
//
// enum { TIE = 1, SHIRT = 2 };
//
// solver->add (-TIE), solver->add (SHIRT), solver->add (0);
// solver->add (TIE), solver->add (SHIRT), solver->add (0);
// solver->add (-TIE), solver->add (-SHIRT), solver->add (0);
//
// int res = solver->solve (); // Solve instance.
// assert (res == 10); // Check it is 'SATISFIABLE'.
//
// res = solver->val (TIE); // Obtain assignment of 'TIE'.
// assert (res < 0); // Check 'TIE' assigned to 'false'.
//
// res = solver->val (SHIRT); // Obtain assignment of 'SHIRT'.
// assert (res > 0); // Check 'SHIRT' assigned to 'true'.
//
// // ------------------------------------------------------------------
// // Incrementally solve again under one assumption.译文:在一个假设下再次递增求解
//
// solver->assume (TIE); // Now force 'TIE' to true.
//
// res = solver->solve (); // Solve again incrementally.
// assert (res == 20); // Check it is 'UNSATISFIABLE'.
//
// res = solver->failed (TIE); // Check 'TIE' responsible.
// assert (res); // Yes, 'TIE' in core.
//
// res = solver->failed (SHIRT); // Check 'SHIRT' responsible.
// assert (!res); // No, 'SHIRT' not in core.
//
// // ------------------------------------------------------------------
// // Incrementally solve once more under another assumption.译文:在另一种假设下再次递增求解。
//
// solver->assume (-SHIRT); // Now force 'SHIRT' to false.
//
// res = solver->solve (); // Solve again incrementally.
// assert (res == 20); // Check it is 'UNSATISFIABLE'.
//
// res = solver->failed (TIE); // Check 'TIE' responsible.
// assert (!res); // No, 'TIE' not in core.
//
// res = solver->failed (-SHIRT); // Check '!SHIRT' responsible.
// assert (res); // Yes, '!SHIRT' in core.
//
// // ------------------------------------------------------------------
//
// delete solver;

/*========================================================================*/

// [States and Transitions]
//
// Compared to IPASIR we also use an 'ADDING' state in which the solver  stays while adding non-zero literals until the clause is completed  through adding a zero literal.  译文:与IPASIR相比,我们还使用了“添加”状态,求解器在添加非零字面值时保持不变,直到通过添加零字面值完成子句。

//The additional 'INITIALIZING',
// 'CONFIGURING' and 'DELETING' states are also not part of IPASIR but also
// useful for testing and debugging.
//
// We have the following transitions which are all synchronous except for the reentrant 'terminate' call:
//
// new
// INITIALIZING --------------------------> CONFIGURING
//
// set / trace
// CONFIGURING --------------------------> CONFIGURING
//
// add (non zero literal)
// VALID --------------------------> ADDING
//
// add (zero literal)
// VALID --------------------------> UNKNOWN
//
// assume (non zero literal)
// READY --------------------------> UNKNOWN
//
// solve
// READY --------------------------> SOLVING
//
// (internal)
// SOLVING --------------------------> READY
//
// val (non zero literal)
// SATISFIED --------------------------> SATISFIED
//
// failed (non zero literal )
// UNSATISFIED --------------------------> UNSATISFIED
//
// delete
// VALID --------------------------> DELETING
//
// where
//
// READY = CONFIGURING | UNKNOWN | SATISFIED | UNSATISFIED
// VALID = READY | ADDING
// INVALID = INITIALIZING | DELETING
//
// The 'SOLVING' state is only visible in different contexts, i.e., from
// another thread or from a signal handler. It is used to implement
// 'terminate'. Here is the only asynchronous transition:
//
// terminate (asynchronously)异步通信
// SOLVING -------------------------> UNKNOWN
//
// The important behaviour to remember is that adding or assuming a literal  (immediately) destroys the satisfying assignment in the 'SATISFIED' state  and vice versa resets all assumptions in the 'UNSATISFIED' state. This is exactly the behaviour required by the IPASIR interface. 译文:需要记住的重要行为是,添加或假设一个文字(立即)破坏了“满意”状态下令人满意的赋值,反之亦然,重置所有“不满意”状态下的假设。这正是IPASIR接口所要求的行为。
//
// Furthermore, the model can only be queried through 'val' in the  'SATISFIED' state, while extracting failed assumptions with 'val' only in  the 'UNSATISFIED' state. Solving can only be started in the 'UNKNOWN' or  'CONFIGURING' state or after the previous call to 'solve' yielded an  'UNKNOWN, 'SATISFIED' or 'UNSATISFIED' state.译文:此外,模型只能在“满意”状态下通过“val”查询,而在“不满意”状态下使用“val”提取失败假设。解决只能在“未知”或“配置”状态下启动或者在前一次对“解决”的调用产生“未知”、“满意”或“不满意”状态之后启动
//
// All literals have to be valid literals too, i.e., 32-bit integers different from 'INT_MIN'. If any of these requirements is violated the solver aborts with an 'API contract violation' message.译文:所有的字面值也必须是有效的字面值,即与'INT_MIN'不同的32位整数。如果违反了其中任何一个要求,求解器将以“API契约违背”消息中止。
//
// HINT: If you do not understand why a contract is violated you can run  'mobical' on the failing API call trace.译文:如果你不明白为什么契约被违反了,你可以在失败的API调用跟踪中运行“mobical”。

Point the environment variable  'CADICAL_API_TRACE' to the file where you want to save the trace during execution of your program linking against the library.译文:将环境变量'CADICAL_API_TRACE'指向您希望在执行程序链接库期间保存跟踪的文件

You probably need for 'mobical' to use the option '--do-not-enforce-contracts' though to  force running into the same contract violation.译文:您可能需要“mobical”使用“—do-not-enforce-contracts”选项来强制执行相同的合同违例。
//
// Additional API calls (like 'freeze' and 'melt') do not change the state of the solver and are all described below.译文:其他API调用(如“冻结”和“融化”)不会改变求解器的状态,下文将对此进行描述。

/*========================================================================*/

   
   

// Connected terminators are checked for termination regularly. If the  'terminate' function of the terminator returns true the solver is terminated synchronously as soon it calls this function.译文:定期检查已连接的终端是否终止。如果终止符的'terminate'函数返回true,求解程序在调用这个函数时就会同步终止。

class Terminator {
public:
virtual ~Terminator () { }
virtual bool terminate () = 0;
};

   
   

// Connected learners which can be used to export learned clauses.译文:连接学习者,可以用来输出学习过的从句。


// The 'learning' can check the size of the learn clause and only if it returns true then the individual literals of the learned clause are given to the learn through 'learn' one by one terminated by a zero literal.译文:'learning'可以检查learn子句的大小,只有当它返回true时,learned子句的单个字面值才会通过'learn'一个接一个地以零字面值结束

class Learner {
public:
virtual ~Learner () { }
virtual bool learning (int size) = 0;
virtual void learn (int lit) = 0;
};

   
   

// Allows to traverse all remaining irredundant clauses.译文:允许遍历所有剩余的不冗余的子句。

//Satisfied and eliminated clauses are not included, nor any derived units unless such a unit literal is frozen.译文:满足和消除子句不包括在内,也不包括派生单元,除非这样的单元字面量被冻结.

//Falsified literals are skipped. If the solver is inconsistent only the empty clause is traversed.

// If 'clause' returns false traversal aborts early.

class ClauseIterator {
public:
virtual ~ClauseIterator () { }
virtual bool clause (const std::vector<int> &) = 0;
};

   
 

// Allows to traverse all clauses on the extension stack together with their
witness cubes. If the solver is inconsistent, i.e., an empty clause is
 found and the formula is unsatisfiable, then nothing is traversed.

译文:允许遍历扩展堆栈上的所有子句及其见证多维数据集。如果求解器不一致,即空子句是发现公式是不可满足的,那就什么都不遍历了。


// The clauses traversed in 'traverse_clauses' together with the clauses on the extension stack are logically equivalent to the original clauses.译文:在' traverse_子句'中遍历的子句与扩展堆栈上的子句在逻辑上等价于原始子句。
 See our SAT'19 paper for more details.

// The witness literals can be used to extend and fix an assignment on the  remaining clauses to satisfy the clauses on the extension stack too.译文:见证字面值可用于扩展和确定其余子句上的赋值,以满足扩展堆栈上的子句。

// All derived units of non-frozen variables are included too.译文:所有非冻结变量的导出单位也包括在内。

// If 'witness' returns false traversal aborts early.译文:如果'witness'返回false,则会提前终止遍历。

class WitnessIterator {
public:
virtual ~WitnessIterator () { }
virtual bool witness (const std::vector<int> & clause,
const std::vector<int> & witness) = 0;
};

 
   
    void assume (int lit);

// Assume valid non zero literal for next call to 'solve'. These assumptions are reset after the call to 'solve' as well as after returning from 'simplify' and 'lookahead. 译文:假设在下一次调用“solve”时有效的非零文字。这些假设在调用“solve”后以及从“simplify”和“lookahead”返回后重置。

   
 

 int solve ();

// Note, that while in this call the solver actually transitions to state 'SOLVING', which however is only visible from a different context,  i.e., from a different thread or from a signal handler. Only right before returning from this call it goes into a 'READY' state.

译文:注意,在这个调用中,解算器实际上会转换到状态“SOLVING”,但这只在不同的上下文中可见,例如,从不同的线程或信号处理器。只有在从这个调用返回之前,它才进入“就绪”状态。

   
   int val (int lit);

// Get value (-lit=false, lit=true) of valid non-zero literal.

   
 

 

bool failed (int lit);

// Determine whether the valid non-zero literal is in the core.  Returns 'true' if the literal is in the core and 'false' otherwise. Note that the core does not have to be minimal.

译文:确定有效的非零文字是否在核心中。如果字面量在核心中,则返回'true',否则返回'false'。注意,核心不一定是最小的。

   
   
 

void connect_terminator (Terminator * terminator);
void disconnect_terminator ();

// Add call-back which is checked regularly for termination. There can only be one terminator connected. If a second (non-zero) one is added  the first one is implicitly disconnected.

译文:添加定期检查是否终止的回调函数。只能连接一个终结者。如果添加第二个(非零的)1,则第一个将隐式断开连接。

   
 

void connect_learner (Learner * learner);
void disconnect_learner ();

// Add call-back which allows to export learned clauses.译文:添加回调,允许导出学到的子句。

   
 

// This function determines a good splitting literal. The result can be zero if the formula is proven to be satisfiable or unsatisfiable. This can then be checked by 'state ()'. If the formula is empty and the function is not able to determine satisfiability also zero is returned but the state remains unknown.

译文:这个函数确定一个良好的拆分文字。如果公式被证明是可满足的或不可满足的,结果可以是零。然后可以通过'state()'进行检查。如果公式为空,函数不能确定可满足性,则返回零,但状态仍然未知。

int lookahead(void);

struct CubesWithStatus {
  int status;
  std::vector<std::vector<int>> cubes;
};

CubesWithStatus generate_cubes(int);

void reset_assumptions();

   
 

// Return the current state of the solver as defined above.译文:返回上述定义的解算器的当前状态。

const State & state () const { return _state; }

 

// Similar to 'state ()' but using the staddard competition exit codes of
// '10' for 'SATISFIABLE', '20' for 'UNSATISFIABLE' and '0' otherwise.
//
int status () const {
    if (_state == SATISFIED) return 10;
    else if (_state == UNSATISFIED) return 20;
    else return 0;
}

   
 

/*----------------------------------------------------------------------*/
// Copy 'this' into a fresh 'other'. The copy procedure is not a deep clone, but only copies irredundant clauses and units. It also makes sure that witness reconstruction works with the copy as with the original formula such that both solvers have the same models.

译文:将'this'复制到一个新的'other'中。复制过程不是深度克隆,而是只复制不冗余的子句和单元。它还确保witness重建工作与原始公式的副本一样,这样两个求解器都有相同的模型.


// Assumptions are not copied. Options however are copied as well as flags which remember the current state of variables in preprocessing.

译文:假设不会被复制。但是,在预处理中复制选项以及记住变量当前状态的标志。

void copy (Solver & other) const;

   
   

// Variables are usually added and initialized implicitly whenever a literal is used as an argument except for the functions 'val', 'fixed', 'failed' and 'frozen'.

译文:除了函数'val', 'fixed', 'failed'和'frozen'外,当使用文字作为参数时,通常都会隐式添加和初始化变量

However, the library internally keeps a maximum variable index, which can be queried.

 

int vars ();

   
 

// Increase the maximum variable index explicitly.

This function makes sure that at least 'min_max_var' variables are initialized. Since it  might need to reallocate tables, it destroys a satisfying assignment   and has the same state transition and conditions as 'assume' etc.

译文:这个函数确保至少对'min_max_var'变量进行了初始化。因为它可能需要重新分配表,它破坏了一个令人满意的分配,并具有与“假定”等相同的状态转换和条件。

void reserve (int min_max_var);

   
   

// Specify search limits, where currently 'name' can be "conflicts",  "decisions", "preprocessing", or "localsearch".

译文:指定搜索限制,目前的“名称”可以是“冲突”、“决定”、“预处理”或“localsearch”

 

 

The first two limits  are unbounded by default. Thus using a negative limit for conflicts or  decisions switches back to the default of unlimited search (for that particular limit). 译文:默认情况下,前两个限制是无限制的。因此,对冲突或决策使用负限制将切换回默认的无限搜索(对于该特定限制)。

The preprocessing limit determines the number of preprocessing rounds, which is zero by default. Similarly, the local  search limit determines the number of local search rounds (also zero by default). 译文:预处理限制决定了预处理轮数,默认为0。类似地,本地搜索限制决定了本地搜索轮数(默认也是0)。

As with 'set', the return value denotes whether the limit  'name' is valid. These limits are only valid for the next 'solve' or  'simplify' call and reset to their default after 'solve' returns (as  well as overwritten and reset during calls to 'simplify' and  'lookahead').译文:与'set'一样,返回值表示限制'name'是否有效。这些限制只对下一个'solve'或'simplify'调用有效,并在'solve'返回后重置为默认值(以及在调用'simplify'和'lookahead'时覆盖和重置)

We actually also have an internal "terminate" limit which however should only be used for testing and debugging.译文:实际上,我们也有一个内部的“终止”限制,但是它应该只用于测试和调试。

 

bool limit (const char * arg, int val);
bool is_valid_limit (const char * arg);

   
 

// The number of currently active variables and clauses can be queried by these functions.

译文:这些函数可以查询当前活动的变量和子句的数量。

 

 

Variables become active if a clause is added with it. 译文:如果添加了子句,变量就变成活动的。


They become inactive if they are eliminated or fixed at the root level Clauses become inactive if they are satisfied, subsumed, eliminated. 译文:如果消除了它们,它们就变成不活动的;如果满足、包含、消除了根级子句,它们就变成不活动的。


// Redundant clauses are reduced regularly and thus the 'redundant'  function is less useful.

int active () const;                // Number of active variables.
int64_t redundant () const;   // Number of active redundant clauses.
int64_t irredundant () const; // Number of active irredundant clauses.

   
 

This function executes the given number of preprocessing rounds.

译文:这个函数执行给定的预处理轮数.

 

 

It is  similar to 'solve' with 'limits ("preprocessing", rounds)' except that  no CDCL nor local search, nor lucky phases are executed.

The result  values are also the same: 0=unknown, 10=satisfiable, 20=unsatisfiable.


 As 'solve' it resets current assumptions and limits before returning.


The numbers of rounds should not be negative.

If the number of rounds  is zero only clauses are restored (if necessary) and top level unit  propagation is performed, which both take some time.译文:如果轮数为零,则只恢复子句(如果有必要)并执行顶级单元传播,这两者都需要一些时间。


int simplify (int rounds = 3);

   
 

// Force termination of 'solve' asynchronously.译文:异步强制终止“solve”
//
// require (SOLVING | READY)
// ensure (UNKNOWN) // actually not immediately (synchronously)译文:实际上不是立即(同步地)

void terminate ();

   
 

// We have the following common reference counting functions, which avoid  to restore clauses but require substantial user guidance.译文:我们有以下常见的引用计数函数,它们避免了恢复子句,但需要大量的用户指导。

This was the  only way to use inprocessing in incremental SAT solving in Lingeling  (and before in MiniSAT's 'freeze' / 'thaw') and which did not use  automatic clause restoring. In general this is slower than  restoring clauses and should not be used.译文:这是在Lingeling的增量SAT解决方案中使用inprocessing的唯一方法(在MiniSAT的‘freeze’/‘thaw’之前也是),而且它不使用自动子句恢复。一般来说,这比restore子句要慢,不应该使用。

 In essence the user freezes variables which potentially are still  needed in clauses added or assumptions used after the next 'solve'  call. As in Lingeling you can freeze a variable multiple times, but  then have to melt it the same number of times again in order to enable  variable eliminating on it etc. The arguments can be literals  (negative indices) but conceptually variables are frozen.译文:从本质上说,用户冻结的变量可能仍然需要添加的子句或下一个“solve”调用后使用的假设。在《lingling》中,你可以多次冻结一个变量,但随后必须再次融化相同的次数,以消除变量等等。参数可以是字面量(负索引),但概念变量是固定的

 In the old way of doing things without restore you should not use a  variable incrementally (in 'add' or 'assume'), which was used before  and potentially could have been eliminated in a previous 'solve' call.
This can lead to spurious satisfying assignment.

在没有恢复的旧方法中,你不应该增量地使用变量(在‘add’或‘assume’中),这在之前的‘solve’调用中已经使用过,并且可能已经在之前的‘solve’调用中删除了。这可能导致虚假的令人满意的任务。

 

In order to check this API contract one can use the 'checkfrozen' option. This has the  drawback that restoring clauses implicitly would fail with a fatal error message even if in principle the solver could just restore clauses. Thus this option is disabled by default. 译文:为了检查这个API合同,可以使用“checkfrozen”选项。这样做的缺点是,恢复子句会隐式地失败,并产生致命的错误消息,即使在原则上,求解器可以只恢复子句。因此,该选项在默认情况下是禁用的

See our SAT'19 paper [FazekasBiereScholl-SAT'19] for more details.


bool frozen (int lit) const;
void freeze (int lit);
void melt (int lit); // Also needs 'require (frozen (lit))'.

   
 

// Root level assigned variables can be queried with this function. It returns '1' if the literal is implied by the formula, '-1' if its negation is implied, or '0' if this is unclear at this point.

       译文:可以使用这个函数查询根级别指定的变量。如果公式隐含了字面量,则返回'1';如果隐含了否定,则返回'-1';如果此时不清楚,则返回'0'。

      int fixed (int lit) const;

   
 

// The actual app is allocated on the stack and then its 'main' function is called.译文:实际的应用程序是在堆栈上分配的,然后它的'main'函数被调用

This looks like that there are no static variables, which is not  completely true, since both the signal handler connected to the app as  well as the terminal have statically allocated components as well as the options table 'Options::table'. All are shared among solvers.

译文:这看起来好像没有静态变量,但这并不完全正确,因为连接到应用程序的信号处理器和终端都有静态分配的组件,以及选项表' options::table'。所有这些都在求解器之间共享.

   
 

/*----------------------------------------------------------------------*/
 The '--less' option is not fully functional yet (it is also not mentioned in the 'usage' message yet). It only works as expected if you let the solver run until it exits. The goal is to have a similar experience as with 'git diff' if the terminal is too small for the printed messages, but this needs substantial hacking.
译文:“——less”选项还没有完全发挥作用(它也没有在“使用”信息中提到)。只有当您让求解器运行直到它退出时,它才会按预期工作。我们的目标是,如果终端对于打印的消息来说太小了,那么就像使用“git diff”一样,但这需要大量的黑客攻击。

   
posted on 2021-01-26 11:34  海阔凭鱼跃越  阅读(288)  评论(0编辑  收藏  举报