Esempio n. 1
0
def check_and_model(expr):
    z3str_register(expr)
    z3.z3core.Z3_assert_cnstr(ctx.ctx, expr.as_ast())

    _m = z3.Model(None)
    _ok = z3.z3core.Z3_check_and_get_model(ctx.ctx, ctypes.byref(_m))
    ok = z3.CheckSatResult(_ok)
    if ok == z3.sat:
        m = z3.ModelRef(_m, ctx)
        return (ok, m)
    else:
        return (ok, None)
Esempio n. 2
0
def solve_with_approx(formula, reduction_type, q_type, bit_places, polarity,
                      result_queue):
    """Recursively go through `formula` and approximate it. Check
    satisfiability of the approximated formula. Put the result to
    the `result_queue`.
    """

    # Approximate until maximal bit width is reached
    while (bit_places < (max_bit_width - 2) or
           max_bit_width == 0):

        # Approximate the formula
        approximated_formula = rec_go(formula,
                                      [],
                                      reduction_type,
                                      q_type,
                                      bit_places,
                                      polarity)

        # Solve the approximated formula
        s = z3.Solver()
        s.add(approximated_formula)
        result = s.check()

        # Continue with approximation or return the result
        if q_type == Quantification.UNIVERSAL:
            # Over-approximation of the formula is SAT or unknown
            # Approximation continues
            if (result == z3.CheckSatResult(z3.Z3_L_TRUE) or
                    result == z3.CheckSatResult(z3.Z3_L_UNDEF)):
                # Update reduction type and increase bit width
                (reduction_type, bit_places) = next_approx(reduction_type,
                                                           bit_places)

            # Over-approximation of the formula is UNSAT
            # Original formula is UNSAT
            elif result == z3.CheckSatResult(z3.Z3_L_FALSE):
                result_queue.put(result)
                return

        else:
            # Under-approximation of the formula is SAT
            # Original formula is SAT
            if result == z3.CheckSatResult(z3.Z3_L_TRUE):
                result_queue.put(result)
                return

            # Under-approximation of the formula is UNSAT or unknown
            # Approximation continues
            elif (result == z3.CheckSatResult(z3.Z3_L_FALSE) or
                  result == z3.CheckSatResult(z3.Z3_L_UNDEF)):

                # Update reduction type and increase bit width
                (reduction_type, bit_places) = next_approx(reduction_type,
                                                           bit_places)

    solve_without_approx(formula, result_queue)
Esempio n. 3
0
def sols_v2(smt_sol, x_list, lw_bounds_list, up_bounds_list, count, fnl_sol,
            max_count):
    if (count < max_count):

        if (smt_sol.check() == z3.CheckSatResult(z3.Z3_L_FALSE)):
            return fnl_sol
        else:
            sol = []
            count = count + 1
            smt_sol.check()
            init_model = smt_sol.model()
            if (lw_bounds_list != []):
                for index, x_var, in enumerate(x_list):
                    lw_bound = lw_bounds_list[index]
                    smt_sol.add(x_var < lw_bound)
                return sols_v2(smt_sol, x_list, [], [], count, fnl_sol,
                               max_count)
            elif (up_bounds_list != []):
                for index, x_var, in enumerate(x_list):
                    up_bound = up_bounds_list[index]
                    smt_sol.add(x_var > up_bound)
                return sols_v2(smt_sol, x_list, [], [], count, fnl_sol,
                               max_count)
            else:
                for x_var in x_list:

                    x_val = convert_to_float(init_model[x_var].as_decimal(2))
                    sol.append(x_val)
                    up_bound = x_val * 1.005
                    lw_bound = x_val * 0.995
                    lw_bounds_list.append(lw_bound)
                    up_bounds_list.append(up_bound)
                fnl_sol.append(sol)
                smt_sol_2 = z3.Solver()
                smt_sol_2.add(smt_sol.assertions())
                l1 = sols_v2(smt_sol, x_list, lw_bounds_list, [], count,
                             fnl_sol, max_count)
                l2 = sols_v2(smt_sol_2, x_list, [], up_bounds_list, count,
                             fnl_sol, max_count)
                fnl_l = list(set(map(tuple, l1 + l2)))
                return fnl_l

    else:
        return fnl_sol
