1use std::{
4 cmp,
5 collections::{BTreeSet, TryReserveError},
6 io,
7 ops::Index,
8 path::Path,
9};
10
11use crate::{
12 clause,
13 encodings::{atomics, card, pb, CollectClauses},
14 lit,
15 types::{
16 constraints::{CardConstraint, ConstraintRef, PbConstraint},
17 Assignment, Clause, Lit, TernaryVal, Var,
18 },
19 utils::{unreachable_err, LimitedIter},
20};
21
22use super::{
23 fio::{self, dimacs::CnfLine},
24 BasicVarManager, ManageVars, ReindexVars, WriteDimacsError,
25};
26
27#[derive(Clone, PartialEq, Eq, Default)]
36#[cfg_attr(
37 any(feature = "serde", test),
38 derive(serde::Serialize, serde::Deserialize)
39)]
40pub struct Cnf {
41 pub(super) clauses: Vec<Clause>,
42}
43
44impl std::fmt::Debug for Cnf {
45 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 f.debug_struct("Cnf")
47 .field("clauses", &self.clauses)
48 .finish()
49 }
50}
51
52impl Cnf {
53 #[must_use]
55 pub fn new() -> Cnf {
56 Cnf::default()
57 }
58
59 #[must_use]
61 pub fn with_capacity(capacity: usize) -> Cnf {
62 Cnf {
63 clauses: Vec::with_capacity(capacity),
64 }
65 }
66
67 #[inline]
73 pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
74 self.clauses.try_reserve(additional)
75 }
76
77 #[inline]
79 pub fn shrink_to_fit(&mut self) {
80 self.clauses.shrink_to_fit();
81 }
82
83 #[inline]
85 #[must_use]
86 pub fn capacity(&self) -> usize {
87 self.clauses.capacity()
88 }
89
90 #[inline]
92 #[must_use]
93 pub fn is_empty(&self) -> bool {
94 self.clauses.is_empty()
95 }
96
97 #[inline]
99 #[must_use]
100 pub fn len(&self) -> usize {
101 self.clauses.len()
102 }
103
104 #[inline]
106 pub fn clear(&mut self) {
107 self.clauses.clear();
108 }
109
110 pub fn add_nary(&mut self, lits: &[Lit]) {
114 *self &= Clause::from(lits);
115 }
116
117 pub fn add_lit_impl_lit(&mut self, a: Lit, b: Lit) {
119 *self &= atomics::lit_impl_lit(a, b);
120 }
121
122 pub fn add_lit_impl_clause(&mut self, a: Lit, b: &[Lit]) {
124 *self &= atomics::lit_impl_clause(a, b);
125 }
126
127 pub fn add_lit_impl_cube(&mut self, a: Lit, b: &[Lit]) {
129 self.extend(atomics::lit_impl_cube(a, b));
130 }
131
132 pub fn add_cube_impl_lit(&mut self, a: &[Lit], b: Lit) {
134 *self &= atomics::cube_impl_lit(a, b);
135 }
136
137 pub fn add_clause_impl_lit(&mut self, a: &[Lit], b: Lit) {
139 self.extend(atomics::clause_impl_lit(a, b));
140 }
141
142 pub fn add_cube_impl_clause(&mut self, a: &[Lit], b: &[Lit]) {
144 *self &= atomics::cube_impl_clause(a, b);
145 }
146
147 pub fn add_clause_impl_clause(&mut self, a: &[Lit], b: &[Lit]) {
149 self.extend(atomics::clause_impl_clause(a, b));
150 }
151
152 pub fn add_clause_impl_cube(&mut self, a: &[Lit], b: &[Lit]) {
154 self.extend(atomics::clause_impl_cube(a, b));
155 }
156
157 pub fn add_cube_impl_cube(&mut self, a: &[Lit], b: &[Lit]) {
159 self.extend(atomics::cube_impl_cube(a, b));
160 }
161
162 #[must_use]
165 pub fn join(mut self, other: Cnf) -> Cnf {
166 self.extend(other);
167 self
168 }
169
170 pub fn iter(&self) -> std::slice::Iter<'_, Clause> {
172 self.clauses.iter()
173 }
174
175 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Clause> {
177 self.clauses.iter_mut()
178 }
179
180 #[must_use]
184 pub fn normalize(self) -> Self {
185 let mut norm_clauses: Vec<Clause> =
186 self.into_iter().filter_map(Clause::normalize).collect();
187 norm_clauses.sort_unstable();
189 norm_clauses.dedup();
190 Self {
191 clauses: norm_clauses,
192 }
193 }
194
195 #[must_use]
198 pub fn sanitize(self) -> Self {
199 Self {
200 clauses: self.into_iter().filter_map(Clause::sanitize).collect(),
201 }
202 }
203
204 #[cfg(feature = "rand")]
205 #[must_use]
207 pub fn shuffle(mut self) -> Self {
208 use rand::seq::SliceRandom;
209 let mut rng = rand::rng();
210 self.clauses[..].shuffle(&mut rng);
211 self
212 }
213
214 #[inline]
218 pub fn add_clause(&mut self, clause: Clause) {
219 self.clauses.push(clause);
220 }
221
222 pub fn add_unit(&mut self, unit: Lit) {
226 *self &= unit;
227 }
228
229 pub fn add_binary(&mut self, lit1: Lit, lit2: Lit) {
233 *self &= lit1 | lit2;
234 }
235
236 pub fn add_ternary(&mut self, lit1: Lit, lit2: Lit, lit3: Lit) {
240 *self &= lit1 | lit2 | lit3;
241 }
242
243 pub fn write_dimacs_path<P: AsRef<Path>>(&self, path: P, n_vars: u32) -> Result<(), io::Error> {
249 let mut writer = fio::open_compressed_uncompressed_write(path)?;
250 self.write_dimacs(&mut writer, n_vars)
251 }
252
253 pub fn write_dimacs<W: io::Write>(&self, writer: W, n_vars: u32) -> Result<(), io::Error> {
263 fio::dimacs::write_cnf_annotated(writer, self, n_vars)
264 }
265
266 #[must_use]
268 pub fn evaluate(&self, assign: &Assignment) -> TernaryVal {
269 let mut val = TernaryVal::True;
270 for clause in &self.clauses {
271 match clause.evaluate(assign) {
272 TernaryVal::True => (),
273 TernaryVal::False => return TernaryVal::False,
274 TernaryVal::DontCare => val = TernaryVal::DontCare,
275 }
276 }
277 val
278 }
279}
280
281impl<'slf> IntoIterator for &'slf Cnf {
282 type Item = &'slf Clause;
283
284 type IntoIter = std::slice::Iter<'slf, Clause>;
285
286 fn into_iter(self) -> Self::IntoIter {
287 self.iter()
288 }
289}
290
291impl<'slf> IntoIterator for &'slf mut Cnf {
292 type Item = &'slf mut Clause;
293
294 type IntoIter = std::slice::IterMut<'slf, Clause>;
295
296 fn into_iter(self) -> Self::IntoIter {
297 self.iter_mut()
298 }
299}
300
301impl CollectClauses for Cnf {
302 fn n_clauses(&self) -> usize {
303 self.clauses.len()
304 }
305
306 fn extend_clauses<T>(&mut self, cl_iter: T) -> Result<(), crate::OutOfMemory>
307 where
308 T: IntoIterator<Item = Clause>,
309 {
310 let cl_iter = cl_iter.into_iter();
311 if let Some(ub) = cl_iter.size_hint().1 {
312 self.try_reserve(ub)?;
313 self.extend(cl_iter);
314 } else {
315 let mut cl_iter = cl_iter.peekable();
317 while cl_iter.peek().is_some() {
318 let additional = (self.len() + cmp::max(cl_iter.size_hint().0, 1))
319 .next_power_of_two()
320 - self.len();
321 self.try_reserve(additional)?;
322 self.extend(LimitedIter::new(&mut cl_iter, additional));
323 }
324 }
325 Ok(())
326 }
327}
328
329#[cfg(feature = "proof-logging")]
330impl crate::encodings::cert::CollectClauses for Cnf {}
331
332impl IntoIterator for Cnf {
333 type Item = Clause;
334
335 type IntoIter = std::vec::IntoIter<Clause>;
336
337 fn into_iter(self) -> Self::IntoIter {
338 self.clauses.into_iter()
339 }
340}
341
342impl FromIterator<Clause> for Cnf {
343 fn from_iter<T: IntoIterator<Item = Clause>>(iter: T) -> Self {
344 Self {
345 clauses: iter.into_iter().collect(),
346 }
347 }
348}
349
350impl FromIterator<CnfLine> for Cnf {
351 fn from_iter<T: IntoIterator<Item = CnfLine>>(iter: T) -> Self {
352 iter.into_iter().filter_map(CnfLine::clause).collect()
353 }
354}
355
356impl Extend<Clause> for Cnf {
357 fn extend<Iter: IntoIterator<Item = Clause>>(&mut self, iter: Iter) {
358 self.clauses.extend(iter);
359 }
360}
361
362impl Index<usize> for Cnf {
363 type Output = Clause;
364
365 fn index(&self, index: usize) -> &Self::Output {
366 &self.clauses[index]
367 }
368}
369
370#[derive(Clone, Debug, PartialEq, Eq)]
373#[cfg_attr(
374 any(feature = "serde", test),
375 derive(serde::Serialize, serde::Deserialize)
376)]
377pub struct Instance<VM: ManageVars = BasicVarManager> {
378 pub(super) cnf: Cnf,
379 pub(super) cards: Vec<CardConstraint>,
380 pub(super) pbs: Vec<PbConstraint>,
381 pub(super) var_manager: VM,
382}
383
384impl<VM: ManageVars> Instance<VM> {
385 pub fn new_with_manager(var_manager: VM) -> Self {
387 Instance {
388 cnf: Cnf::new(),
389 cards: vec![],
390 pbs: vec![],
391 var_manager,
392 }
393 }
394
395 pub fn n_clauses(&self) -> usize {
397 self.cnf.n_clauses()
398 }
399
400 pub fn n_cards(&self) -> usize {
402 self.cards.len()
403 }
404
405 pub fn n_pbs(&self) -> usize {
407 self.pbs.len()
408 }
409
410 pub fn n_constraints(&self) -> usize {
419 self.n_clauses() + self.n_cards() + self.n_pbs()
420 }
421
422 pub fn add_clause(&mut self, cl: Clause) {
426 cl.iter().for_each(|l| {
427 self.var_manager.mark_used(l.var());
428 });
429 self.cnf.add_clause(cl);
430 }
431
432 pub fn add_nary(&mut self, lits: &[Lit]) {
436 *self &= Clause::from(lits);
437 }
438
439 pub fn add_unit(&mut self, unit: Lit) {
443 *self &= unit;
444 }
445
446 pub fn add_binary(&mut self, lit1: Lit, lit2: Lit) {
448 *self &= lit1 | lit2;
449 }
450
451 pub fn add_ternary(&mut self, lit1: Lit, lit2: Lit, lit3: Lit) {
453 *self &= lit1 | lit2 | lit3;
454 }
455
456 pub fn add_lit_impl_lit(&mut self, a: Lit, b: Lit) {
458 self.var_manager.mark_used(a.var());
459 self.var_manager.mark_used(b.var());
460 self.cnf.add_lit_impl_lit(a, b);
461 }
462
463 pub fn add_lit_impl_clause(&mut self, a: Lit, b: &[Lit]) {
465 self.var_manager.mark_used(a.var());
466 for l in b {
467 self.var_manager.mark_used(l.var());
468 }
469 self.cnf.add_lit_impl_clause(a, b);
470 }
471
472 pub fn add_lit_impl_cube(&mut self, a: Lit, b: &[Lit]) {
474 self.var_manager.mark_used(a.var());
475 for l in b {
476 self.var_manager.mark_used(l.var());
477 }
478 self.cnf.add_lit_impl_cube(a, b);
479 }
480
481 pub fn add_cube_impl_lit(&mut self, a: &[Lit], b: Lit) {
483 for l in a {
484 self.var_manager.mark_used(l.var());
485 }
486 self.var_manager.mark_used(b.var());
487 self.cnf.add_cube_impl_lit(a, b);
488 }
489
490 pub fn add_clause_impl_lit(&mut self, a: &[Lit], b: Lit) {
492 for l in a {
493 self.var_manager.mark_used(l.var());
494 }
495 self.var_manager.mark_used(b.var());
496 self.cnf.add_clause_impl_lit(a, b);
497 }
498
499 pub fn add_cube_impl_clause(&mut self, a: &[Lit], b: &[Lit]) {
501 for l in a {
502 self.var_manager.mark_used(l.var());
503 }
504 for l in b {
505 self.var_manager.mark_used(l.var());
506 }
507 self.cnf.add_cube_impl_clause(a, b);
508 }
509
510 pub fn add_clause_impl_clause(&mut self, a: &[Lit], b: &[Lit]) {
512 for l in a {
513 self.var_manager.mark_used(l.var());
514 }
515 for l in b {
516 self.var_manager.mark_used(l.var());
517 }
518 self.cnf.add_clause_impl_clause(a, b);
519 }
520
521 pub fn add_clause_impl_cube(&mut self, a: &[Lit], b: &[Lit]) {
523 for l in a {
524 self.var_manager.mark_used(l.var());
525 }
526 for l in b {
527 self.var_manager.mark_used(l.var());
528 }
529 self.cnf.add_clause_impl_cube(a, b);
530 }
531
532 pub fn add_cube_impl_cube(&mut self, a: &[Lit], b: &[Lit]) {
534 for l in a {
535 self.var_manager.mark_used(l.var());
536 }
537 for l in b {
538 self.var_manager.mark_used(l.var());
539 }
540 self.cnf.add_cube_impl_cube(a, b);
541 }
542
543 pub fn add_card_constr(&mut self, card: CardConstraint) {
545 for l in &card {
546 self.var_manager.mark_used(l.var());
547 }
548 self.cards.push(card);
549 }
550
551 pub fn add_pb_constr(&mut self, pb: PbConstraint) {
553 for (l, _) in &pb {
554 self.var_manager.mark_used(l.var());
555 }
556 self.pbs.push(pb);
557 }
558
559 pub fn cnf(&self) -> &Cnf {
561 &self.cnf
562 }
563
564 pub fn var_manager_mut(&mut self) -> &mut VM {
566 &mut self.var_manager
567 }
568
569 pub fn var_manager_ref(&self) -> &VM {
571 &self.var_manager
572 }
573
574 pub fn new_var(&mut self) -> Var {
577 self.var_manager_mut().new_var()
578 }
579
580 pub fn new_lit(&mut self) -> Lit {
583 self.var_manager_mut().new_lit()
584 }
585
586 pub fn max_var(&self) -> Option<Var> {
589 self.var_manager_ref().max_var()
590 }
591
592 pub fn n_vars(&self) -> u32 {
594 self.var_manager_ref().n_used()
595 }
596
597 pub fn change_var_manager<VM2, VMC>(self, vm_converter: VMC) -> (Instance<VM2>, VM)
599 where
600 VM2: ManageVars,
601 VMC: Fn(&VM) -> VM2,
602 {
603 (
604 Instance {
605 cnf: self.cnf,
606 cards: self.cards,
607 pbs: self.pbs,
608 var_manager: vm_converter(&self.var_manager),
609 },
610 self.var_manager,
611 )
612 }
613
614 pub fn into_cnf(self) -> (Cnf, VM) {
623 self.into_cnf_with_encoders(
624 |constr, cnf, vm| {
625 card::default_encode_cardinality_constraint(constr, cnf, vm)
626 .expect("cardinality encoding ran out of memory");
627 },
628 |constr, cnf, vm| {
629 pb::default_encode_pb_constraint(constr, cnf, vm)
630 .expect("pb encoding ran out of memory");
631 },
632 )
633 }
634
635 pub fn convert_to_cnf(&mut self) {
644 self.convert_to_cnf_with_encoders(
645 |constr, cnf, vm| {
646 card::default_encode_cardinality_constraint(constr, cnf, vm)
647 .expect("cardinality encoding ran out of memory");
648 },
649 |constr, cnf, vm| {
650 pb::default_encode_pb_constraint(constr, cnf, vm)
651 .expect("pb encoding ran out of memory");
652 },
653 );
654 }
655
656 pub fn into_cnf_with_encoders<CardEnc, PBEnc>(
665 mut self,
666 card_encoder: CardEnc,
667 pb_encoder: PBEnc,
668 ) -> (Cnf, VM)
669 where
670 CardEnc: FnMut(CardConstraint, &mut Cnf, &mut dyn ManageVars),
671 PBEnc: FnMut(PbConstraint, &mut Cnf, &mut dyn ManageVars),
672 {
673 self.convert_to_cnf_with_encoders(card_encoder, pb_encoder);
674 (self.cnf, self.var_manager)
675 }
676
677 pub fn convert_to_cnf_with_encoders<CardEnc, PBEnc>(
686 &mut self,
687 mut card_encoder: CardEnc,
688 mut pb_encoder: PBEnc,
689 ) where
690 CardEnc: FnMut(CardConstraint, &mut Cnf, &mut dyn ManageVars),
691 PBEnc: FnMut(PbConstraint, &mut Cnf, &mut dyn ManageVars),
692 {
693 self.cards
694 .drain(..)
695 .for_each(|constr| card_encoder(constr, &mut self.cnf, &mut self.var_manager));
696 self.pbs
697 .drain(..)
698 .for_each(|constr| pb_encoder(constr, &mut self.cnf, &mut self.var_manager));
699 }
700
701 pub fn into_pbs(mut self) -> (Vec<PbConstraint>, VM) {
703 self.pbs
704 .extend(self.cards.into_iter().map(PbConstraint::from));
705 self.pbs
706 .extend(self.cnf.into_iter().map(PbConstraint::from));
707 (self.pbs, self.var_manager)
708 }
709
710 pub fn extend(&mut self, other: Instance<VM>) {
712 self.cnf.extend(other.cnf);
713 self.var_manager.combine(other.var_manager);
714 }
715
716 #[must_use]
718 pub fn reindex<R: ReindexVars>(mut self, mut reindexer: R) -> Instance<R> {
719 self.cnf
720 .iter_mut()
721 .for_each(|cl| cl.iter_mut().for_each(|l| *l = reindexer.reindex_lit(*l)));
722 self.cards
723 .iter_mut()
724 .for_each(|card| card.iter_mut().for_each(|l| *l = reindexer.reindex_lit(*l)));
725 self.pbs.iter_mut().for_each(|pb| {
726 pb.iter_mut()
727 .for_each(|(l, _)| *l = reindexer.reindex_lit(*l));
728 });
729 Instance {
730 cnf: self.cnf,
731 cards: self.cards,
732 pbs: self.pbs,
733 var_manager: reindexer,
734 }
735 }
736
737 pub(crate) fn extend_var_set(&self, varset: &mut BTreeSet<Var>) {
738 varset.extend(self.cnf.iter().flat_map(|cl| cl.iter().map(|l| l.var())));
739 varset.extend(
740 self.cards
741 .iter()
742 .flat_map(|card| card.iter().map(|l| l.var())),
743 );
744 varset.extend(
745 self.pbs
746 .iter()
747 .flat_map(|pbs| pbs.iter().map(|(l, _)| l.var())),
748 );
749 }
750
751 pub fn var_set(&self) -> BTreeSet<Var> {
753 let mut varset = BTreeSet::new();
754 self.extend_var_set(&mut varset);
755 varset
756 }
757
758 #[must_use]
763 pub fn reindex_ordered<R: ReindexVars>(self, mut reindexer: R) -> Instance<R> {
764 let mut varset = BTreeSet::new();
765 self.extend_var_set(&mut varset);
766 for var in varset {
768 reindexer.reindex(var);
769 }
770 self.reindex(reindexer)
771 }
772
773 #[cfg(feature = "rand")]
774 #[must_use]
776 pub fn shuffle(mut self) -> Self {
777 use rand::seq::SliceRandom;
778 self.cnf = self.cnf.shuffle();
779 let mut rng = rand::rng();
780 self.cards[..].shuffle(&mut rng);
781 self.pbs[..].shuffle(&mut rng);
782 self
783 }
784
785 pub fn write_dimacs_path<P: AsRef<Path>>(&self, path: P) -> Result<(), WriteDimacsError> {
795 let mut writer = fio::open_compressed_uncompressed_write(path)?;
796 self.write_dimacs(&mut writer)
797 }
798
799 pub fn write_dimacs<W: io::Write>(&self, writer: W) -> Result<(), WriteDimacsError> {
813 if self.n_cards() > 0 || self.n_pbs() > 0 {
814 return Err(WriteDimacsError::RequiresClausal);
815 }
816 let n_vars = self.n_vars();
817 Ok(fio::dimacs::write_cnf_annotated(writer, &self.cnf, n_vars)?)
818 }
819
820 pub fn write_opb_path<P: AsRef<Path>>(
826 &self,
827 path: P,
828 opts: fio::opb::Options,
829 ) -> Result<(), io::Error> {
830 let mut writer = fio::open_compressed_uncompressed_write(path)?;
831 self.write_opb(&mut writer, opts)
832 }
833
834 pub fn write_opb<W: io::Write>(
844 &self,
845 writer: W,
846 opts: fio::opb::Options,
847 ) -> Result<(), io::Error> {
848 fio::opb::write_sat(writer, self, opts)
849 }
850
851 #[must_use]
855 pub fn sanitize(self) -> Self {
856 let mut unsat = false;
857 let mut cnf = self.cnf;
858 let mut cards = self.cards;
859 let pbs = self
860 .pbs
861 .into_iter()
862 .filter_map(|pb| {
863 if pb.is_tautology() {
864 return None;
865 }
866 if pb.is_unsat() {
867 unsat = true;
868 return None;
869 }
870 if pb.is_positive_assignment() {
871 pb.into_lits()
873 .into_iter()
874 .for_each(|(l, _)| cnf.add_unit(l));
875 return None;
876 }
877 if pb.is_negative_assignment() {
878 pb.into_lits()
880 .into_iter()
881 .for_each(|(l, _)| cnf.add_unit(!l));
882 return None;
883 }
884 if pb.is_clause() {
885 cnf.add_clause(unreachable_err!(pb.into_clause()));
886 return None;
887 }
888 if pb.is_card() {
889 cards.push(unreachable_err!(pb.into_card_constr()));
890 return None;
891 }
892 Some(pb)
893 })
894 .collect();
895 let cards = cards
896 .into_iter()
897 .filter_map(|card| {
898 if card.is_tautology() {
899 return None;
900 }
901 if card.is_unsat() {
902 unsat = true;
903 return None;
904 }
905 if card.is_positive_assignment() {
906 card.into_lits().into_iter().for_each(|l| cnf.add_unit(l));
908 return None;
909 }
910 if card.is_negative_assignment() {
911 card.into_lits().into_iter().for_each(|l| cnf.add_unit(!l));
913 return None;
914 }
915 if card.is_clause() {
916 cnf.add_clause(unreachable_err!(card.into_clause()));
917 return None;
918 }
919 Some(card)
920 })
921 .collect();
922 if unsat {
923 return Self {
924 cnf: Cnf::from_iter(vec![clause![lit![0]], clause![!lit![0]]]),
925 cards: vec![],
926 pbs: vec![],
927 var_manager: self.var_manager,
928 };
929 }
930 Self {
931 cnf: cnf.into_iter().filter_map(Clause::sanitize).collect(),
932 cards,
933 pbs,
934 var_manager: self.var_manager,
935 }
936 }
937
938 #[must_use]
940 pub fn evaluate(&self, assign: &Assignment) -> TernaryVal {
941 let mut val = TernaryVal::True;
942 match self.cnf.evaluate(assign) {
943 TernaryVal::True => (),
944 TernaryVal::False => return TernaryVal::False,
945 TernaryVal::DontCare => val = TernaryVal::DontCare,
946 }
947 for card in &self.cards {
948 match card.evaluate(assign) {
949 TernaryVal::True => (),
950 TernaryVal::False => return TernaryVal::False,
951 TernaryVal::DontCare => val = TernaryVal::DontCare,
952 }
953 }
954 for pb in &self.pbs {
955 match pb.evaluate(assign) {
956 TernaryVal::True => (),
957 TernaryVal::False => return TernaryVal::False,
958 TernaryVal::DontCare => val = TernaryVal::DontCare,
959 }
960 }
961 val
962 }
963
964 pub fn unsat_constraint(&self, assign: &Assignment) -> Option<ConstraintRef<'_>> {
966 for clause in &self.cnf {
967 if clause.evaluate(assign) != TernaryVal::True {
968 return Some(ConstraintRef::Clause(clause));
969 }
970 }
971 for card in &self.cards {
972 if card.evaluate(assign) != TernaryVal::True {
973 return Some(ConstraintRef::Card(card));
974 }
975 }
976 for pb in &self.pbs {
977 if pb.evaluate(assign) != TernaryVal::True {
978 return Some(ConstraintRef::Pb(pb));
979 }
980 }
981 None
982 }
983}
984
985impl<VM: ManageVars + Default> Instance<VM> {
986 #[must_use]
988 pub fn new() -> Instance<VM> {
989 Instance::default()
990 }
991
992 pub fn from_dimacs<R: io::BufRead>(reader: R) -> Result<Self, fio::Error> {
1007 let header_data =
1008 fio::dimacs::Parser::<fio::dimacs::CnfHeader, _>::new(reader).forward_to_body()?;
1009 let mut inst = Self::default();
1010 inst.var_manager_mut()
1011 .increase_next_free(Var::new(header_data.n_vars));
1012 for data in header_data.body_parser {
1013 match data? {
1014 fio::dimacs::CnfData::Clause(clause) => inst.add_clause(clause),
1015 fio::dimacs::CnfData::Comment(_) => (),
1016 }
1017 }
1018 Ok(inst)
1019 }
1020
1021 pub fn from_dimacs_path<P: AsRef<Path>>(path: P) -> Result<Self, fio::Error> {
1029 let mut reader = fio::open_compressed_uncompressed_read(path)?;
1030 Instance::from_dimacs(&mut reader)
1031 }
1032
1033 pub fn from_opb<R: io::BufRead>(
1045 reader: R,
1046 opts: fio::opb::Options,
1047 ) -> Result<Self, fio::Error> {
1048 let parser = fio::opb::Parser::new(reader, opts);
1049 let mut inst = Self::new();
1050 for data in parser {
1051 match data? {
1052 fio::opb::Data::Cmt(_) => {}
1053 fio::opb::Data::Constr(constr) => inst.add_pb_constr(constr),
1054 #[cfg(feature = "optimization")]
1055 fio::opb::Data::Obj(_) => {
1056 return Err(fio::Error::ObjInSat);
1057 }
1058 }
1059 }
1060 Ok(inst)
1061 }
1062
1063 pub fn from_opb_path<P: AsRef<Path>>(
1071 path: P,
1072 opts: fio::opb::Options,
1073 ) -> Result<Self, fio::Error> {
1074 let mut reader = fio::open_compressed_uncompressed_read(path)?;
1075 Instance::from_opb(&mut reader, opts)
1076 }
1077}
1078
1079impl<VM: ManageVars + Default> Default for Instance<VM> {
1080 fn default() -> Self {
1081 Self {
1082 cnf: Cnf::default(),
1083 cards: Vec::default(),
1084 pbs: Vec::default(),
1085 var_manager: VM::default(),
1086 }
1087 }
1088}
1089
1090impl<VM: ManageVars + Default> FromIterator<Clause> for Instance<VM> {
1091 fn from_iter<T: IntoIterator<Item = Clause>>(iter: T) -> Self {
1092 let mut inst = Self::default();
1093 iter.into_iter().for_each(|cl| inst.add_clause(cl));
1094 inst
1095 }
1096}
1097
1098impl<VM: ManageVars + Default> FromIterator<CnfLine> for Instance<VM> {
1099 fn from_iter<T: IntoIterator<Item = CnfLine>>(iter: T) -> Self {
1100 iter.into_iter().filter_map(CnfLine::clause).collect()
1101 }
1102}
1103
1104impl<VM: ManageVars + Default> FromIterator<PbConstraint> for Instance<VM> {
1105 fn from_iter<T: IntoIterator<Item = PbConstraint>>(iter: T) -> Self {
1106 let mut inst = Self::default();
1107 iter.into_iter()
1108 .for_each(|constr| inst.add_pb_constr(constr));
1109 inst
1110 }
1111}
1112
1113impl<VM: ManageVars + Default> FromIterator<CardConstraint> for Instance<VM> {
1114 fn from_iter<T: IntoIterator<Item = CardConstraint>>(iter: T) -> Self {
1115 let mut inst = Self::default();
1116 iter.into_iter()
1117 .for_each(|constr| inst.add_card_constr(constr));
1118 inst
1119 }
1120}
1121
1122impl<VM: ManageVars + Default> FromIterator<fio::opb::Data> for Instance<VM> {
1123 fn from_iter<T: IntoIterator<Item = fio::opb::Data>>(iter: T) -> Self {
1124 iter.into_iter()
1125 .filter_map(fio::opb::Data::constraint)
1126 .collect()
1127 }
1128}
1129
1130impl<VM: ManageVars + Default> From<Cnf> for Instance<VM> {
1131 fn from(value: Cnf) -> Self {
1132 let mut inst = Self {
1133 cnf: value,
1134 ..Default::default()
1135 };
1136 for cl in &inst.cnf {
1137 for l in cl {
1138 inst.var_manager.increase_next_free(l.var() + 1);
1139 }
1140 }
1141 inst
1142 }
1143}
1144
1145impl<VM: ManageVars> Extend<Clause> for Instance<VM> {
1146 fn extend<T: IntoIterator<Item = Clause>>(&mut self, iter: T) {
1147 self.cnf.extend(iter);
1148 }
1149}
1150
1151impl CollectClauses for Instance {
1152 fn n_clauses(&self) -> usize {
1153 self.n_clauses()
1154 }
1155
1156 fn extend_clauses<T>(&mut self, cl_iter: T) -> Result<(), crate::OutOfMemory>
1157 where
1158 T: IntoIterator<Item = Clause>,
1159 {
1160 self.cnf.extend_clauses(cl_iter)
1161 }
1162}
1163
1164#[cfg(test)]
1165mod tests {
1166 use crate::{instances::Cnf, lit};
1167
1168 #[test]
1169 fn reindex_ordered() {
1170 let mut inst: super::Instance = super::Instance::default();
1171 inst.add_nary(&[lit![4], lit![1]]);
1172 inst.add_nary(&[lit![0], lit![2]]);
1173 let inst = inst.reindex_ordered(super::super::ReindexingVarManager::default());
1174 let (cnf, _) = inst.into_cnf();
1175 assert_eq!(cnf, Cnf::from_iter([lit![3] | lit![1], lit![0] | lit![2]]));
1176 }
1177}