예제 #1
0
파일: convert.go 프로젝트: vale1410/bule
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)

}
예제 #2
0
파일: pbo.go 프로젝트: vale1410/bule
// 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
}