Esempio n. 4
0
    def execute(trial=False):
        #http://stackoverflow.com/questions/15736995/how-can-i-quickly-estimate-the-distance-between-two-latitude-longitude-points
        def haversine(lat1, lon1, lat2, lon2):
            """
		    Calculate the great circle distance between two points 
		    on the earth (specified in decimal degrees)
		    """
            # convert decimal degrees to radians
            lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
            # haversine formula
            dlon = lon2 - lon1
            dlat = lat2 - lat1
            a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
            c = 2 * asin(sqrt(a))
            km = 6367 * c
            return km

        startTime = datetime.datetime.now()

        client = dml.pymongo.MongoClient()
        repo = client.repo

        # Connect to mongoDB
        repo.authenticate('mbyim_seanz', 'mbyim_seanz')

        # Constraints----------------------------------------------------------------
        # Kendall Square -- hardcoded location
        company_lat = 42.3629
        company_lng = -71.0901

        #Optimize----------------------------------------------------------------
        res_transit_data = repo.mbyim_seanz.residential_transit.find()

        # get residential/transit data from database
        pulled_res_transit = []
        for row in res_transit_data:
            res_transit_dict = dict(row)

            inner_dict = {}
            parcel_id = res_transit_dict['parcel_id']
            res_transit_subdata = res_transit_dict['res_transit_data']

            inner_dict['parcel_id'] = parcel_id
            inner_dict['res_transit_data'] = res_transit_subdata

            pulled_res_transit.append(inner_dict)

        zipcodes_used = {}
        final_satisfiable_set = []
        # for each zip code region
        for data_point in pulled_res_transit:
            curr_res_zipcode = data_point['res_transit_data']['res_zipcode']

            #loop through unique zipcodes only
            if curr_res_zipcode in zipcodes_used:
                continue

            zipcodes_used[curr_res_zipcode] = 1

            # store to use in z3 optimization
            walk_times = []
            transit_times = []
            res_costs = []

            # loop through all residential properties in this zip code region
            for zip_code_data_point in pulled_res_transit:
                # check if it's in the current zip code
                if zip_code_data_point['res_transit_data'][
                        'res_zipcode'] != curr_res_zipcode:
                    continue

                # otherwise start to get the data
                res_cost = int(zip_code_data_point['res_transit_data']['cost'])
                res_address = zip_code_data_point['res_transit_data'][
                    'res_address']

                # simple initial filter because some of the Boston data was missing or inaccurate
                if res_cost < 10000 or res_address[
                        0] == '0' or res_address == 'NULL':
                    continue

                res_lat = zip_code_data_point['res_transit_data']['res_lat']
                res_lng = zip_code_data_point['res_transit_data']['res_lng']
                closest_transit_lat = zip_code_data_point['res_transit_data'][
                    'nearby_stops'][0]['stop_lat']
                closest_transit_lng = zip_code_data_point['res_transit_data'][
                    'nearby_stops'][0]['stop_lng']

                # Assume a person walks 1 km in 10 minutes on average
                walk_time = int(
                    haversine(res_lat, res_lng, closest_transit_lat,
                              closest_transit_lng)) * 10

                # Assume public transit travels 1 km in 5 minutes on average
                transit_time = int(
                    haversine(closest_transit_lat, closest_transit_lng,
                              company_lat, company_lng)) * 5

                walk_times.append(walk_time)
                transit_times.append(transit_time)
                res_costs.append(res_cost)

            # weights that we are trying to solve for
            w = z3.Real('w')
            t = z3.Real('t')
            r = z3.Real('r')

            opt = z3.Solver()
            opt.add(w > 0, r > 0, t > 0)

            # loop through the residents in the same zip code
            for i in range(len(walk_times)):
                # provide some leeway in terms of constraint satisfaction, explained in README
                opt.add(w * walk_times[i] + t * transit_times[i] +
                        r * res_costs[i] <= 1)
                opt.add(w * walk_times[i] + t * transit_times[i] +
                        r * res_costs[i] > 0.99)

            # check if constraint is satisfiable
            opt_check = opt.check()
            sat = z3.CheckSatResult(z3.Z3_L_TRUE)

            # if it was satisfiable, what were the weights?
            satisfiable_set = {}
            if opt_check == sat:
                model = opt.model()
                # weight_key is w,r,t
                # model[weight_key] is the actual fraction/weight
                for weight_key in model:
                    weight_value = model[weight_key].as_string()

                    # weight_value = float((model[weight_key].as_decimal(30)))
                    satisfiable_set[weight_key.name()] = weight_value

                satisfiable_set["res_zipcode"] = curr_res_zipcode
                satisfiable_set["data_points"] = len(walk_times)

            # only prepare it for the database if it was satisfiable
            if len(satisfiable_set) != 0:
                final_satisfiable_set.append(satisfiable_set)

        # prepare for json
        final_data_string_fixed = json.dumps(final_satisfiable_set)
        final_data_string_fixed.replace("'", '"')

        r = json.loads(final_data_string_fixed)
        s = json.dumps(r, sort_keys=True, indent=2)

        repo.dropCollection("optimization")
        repo.createCollection("optimization")
        repo['mbyim_seanz.optimization'].insert_many(r)
        repo['mbyim_seanz.optimization'].metadata({'complete': True})
        print('finished res transit optimization')
        print(repo['mbyim_seanz.optimization'].metadata())
