From 2f42381155f600b6cb37790ad3d96166b8c84262 Mon Sep 17 00:00:00 2001 From: rocky Date: Mon, 13 Jan 2025 17:03:45 -0500 Subject: [PATCH] Add GraphQ; lint some --- .github/workflows/ubuntu.yml | 2 +- .pre-commit-config.yaml | 25 +++++++---------- pymathics/graph/__init__.py | 4 +-- pymathics/graph/properties.py | 51 ++++++++++++++++++++++++++--------- pymathics/graph/random.py | 6 +++-- 5 files changed, 55 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index fb6f057..d5e5e75 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -26,7 +26,7 @@ jobs: python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full] python -m pip install -e git+https://github.com/Mathics3/mathics-core#egg=Mathics3[full] python -m pip install -e . - (cd src/mathics3 && bash ./admin-tools/make-op-tables.sh) + (cd src/mathics3 && bash ./admin-tools/make-JSON-tables.sh) - name: install pymathics graph run: | make develop diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e8e521e..2ac7b58 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,27 +2,22 @@ default_language_version: python: python repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.5.0 hooks: - id: check-merge-conflict - id: debug-statements - stages: [commit] + stages: [pre-commit] - id: end-of-file-fixer - stages: [commit] -# - repo: https://github.com/pycqa/isort -# rev: 5.10.1 -# hooks: -# - id: isort -# stages: [commit] + stages: [pre-commit] +- repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + stages: [pre-commit] - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 24.10.0 hooks: - id: black language_version: python3 exclude: 'pymathics/graph/version.py' - stages: [commit] -- repo: https://github.com/pycqa/flake8 - rev: 3.9.2 - hooks: - - id: flake8 - stages: [commit] + stages: [pre-commit] diff --git a/pymathics/graph/__init__.py b/pymathics/graph/__init__.py index 05e7341..17c9e9b 100644 --- a/pymathics/graph/__init__.py +++ b/pymathics/graph/__init__.py @@ -60,7 +60,6 @@ VertexIndex, VertexList, ) - from pymathics.graph.centralities import ( BetweennessCentrality, ClosenessCentrality, @@ -70,7 +69,6 @@ KatzCentrality, PageRankCentrality, ) - from pymathics.graph.components import ConnectedComponents, WeaklyConnectedComponents from pymathics.graph.curated import GraphData from pymathics.graph.measures_and_metrics import ( @@ -99,6 +97,7 @@ AcyclicGraphQ, ConnectedGraphQ, DirectedGraphQ, + GraphQ, LoopFreeGraphQ, MixedGraphQ, MultigraphQ, @@ -151,6 +150,7 @@ "GraphBox", "GraphData", "GraphDistance", + "GraphQ", "HITSCentrality", "HighlightGraph", "HknHararyGraph", diff --git a/pymathics/graph/properties.py b/pymathics/graph/properties.py index 2e9e94a..7d85b19 100644 --- a/pymathics/graph/properties.py +++ b/pymathics/graph/properties.py @@ -52,7 +52,7 @@ class AcyclicGraphQ(_NetworkXBuiltin): summary_text = "test if is a graph is acyclic" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "AcyclicGraphQ[graph_, OptionsPattern[AcyclicGraphQ]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=False) if not graph or graph.empty(): @@ -73,7 +73,7 @@ class ConnectedGraphQ(_NetworkXBuiltin): #Connected_vertices_and_graphs test ( :NetworkX: -https://networkx.org/documentation/networkx-2.8.8/reference/algorithms\ +https://networkx.org/documentation/stable/reference/algorithms\ /generated/networkx.algorithms.components.is_connected.html , :WMA: @@ -111,7 +111,7 @@ class ConnectedGraphQ(_NetworkXBuiltin): summary_text = "test if a graph is a connected" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "%(name)s[graph_, OptionsPattern[%(name)s]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=True) if graph: @@ -127,7 +127,7 @@ class DirectedGraphQ(_NetworkXBuiltin): https://en.wikipedia.org/wiki/Directed_graph test ( :NetworkX: - https://networkx.org/documentation/networkx-2.8.8/reference\ + https://networkx.org/documentation/stable/reference\ /generated/networkx.classes.function.is_directed.html , :WMA: @@ -153,7 +153,7 @@ class DirectedGraphQ(_NetworkXBuiltin): summary_text = "test if a graph is directed" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "DirectedGraphQ[graph_, OptionsPattern[DirectedGraphQ]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=True) if graph: @@ -162,6 +162,31 @@ def eval(self, graph, expression, evaluation, options): return SymbolFalse +class GraphQ(_NetworkXBuiltin): + """ + :WMA link: + https://reference.wolfram.com/language/ref/GraphQ.html +
+
'GraphQ'[$graph$] +
True if $graph$ is a 'Graph'. +
+ + A graph with one one node and one self-looping edge: + >> GraphQ[{1 -> 2, 2 -> 3, 3 -> 1}] + = True + + >> GraphQ[{1, 2, 3}] + = False + """ + + summary_text = "test object is a graph" + + def eval(self, graph, expression, evaluation: Evaluation, options: dict): + "GraphQ[graph_, OptionsPattern[GraphQ]]" + graph = self._build_graph(graph, evaluation, options, expression, quiet=True) + return SymbolTrue if graph else SymbolFalse + + class LoopFreeGraphQ(_NetworkXBuiltin): """ @@ -169,7 +194,7 @@ class LoopFreeGraphQ(_NetworkXBuiltin): https://en.wikipedia.org/wiki/Loop_(graph_theory) test ( :NetworkX: - https://networkx.org/documentation/networkx-2.8.8/reference/\ + https://networkx.org/documentation/stable/reference/\ generated/networkx.classes.function.nodes_with_selfloops.html , :WMA: @@ -195,7 +220,7 @@ class LoopFreeGraphQ(_NetworkXBuiltin): summary_text = "test if a graph is loop free" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "LoopFreeGraphQ[graph_, OptionsPattern[LoopFreeGraphQ]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=True) if not graph or graph.empty(): @@ -240,7 +265,7 @@ class MixedGraphQ(_NetworkXBuiltin): summary_text = "test if a graph has directed and undirected edges" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "MixedGraphQ[graph_, OptionsPattern[MixedGraphQ]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=True) if graph: @@ -254,7 +279,7 @@ class MultigraphQ(_NetworkXBuiltin): :Multigraph: https://en.wikipedia.org/wiki/Multigraph test ( :NetworkX: -https://networkx.org/documentation/networkx-2.8.8/reference/classes/multigraph.html, \ +https://networkx.org/documentation/stable/reference/classes/multigraph.html
, \ :WMA: https://reference.wolfram.com/language/ref/MulitGraphQ.html) @@ -281,7 +306,7 @@ class MultigraphQ(_NetworkXBuiltin): summary_text = "test if a graph is a multi graph" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "MultigraphQ[graph_, OptionsPattern[MultigraphQ]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=True) if graph: @@ -339,7 +364,7 @@ class PathGraphQ(_NetworkXBuiltin): summary_text = "test if a graph is a path-like graph" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "PathGraphQ[graph_, OptionsPattern[PathGraphQ]]" if not isinstance(graph, Graph) or graph.empty(): return SymbolFalse @@ -365,7 +390,7 @@ class PlanarGraphQ(_NetworkXBuiltin): :Planar Graph: https://en.wikipedia.org/wiki/Planar_graph test ( :NetworkX: - https://networkx.org/documentation/networkx-2.8.8/reference/algorithms/ + https://networkx.org/documentation/stable/reference/algorithms/ generated/networkx.algorithms.planarity.check_planarity.html, :WMA: https://reference.wolfram.com/language/ref/PlanaGraphQ.html) @@ -436,7 +461,7 @@ class SimpleGraphQ(_NetworkXBuiltin): summary_text = "test if a graph is simple (not multigraph)" - def eval(self, graph, expression, evaluation, options): + def eval(self, graph, expression, evaluation: Evaluation, options: dict): "SimpleGraphQ[graph_, OptionsPattern[LoopFreeGraphQ]]" graph = self._build_graph(graph, evaluation, options, expression, quiet=True) if graph: diff --git a/pymathics/graph/random.py b/pymathics/graph/random.py index 90c35c9..13455b8 100644 --- a/pymathics/graph/random.py +++ b/pymathics/graph/random.py @@ -2,6 +2,8 @@ Random Graphs """ +from typing import Any, Generator + import networkx as nx from mathics.builtin.numbers.randomnumbers import RandomEnv from mathics.core.atoms import Integer, Integer1 @@ -36,7 +38,7 @@ class RandomGraph(_NetworkXBuiltin): def _generate( self, n: Integer, m: Integer, k: Integer, evaluation: Evaluation, options: dict - ) -> Graph: + ) -> Generator[Any, Any, Any]: py_n = n.value py_m = m.value py_k = k.value @@ -64,6 +66,6 @@ def eval_nmk( expression, evaluation: Evaluation, options: dict, - ) -> Graph: + ) -> ListExpression: "RandomGraph[{n_Integer, m_Integer}, k_Integer, OptionsPattern[RandomGraph]]" return ListExpression(*self._generate(n, m, k, evaluation, options))