def test_apply_constraints_multi_output(self): # nonnegative objective, one constraint tkwargs = {"device": self.device} for dtype in (torch.float, torch.double): tkwargs["dtype"] = dtype samples = torch.rand(3, 2, **tkwargs) obj = samples.clone() obj = apply_constraints(obj=obj, constraints=[zeros_f], samples=samples, infeasible_cost=0.0) self.assertTrue(torch.equal(obj, samples * 0.5)) # nonnegative objective, two constraint obj = samples.clone() obj = apply_constraints( obj=obj, constraints=[zeros_f, zeros_f], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj, samples * 0.5 * 0.5)) # negative objective, one constraint, infeasible_cost obj = samples.clone().clamp_min(-1.0) obj = apply_constraints(obj=obj, constraints=[zeros_f], samples=samples, infeasible_cost=2.0) self.assertTrue( torch.allclose(obj, samples.clamp_min(-1.0) * 0.5 - 1.0)) # nonnegative objective, one constraint, eta = 0 obj = samples with self.assertRaises(ValueError): apply_constraints( obj=obj, constraints=[zeros_f], samples=samples, infeasible_cost=0.0, eta=0.0, )
def test_apply_constraints(self): # nonnegative objective, one constraint samples = torch.randn(1) obj = ones_f(samples) obj = apply_constraints(obj=obj, constraints=[zeros_f], samples=samples, infeasible_cost=0.0) self.assertTrue(torch.equal(obj, ones_f(samples) * 0.5)) # nonnegative objective, two constraint samples = torch.randn(1) obj = ones_f(samples) obj = apply_constraints( obj=obj, constraints=[zeros_f, zeros_f], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj, ones_f(samples) * 0.5 * 0.5)) # negative objective, one constraint, infeasible_cost samples = torch.randn(1) obj = minus_one_f(samples) obj = apply_constraints(obj=obj, constraints=[zeros_f], samples=samples, infeasible_cost=2.0) self.assertTrue(torch.equal(obj, ones_f(samples) * 0.5 - 2.0)) # nonnegative objective, one constraint, eta = 0 samples = torch.randn(1) obj = ones_f(samples) with self.assertRaises(ValueError): apply_constraints( obj=obj, constraints=[zeros_f], samples=samples, infeasible_cost=0.0, eta=0.0, )
def forward(self, samples: Tensor) -> Tensor: r"""Evaluate the feasibility-weighted objective on the samples. Args: samples: A `sample_shape x batch_shape x q x m`-dim Tensors of samples from a model posterior. Returns: A `sample_shape x batch_shape x q`-dim Tensor of objective values weighted by feasibility (assuming maximization). """ obj = super().forward(samples=samples) return apply_constraints( obj=obj, constraints=self.constraints, samples=samples, infeasible_cost=self.infeasible_cost, eta=self.eta, )
def forward(self, samples: Tensor) -> Tensor: r"""Evaluate the feasibility-weighted objective on the samples. Args: samples: A `sample_shape x batch_shape x q x o`-dim Tensors of samples from a model posterior. Returns: A `sample_shape x batch_shape x q`-dim Tensor of objective values weighted by feasibility (assuming maximization). """ obj = super().forward(samples=samples) return apply_constraints( obj=obj, constraints=self.constraints, samples=samples, infeasible_cost=self.infeasible_cost, eta=self.eta, )
def forward(self, samples: Tensor, X: Optional[Tensor] = None) -> Tensor: r"""Evaluate the feasibility-weighted objective on the samples. Args: samples: A `sample_shape x batch_shape x q x m`-dim Tensors of samples from a model posterior. X: A `batch_shape x q x d`-dim tensor of inputs. Relevant only if the objective depends on the inputs explicitly. Returns: A `sample_shape x batch_shape x q`-dim Tensor of objective values weighted by feasibility (assuming maximization). """ obj = super().forward(samples=samples) return apply_constraints( obj=obj, constraints=self.constraints, samples=samples, infeasible_cost=self.infeasible_cost, eta=self.eta, )
def test_constrained_mc_objective(self): for dtype in (torch.float, torch.double): # one feasible constraint obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con] ) samples = torch.randn(1, device=self.device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one infeasible constraint obj = ConstrainedMCObjective( objective=generic_obj, constraints=[infeasible_con] ) samples = torch.randn(2, device=self.device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[infeasible_con], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one feasible, one infeasible obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con, infeasible_con] ) samples = torch.randn(2, 1, device=self.device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con, infeasible_con], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one feasible, one infeasible, infeasible_cost obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con, infeasible_con], infeasible_cost=5.0, ) samples = torch.randn(3, 2, device=self.device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con, infeasible_con], samples=samples, infeasible_cost=5.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one feasible, one infeasible, infeasible_cost, higher dimension obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con, infeasible_con], infeasible_cost=5.0, ) samples = torch.randn(4, 3, 2, device=self.device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con, infeasible_con], samples=samples, infeasible_cost=5.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj))
def test_constrained_mc_objective(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): # one feasible constraint obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con] ) samples = torch.randn(1, device=device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one infeasible constraint obj = ConstrainedMCObjective( objective=generic_obj, constraints=[infeasible_con] ) samples = torch.randn(2, device=device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[infeasible_con], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one feasible, one infeasible obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con, infeasible_con] ) samples = torch.randn(2, 1, device=device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con, infeasible_con], samples=samples, infeasible_cost=0.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one feasible, one infeasible, infeasible_cost obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con, infeasible_con], infeasible_cost=5.0, ) samples = torch.randn(3, 2, device=device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con, infeasible_con], samples=samples, infeasible_cost=5.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj)) # one feasible, one infeasible, infeasible_cost, higher dimension obj = ConstrainedMCObjective( objective=generic_obj, constraints=[feasible_con, infeasible_con], infeasible_cost=5.0, ) samples = torch.randn(4, 3, 2, device=device, dtype=dtype) constrained_obj = generic_obj(samples) constrained_obj = apply_constraints( obj=constrained_obj, constraints=[feasible_con, infeasible_con], samples=samples, infeasible_cost=5.0, ) self.assertTrue(torch.equal(obj(samples), constrained_obj))