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) }
// 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 }