Пример #1
0
 def test_cse573(self):
     data = [
         'ParentOf(Tom,Jill)',
         '!ParentOf(Frank,Frank) Ancestor(Frank,Frank) !ParentOf(Tom,Jill)'
     ]
     parsed = parser.parse_cse573(data)
     assert_equal(parsed, (3, [[1], [-2, 3, -1]], {
         1: 'ParentOf(Tom,Jill)',
         2: 'ParentOf(Frank,Frank)',
         3: 'Ancestor(Frank,Frank)'
     }))
Пример #2
0
 def test_cse573(self):
     data = ['ParentOf(Tom,Jill)',
             '!ParentOf(Frank,Frank) Ancestor(Frank,Frank) !ParentOf(Tom,Jill)']
     parsed = parser.parse_cse573(data)
     assert_equal(parsed, (3, [[1], [-2, 3, -1]],
                  {1: 'ParentOf(Tom,Jill)', 2: 'ParentOf(Frank,Frank)', 3: 'Ancestor(Frank,Frank)'}))
Пример #3
0
def main():
    global VERBOSE

    # entry point for the program
    np.set_printoptions(linewidth=2000000000)

    clp = argparse.ArgumentParser(description='SAT solver.')
    clp.add_argument('-a',
                     '--algorithm',
                     dest='algo',
                     default='genetic',
                     choices=['genetic', 'ant', 'walksat'],
                     help='select algorithm for solving')
    clp.add_argument('-v',
                     '--verbose',
                     dest='verbose',
                     default=False,
                     action='store_true',
                     help='print stats and status message')
    clp.add_argument('-s',
                     '--seed',
                     dest='seed',
                     type=int,
                     default=42,
                     help='seed for random number generator, 0 means random')
    clp.add_argument('-N',
                     '--number',
                     dest='N',
                     default=None,
                     type=int,
                     help='number of worker processes')
    clp.add_argument('-i',
                     '--max_iterations',
                     dest='max_iterations',
                     default=25000,
                     type=int,
                     help='number of worker processes')
    clp.add_argument('-f',
                     '--factor',
                     dest='f',
                     default=0,
                     type=int,
                     help='number of factored (most-constrained) variables')
    clp.add_argument('-c',
                     '--cse573',
                     dest='cse573',
                     default=False,
                     action='store_true',
                     help='use format for CSE 573')
    clp.add_argument('-np',
                     '--no-preprocessing',
                     dest='no_preprocessing',
                     default=False,
                     action='store_true',
                     help='disable factorization and unit propagation')
    clp.add_argument('infile',
                     nargs='?',
                     type=argparse.FileType('r'),
                     default=sys.stdin)

    args = clp.parse_args()
    VERBOSE = args.verbose

    # parse input file
    if args.cse573:
        num_vars, clauses, mapping = parser.parse_cse573(args.infile)
    else:
        num_vars, clauses = parser.parse(args.infile)

    if args.seed == 0:
        args.seed = random.randint(0, 1e9)

    def print_solution(instance_solution):
        """
        Print the solution. To retrieve the correct solution, preprocessing steps have to be undone.
        """
        if instance_solution is False:
            # unsatisfiability can only be determined during preprocessing
            sys.stdout.write("s UNSATISFIABLE\n")
        elif instance_solution[1] is not None:
            instance, p_solution = instance_solution
            solution = preprocessing.restore_original_solution(
                instance, p_solution, num_vars)
            sol = []
            if args.cse573:
                for i, lit in enumerate(solution):
                    orig_lit = i + 1 if lit else -(i + 1)
                    neg = orig_lit < 0
                    sol.append(('!' if neg else '') + mapping[abs(orig_lit)])
                sys.stdout.write("v " + ' '.join(sol) + '\n')
            else:
                for i, lit in enumerate(solution):
                    sol.append(str(i + 1 if lit else -(i + 1)))
                sys.stdout.write("v " + ' '.join(sol) + ' 0\n')
            sys.stdout.write("s SATISFIABLE\n")
        else:
            sys.stdout.write("s UNKNOWN\n")

    # make clauses sets
    clauses = preprocessing.clause_dupl_elim(clauses)

    if args.no_preprocessing:
        factored_instances = [(num_vars, clauses, [],
                               {v: v
                                for v in range(1, num_vars + 1)})]
    else:
        # pre-process instance and generate factored instances
        factored_instances = preprocessing.factored_instances(
            num_vars, clauses, min(args.f, num_vars))

    # filter unsatisfiable factored instances (detected during preprocessing)
    factored_instances = filter(lambda i: i is not False, factored_instances)

    # find instances solved completely during preprocessing
    solved_instances = filter(lambda i: len(i[1]) == 0, factored_instances)

    # initialize Python random with seed (not used during computation, only for choosing next configuration)
    random.seed(args.seed)

    if len(factored_instances) == 0:
        # if all factored instances are unsatisfiable, then the instance is unsatisfiable
        dprint("Proved unsatisfiable during preprocessing.")
        print_solution(False)
        exit()
    elif len(solved_instances) > 0:
        dprint("Solved during preprocessing.")
        print_solution((solved_instances[0], []))
        exit()

    if args.algo == 'genetic':
        dprint("Selected genetic algorithm.")
        algo = ga.GeneticAlgorithm
    elif args.algo == 'ant':
        dprint("Selected ant colony optimization.")
        algo = aa.AntColonyAlgorithm
    elif args.algo == 'walksat':
        dprint("Selected WalkSAT.")
        algo = ws.WalkSAT
    else:
        print("Argument error: No such algorithm.")

    dprint("Reduced instances:")

    for i in factored_instances:
        dprint(i, " / ", num_vars, "original variables")

    processes = []
    queue = Queue()
    MAX_ITERATIONS = args.max_iterations

    if not args.N:
        args.N = multiprocessing.cpu_count()

    # run profiles
    dprint("Run {} processes (N = {}, {} factored instances)".format(
        max(args.N, len(factored_instances)), args.N, len(factored_instances)))

    # no spawning if only one task
    if max(args.N, len(factored_instances)) == 1:
        instance = factored_instances[0]
        profile = algo.profiles[0]
        config = {
            'VERBOSE': VERBOSE,
            'SEED': args.seed,
            'MAX_ITERATIONS': MAX_ITERATIONS
        }
        config.update(profile)
        dprint("Start", config)
        dprint("Start on same process with config", config)

        a = algo(instance[0], instance[1], config)

        solution = a.run()
        dprint("Solution", str(solution))
        print_solution((instance, solution))
        return

    # run algorithm for every factored instance with every profile
    for instance in factored_instances:
        profile = algo.profiles[0]
        start_process(algo, instance, profile, args.seed, MAX_ITERATIONS,
                      queue, VERBOSE, processes)

    for i in range(args.N - len(factored_instances)):
        profile = random.choice(algo.profiles)
        instance = random.choice(factored_instances)
        start_process(algo, instance, profile, random.randint(1, 10000),
                      MAX_ITERATIONS, queue, VERBOSE, processes)

    # wait for the first process to finish with a solution
    while True:
        solution = queue.get()

        for instance in factored_instances:
            MAX_ITERATIONS = int(MAX_ITERATIONS * 1.75)

            if solution[1] is not None:
                print_solution(solution)

                for process in processes:
                    process.terminate()

                exit()

            else:
                # start another thread with more iterations and different configuration
                profile = random.choice(algo.profiles)
                start_process(algo, instance, profile,
                              random.randint(1, 10000), MAX_ITERATIONS, queue,
                              VERBOSE, processes)
