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)
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)
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
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())
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