def test_smoothjoin_alpha(self): a = AbsInterval(torch.tensor([0.0, 1.0]), torch.tensor([5.0, 6.0]), 0.6) b = AbsInterval(torch.tensor([-2.0, 0.0]), torch.tensor([-1.0, 1.0]), 0.4) res = AbsInterval.smooth_join([a, b]) print(res) self.assertEqual(res.alpha, 1.0)
def test_simple_ite(self): # x in [-1, 5] x = AbsInterval(torch.tensor([-1.0]), torch.tensor([5.0]), 1.0) # if x > c # then x = 2x # else x = -0.5 program = IfThenElse( IntervalBool(torch.tensor([1.0]), torch.tensor([0.0])), AssignStatement(torch.tensor([[2.0]]), torch.tensor([0.0])), AssignStatement(torch.tensor([[0.0]]), torch.tensor([-0.5]))) # x in [-0.5, 10] self.assertEqual( program.propagate(x, t_os), AbsInterval(torch.tensor([-0.5]), torch.tensor([10.0]), 1.0))
def test_ite_alwaystrue(self): # x in [-1, 5] x = AbsInterval(torch.tensor([-1.0]), torch.tensor([5.0]), 1.0) # if 0x + 3 >= 0 # then x = 2x # else x = -5 program = IfThenElse( IntervalBool(torch.tensor([0.0]), torch.tensor([3.0])), AssignStatement(torch.tensor([[2.0]]), torch.tensor([0.0])), AssignStatement(torch.tensor([[0.0]]), torch.tensor([-5.0]))) # x in [-2, 10] self.assertEqual( program.propagate(x, t_os), AbsInterval(torch.tensor([-2.0]), torch.tensor([10.0]), 1.0))
def repl(program): inptL = torch.tensor([-1.0, -1.0]) inptH = torch.tensor([1.0, 1.0]) beta = 1.0 while (True): cmd = input("> ") cmds = cmd.split(" ") if len(cmds) == 3 and cmds[1] == '=': if cmds[0] == 'xL': inptL[0] = float(cmds[2]) elif cmds[0] == 'xH': inptH[0] = float(cmds[2]) elif cmds[0] == 'cL': inptL[1] = float(cmds[2]) elif cmds[0] == 'cH': inptH[1] = float(cmds[2]) elif cmds[0] == 'beta': beta = float(cmds[2]) else: print("Unknown var") elif cmd == 'run': interval = AbsInterval(inptL, inptH, 1.0) optim_state = OptimizerState(beta=beta, lambda_const=1 / 2, smooth=True) print("Output:") print(program.propagate(interval, optim_state)) else: print("Usage:") print("\tx = v\t x is a name of a variable, v is a value") print("Variables are xL, xH, cL, cH, beta") print("\trun\t runs the program")
def propagate(self, A, optim_state): Lval, Hval = self.E.evaluate(A) #print("L:%s, H:%s" % (str(Lval), str(Hval))) L = A.L.clone() H = A.H.clone() L[self.i] = Lval H[self.i] = Hval return AbsInterval(L, H, A.alpha)
def test_size_decreases_with_alpha(self): last_width = torch.tensor([0.0, 0.0]) for a in np.arange(0.01, 1.5, 0.02): # Keep one alpha 1.0, increase the other v1 = AbsInterval(torch.tensor([2.0, 1.0]), torch.tensor([4.0, 3.0]), 1.0) v2 = AbsInterval(torch.tensor([-1.0, 0.0]), torch.tensor([5.0, 4.0]), a) joined = AbsInterval.smooth_join([v1, v2]) hard_joined = v1.join(v2) # Our interval should get bigger at all iterations self.assertTrue((joined.H - joined.L >= last_width).all()) # Our interval should be inside a hard join self.assertTrue((joined.L >= hard_joined.L).all()) self.assertTrue((joined.H <= hard_joined.H).all()) # Our interval should be bigger than the interval with alpha=1.0 self.assertTrue((joined.H >= v1.H).all()) self.assertTrue((joined.L <= v1.L).all()) last_width = joined.H -joined.L
def test_ite_alwaysfalse(self): # x in [-5, 5] x = AbsInterval(torch.tensor([-5.0]), torch.tensor([5.0]), 1.0) # if 2x - 11 >= 0 # then x = 2x # else x = -5 program = IfThenElse( IntervalBool(torch.tensor([2.0]), torch.tensor([-11.0])), AssignStatement(torch.tensor([[2.0]]), torch.tensor([0.0])), AssignStatement(torch.tensor([[0.0]]), torch.tensor([-5.0]))) # x in [-5, -5] self.assertEqual( program.propagate(x, t_os), AbsInterval(torch.tensor([-5.0]), torch.tensor([-5.0]), 1.0)) # Discontinuity exhibit 1: as input bound increases by 1, output jumps by 17 # x in [-5, 6] x = AbsInterval(torch.tensor([-5.0]), torch.tensor([6.0]), 1.0) # x in [-5, 12] self.assertEqual( program.propagate(x, t_os), AbsInterval(torch.tensor([-5.0]), torch.tensor([12.0]), 1.0))
def closure(): optimizer.zero_grad() optim_state.loss = torch.tensor([0.0], requires_grad=True) inferred_xL = torch.cat((xL, inferred_paramL), 0) inferred_xH = torch.cat((xH, inferred_paramH), 0) interval = AbsInterval(inferred_xL, inferred_xH, 1.0) #print("in: %s" % (str(interval))) y = program.propagate(interval, optim_state) loss = optim_state.loss loss.backward() print("b: %f, Loss: %s,\n in: %s, \n out: %s" % (beta, str(loss.item()), str(interval), str(y))) return loss
def test_ite_bad_ex(self): val = AbsInterval(torch.tensor([-10.0, 0.0]), torch.tensor([1.0, -0.0001])) program = StatementBlock([ IfThenElse( IntervalBool(torch.tensor([0.0, 1.0]), torch.tensor([0.0, 0.0])), AssignStatement(torch.tensor([[2.0, 1.0], [0.0, 1.0]]), torch.tensor([0.0, 0.0])), AssignStatement(torch.tensor([[0.0, 0.0], [0.0, 1.0]]), torch.tensor([700.0, 0.0]))), ReturnStatement(torch.tensor([1.0, 0.0]), torch.tensor([0.0, 0.0])) ])
def create_interval(inferred_param, xL, xH): inferred_paramL, inferred_paramH = toWZ(inferred_param) inferred_paramL, inferred_paramH = torch.tensor(inferred_paramL).type( torch.FloatTensor), torch.tensor(inferred_paramH).type( torch.FloatTensor) inferred_paramL, inferred_paramH = torch.min( inferred_paramL, inferred_paramH), torch.max(inferred_paramL, inferred_paramH) optim_state.loss = torch.tensor([0.0]) inferred_xL = torch.cat((xL, inferred_paramL), 0) inferred_xH = torch.cat((xH, inferred_paramH), 0) return AbsInterval(inferred_xL, inferred_xH, 1.0)
def test_simple_ite_full(self): x1 = AbsInterval(torch.tensor([-10.0, 0.5]), torch.tensor([1.0, 0.5]), 1.0) x2 = AbsInterval(torch.tensor([-10.0, -0.5]), torch.tensor([1.0, -0.5]), 1.0) program = StatementBlock([ IfThenElse( IntervalBool(torch.tensor([0.0, 1.0]), torch.tensor([0.0, 0.0])), AssignStatement(torch.tensor([[2.0, -1.0], [0.0, 1.0]]), torch.tensor([0.0, 0.0])), AssignStatement(torch.tensor([[0.0, 0.0], [0.0, 1.0]]), torch.tensor([700.0, 0.0]))), ReturnStatement(torch.tensor([1.0, 0.0]), torch.tensor([0.0, 0.0])) ]) self.assertEqual( program.propagate(x1, t_os), AbsInterval(torch.tensor([-20.5, 0.5]), torch.tensor([1.5, 0.5]), 1.0)) self.assertEqual( program.propagate(x2, t_os), AbsInterval(torch.tensor([700.0, -0.5]), torch.tensor([700.0, -0.5]), 1.0))
def propagate(self, A, optim_state): L, H = self.expr.evaluate(A) Ap = AbsInterval(L, H, A.alpha) optim_state.add_loss(Ap.signed_volume()) return Ap
def test_meet_div0_true(self): # [1, 5] meet (0x + 1 > 0) -> [1, 5] val = AbsInterval(torch.tensor([1.0]), torch.tensor([5.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([0.0]), torch.tensor([1.0])), t_os), AbsInterval(torch.tensor([1.0]), torch.tensor([5.0]), 1.0))
def test_meet_div0_false(self): # [1, 5] meet (0x - 1 > 0) -> empty val = AbsInterval(torch.tensor([1.0]), torch.tensor([5.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([0.0]), torch.tensor([-1.0])), t_os), AbsInterval(torch.tensor([float('inf')]), torch.tensor([float('-inf')]), 0.0)) # ([-1, 5], [1, 3]) meet 0x1 >= 0 and 0x2 - 1 >= 0 => EMPTY val = AbsInterval(torch.tensor([-1.0, 1.0]), torch.tensor([5.0, 3.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([0.0, 0.0]), torch.tensor([0.0, -1.0])), t_os), AbsInterval(torch.tensor([float('inf'), float('inf')]), torch.tensor([float('-inf'), float('-inf')]), 0.0)) # ([-1, 5], [1, 3]) meet 0x1 >= 0 and 0x2 + 1 >= 0 => ([-1, 5], [1, 3]) val = AbsInterval(torch.tensor([-1.0, 1.0]), torch.tensor([5.0, 3.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([0.0, 0.0]), torch.tensor([0.0, 1.0])), t_os), val)
def test_meet_prog(self): x1 = AbsInterval(torch.tensor([-10.0, 0.5]), torch.tensor([1.0, 0.5]), 1.0) x2 = AbsInterval(torch.tensor([-10.0, -0.5]), torch.tensor([1.0, -0.5]), 1.0) x3 = AbsInterval(torch.tensor([-10.0, -0.5]), torch.tensor([1.0, 0.5]), 1.0) b = IntervalBool(torch.tensor([0.0, 1.0]), torch.tensor([0.0, 0.0])) self.assertEqual(x1.meet(b, t_os), x1) self.assertEqual(x2.meet(b, t_os), AbsInterval(torch.tensor([float('inf'), float('inf')]), torch.tensor([float('-inf'), float('-inf')]), 1.0)) self.assertEqual(x3.meet(b, t_os), AbsInterval(torch.tensor([-10.0, 0.0]), torch.tensor([1.0, 0.5]), 1.0))
def test_meet_basic(self): # [-1, 5] meet x > 0 => [0, 5] val = AbsInterval(torch.tensor([-1.0]), torch.tensor([5.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([1.0]), torch.tensor([0.0])), t_os), AbsInterval(torch.tensor([0.0]), torch.tensor([5.0]), 1.0)) # [-1, 5] meet x - 3 > 0 => [3, 5] val = AbsInterval(torch.tensor([-1.0]), torch.tensor([5.0]), 1.0) out = val.meet(IntervalBool(torch.tensor([1.0]), torch.tensor([-3.0])), t_os) self.assertEqual(out.L, torch.tensor([3.0])) self.assertEqual(out.H, torch.tensor([5.0])) # [-5, 3] meet 2x + 3 > 0 => [3, 5] val = AbsInterval(torch.tensor([-5.0]), torch.tensor([3.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([2.0]), torch.tensor([3.0])), t_os), AbsInterval(torch.tensor([-1.5]), torch.tensor([3.0]), 1.0)) # ([-1, 5], [1, 3]) meet x1 > 0 and x2 < 0 => ([0, 5], [inf, -inf]) val = AbsInterval(torch.tensor([-1.0, 1.0]), torch.tensor([5.0, 3.0]), 1.0) self.assertEqual(val.meet(IntervalBool(torch.tensor([1.0, -1.0]), torch.tensor([0.0, 0.0])), t_os), AbsInterval(torch.tensor([float('inf'), float('inf')]), torch.tensor([float('-inf'), float('-inf')]), 0.0))
def test_smooth_join_basic(self): v1 = AbsInterval(torch.tensor([-1.0, 1.0, 1.0]), torch.tensor([5.0, 3.0, 3.0]), 1.0) v2 = AbsInterval(torch.tensor([-1.0, 1.0, 1.0]), torch.tensor([5.0, 3.0, 3.0]), 1.0) self.assertEqual(AbsInterval.smooth_join([v1, v2]), AbsInterval(torch.tensor([-1.0, 1.0, 1.0]), torch.tensor([5.0, 3.0, 3.0]), 1.0))