Esempio n. 5
0
def main():
    parser = argparse.ArgumentParser(description="Solve given formula.")
    parser.add_argument("formula", metavar="formula_file", type=str,
                        help="path to .smt2 formula file")
    parser.add_argument("-r", "--reduction", default="0", type=str,
                        help="determine the reduction type (0/1/s)")
    args = parser.parse_args()

    # Determine the type of reduction
    if args.reduction == "1":
        reduction_type = ReductionType.ONE_EXTENSION
    elif args.reduction == "s":
        reduction_type = ReductionType.SIGN_EXTENSION
    else:
        reduction_type = ReductionType.ZERO_EXTENSION

    # File with .smt2 formula
    formula_file = args.formula

    # Parse SMT2 formula to Z3 format
    formula = z3.parse_smt2_file(formula_file)

    # Parallel run of original and approximated formula
    with multiprocessing.Manager() as manager:
        result_queue = multiprocessing.Queue()

        # ORIGINAL FORMULA: Create process
        p0 = multiprocessing.Process(target=solve_without_approx,
                                     args=(formula, result_queue))

        # APPROXIMATED FORMULA - Over-approximation: Create process
        p1 = multiprocessing.Process(target=solve_with_approx,
                                     args=(formula,
                                           reduction_type,
                                           Quantification.UNIVERSAL,
                                           1,
                                           Polarity.POSITIVE,
                                           result_queue))

        # APPROXIMATED FORMULA - Under-approximation: Create process
        p2 = multiprocessing.Process(target=solve_with_approx,
                                     args=(formula,
                                           reduction_type,
                                           Quantification.EXISTENTIAL,
                                           1,
                                           Polarity.POSITIVE,
                                           result_queue))

        # Start all
        p0.start()
        p1.start()
        p2.start()

        # Get result
        try:
            # Wait at most 60 seconds for a return
            result = result_queue.get(timeout=300)
        except multiprocessing.queues.Empty:
            # If queue is empty, set result to undef
            result = z3.CheckSatResult(z3.Z3_L_UNDEF)

        # Terminate all
        p0.terminate()
        p1.terminate()
        p2.terminate()

    print(result)
    return result