Пример #4
0
def main():
    global VERBOSE

    # entry point for the program
    np.set_printoptions(linewidth=2000000000)

    clp = argparse.ArgumentParser(description='SAT solver.')
    clp.add_argument('-a', '--algorithm', dest='algo',
                     default='genetic', choices=['genetic', 'ant', 'walksat'],
                     help='select algorithm for solving')
    clp.add_argument('-v', '--verbose', dest='verbose',
                     default=False, action='store_true',
                     help='print stats and status message')
    clp.add_argument('-s', '--seed', dest='seed', type=int,
                     default=42,
                     help='seed for random number generator, 0 means random')
    clp.add_argument('-N', '--number', dest='N',
                     default=None, type=int,
                     help='number of worker processes')
    clp.add_argument('-i', '--max_iterations', dest='max_iterations',
                     default=25000, type=int,
                     help='number of worker processes')
    clp.add_argument('-f', '--factor', dest='f',
                     default=0, type=int,
                     help='number of factored (most-constrained) variables')
    clp.add_argument('-c', '--cse573', dest='cse573',
                     default=False, action='store_true',
                     help='use format for CSE 573')
    clp.add_argument('-np', '--no-preprocessing', dest='no_preprocessing',
                     default=False, action='store_true',
                     help='disable factorization and unit propagation')
    clp.add_argument('infile', nargs='?', type=argparse.FileType('r'),
                     default=sys.stdin)

    args = clp.parse_args()
    VERBOSE = args.verbose

    # parse input file
    if args.cse573:
        num_vars, clauses, mapping = parser.parse_cse573(args.infile)
    else:
        num_vars, clauses = parser.parse(args.infile)

    if args.seed == 0:
        args.seed = random.randint(0, 1e9)

    def print_solution(instance_solution):
        """
        Print the solution. To retrieve the correct solution, preprocessing steps have to be undone.
        """
        if instance_solution is False:
            # unsatisfiability can only be determined during preprocessing
            sys.stdout.write("s UNSATISFIABLE\n")
        elif instance_solution[1] is not None:
            instance, p_solution = instance_solution
            solution = preprocessing.restore_original_solution(instance, p_solution, num_vars)
            sol = []
            if args.cse573:
                for i, lit in enumerate(solution):
                    orig_lit = i + 1 if lit else -(i + 1)
                    neg = orig_lit < 0
                    sol.append(('!' if neg else '') + mapping[abs(orig_lit)])
                sys.stdout.write("v " + ' '.join(sol) + '\n')
            else:
                for i, lit in enumerate(solution):
                    sol.append(str(i + 1 if lit else -(i + 1)))
                sys.stdout.write("v " + ' '.join(sol) + ' 0\n')
            sys.stdout.write("s SATISFIABLE\n")
        else:
            sys.stdout.write("s UNKNOWN\n")

    # make clauses sets
    clauses = preprocessing.clause_dupl_elim(clauses)

    if args.no_preprocessing:
        factored_instances = [(num_vars, clauses, [], {v: v for v in range(1, num_vars + 1)})]
    else:
        # pre-process instance and generate factored instances
        factored_instances = preprocessing.factored_instances(num_vars, clauses, min(args.f, num_vars))

    # filter unsatisfiable factored instances (detected during preprocessing)
    factored_instances = filter(lambda i: i is not False, factored_instances)

    # find instances solved completely during preprocessing
    solved_instances = filter(lambda i: len(i[1]) == 0, factored_instances)

    # initialize Python random with seed (not used during computation, only for choosing next configuration)
    random.seed(args.seed)

    if len(factored_instances) == 0:
        # if all factored instances are unsatisfiable, then the instance is unsatisfiable
        dprint("Proved unsatisfiable during preprocessing.")
        print_solution(False)
        exit()
    elif len(solved_instances) > 0:
        dprint("Solved during preprocessing.")
        print_solution((solved_instances[0], []))
        exit()

    if args.algo == 'genetic':
        dprint("Selected genetic algorithm.")
        algo = ga.GeneticAlgorithm
    elif args.algo == 'ant':
        dprint("Selected ant colony optimization.")
        algo = aa.AntColonyAlgorithm
    elif args.algo == 'walksat':
        dprint("Selected WalkSAT.")
        algo = ws.WalkSAT
    else:
        print("Argument error: No such algorithm.")

    dprint("Reduced instances:")

    for i in factored_instances:
        dprint(i, " / ", num_vars, "original variables")

    processes = []
    queue = Queue()
    MAX_ITERATIONS = args.max_iterations

    if not args.N:
        args.N = multiprocessing.cpu_count()

    # run profiles
    dprint("Run {} processes (N = {}, {} factored instances)".format(max(args.N, len(factored_instances)), args.N, len(factored_instances)))

    # no spawning if only one task
    if max(args.N, len(factored_instances)) == 1:
        instance = factored_instances[0]
        profile = algo.profiles[0]
        config = {
            'VERBOSE': VERBOSE,
            'SEED': args.seed,
            'MAX_ITERATIONS': MAX_ITERATIONS
        }
        config.update(profile)
        dprint("Start", config)
        dprint("Start on same process with config", config)

        a = algo(instance[0], instance[1], config)

        solution = a.run()
        dprint("Solution", str(solution))
        print_solution((instance, solution))
        return

    # run algorithm for every factored instance with every profile
    for instance in factored_instances:
        profile = algo.profiles[0]
        start_process(algo, instance, profile, args.seed, MAX_ITERATIONS, queue, VERBOSE, processes)

    for i in range(args.N - len(factored_instances)):
        profile = random.choice(algo.profiles)
        instance = random.choice(factored_instances)
        start_process(algo, instance, profile, random.randint(1, 10000), MAX_ITERATIONS, queue, VERBOSE, processes)

    # wait for the first process to finish with a solution
    while True:
        solution = queue.get()

        for instance in factored_instances:
            MAX_ITERATIONS = int(MAX_ITERATIONS * 1.75)

            if solution[1] is not None:
                print_solution(solution)

                for process in processes:
                    process.terminate()

                exit()

            else:
                # start another thread with more iterations and different configuration
                profile = random.choice(algo.profiles)
                start_process(algo, instance, profile, random.randint(1, 10000), MAX_ITERATIONS, queue, VERBOSE, processes)