1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*!
A queue of observed consequences to be propagated.
Observed consequences are atom-value pairs, such that the given atom *must* have the given value on the current valuation.
For convenience, each atom-value pair represented as a literal.
```rust,ignore
match context.value_and_queue(CLiteral::new(atom, false), QPosition::Back, 0) {
Ok(Qd) => context.record_literal(literal, literal::Source::Decision),
Ok(Skip) => break,
Err(e) => return Err(e),
}
```
Queuing a consequence requires specifying:
- The atom and it's value, represented as a literal.
- Whether to push the consequence to the [front](QPosition::Front) or the [back](QPosition::Back) of the queue.
- The decision level at which the consequence was queued.
Consequences are queued in various places, such as when adding a unit clause through [add_clause](GenericContext::add_clause).
Consequences are applied using [procedures::apply_consequences](crate::procedures::apply_consequences).
# Invariants
The following invariant is always upheld:
<div class="warning">
Whenever the valuation is extended so that atom <i>a</i> has value <i>v</i>, that atom <i>a</i> has value <i>v</i> is added to the consequence queue.
</div>
# Details
In order to help uphold the given invariant, queuing a literal results in an immediate attempt to update the current valuation with the observation.
So, it is sufficient to push to the queue in order to update the valuation.
- If the consequence is *already* part of the current valuation, nothing happens.\
In this case, given the invariant above conseqence is, or has already been, on the queue.
- If the consequence is *not* already part of the current valuation, the valuation is updated with the consequence and a literal representing the atom-value pair is added to the queue, ready to be examined by a process such as [BCP](crate::procedures::bcp).
- If the consequence *conflicts* with the current valuation, a conflict has been found and an error is returned.\
Here, a prodedure such as [analysis](crate::procedures::analysis) may be used to recover from the conflict.
Interaction with the queue as a [std::collections::VecDeque] is preferred, though further methods may be attached to other structs.
For example, [GenericContext::clear_q] provides a convenient way to clear all consequences from a given level.
# Consequence delay
The intended use of the consequence queue is to allow for the decision that a atom *will* have, or the observation that an atom *must* have, some value to be used to update the valuation immediately, and for the task of examining the consequences of this to be delayed.
This is particularly useful to avoid multiple passes as updating the watch literals for a clause, as multiple candidate watch literals at the time of the queuing may be ruled out by the time the consequence is applied.
Further, as a conflict requires immediate backjumping, this use may avoid redundant propagation from consequences queued when a conflict is found --- though, it may be that applying those consequences would have led to a different (and perhaps more useful) learned clause.
*/
use Borrow;
use crate::;
/// A queue of observed consequences and the level at which the consequence was observed.
pub type ConsequenceQ = VecDeque;
/// Possible 'Ok' results of queuing a literal.
/// Relative positions to place a literal on the consequence queue.