MatterGen / model /diffusion /corruption /corruption.py
dadadaxi's picture
Upload folder using huggingface_hub
f15d29e verified
Raw
History Blame Contribute Delete
3.48 kB
"""
Copyright 2020 The Google Research Authors.
Copyright (c) Microsoft Corporation.
Licensed under the MIT License.
Based on code from https://github.com/yang-song/score_sde_pytorch/blob/main/sde_lib.py
which is released under Apache licence.
Abstract SDE classes, Reverse SDE, and VE/VP SDEs.
Key changes:
- Rename SDE => Corruption
- Remove several methods like .reverse(), .discretize()
"""
import abc
import logging
from typing import Optional, Tuple, Union
import torch
from ...diffusion.data.batched_data import BatchedData
B = Optional[torch.LongTensor]
def _broadcast_like(x, like):
"""
add broadcast dimensions to x so that it can be broadcast over ``like``
"""
if like is None:
return x
return x[(...,) + (None,) * (like.ndim - x.ndim)]
def maybe_expand(x: torch.Tensor, batch: B, like: torch.Tensor = None) -> torch.Tensor:
"""
Args:
x: shape (batch_size, ...)
batch: shape (num_thingies,) with integer entries in the range [0, batch_size), indicating which sample each thingy belongs to
like: shape x.shape + potential additional dimensions
Returns:
expanded x with shape (num_thingies,), or if given like.shape, containing value of x for each thingy.
If `batch` is None, just returns `x` unmodified, to avoid pointless work if you have exactly one thingy per sample.
"""
x = _broadcast_like(x, like)
if batch is None:
return x
else:
if x.shape[0] == batch.shape[0]:
logging.warning(
"Warning: batch shape is == x shape, are you trying to expand something that is already expanded?"
)
return x[batch]
class Corruption(abc.ABC):
"""Abstract base class for corruption processes"""
@property
@abc.abstractmethod
def T(self) -> float:
"""End time of the corruption process."""
pass
@abc.abstractmethod
def marginal_prob(
self,
x: torch.Tensor,
t: torch.Tensor,
batch_idx: B = None,
batch: Optional[BatchedData] = None,
) -> Tuple[torch.Tensor, torch.Tensor]:
"""Parameters to determine the marginal distribution of the SDE, $p_t(x)$."""
pass # mean: (num_nodes, num_features), std (num_nodes,)
@abc.abstractmethod
def prior_sampling(
self,
shape: Union[torch.Size, Tuple],
conditioning_data: Optional[BatchedData] = None,
batch_idx: B = None, # This is normally unused but is needed for special cases such as sample-wise zero-centering.
) -> torch.Tensor:
"""Generate one sample from the prior distribution, $p_T(x)$."""
pass
@abc.abstractmethod
def prior_logp(
self,
z: torch.Tensor,
batch_idx: B = None,
batch: Optional[BatchedData] = None,
) -> torch.Tensor:
"""Compute log-density of the prior distribution.
Useful for computing the log-likelihood via probability flow ODE.
Args:
z: latent code
Returns:
log probability density
"""
pass # prior_logp: (batch_size,)
@abc.abstractmethod
def sample_marginal(
self,
x: torch.Tensor,
t: torch.Tensor,
batch_idx: B = None,
batch: Optional[BatchedData] = None,
) -> torch.Tensor:
"""Sample marginal for x(t) given x(0).
Returns:
sampled x(t) (same shape as input x).
"""
pass