diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..05fcaa01 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + pull_request: + workflow_dispatch: + +jobs: + tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Install PyTorch CPU + run: | + python -m pip install --upgrade pip + pip install torch==2.3.0 torchvision==0.18.0 torchaudio==2.3.0 --index-url https://download.pytorch.org/whl/cpu --no-cache-dir + + - name: Install NVTX mock bindings + run: | + pip install git+https://github.com/YaoYinYing/nvtx-mock --force-reinstall + pip install nvtx + + - name: Install graph dependencies + run: | + pip install "dgl<=2.4.0" -f https://data.dgl.ai/wheels/repo.html + pip install pyg_lib torch_scatter torch_sparse torch_cluster torch_spline_conv -f https://data.pyg.org/whl/torch-2.3.0+cpu.html + pip install torch_geometric + + - name: Install project + run: | + pip install -e . + + - name: Run smoke tests + run: | + python -m pytest -q tests/smoke diff --git a/.gitignore b/.gitignore index 835e724c..3d5a7125 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ tests/tim_barrel_scaffold tests/tests_* examples/outputs/* examples/example_outputs/* +.venv/ diff --git a/examples/minimal_graph_migration.py b/examples/minimal_graph_migration.py new file mode 100644 index 00000000..731efec0 --- /dev/null +++ b/examples/minimal_graph_migration.py @@ -0,0 +1,30 @@ +""" +Minimal example derived from the example suite to exercise both DGL and +PyTorch Geometric backends during the migration process. +""" + +import torch +import dgl +from torch_geometric.data import Data + + +def build_graphs(): + src = torch.tensor([0, 1, 2, 2]) + dst = torch.tensor([1, 2, 0, 3]) + features = torch.arange(4, dtype=torch.float32).unsqueeze(-1) + + dgl_graph = dgl.graph((src, dst)) + dgl_graph.ndata["x"] = features + + pyg_graph = Data(x=features, edge_index=torch.stack([src, dst], dim=0)) + return dgl_graph, pyg_graph + + +def main(): + dgl_graph, pyg_graph = build_graphs() + print("DGL graph:", dgl_graph) + print("PyG graph:", pyg_graph) + + +if __name__ == "__main__": + main() diff --git a/tests/smoke/test_graph_backends.py b/tests/smoke/test_graph_backends.py new file mode 100644 index 00000000..25bd6b19 --- /dev/null +++ b/tests/smoke/test_graph_backends.py @@ -0,0 +1,22 @@ +import torch +import dgl +from torch_geometric.data import Data + + +def test_graph_construction_parity(): + src = torch.tensor([0, 1, 2, 2]) + dst = torch.tensor([1, 2, 0, 3]) + features = torch.arange(4, dtype=torch.float32).unsqueeze(-1) + + dgl_graph = dgl.graph((src, dst)) + dgl_graph.ndata["x"] = features + + pyg_graph = Data(x=features, edge_index=torch.stack([src, dst], dim=0)) + + assert dgl_graph.num_nodes() == pyg_graph.num_nodes + assert dgl_graph.num_edges() == pyg_graph.num_edges + + dgl_edges = torch.stack(dgl_graph.edges(order="eid"), dim=0) + pyg_edges = pyg_graph.edge_index + assert torch.equal(dgl_edges, pyg_edges) + assert torch.equal(dgl_graph.ndata["x"], pyg_graph.x)