Exemple #1
0
func buildLogEncoding(pred sat.Pred, uId int, cutoff int, depth int, tag string, lits []sat.Literal) (clauses sat.ClauseSet) {
	if len(lits) <= cutoff {
		trans2 := TranslateAtMostOne(Naive, tag, lits)
		clauses.AddClauseSet(trans2.Clauses)
	} else {
		atom := sat.NewAtomP2(pred, uId, depth)
		first := lits[:len(lits)/2]
		for _, l := range first {
			clauses.AddTaggedClause(tag, sat.Literal{true, atom}, sat.Neg(l))
		}
		second := lits[len(lits)/2:]
		for _, l := range second {
			clauses.AddTaggedClause(tag, sat.Literal{false, atom}, sat.Neg(l))
		}
		depth++
		clauses.AddClauseSet(buildLogEncoding(pred, uId, cutoff, depth, tag, first))
		clauses.AddClauseSet(buildLogEncoding(pred, uId, cutoff, depth, tag, second))
	}
	return
}
Exemple #2
0
func (t *Threshold) NormalizePositiveLiterals() {
	glob.A(len(t.Chains) == 0, "cant reorder Entries with chains")

	for i, e := range t.Entries {
		if t.Entries[i].Literal.Sign == false {
			t.Entries[i].Literal = sat.Neg(e.Literal)
			t.K -= t.Entries[i].Weight
			t.Entries[i].Weight = -t.Entries[i].Weight
		}
	}
}
Exemple #3
0
// finds trivially implied facts, returns set of facts
// removes such entries from the pb
// threshold can become empty!
func (pb *Threshold) Simplify() {

	if pb.Typ == OPT {
		glob.D(pb.IdS(), " is not simplyfied because is OPT")
		return
	}

	pb.Normalize(LE, true)

	entries := make([]Entry, 0, len(pb.Entries))

	for _, x := range pb.Entries {
		if x.Weight > pb.K {
			pb.Clauses.AddTaggedClause(pb.IdS()+"-simpl", sat.Neg(x.Literal))
		} else {
			entries = append(entries, x)
		}
	}

	pb.Entries = entries
	pb.Normalize(GE, true)

	if pb.SumWeights() == pb.K {
		for _, x := range pb.Entries {
			pb.Clauses.AddTaggedClause("Fact", x.Literal)
		}
		pb.Entries = []Entry{}
	}

	if pb.SumWeights() < pb.K {
		glob.D("c PB", pb.Id, "is UNSAT")
		pb.Entries = []Entry{}
		pb.K = -1
		// is unsatisfied: how to do that?
	}

	pb.Normalize(LE, true)
	if pb.SumWeights() <= pb.K {
		glob.D("c PB", pb.Id, "is redundant")
		pb.Entries = []Entry{}
	}

	if pb.Empty() {
		pb.Translated = true
	}

	return
}
Exemple #4
0
func TestRewriteExactly4(test *testing.T) {
	glob.D("TestExactly3")

	pb1 := CreatePB([]int64{2, 2, 3, 4, 1, 1}, 6)
	pb1.Typ = LE

	pb2 := CreatePB([]int64{1, 1, 1, 1}, 2)
	pb2.Typ = EQ
	pb2.Entries[2].Literal = sat.Neg(pb2.Entries[2].Literal)

	b := PreprocessPBwithExactly(&pb1, &pb2)

	if b {
		test.Fail()
	}

}
Exemple #5
0
// Translate monotone MDDs to SAT
// Together with AMO translation
func convertMDD2Clauses(store mdd.IntervalMddStore, pb *Threshold) (clauses sat.ClauseSet) {

	pred := sat.Pred("mdd" + strconv.Itoa(pb.Id))

	top_lit := sat.Literal{true, sat.NewAtomP1(pred, store.Top)}
	clauses.AddTaggedClause("Top", top_lit)
	for _, n := range store.Nodes {
		v_id, l, vds := store.ClauseIds(*n)
		if !n.IsZero() && !n.IsOne() {

			v_lit := sat.Literal{false, sat.NewAtomP1(pred, v_id)}
			last_id := -1
			for i, vd_id := range vds {
				if last_id != vd_id {
					vd_lit := sat.Literal{true, sat.NewAtomP1(pred, vd_id)}
					if i > 0 {
						literal := pb.Entries[len(pb.Entries)-l+i-1].Literal
						clauses.AddTaggedClause("1B", v_lit, sat.Neg(literal), vd_lit)
					} else {
						clauses.AddTaggedClause("0B", v_lit, vd_lit)
					}
				}
				last_id = vd_id
			}
		} else if n.IsZero() {
			v_lit := sat.Literal{false, sat.NewAtomP1(pred, v_id)}
			clauses.AddTaggedClause("False", v_lit)
		} else if n.IsOne() {
			v_lit := sat.Literal{true, sat.NewAtomP1(pred, v_id)}
			clauses.AddTaggedClause("True", v_lit)
		}

	}

	return
}
Exemple #6
0
// Create Encoding for Sorting Network
// 0)  Omitted for clarity (ids as in paper)
// 1)  A or -D
// 2)  B or -D
// 3) -A or -B or D
// 4) -A or  C
// 5) -B or  C
// 6)  A or  B or -C
// 7)  C or -D
// -1,0,1 = *, false, true
func CreateEncoding(input []sat.Literal, which [8]bool, output []sat.Literal, tag string, pred sat.Pred, sorter sorters.Sorter) (cs sat.ClauseSet) {

	//cs.list = make([]Clause, 0, 7*len(sorter.Comparators))

	backup := make(map[int]sat.Literal, len(sorter.Out)+len(sorter.In))

	for i, x := range sorter.In {
		backup[x] = input[i]
	}

	for i, x := range sorter.Out {
		backup[x] = output[i]
	}

	for _, comp := range sorter.Comparators {

		if comp.D == 1 || comp.C == 0 {
			fmt.Println("something is wrong with the comparator", comp)
			panic("something is wrong with the comparator")
		}

		getLit := func(x int) sat.Literal {
			if lit, ok := backup[x]; ok {
				return lit
			} else {
				return sat.Literal{true, sat.NewAtomP1(pred, x)}
			}
		}

		a := getLit(comp.A)
		b := getLit(comp.B)
		c := getLit(comp.C)
		d := getLit(comp.D)

		if comp.C == 1 { // 6) A or B
			//if which[6] {
			cs.AddTaggedClause(tag, a, b)
			//}
		} else if comp.C > 0 { // 4) 5) 6)
			//4)
			if which[4] {
				cs.AddTaggedClause(tag, sat.Neg(a), c)
			}
			//5)
			if which[5] {
				cs.AddTaggedClause(tag, sat.Neg(b), c)
			}
			//6)
			if which[6] {
				cs.AddTaggedClause(tag, a, b, sat.Neg(c))
			}
		}
		if comp.D == 0 { //3)
			//if which[3] {
			cs.AddTaggedClause(tag, sat.Neg(a), sat.Neg(b))
			//}
		} else if comp.D > 0 { // 1) 2) 3)
			//1)
			if which[1] {
				cs.AddTaggedClause(tag, a, sat.Neg(d))
			}
			//2)
			if which[2] {
				cs.AddTaggedClause(tag, b, sat.Neg(d))
			}
			//3)
			if which[3] {
				cs.AddTaggedClause(tag, sat.Neg(a), sat.Neg(b), d)
			}
		}

		if which[7] && comp.C != 1 && comp.D != 0 && comp.C != -1 && comp.D != -1 { // 7)

			if comp.C == 0 || comp.D == 1 {
				panic("something is wrong with this comparator")
			}
			cs.AddTaggedClause(tag, c, sat.Neg(d))
		}
	}
	return
}
Exemple #7
0
func main() {
	glob.Init()
	input, err2 := os.Open(*glob.Filename_flag)
	defer input.Close()
	if err2 != nil {
		panic("Could not read file")
		return
	}
	scanner := bufio.NewScanner(input)
	buf := make([]byte, 0, 64*1024)
	scanner.Buffer(buf, 1024*1024)

	state := 0 // 0: read size, 1: read graph 1, 2: read graph 2
	vars := 0
	orig_vars := 0
	size := 0
	i := 0
	var entries []entry

	for scanner.Scan() {
		l := strings.Trim(scanner.Text(), " ")
		if l == "" || strings.HasPrefix(l, "%") || strings.HasPrefix(l, "*") {
			continue
		}
		elements := strings.Fields(l)
		var b error
		switch state {
		case 0: // deprecated: for parsing the "header" of pb files, now parser is flexible
			{
				vars, b = strconv.Atoi(elements[0])
				if b != nil {
					panic("bad conversion of numbers")
				}
				orig_vars = vars
				size, b = strconv.Atoi(elements[1])
				if b != nil {
					panic("bad conversion of numbers")
				}
				entries = make([]entry, size)
				state = 1
			}
		case 1:
			{
				entries[i].id1, b = strconv.Atoi(elements[0])
				if b != nil {
					panic("bad conversion of numbers")
				}
				entries[i].id2, b = strconv.Atoi(elements[1])
				if b != nil {
					panic("bad conversion of numbers")
				}
				var f float64
				f, b = strconv.ParseFloat(elements[2], 64)
				if b != nil {
					panic("bad conversion of numbers")
				}
				entries[i].c = int64(f)
				if entries[i].id1 != entries[i].id2 {
					vars++
					entries[i].and = vars
				}
				i++
			}
		}
	}

	var clauses sat.ClauseSet
	var opt constraints.Threshold
	opt.Typ = constraints.OPT

	lits := make([]sat.Literal, vars+1)

	primaryVars := make(map[string]bool, 0)
	for i := 0; i <= vars; i++ {
		primaryVars[sat.NewAtomP1(sat.Pred("x"), i).Id()] = true
	}
	for i, _ := range lits {
		lits[i] = sat.Literal{true, sat.NewAtomP1(sat.Pred("x"), i)}
	}

	for _, e := range entries {
		if e.id1 == e.id2 {
			opt.Entries = append(opt.Entries, constraints.Entry{lits[e.id1], int64(e.c)})
		} else {
			clauses.AddClause(sat.Neg(lits[e.id1]), sat.Neg(lits[e.id2]), lits[e.and])
			clauses.AddClause(lits[e.id1], sat.Neg(lits[e.and]))
			clauses.AddClause(lits[e.id2], sat.Neg(lits[e.and]))
			opt.Entries = append(opt.Entries, constraints.Entry{lits[e.and], int64(e.c)})
		}
	}

	if *glob.Gringo_flag {
		for i := 0; i <= orig_vars; i++ {
			fmt.Println("{x(", i, ")}.")
		}
		for _, e := range entries {
			if e.id1 != e.id2 {
				fmt.Println(lits[e.and].ToTxt(), ":-", lits[e.id1].ToTxt(), ",", lits[e.id2].ToTxt(), ".")

			}
		}
		opt.PrintGringo()
		return
	}

	g := sat.IdGenerator(clauses.Size()*7 + 1)
	g.PrimaryVars = primaryVars
	opt.NormalizePositiveCoefficients()
	opt.Offset = opt.K

	//	opt.PrintGringo()
	//	clauses.PrintDebug()
	glob.D("offset", opt.Offset)

	glob.A(opt.Positive(), "opt only has positive coefficients")
	g.Solve(clauses, &opt, *glob.Opt_bound_flag, -opt.Offset)

}
Exemple #8
0
func (pb *Threshold) CatSimpl() {

	glob.A(!pb.Empty(), "pb should not be empty")

	if pb.Typ == OPT {
		glob.D(pb.IdS(), " is not simplyfied because is OPT")
		pb.TransTyp = UNKNOWN
		return
	}

	pb.Simplify()

	if pb.Empty() {
		pb.TransTyp = Facts
		return
	} else {

		if b, literals := pb.Cardinality(); b {

			if pb.K == int64(len(pb.Entries)-1) {
				switch pb.Typ {
				case LE:
					pb.Normalize(GE, true)
					for i, x := range literals {
						literals[i] = sat.Neg(x)
					}
				case GE:
					for i, x := range literals {
						literals[i] = sat.Neg(x)
					}
					pb.Normalize(LE, true)
				case EQ:
					for i, x := range literals {
						literals[i] = sat.Neg(x)
					}
					pb.Multiply(-1)
					pb.NormalizePositiveCoefficients()
				}
			}

			if pb.K == 1 {
				switch pb.Typ {
				case LE: // check for binary, which is also a clause ( ~l1 \/ ~l2 )
					if len(pb.Entries) == 2 {
						pb.Clauses.AddTaggedClause("Cls", sat.Neg(pb.Entries[0].Literal), sat.Neg(pb.Entries[1].Literal))
						pb.TransTyp = Clause
					} else {
						pb.TransTyp = AMO
					}
				case GE: // its a clause!
					pb.Clauses.AddTaggedClause("Cls", literals...)
					pb.TransTyp = Clause
				case EQ:
					pb.TransTyp = EX1
				}
			} else { //cardinality
				switch pb.Typ {
				case LE, GE, EQ:
					pb.CreateCardinality()
					pb.TransTyp = CARD
				}
			}
		}
	}
	return
}
Exemple #9
0
func TranslateAtMostOne(typ OneTranslationType, tag string, lits []sat.Literal) (trans CardTranslation) {

	var clauses sat.ClauseSet

	switch typ {

	case Naive:
		for i, l := range lits {
			for j := i + 1; j < len(lits); j++ {
				clauses.AddTaggedClause(tag, sat.Neg(l), sat.Neg(lits[j]))
			}
		}

	case Split:

		// a constant that should be exposed,
		// its the cuttoff for the split method of atMostOne

		cutoff := 5

		if len(lits) <= cutoff {
			return TranslateAtMostOne(Naive, tag, lits)
		} else {
			aux := sat.NewAtomP1(sat.Pred("split"), newId())
			trans.Aux = append(trans.Aux, sat.Literal{true, aux})

			for _, l := range lits[:len(lits)/2] {
				clauses.AddTaggedClause(tag, sat.Literal{true, aux}, sat.Neg(l))
			}
			for _, l := range lits[len(lits)/2:] {
				clauses.AddTaggedClause(tag, sat.Literal{false, aux}, sat.Neg(l))
			}

			clauses.AddClauseSet(TranslateAtMostOne(typ, tag, lits[:len(lits)/2]).Clauses)
			clauses.AddClauseSet(TranslateAtMostOne(typ, tag, lits[len(lits)/2:]).Clauses)
		}

	case Count:

		pred := sat.Pred("c")
		counterId := newId()

		auxs := make([]sat.Literal, len(lits))
		for i, _ := range auxs {
			auxs[i] = sat.Literal{true, sat.NewAtomP2(pred, counterId, i)}
		}
		trans.Aux = auxs

		// S_i -> S_{i-1}
		for i := 1; i < len(lits); i++ {
			clauses.AddTaggedClause(tag, auxs[i-1], sat.Neg(auxs[i]))
		}

		// X_i -> S_i
		for i := 0; i < len(lits); i++ {
			clauses.AddTaggedClause(tag, auxs[i], sat.Neg(lits[i]))
		}

		// X_i-1 -> -S_i
		for i := 1; i < len(lits); i++ {
			clauses.AddTaggedClause(tag, sat.Neg(auxs[i]), sat.Neg(lits[i-1]))
		}

		// (S_i-1 /\ -S_i) -> X_i-1
		for i := 1; i <= len(lits); i++ {
			if i != len(lits) {
				clauses.AddTaggedClause(tag, sat.Neg(auxs[i-1]), auxs[i], lits[i-1])
			} else {
				clauses.AddTaggedClause(tag, sat.Neg(auxs[i-1]), lits[i-1])
			}
		}

	case Heule:

		k := 4 // fixed size for the heule encoding

		if len(lits) > k+1 {
			aux := sat.NewAtomP1(sat.Pred("heule"), newId())
			trans.Aux = append(trans.Aux, sat.Literal{true, aux})

			front := make([]sat.Literal, k+1)
			copy(front, lits[:k])
			front[k] = sat.Literal{true, aux}

			trans2 := TranslateAtMostOne(Naive, tag, front)
			clauses.AddClauseSet(trans2.Clauses)

			back := make([]sat.Literal, len(lits)-k+1)
			copy(back, lits[k:])
			back[len(lits)-k] = sat.Literal{false, aux}

			trans2 = TranslateAtMostOne(typ, tag, back)
			trans.Aux = append(trans.Aux, trans2.Aux...)
			clauses.AddClauseSet(trans2.Clauses)

		} else {
			trans2 := TranslateAtMostOne(Naive, tag, lits)
			clauses.AddClauseSet(trans2.Clauses)
		}

	case Log:

		cutoff := 5 //will be a parameter of this encoding
		clauses = buildLogEncoding(sat.Pred("logE"), newId(), cutoff, 0, tag, lits)
	case Sort:
		panic("CNF translation for this type not implemented yet")
	default:
		panic("CNF translation for this type not implemented yet")

	}

	trans.Typ = typ
	trans.Clauses = clauses

	return

}
Exemple #10
0
func TranslateExactlyOne(typ OneTranslationType, tag string, lits []sat.Literal) (trans CardTranslation) {

	var clauses sat.ClauseSet

	switch typ {
	case Heule, Log, Naive, Split:

		trans2 := TranslateAtMostOne(typ, tag, lits)
		trans.Aux = append(trans.Aux, trans2.Aux...)
		clauses.AddClauseSet(trans2.Clauses)
		clauses.AddTaggedClause(tag, lits...)

	case Count:

		pred := sat.Pred("cx")
		counterId := newId()

		auxs := make([]sat.Literal, len(lits))
		for i, _ := range auxs {
			auxs[i] = sat.Literal{true, sat.NewAtomP2(pred, counterId, i)}
		}
		trans.Aux = auxs

		// S_i -> S_{i-1}
		for i := 1; i < len(lits); i++ {
			clauses.AddTaggedClause(tag, auxs[i-1], sat.Neg(auxs[i]))
		}

		// X_i -> S_i
		for i := 0; i < len(lits); i++ {
			clauses.AddTaggedClause(tag, auxs[i], sat.Neg(lits[i]))
		}

		// X_i-1 -> -S_i
		for i := 1; i < len(lits); i++ {
			clauses.AddTaggedClause(tag, sat.Neg(auxs[i]), sat.Neg(lits[i-1]))
		}

		// (S_i-1 /\ -S_i) -> X_i-1
		for i := 1; i <= len(lits); i++ {
			if i != len(lits) {
				clauses.AddTaggedClause(tag, sat.Neg(auxs[i-1]), auxs[i], lits[i-1])
			} else {
				clauses.AddTaggedClause(tag, sat.Neg(auxs[i-1]), lits[i-1])
			}
		}

		clauses.AddTaggedClause(tag, auxs[0])

	case Sort:
		panic("CNF translation for this type not implemented yet")
	default:
		panic("CNF translation for this type not implemented yet")
	}

	trans.Typ = typ
	trans.Clauses = clauses

	return

}
Exemple #11
0
func (pb *Threshold) CategorizeTranslate1() {

	pb.SortDescending()
	// per default all information that can be simplified will be in form of facts
	pb.Simplify()
	pb.TransTyp = Facts
	pb.Translated = true

	if len(pb.Entries) == 0 {
		//glob.D(pb.Id, "was simplified completely")
	} else {
		if b, literals := pb.Cardinality(); b {
			//	glob.D("debug")
			//			pb.Print10()

			if pb.K == int64(len(pb.Entries)-1) {
				switch pb.Typ {
				case LE:
					pb.Normalize(GE, true)
					for i, x := range literals {
						literals[i] = sat.Neg(x)
					}
				case GE:
					for i, x := range literals {
						literals[i] = sat.Neg(x)
					}
					pb.Normalize(LE, true)
				case EQ:
					for i, x := range literals {
						literals[i] = sat.Neg(x)
					}
					pb.Multiply(-1)
					pb.NormalizePositiveCoefficients()
				}
			}

			if pb.K == 1 {
				switch pb.Typ {
				case LE: // AMO
					if len(pb.Entries) == 2 {
						pb.Clauses.AddTaggedClause("Cls", sat.Neg(pb.Entries[0].Literal), sat.Neg(pb.Entries[1].Literal))
						pb.TransTyp = Clause
					} else {
						trans := TranslateAtMostOne(Heule, "H_AMO", literals)
						pb.Clauses.AddClauseSet(trans.Clauses)
						pb.TransTyp = AMO
					}
				case GE: // its a clause!
					pb.Clauses.AddTaggedClause("Cls", literals...)
					pb.TransTyp = Clause
				case EQ: // Ex1
					trans := TranslateExactlyOne(Heule, "H_EX1", literals)
					pb.Clauses.AddClauseSet(trans.Clauses)
					pb.TransTyp = EX1
				}
			} else {
				pb.CreateCardinality()
				pb.TransTyp = CARD
			}

		} else {
			// treat equality as two constraints!
			if pb.Typ == EQ {
				glob.D(pb.Id, " decompose in >= amd <=")
				pbLE := pb.Copy()
				pbLE.Typ = LE
				pbGE := pb.Copy()
				pbGE.Typ = GE
				pbGE.Id = -pb.Id
				pbLE.TranslateComplexThreshold()
				pbGE.TranslateComplexThreshold()
				pb.Clauses.AddClauseSet(pbLE.Clauses)
				pb.Clauses.AddClauseSet(pbGE.Clauses)
			} else {
				pb.TranslateComplexThreshold()
			}
		}
	}
	return
}