-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathverification_utils.py
More file actions
136 lines (86 loc) · 3.92 KB
/
verification_utils.py
File metadata and controls
136 lines (86 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import numpy as np
import numpy.polynomial.chebyshev as cb
LARGE_NUMBER = 1e8
IMAGINARY_PART_CUTOFF = 1e-8
def get_offending_locs_by_grid(coeffs, verification_grid_size, multiplier = 1e-3):
(q_plus_one, N) = coeffs.shape
grid = np.cos(np.linspace(0, np.pi, verification_grid_size))
chebys_on_grid = np.zeros((verification_grid_size, N))
chebys_on_grid[:,0] = 1
chebys_on_grid[:,1] = grid
for i in range(2, N):
chebys_on_grid[:,i] = 2 * (grid * chebys_on_grid[:, i-1]) - chebys_on_grid[:, i-2]
min_evals = []
for t in range(1, q_plus_one-1):
evals_on_grid = chebys_on_grid @ coeffs[t,:]
min_evals += [np.min(evals_on_grid)]
offending_locs = []
for t in range(1, q_plus_one-1):
evals_on_grid = chebys_on_grid @ coeffs[t,:]
threshold = min_evals[t-1] * multiplier
current_offending_idx = np.where(evals_on_grid < threshold)[0]
offending_locs += [grid[current_offending_idx]]
return (np.min(min_evals), offending_locs)
def print_grid_sizes_for_different_cutoffs(positivity_constraints, cutoff):
cutoff = cutoff * 1e3
for _ in range(7):
idxx = get_relevant_constr_idx_for_cutoff(positivity_constraints, cutoff)
lens = []
for idx in idxx:
lens += [len(idx)]
print(cutoff, lens)
cutoff = cutoff / 10
def get_relevant_locs(positivity_grids, positivity_constraints, cutoff):
print_grid_sizes_for_different_cutoffs(positivity_constraints, cutoff)
idxx = get_relevant_constr_idx_for_cutoff(positivity_constraints, cutoff)
locs = []
for (idx, grid) in zip(idxx, positivity_grids):
locs += [grid[idx]]
return locs
def get_relevant_constr_idx_for_cutoff(positivity_constraints, dual_val_cutoff):
relevant_constraint_idx = []
for constraint_vec in positivity_constraints:
relevant_constraint_idx += [list(np.argwhere(constraint_vec.dual_value > dual_val_cutoff).flatten())]
return relevant_constraint_idx
def get_combined_dual_val_of_grid_idx(constraints, idxx):
res = 0
for (constraint_vec, idx) in zip(constraints, idxx):
res += np.sum(constraint_vec.dual_value[idx])
return res
def merge_grids(lefts, rights):
merged_grids = []
for (l, r) in zip(lefts, rights):
merged_grids += [np.array(list(l) + list(r))]
return merged_grids
def prune(grid, round = 5):
return list(np.unique(np.round(grid, round)))
def cheb_extrema(poly_coeffs):
deriv = cb.chebder(poly_coeffs)
deriv_roots = cb.chebroots(deriv)
return deriv_roots
def cheb_points_below_cutoff(poly_coeffs, cutoff=1e-10):
extrema = cheb_extrema(poly_coeffs)
r_real = extrema.real[np.abs(extrema.imag) < IMAGINARY_PART_CUTOFF]
r_less = r_real[r_real < 1.0]
relevant_extrema = np.concatenate((np.array([-1]), r_less[r_less > -1.0], np.array([1])))
vals_at_relevant_extrema = cb.chebval(relevant_extrema, poly_coeffs)
violating_inds = (vals_at_relevant_extrema < -cutoff)
return (relevant_extrema[violating_inds], vals_at_relevant_extrema[violating_inds])
# Returns a boolean for whether chebyshev polynomial p is positive in the interval [-1, 1]
def cheb_is_positive(poly_coeffs, cutoff = 1e-10):
(extrema_locs, _) = cheb_points_below_cutoff(poly_coeffs, cutoff)
return (len(extrema_locs) == 0)
def get_offending_locs_by_derivative(coeffs, cutoff = 1e-10):
(q_plus_one, N) = coeffs.shape
offending_locs = []
min_evals = []
vals_at_offending_locs = []
for t in range(q_plus_one):
(extrema_locs, vals_at_extrema) = cheb_points_below_cutoff(coeffs[t, :], cutoff)
offending_locs += [extrema_locs]
vals_at_offending_locs += [vals_at_extrema]
if len(vals_at_extrema) != 0:
min_evals += [np.min(vals_at_extrema)]
else:
min_evals += [LARGE_NUMBER]
return (np.min(min_evals), offending_locs, vals_at_offending_locs)