def forward(self, mol_batch, beta=0):
    batch_size = len(mol_batch)
    (tree_mess, tree_vec, mol_vec) = self.encode(mol_batch)
    tree_mean = self.T_mean(tree_vec)
    tree_log_var = (- torch.abs(self.T_var(tree_vec)))
    mol_mean = self.G_mean(mol_vec)
    mol_log_var = (- torch.abs(self.G_var(mol_vec)))
    z_mean = torch.cat([tree_mean, mol_mean], dim=1)
    z_log_var = torch.cat([tree_log_var, mol_log_var], dim=1)
    kl_loss = (((- 0.5) * torch.sum((((1.0 + z_log_var) - (z_mean * z_mean)) - torch.exp(z_log_var)))) / batch_size)
    epsilon = create_var(torch.randn(batch_size, (self.latent_size // 2)), False)
    tree_vec = (tree_mean + (torch.exp((tree_log_var // 2)) * epsilon))
    epsilon = create_var(torch.randn(batch_size, (self.latent_size // 2)), False)
    mol_vec = (mol_mean + (torch.exp((mol_log_var // 2)) * epsilon))
    (word_loss, topo_loss, word_acc, topo_acc) = self.decoder(mol_batch, tree_vec)
    (assm_loss, assm_acc) = self.assm(mol_batch, mol_vec, tree_mess)
    if self.use_stereo:
        (stereo_loss, stereo_acc) = self.stereo(mol_batch, mol_vec)
    else:
        (stereo_loss, stereo_acc) = (0, 0)
    all_vec = torch.cat([tree_vec, mol_vec], dim=1)
    loss = ((((word_loss + topo_loss) + assm_loss) + (2 * stereo_loss)) + (beta * kl_loss))
    return (loss, kl_loss.item(), word_acc, topo_acc, assm_acc, stereo_acc)
def forward(self, mol_batch, beta=0):
    batch_size = len(mol_batch)
    (tree_mess, tree_vec, mol_vec) = self.encode(mol_batch)
    tree_mean = self.T_mean(tree_vec)
    tree_log_var = (- torch.abs(self.T_var(tree_vec)))
    mol_mean = self.G_mean(mol_vec)
    mol_log_var = (- torch.abs(self.G_var(mol_vec)))
    z_mean = torch.cat([tree_mean, mol_mean], dim=1)
    z_log_var = torch.cat([tree_log_var, mol_log_var], dim=1)
    kl_loss = (((- 0.5) * torch.sum((((1.0 + z_log_var) - (z_mean * z_mean)) - torch.exp(z_log_var)))) / batch_size)
    epsilon = create_var(torch.randn(batch_size, (self.latent_size // 2)), False)
    tree_vec = (tree_mean + (torch.exp((tree_log_var // 2)) * epsilon))
    epsilon = create_var(torch.randn(batch_size, (self.latent_size // 2)), False)
    mol_vec = (mol_mean + (torch.exp((mol_log_var // 2)) * epsilon))
    (word_loss, topo_loss, word_acc, topo_acc) = self.decoder(mol_batch, tree_vec)
    (assm_loss, assm_acc) = self.assm(mol_batch, mol_vec, tree_mess)
    if self.use_stereo:
        (stereo_loss, stereo_acc) = self.stereo(mol_batch, mol_vec)
    else:
        (stereo_loss, stereo_acc) = (0, 0)
    all_vec = torch.cat([tree_vec, mol_vec], dim=1)
    loss = ((((word_loss + topo_loss) + assm_loss) + (2 * stereo_loss)) + (beta * kl_loss))
    return (loss, kl_loss.item(), word_acc, topo_acc, assm_acc, stereo_acc)