-
Notifications
You must be signed in to change notification settings - Fork 0
/
l1_balls.py
54 lines (40 loc) · 1.42 KB
/
l1_balls.py
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
import numpy as np
import torch
import torch.nn as nn
from hyperbox import Domain
import utilities as utils
class L1BallFactory(Domain):
def __init__(self, radius):
self.radius = radius
def make_l1_ball(center):
return L1Ball.build_linf_ball(center, self.radius)
class L1Ball(object):
""" Class representing l1 balls """
def __init__(self, center, radius):
self.center = center
self.radius = radius
self.dimension = len(center)
@classmethod
def make_unit_ball(cls, dimension):
""" Makes the unit l1 ball in the correct dimension """
return L1Ball(np.zeros(dimension), 1.0)
def encode_as_gurobi_model(self, squire, key):
model = squire.model
pos_key = key + '_pos'
neg_key = key + '_neg'
# Create namers
key_namer = utils.build_var_namer(key)
pos_namer = utils.build_var_namer(pos_key)
neg_namer = utils.build_var_namer(neg_key)
key_vars, pos_vars, neg_vars = [], [], []
# Add all the variables and constraints
for i in range(self.dimension):
pos_vars.append(model.addVar(lb=0.0, ub=1.0, name=pos_namer(i)))
neg_vars.append(model.addVar(lb=0.0, ub=1.0, name=neg_namer(i)))
key_vars.append(model.addVar(lb=-1.0, ub=1.0, name=key_namer(i)))
model.addConstr(key_vars[-1] == pos_vars[-1] - neg_vars[-1])
model.addConstr(sum(pos_vars) + sum(neg_vars) <= 1.0)
model.update()
for pair in [(key, key_vars), (pos_key, pos_vars), (neg_key, neg_vars)]:
squire.set_vars(*pair)
return