Пример #1
0
func (pb *Threshold) TranslateComplexThreshold() {

	glob.A(!pb.Empty(), "No Empty at this point.")
	glob.A(len(pb.Chains) == 0, "should not contain a chain")

	pb.Normalize(LE, true)
	pb.SortDescending()

	var err error
	switch *glob.Complex_flag {
	case "mdd":
		pb.Print10()
		pb.TranslateByMDD()
		if pb.Err != nil {
			panic(err.Error())
		}
		glob.D(pb.Id, " mdd:", pb.Clauses.Size())
	case "sn":
		pb.TranslateBySN()
		if pb.Err != nil {
			panic(err.Error())
		}
		glob.D(pb.Id, " Complex, SN:", pb.Clauses.Size())
	case "hybrid":
		tSN := pb.Copy()
		tMDD := pb.Copy()
		tSN.TranslateBySN()
		tMDD.TranslateByMDD()

		if tSN.Err != nil {
			panic(tSN.Err.Error())
		}

		glob.D(pb.Id, "Complex, SN:", tSN.Clauses.Size(), " mdd:", tMDD.Clauses.Size())

		if tMDD.Err == nil && tMDD.Clauses.Size() < tSN.Clauses.Size() {
			pb.Clauses.AddClauseSet(tMDD.Clauses)
			pb.TransTyp = CMDD
		} else {
			pb.Clauses.AddClauseSet(tSN.Clauses)
			pb.TransTyp = CSN
		}
	default:
		panic("Complex_flag option not available: " + *glob.Complex_flag)
	}

	glob.A(pb.Clauses.Size() > 0, pb.Id, " non-trivial pb should produce some clauses...")

	return
}
Пример #2
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
}
Пример #3
0
// returns the encoding of this PB
func (pb *Threshold) Translate(K_lessOffset int64) sat.ClauseSet {
	glob.A(pb.Positive(), "no negative coefficients beyond this point")

	K := K_lessOffset + pb.Offset
	if pb.SumWeights() <= K {
		glob.D("opt init ignored")
		return sat.ClauseSet{}
	}

	pb_K := pb.Copy() //removes all clauses !
	pb_K.K = K
	pb_K.Typ = LE
	if len(pb_K.Chains) > 0 {
		pb_K.TranslateByMDDChain(pb_K.Chains)
	} else {
		pb_K.CategorizeTranslate1()
	}

	if pb_K.Err != nil { // case MDD construction did go wrong!
		glob.A(false, "Capacity of MDD reached, try to solve by not taking chains into account")
		pb_K := pb.Copy() //removes all clauses !
		pb_K.K = K
		pb_K.Typ = LE
		pb_K.CategorizeTranslate1()
	}
	return pb_K.Clauses
}
Пример #4
0
func TestTranslateAMO2(test *testing.T) {
	glob.D("TestTranslateAMO2")
	*glob.MDD_max_flag = 300000
	*glob.MDD_redundant_flag = false

	results := []int{40, 33, 29}

	for i := 0; i < 3; i++ {

		//fmt.Println()
		pb1 := CreatePB([]int64{2, 2, 3, 4, 4, 5, 2, 1}, 8)
		pb2 := CreatePBOffset(i, []int64{1, 1, 1, 1}, 1)

		//pb1.Print10()
		//pb2.Print10()

		b, literals := pb2.Cardinality()
		amo := TranslateAtMostOne(Count, "c", literals)
		amo.PB = &pb2

		TranslatePBwithAMO(&pb1, amo)
		//t.Clauses.PrintDebug()

		if !b || pb1.Clauses.Size() != results[i] {
			fmt.Println("translation size incorrect", pb1.Clauses.Size(), " should be", results[i])
			//t.Clauses.PrintDebug()
			test.Fail()
		}
	}

}
Пример #5
0
func TestTranslate(test *testing.T) {
	glob.D("TestTranslate")

	pb1 := CreatePB([]int64{1, 1, 1}, 1)
	pb1.CategorizeTranslate1()
	if pb1.TransTyp != AMO {
		pb1.Print10()
		test.Errorf("1: Does not classify atmostOne")
	}

	pb2 := CreatePB([]int64{1, 1, 1}, 1)
	pb2.Typ = GE
	pb2.CategorizeTranslate1()
	if pb2.TransTyp != Clause {
		pb2.Print10()
		test.Errorf("2: Does not classify a clause")
	}

	pb3 := CreatePB([]int64{1, 1, 1}, 1)
	pb3.Typ = EQ
	pb3.CategorizeTranslate1()

	if pb3.TransTyp != EX1 {
		pb3.Print10()
		test.Errorf("3: Does not classify ExactlyOne")
	}

	pb4 := CreatePB([]int64{1, 1, -1}, 0)
	pb4.Typ = EQ
	pb4.CategorizeTranslate1()

	if pb4.TransTyp != EX1 {
		pb4.Print10()
		test.Errorf("4: Does not classify ExactlyOne")
	}

	pb5 := CreatePB([]int64{-3, 3, -3}, 0)
	pb5.Typ = LE
	pb5.CategorizeTranslate1()

	if pb5.TransTyp != Clause { // should be different
		pb5.Print10()
		test.Errorf("5: Does not classify clause", pb5)
	}

	pb6 := CreatePB([]int64{1, 1, 1, 1, 1}, 4)
	pb6.Typ = EQ
	pb6.CategorizeTranslate1()

	if pb6.TransTyp != EX1 {
		test.Errorf("6: Does not classify ExactlyOne", pb6)
	}

}
Пример #6
0
func TestRemoveZeros(test *testing.T) {
	glob.D("TestRemoveZeros")

	pb1 := CreatePB([]int64{1, 2, 3, 0, 321, 0, 0, -123, 0}, 1347)
	c := len(pb1.Entries)
	pb1.RemoveZeros()

	if len(pb1.Entries) != c-4 {
		test.Fail()
	}
}
Пример #7
0
func doChaining(pbs []*Threshold, complOcc map[sat.Literal][]int, simplOcc map[sat.Literal][]int,
	lit2id map[sat.Literal]int, litSets []intsets.Sparse) {

	//2) Prepare Matchings

	checked := make(map[Match]bool, 0)

	//ex_matchings := make(map[int][]Matching, 0)  // simpl_id -> []Matchings
	//currently ex and amo matchings are treated equivalently, the only
	//difference is that ex adds the unit clause of the ladder encoding, thus
	//the rewrite is correct and after UP the first value in the Ex is propagated.
	// TODO: explicitly rewrite and remove smallest value

	amo_matchings := make(map[int][]Matching, 0) // compl_id -> []Matchings

	for lit, list := range complOcc {
		//id2lit[lit2id[lit]] = lit
		for _, c := range list {
			for _, s := range simplOcc[lit] {
				if !checked[Match{c, s}] {
					// of comp c and simpl s there is at least
					checked[Match{c, s}] = true
					// 0 means it has not been checked,
					// as there is at least one intersection
					var inter intsets.Sparse
					inter.Intersection(&litSets[c], &litSets[s])
					if pbs[s].Typ == LE {
						if inter.Len() >= *glob.Len_rewrite_amo_flag {
							amo_matchings[c] = append(amo_matchings[c], Matching{s, &inter})
						}
					} else if pbs[s].Typ == EQ {
						if inter.Len() >= *glob.Len_rewrite_ex_flag {
							amo_matchings[c] = append(amo_matchings[c], Matching{s, &inter})
							//ex_matchings[c] = append(amo_matchings[c], Matching{s, &inter})
						}
					} else {
						glob.A(false, "case not treated")
					}
				}
			}
		}
	}

	glob.D("amo/ex_matchings:", len(amo_matchings))

	//3) amo/ex matchings

	for comp, _ := range pbs {
		if matchings, b := amo_matchings[comp]; b {
			workOnMatching(pbs, comp, matchings, lit2id, litSets)
		}
	}
}
Пример #8
0
func TestSNTranslation(test *testing.T) {
	glob.D("TestSortingNetworkTranslation")

	pb := createIgnasi2()

	pb.TranslateBySN()

	//filename := "test"
	//typ := sorters.Bubble
	//typ := sorters.Pairwise
	//typ := sorters.Bitonic
	//typ := sorters.OddEven

	//Example 1
	//t := createCardinality(4, 15, 5)
	//t := createCardinality(2, 1, 1)
	//t := createCardinality(9, 1, 1)

	//Example 2
	//t := createCardinality(8, 4, 1)
	//t := createCardinality(8,8,2)
	//t := createCardinality(8,16,4)
	//filename := "cardinality_8_16_4"

	//Example 3
	//t := createCardinality(8,12,3)
	//filename := "cardinality_8_12_3"

	//Example 4
	//t := createExample1()
	//filename := "example1"

	//Example 5
	//t := createJapan1(80)
	//filename := "japan1_10"

	//Example 6
	//t := createJapan2(3)
	//filename := "japan2_3"

	//t1 := createIgnasi1()
	//t2 := createIgnasi2()

	//s1 := NewSortingNetwork(t1)
	//s2 := NewSortingNetwork(t2)

	//fmt.Println(t)

	//PrintThresholdTikZ(filename+".tex", []SortingNetwork{s1, s2})

}
Пример #9
0
func (g *Gen) generateIds(cs ClauseSet, inferPrimeVars bool) { // recalculates new sat ids for each atom:
	// assuming full regeneration of Ids
	// might change existing mappings

	g.refresh()

	glob.D("c auxiliary Ids start with", g.nextId)

	for _, c := range cs.list {
		for _, l := range c.Literals {
			g.putAtom(l.A)
		}
	}
}
Пример #10
0
func (pb *Threshold) Evaluate(a sat.Assignment) (r int64) {

	for _, e := range pb.Entries {
		v, b := a[e.Literal.A.Id()]
		glob.DT(!b, "Literal not found in assignment: ", e.Literal.ToTxt())
		if e.Literal.Sign {
			r += int64(v) * e.Weight
		} else {
			r += (1 - int64(v)) * e.Weight
		}
	}
	glob.D("evaluate", r, pb.Offset)

	return r - pb.Offset
}
Пример #11
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()
	}

}
Пример #12
0
func TestMDDChains1(test *testing.T) {
	//glob.Debug_flag = true

	glob.D("TestMDDChains1")

	*glob.MDD_max_flag = 300000
	*glob.MDD_redundant_flag = false

	var t Threshold
	t.Entries = createEntries([]int64{1, 2, 1, 1, 3, 1})
	t.Typ = LE
	t.K = 5
	//t.Print10()

	{ // check
		store := mdd.InitIntervalMdd(len(t.Entries))
		_, _, _, s1 := CreateMDD(&store, t.K, t.Entries)
		//store.Debug(true)
		if s1 != nil {
			test.Fail()
		}
	}

	chain := Chain(t.Literals()) //createLiterals(i, 3)

	//fmt.Println("\n\n Chain on index", i, i+3)

	chains := Chains{chain[0:3], chain[3:6]}
	//chains[0].Print()

	store := mdd.InitIntervalMdd(len(t.Entries))
	_, _, _, s1 := CreateMDDChain(&store, t.K, t.Entries, chains)

	if s1 != nil {
		test.Fail()
	}
	if len(store.Nodes) != 6 {
		store.Debug(true)
		test.Fail()
	}
	//glob.Debug_flag = false
}
Пример #13
0
func TestCleanChain(test *testing.T) {
	glob.D("TestCleanChain")

	pb := CreatePB([]int64{1, 2, 3, 0, 321, 0, 1, -123, 0}, 1347)
	results := []int{3, 3, 2, 0, 3, 0}

	chain := pb.Literals()

	pb.RemoveZeros()

	for i := 0; i < len(chain)-4; i++ {
		c1 := chain[i : i+4]
		c2 := CleanChain(pb.Entries, c1)
		if results[i] != len(c2) {
			fmt.Println(results[i], len(c2))
			test.Fail()
		}
	}

}
Пример #14
0
func TestMDDRedundant(test *testing.T) {
	//glob.Debug_flag = true
	//glob.Debug_flag = false

	glob.D("TestMDDRedundant")
	*glob.MDD_max_flag = 300000
	*glob.MDD_redundant_flag = false

	var t Threshold
	t.Entries = createEntries([]int64{1, 2, 1, 1, 3, 1})
	t.Typ = LE
	t.K = 5

	store := mdd.InitIntervalMdd(len(t.Entries))
	CreateMDD(&store, t.K, t.Entries)

	if store.RemoveRedundants() != 5 {
		test.Fail()
	}
}
Пример #15
0
func TestMDDChains2(test *testing.T) {
	//glob.Debug_flag = true

	glob.D("TestMDDChains")

	*glob.MDD_max_flag = 300000
	*glob.MDD_redundant_flag = false

	var t Threshold
	t.Entries = createEntries([]int64{1, 2, 1, 1, 3, 1, 3, 2, 1, 1, 1})
	t.Typ = LE
	t.K = 10
	//t.Print10()

	{ // check
		store := mdd.InitIntervalMdd(len(t.Entries))
		_, _, _, s1 := CreateMDD(&store, t.K, t.Entries)
		//store.Debug(true)
		if s1 != nil {
			test.Fail()
		}
	}

	chain := Chain(t.Literals()) //createLiterals(i, 3)

	chains := Chains{chain[1:3], chain[5:9]}

	store := mdd.InitIntervalMdd(len(t.Entries))
	_, _, _, s1 := CreateMDDChain(&store, t.K, t.Entries, chains)

	if s1 != nil {
		test.Fail()
	}
	if len(store.Nodes) != 31 {
		store.Debug(true)
		test.Fail()
	}
	//glob.Debug_flag = false
}
Пример #16
0
func TestRewriteExactly3(test *testing.T) {
	glob.D("TestExactly3")

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

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

	//pb1.Print10()
	//pb2.Print10()

	b := PreprocessPBwithExactly(&pb1, &pb2)

	//pb1.Print10()
	//pb1.SortVar()
	//pb1.Print10()
	if !b && len(pb1.Entries) != 4 {
		test.Fail()
	}

}
Пример #17
0
func TestRewriteExactly1(test *testing.T) {
	glob.D("TestExactly1")

	//+2 x1 +2 x2 +3 x3 +4 x4 +1 x5 +1 x6 <= 6 ;
	//+1 x1 +1 x2 +1 x3 +1 x4 = 1 ;

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

	pb2 := CreatePB([]int64{1, 1, 1, 1}, 1)
	pb2.Typ = EQ

	//pb1.Print10()
	//pb2.Print10()

	b := PreprocessPBwithExactly(&pb1, &pb2)
	if !b && len(pb1.Entries) != 4 {
		test.Fail()
	}

	//pb1.Print10()

}
Пример #18
0
func TestTranslateAMO1(test *testing.T) {
	glob.D("TestTranslateAMO1")
	*glob.MDD_max_flag = 300000
	*glob.MDD_redundant_flag = false

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

	//pb1.Print10()
	//pb2.Print10()

	//translate AMO, i.e. pb2
	b, literals := pb2.Cardinality()
	amo := TranslateAtMostOne(Count, "c", literals)
	amo.PB = &pb2

	TranslatePBwithAMO(&pb1, amo)

	if !b || pb1.Clauses.Size() != 13 {
		fmt.Println("translation size incorrect", pb1.Clauses.Size(), "should be:", 13)
		pb1.Clauses.PrintDebug()
		test.Fail()
	}
}
Пример #19
0
func TestRewriteAMO(test *testing.T) {
	glob.D("TestRewriteAMO1")

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

	//pb1.Print10()
	//pb2.Print10()

	//translate AMO, i.e. pb2
	b, literals := pb2.Cardinality()
	amo := TranslateAtMostOne(Count, "count", literals)
	amo.PB = &pb2

	b = PreprocessPBwithAMO(&pb1, amo)

	if !b || len(pb1.Entries) != 5 {
		test.Fail()
	}

	if sumE(pb1) != 6 {
		test.Fail()
	}
}
Пример #20
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
}
Пример #21
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
}
Пример #22
0
func (g *Gen) Solve(cs ClauseSet, opt Optimizer, nextOpt int64, lb int64) (result Result) {

	glob.A(cs.Size() > 0, "Needs to contain at least 1 clause.")

	//generate the reverse mapping

	result_chan := make(chan rawResult)
	timeout := make(chan bool, 1)

	go func() {
		time.Sleep(time.Duration(*glob.Timeout_flag) * time.Second)
		timeout <- true
	}()

	finished := false
	current := cs

	result.Value = math.MaxInt64

	if !opt.Empty() && nextOpt != math.MaxInt64 {
		glob.D("init", nextOpt, "lb", lb)
		opt_clauses := opt.Translate(nextOpt)
		fmt.Println("opt cls", opt_clauses.Size())
		current.AddClauseSet(opt_clauses)
	}
	result.Value = math.MaxInt64

	result.Assignment = make(Assignment, len(g.idMap))

	time_total := time.Now()

	iterations := 0

	for !finished {
		iterations++

		//glob.D("Writing", current.Size(), "clauses")
		fmt.Println("tot cls", current.Size())
		//current.PrintDebug()

		if opt.Empty() {
			glob.D("solving...")
		} else {
			fmt.Printf("i: %v\tcur: %v\t lb: %v\tbest: %v\n", iterations, maxS(nextOpt), lb, maxS(result.Value))
		}
		time_before := time.Now()

		if *glob.Cnf_tmp_flag != "" {
			g.PrintDIMACS(current, false)
		}
		go g.solveProblem(current, result_chan)

		select {
		case r := <-result_chan:
			result.Solved = r.solved
			fmt.Printf("Time :\t%.3f s\n", time.Since(time_before).Seconds())
			if r.solved {
				if r.satisfiable {
					result.Satisfiable = true
					ss := strings.Split(strings.TrimSpace(r.assignment), " ")

					count := 0
					for _, x := range ss {
						x = strings.TrimSpace(x)
						if x == "" {
							continue
						}
						id, err := strconv.Atoi(x)
						if err != nil {
							glob.A(false, err.Error())
						}
						if id != 0 {
							sign := 1
							if id < 0 {
								sign = 0
								id = -id
							}

							atom := g.idMap[id]
							if g.PrimaryVars[atom.Id()] {
								count++
								result.Assignment[atom.Id()] = sign
							}
						}
					}

					glob.A(count == len(result.Assignment), "count != assignment")

					if !opt.Empty() {
						result.Value = opt.Evaluate(result.Assignment)
						g.printAssignment(result.Assignment)
						glob.D("SAT for value =", result.Value)
						finished, nextOpt = nextOptValue(lb, &result)

						if !finished {
							current = cs
							opt_clauses := opt.Translate(nextOpt)
							fmt.Println("opt cls", opt_clauses.Size())
							current.AddClauseSet(opt_clauses)
						} else {
							fmt.Println("OPTIMIUM", result.Value)
						}

					} else {
						fmt.Println("SAT")
						result.M = "SAT"
						finished = true
					}

				} else { //UNSAT
					if !opt.Empty() {
						// update lower bound
						glob.D("UNSAT for opt <=", maxS(nextOpt))

						if nextOpt == math.MaxInt64 {
							result.M = "UNSAT"
							finished = true
						} else {
							lb = nextOpt + 1

							finished, nextOpt = nextOptValue(lb, &result)

							if !finished {
								current = cs
								opt_clauses := opt.Translate(nextOpt)
								fmt.Println("opt cls", opt_clauses.Size())
								current.AddClauseSet(opt_clauses)
							} else {
								fmt.Println("OPTIMUM", result.Value)
							}
						}
					} else {
						finished = true
						result.Optimal = true
						result.M = "UNSAT"
					}
				}
			} else {
				result.Solved = false
				glob.D("Error received nothing solved, check log of solver?")
				result.M = "ERROR"
				finished = true
			}
		case <-timeout:
			fmt.Println("TIMEOUT")
			result.M = "TIMEOUT"
			finished = true
			result.Solved = false
			result.Timeout = true
		}
	}

	close(result_chan)
	close(timeout)

	//	fmt.Printf("cTIME: %.3f s\n", time.Since(time_total).Seconds())
	//	fmt.Printf("%v;%v;%v;%v;%v;%v;%v;%.2f;%v;%v;%v\n", "name", "seed", "Amo_chain", "Amo_reuse", "Rewrite_same", "result.M", "maxS(result.Value)", "time ins", "iterations", "cs.Size()", "current.Size()-cs.Size()")
	//	fmt.Printf("%v;%v;%v;%v;%v;%v;%v;%.2f;%v;%v;%v\n", *glob.Filename_flag, *glob.Seed_flag, *glob.Amo_chain_flag, *glob.Amo_reuse_flag, *glob.Rewrite_same_flag, result.M, maxS(result.Value), time.Since(time_total).Seconds(), iterations, cs.Size(), current.Size()-cs.Size())
	fmt.Printf("%v;%v;%v;%.2f\n", *glob.Filename_flag, result.M, maxS(result.Value), time.Since(time_total).Seconds())

	return
}
Пример #23
0
// TODO : set seed
func (g *Gen) solveProblem(clauses ClauseSet, result chan<- rawResult) {

	var solver *exec.Cmd

	switch *glob.Solver_flag {
	case "minisat":
		//solver = exec.Command("minisat", "-rnd-seed=123")
		//solver = exec.Command("minisat", "-rnd-seed="+strconv.FormatInt(*glob.Seed_flag, 10))
		solver = exec.Command("minisat")
	case "glucose":
		solver = exec.Command("glucose", "-model")
	case "clasp":
		solver = exec.Command("clasp")
	case "lingeling":
		solver = exec.Command("lingeling")
	case "treengeling":
		solver = exec.Command("treengeling")
	case "plingeling":
		solver = exec.Command("plingeling")
	case "dimetheus":
		solver = exec.Command("dimetheus", "-seed="+strconv.FormatInt(*glob.Seed_flag, 10))
	case "cmsat":
		solver = exec.Command("cmsat")
	case "local":
		solver = exec.Command("CCAnr", strconv.FormatInt(*glob.Seed_flag, 10))
	case "microsat":
		solver = exec.Command("microsat")
	default:
		glob.A(false, "Solver not available", *glob.Solver_flag)
	}

	stdin, err := solver.StdinPipe()
	if err != nil {
		panic(err)
	}
	stdout, err := solver.StdoutPipe()
	if err != nil {
		panic(err)
	}
	err = solver.Start()
	if err != nil {
		panic(err)
	}

	var wg sync.WaitGroup
	wg.Add(2)

	go func() {
		time_before := time.Now()
		defer stdin.Close()
		defer wg.Done()
		g.generateIds(clauses, false)
		io.Copy(stdin, bytes.NewReader([]byte(fmt.Sprintf("p cnf %v %v\n", g.nextId, len(clauses.list)))))
		for _, c := range clauses.list {
			io.Copy(stdin, bytes.NewReader(g.toBytes(c)))
		}
		fmt.Printf("Read :\t%.3f s\n", time.Since(time_before).Seconds())
	}()

	var res rawResult
	go func() {
		defer wg.Done()
		r := bufio.NewReader(stdout)
		s, err := r.ReadString('\n')
		//fmt.Print(s)

		for {
			if strings.HasPrefix(s, "v ") {
				res.assignment += s[1:]
			} else if strings.HasPrefix(s, "s ") {
				if strings.Contains(s, "UNSATISFIABLE") {
					res.solved = true
					res.satisfiable = false
				} else if strings.Contains(s, "SATISFIABLE") {
					res.solved = true
					res.satisfiable = true
				} else {
					res.solved = false
					glob.D("whats up? Result of sat solver does not contain proper answer!")
				}
			}
			s, err = r.ReadString('\n')
			//	fmt.Print(s)
			if err == io.EOF {
				break
			}
			if err != nil {
				panic(err.Error())
			}
		}
	}()

	wg.Wait()
	err_tmp := solver.Wait()

	if err_tmp != nil {
		//glob.D("return value:",err_tmp() )
	}

	// TODO: why is this uncommented?
	//if err = solver.Process.Kill(); err != nil {
	//	panic(err.Error())
	//}

	result <- res
}
Пример #24
0
func TestAtMostOne(test *testing.T) {
	glob.D("TestTranslateAtMostOne")
	k := 6

	lits := make([]sat.Literal, k)
	atoms := make(map[string]bool)

	for i, _ := range lits {
		lits[i] = sat.Literal{true, sat.NewAtomP1(sat.Pred("x"), i)}
		atoms[lits[i].A.Id()] = true
	}

	t := TranslateAtMostOne(Naive, "naive", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	t = TranslateAtMostOne(Split, "split", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	//	t = TranslateAtMostOne(Sort, "sorter", lits)
	//	if t.Clauses.Size() == 0 {
	//		test.Fail()
	//	}
	t = TranslateAtMostOne(Heule, "heule", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	t = TranslateAtMostOne(Log, "Log", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}

	//fmt.Println()
	t = TranslateAtMostOne(Count, "counter", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	//t.Clauses.PrintDebug()
	//g := sat.IdGenerator(t.Clauses.Size() * 7)
	//g.Filename = "out.cnf"
	//g.PrimaryVars = atoms
	//g.Solve(t.Clauses)
	//g.PrintSymbolTable("sym.txt")

	//fmt.Println()
	t = TranslateExactlyOne(Naive, "naive", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	t = TranslateExactlyOne(Split, "split", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	t = TranslateExactlyOne(Count, "counter", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	//t = TranslateExactlyOne(Sort, "sorter", lits)
	//if t.Clauses.Size() == 0 {
	//	test.Fail()
	//}
	t = TranslateExactlyOne(Heule, "heule", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
	t = TranslateExactlyOne(Log, "Log", lits)
	if t.Clauses.Size() == 0 {
		test.Fail()
	}
}
Пример #25
0
func CategorizeTranslate2(pbs []*Threshold) {

	//1) Categorize
	simplOcc := make(map[sat.Literal][]int, len(pbs)) // literal to list of simplifiers it occurs in
	complOcc := make(map[sat.Literal][]int, len(pbs)) // literal to list of complex pbs it occurs in
	litSets := make([]intsets.Sparse, len(pbs))       // pb.Id -> intsSet of literalIds

	nextId := 0
	lit2id := make(map[sat.Literal]int, 0) // literal to its id

	for i, pb := range pbs {

		if pb.Empty() {
			glob.D("pb is empty. pb.Id:", pb.Id)
			continue
		}

		pb.Normalize(LE, true)
		pb.SortVar()

		pb.CatSimpl()

		switch pb.TransTyp {
		case UNKNOWN:
			addToCategory(&nextId, pb, complOcc, lit2id, &litSets[i])
		case AMO, EX1:
			//fmt.Println(pb.Id, len(pbs))
			//pb.Print10()
			addToCategory(&nextId, pb, simplOcc, lit2id, &litSets[i])
		default: // already translated
			glob.DT(pb.Clauses.Size() == 0, "Translated pb should contain clauses, special case?", pb.Id)
			pb.Translated = true
		}
	}
	if *glob.Amo_chain_flag || *glob.Ex_chain_flag {
		doChaining(pbs, complOcc, simplOcc, lit2id, litSets)
	}

	for _, pb := range pbs {
		if pb.IsComplexTranslation() {

			sort.Sort(EntriesDescending(pb.Entries[pb.PosAfterChains():]))

			if *glob.Rewrite_same_flag {

				pb.RewriteSameWeights()
				//glob.D("rewrite same weights:", pb.Id, len(pb.Chains))

			}
			//pb.Print10()

			if pb.Typ != OPT && len(pb.Chains) > 0 { //TODO: decide on what to use ...
				pb.TranslateByMDDChain(pb.Chains)
				//pbTMP := pb.Copy()
				//pbTMP.Chains = nil
				//pbTMP.TranslateBySN()
				//pb.Clauses = pbTMP.Clauses
				pb.Translated = true
			}
		}

		if !pb.Translated && pb.Typ != OPT {
			glob.A(len(pb.Chains) == 0, "At this point no chain.", pb)
			//glob.A(pb.Clauses.Size() == 0, pb.Id, pb, "not translation means also that there should not be any clauses.")
			pb.CategorizeTranslate1()
			pb.Translated = true
		}

		if pb.Err != nil {
			panic(pb.Err.Error())
		}
		//pb.Print10()
	}
}
Пример #26
0
// returns list of *pb; first one is optimization statement, possibly empty
func parse(filename string) (pbs []*constraints.Threshold, err error) {

	input, err2 := os.Open(filename)
	defer input.Close()
	if err2 != nil {
		err = errors.New("Please specify correct path to instance. Does not exist")
		return
	}
	scanner := bufio.NewScanner(input)
	buf := make([]byte, 0, 64*1024)
	scanner.Buffer(buf, 1024*1024)

	// 0 : first line, 1 : rest of the lines
	var count int
	state := 1
	t := 0
	pbs = make([]*constraints.Threshold, 0)

	for scanner.Scan() {
		l := strings.Trim(scanner.Text(), " ")
		if l == "" || strings.HasPrefix(l, "%") || strings.HasPrefix(l, "*") {
			continue
		}

		elements := strings.Fields(l)

		if len(elements) == 1 { // quick hack to ignore single element lines (not necessary)
			continue
		}

		switch state {
		case 0: // deprecated: for parsing the "header" of pb files, now parser is flexible
			{
				glob.D(l)
				var b1 error
				count, b1 = strconv.Atoi(elements[4])
				vars, b2 := strconv.Atoi(elements[2])
				if b1 != nil || b2 != nil {
					glob.D("cant convert to threshold:", l)
					panic("bad conversion of numbers")
				}
				glob.D("File PB file with", count, "constraints and", vars, "variables")
				state = 1
			}
		case 1:
			{

				var n int  // number of entries
				var f int  // index of entry
				var o bool //optimization
				var pb constraints.Threshold

				offset_back := 0
				if elements[len(elements)-1] != ";" {
					offset_back = 1
				}

				if elements[0] == "min:" || elements[0] == "Min" {
					o = true
					n = (len(elements) + offset_back - 2) / 2
					f = 1
				} else {
					o = false
					n = (len(elements) + offset_back - 3) / 2
					f = 0
				}

				pb.Entries = make([]constraints.Entry, n)

				for i := f; i < 2*n; i++ {

					weight, b1 := strconv.ParseInt(elements[i], 10, 64)
					i++
					if b1 != nil {
						glob.D("cant convert to threshold:", elements[i], "\nin PB\n", l)
						panic("bad conversion of numbers")
					}
					atom := sat.NewAtomP(sat.Pred(elements[i]))
					pb.Entries[(i-f)/2] = constraints.Entry{sat.Literal{true, atom}, weight}
				}
				// fake empty opt in case it does not exist
				if t == 0 && !o {
					pbs = append(pbs, &constraints.Threshold{})
					t++
				}
				pb.Id = t
				if o {
					pb.Typ = constraints.OPT
					glob.D("Scanned optimization statement")
				} else {
					pb.K, err = strconv.ParseInt(elements[len(elements)-2+offset_back], 10, 64)

					if err != nil {
						glob.A(false, " cant parse threshold, error", err.Error(), pb.K)
					}
					typS := elements[len(elements)-3+offset_back]

					if typS == ">=" {
						pb.Typ = constraints.GE
					} else if typS == "<=" {
						pb.Typ = constraints.LE
					} else if typS == "==" || typS == "=" {
						pb.Typ = constraints.EQ
					} else {
						glob.A(false, "cant convert to threshold, equationtype typS:", typS)
					}
				}

				pbs = append(pbs, &pb)
				t++
				//fmt.Println(pb.Id)
				//pb.Print10()
			}
		}
	}

	glob.A(len(pbs) == t, "Id of constraint must correspond to position")
	glob.D("Scanned", t-1, "PB constraints.")
	if len(pbs) > 0 && !pbs[0].Empty() {
		glob.D("Scanned OPT statement.")
	}
	return
}
Пример #27
0
func main() {
	glob.Init()
	if *glob.Ver {
		fmt.Println(`Bule CNF Grounder: Tag 0.97 Pseudo Booleans
Copyright (C) Data61 and Valentin Mayer-Eichberger
License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>
There is NO WARRANTY, to the extent permitted by law.`)
		return
	}

	if len(flag.Args()) >= 2 {
		fmt.Println("Command line flags not recognized", flag.Args())
		return
	}

	if len(flag.Args()) == 1 {
		*glob.Filename_flag = flag.Args()[0]
	}

	if *glob.Debug_filename != "" {

		var err error
		glob.Debug_file, err = os.Create(*glob.Debug_filename)

		if err != nil {
			panic(err)
		}
		defer glob.Debug_file.Close()
	}

	glob.D("Running Debug Mode...")

	problem := parser.New(*glob.Filename_flag)

	if *glob.Pbo_flag {
		problem.PrintPBO()
		return
	}

	if *glob.Gringo_flag {
		problem.PrintGringo()
		return
	}

	if *glob.Gurobi_flag {
		problem.PrintGurobi()
		return
	}

	pbs := problem.Pbs[1:] // opt is just a pointer to first in pbs.
	opt := problem.Opt

	primaryVars := make(map[string]bool, 0)

	for i, _ := range pbs {
		for _, x := range pbs[i].Entries {
			primaryVars[x.Literal.A.Id()] = true
		}
	}

	var clauses sat.ClauseSet

	// Categorize Version 1 (deprecated)
	switch *glob.Cat_flag {
	case 1:
		{
			for _, pb := range pbs {
				pb.Print10()
				pb.CategorizeTranslate1()
				clauses.AddClauseSet(pb.Clauses)
			}
		}
	case 2:
		{
			constraints.CategorizeTranslate2(pbs)
			for _, pb := range pbs {
				clauses.AddClauseSet(pb.Clauses)
			}
		}
	default:
		panic("Category not implemented")
	}

	if *glob.Dimacs_flag {
		clauses.PrintDebug()
	}

	if *glob.Solve_flag {
		g := sat.IdGenerator(clauses.Size()*7 + 1)
		g.PrimaryVars = primaryVars
		opt.NormalizePositiveCoefficients()
		opt.Offset = opt.K
		glob.A(opt.Positive(), "opt only has positive coefficients")
		g.Solve(clauses, opt, *glob.Opt_bound_flag, -opt.Offset)
		//fmt.Println()
	}
}
Пример #28
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)

}