Пример #1
0
func doEncoding(clauses sat.ClauseSet) {

	s := sat.IdGenerator(clauses.Size())

	s.PrintDIMACS(clauses, false)

	if *dbg {
		clauses.PrintDebug()
	}

}
Пример #2
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()
	}
}
Пример #3
0
func printSAT(tasks []Task, workers []Worker) {

	pAssign := sat.Pred("assign")
	pWorks := sat.Pred("works")

	sat.SetUp(4, sorters.Pairwise)
	var clauses sat.ClauseSet

	// at least one: simple clause
	for _, t := range tasks {
		lits := make([]sat.Literal, len(t.worker))
		i := 0
		for wId, _ := range t.worker {
			lits[i] = sat.Literal{true, sat.Atom{pAssign, wId, t.id}}
			i++
		}

		clauses.AddClause("al1", lits...)

		clauses.AddClauseSet(sat.CreateCardinality("am1", lits, 1, sorters.AtMost))

	}

	// count number of employees

	for _, w := range workers {
		for _, tId := range w.skills {

			l1 := sat.Literal{false, sat.Atom{pAssign, w.id, tId}}
			l2 := sat.Literal{true, sat.Atom{pWorks, w.id, 0}}

			clauses.AddClause("wrk", l1, l2)
		}
	}

	lits := make([]sat.Literal, len(workers))
	for i, w := range workers {
		lits[i] = sat.Literal{true, sat.Atom{pWorks, w.id, 0}}
	}

	clauses.AddClauseSet(sat.CreateCardinality("cWo", lits, *nWorkers, sorters.AtMost))

	// intersections on the timeline: two ways to do it
	// 1) list all intersecting tasks
	// 2) find maximal cliques in the interval graph, and post for that

	for _, w := range workers {

		ts := make([]Task, len(w.skills))
		for i, s := range w.skills {
			ts[i] = tasks[s]
		}
		sort.Sort(ByStart(ts))

		switch *typeIntersect {
		case "simple":
			for i, t1 := range ts {
				for j := i + 1; j < len(ts); j++ {
					t2 := ts[j]
					if t2.start < t1.end {
						l1 := sat.Literal{false, sat.Atom{pAssign, w.id, t1.id}}
						l2 := sat.Literal{false, sat.Atom{pAssign, w.id, t2.id}}
						clauses.AddClause("isc1", l1, l2)
					}
				}
			}
		case "clique":
			// find the maximal cliques in the interval graph and pose AMO on them

			clique := make([]Task, 0)

			for _, t := range ts {

				sort.Sort(ByEnd(clique))

				//todo: use a priority queue, e.g. heap
				//first one is earliest end time

				if len(clique) > 0 && clique[0].end <= t.start {
					// max clique reached
					//output the maximal clique!

					if len(clique) > 1 {

						lits := make([]sat.Literal, len(clique))

						for i, c := range clique {
							lits[i] = sat.Literal{true, sat.Atom{pAssign, w.id, c.id}}
							fmt.Print(c.id, "(", c.start, ",", c.end, ") ")
						}
						fmt.Println()

						//fmt.Println("clique", w.id, lits)
						clauses.AddClauseSet(sat.CreateCardinality("cli", lits, 1, sorters.AtMost))
					}

					//start removing elements:
					for len(clique) > 0 && clique[0].end <= t.start {
						clique = clique[1:]
					}
				}
				clique = append(clique, t)
			}
			if len(clique) > 1 {

				lits := make([]sat.Literal, len(clique))

				for i, c := range clique {
					lits[i] = sat.Literal{true, sat.Atom{pAssign, w.id, c.id}}
				}

				//fmt.Println("clique", w.id, lits)
				clauses.AddClauseSet(sat.CreateCardinality("cli", lits, 1, sorters.AtMost))
			}

		default:
			panic("Type not implemented")
		}
	}

	g := sat.IdGenerator(len(clauses) * 7)
	g.GenerateIds(clauses)

	//g.Filename = strings.Split(*f, ".")[0] + ".cnf"
	//g.Filename = *out

	if *dbg {
		g.PrintDebug(clauses)
	} else {
		g.PrintClausesDIMACS(clauses)
	}
}
Пример #4
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)

}
Пример #5
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

}
Пример #6
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

}