def unconstrained_check(state, ast):
    """
    Attempts to check if an ast is completely unconstrained
    :param state: the state to use
    :param ast: the ast to check
    :return: True if the ast is probably completely unconstrained
    """
    size = ast.size()
    test_val_0 = 0
    test_val_1 = (1 << size) - 1
    test_val_2 = int('1010' * 16, 2) % (1 << size)
    test_val_3 = int('0101' * 16, 2) % (1 << size)
    test_val_4 = int('1001' * 2 + '1010' * 2 + '1011' * 2 + '1100' * 2 + 
        '1101' * 2 + '1110' * 2 + '1110' * 2 + '0001' * 2, 2) % (1 << size)
    if not state.solver.satisfiable(extra_constraints=(ast == test_val_0,)):
        return False
    if not state.solver.satisfiable(extra_constraints=(ast == test_val_1,)):
        return False
    if not state.solver.satisfiable(extra_constraints=(ast == test_val_2,)):
        return False
    if not state.solver.satisfiable(extra_constraints=(ast == test_val_3,)):
        return False
    if not state.solver.satisfiable(extra_constraints=(ast == test_val_4,)):
        return False
    return True
