Source code for ccvm_simulators.post_processor.lbfgs
from .post_processor import PostProcessor, MethodType
from .box_qp_model import BoxQPModel
import time
import torch
import tqdm
[docs]
class PostProcessorLBFGS(PostProcessor):
"""A concrete class that implements the PostProcessor interface."""
def __init__(self):
self.pp_time = 0
self.method_type = MethodType.LBFGS
[docs]
def postprocess(
self, c, q_matrix, v_vector, lower_clamp=0.0, upper_clamp=1.0, num_iter=1
):
"""Post processing using LBFGS method.
Args:
c (torch.tensor): The values for each
variable of the problem in the solution found by the solver.
q_matrix (torch.tensor): Coefficients of the quadratic terms.
v_vector (torch.tensor): Coefficients of the linear terms.
lower_clamp (float, optional): Lower bound of the box constraints. Defaults
to 0.0.
upper_clamp (float, optional): Upper bound of the box constraints. Defaults
to 1.0.
num_iter (int, optional): The number of iterations. Defaults to 1.
Returns:
torch.tensor: The values for each variable of the problem in the
solution found by the solver after post-processing.
"""
start_time = time.time()
try:
if not torch.is_tensor(c):
raise TypeError("parameter c must be a tensor")
if not torch.is_tensor(q_matrix):
raise TypeError("parameter q_matrix must be a tensor")
if not torch.is_tensor(v_vector):
raise TypeError("parameter v_vector must be a tensor")
(batch_size, size) = c.size()
except Exception as e:
raise e
variables_pp = torch.zeros((batch_size, size))
for bb in tqdm.tqdm(range(batch_size)):
model = BoxQPModel(c[bb], self.method_type)
for _ in range(num_iter):
optimizer = torch.optim.LBFGS(model.parameters(), lr=0.001, max_iter=1)
def closure():
optimizer.zero_grad()
loss = model(q_matrix, v_vector)
loss.backward()
return loss
optimizer.step(closure)
model.params = torch.nn.Parameter(
torch.clamp(model.params, lower_clamp, upper_clamp)
)
variables_pp[bb] = model.params.detach()
end_time = time.time()
self.pp_time = end_time - start_time
return variables_pp