Oh; I see is loss_weighting lagrange multiplier ?
minimize taks_loss subjected to ∂ NN (X1 ,X2 ) / ∂ X2 > 0
equivalent to minimize taks_loss subjected to (- ∂ NN (X1 ,X2 ) / ∂ X2 < 0)
so it becomes taks_loss +  loss_weighting * ( - ∂ NN (X1 ,X2 ) / ∂ X2 ) ?
Just one more question in the code it looks like

for iters in range(total_runs):
    # some code here
    torch.autograd.grad(task_loss, X2, create_graph=True)[0] # does it takes lots of memory ?

since we are creating graph each iteration; does it gonna take massive memory as the training goes on ? Does the algorithm free graph after optimizer.step() just like regular optimization ?