graphmdo 0.1.2__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.github/workflows/security.yml +15 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/PKG-INFO +3 -2
- {graphmdo-0.1.2 → graphmdo-0.2.0}/README.md +2 -1
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/api/optimization/optimizer.md +1 -1
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/user-guide/quick-start.md +2 -1
- {graphmdo-0.1.2 → graphmdo-0.2.0}/main.py +5 -5
- {graphmdo-0.1.2 → graphmdo-0.2.0}/pyproject.toml +10 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/core/components.py +11 -11
- graphmdo-0.2.0/src/mdo_framework/core/evaluators.py +33 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/core/surrogates.py +6 -6
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/core/topology.py +9 -12
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/core/translator.py +7 -8
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/db/client.py +5 -14
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/db/graph_manager.py +11 -5
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/optimization/optimizer.py +95 -99
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/execution/main.py +25 -17
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/graph/main.py +4 -2
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/optimization/main.py +62 -25
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/conftest.py +1 -2
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_components.py +12 -3
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_db_client.py +2 -1
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_integration.py +3 -3
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_main.py +1 -1
- graphmdo-0.2.0/tests/test_optimizer.py +209 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_services.py +296 -63
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_services_opt.py +1 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_surrogates.py +0 -6
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_topology.py +1 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_translator.py +12 -2
- graphmdo-0.1.2/tests/test_optimizer.py +0 -162
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.github/workflows/docs.yml +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.github/workflows/pypi-publish.yml +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.github/workflows/quality.yml +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.gitignore +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.pre-commit-config.yaml +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/.python-version +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/AGENTS.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/Dockerfile +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/LICENSE +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docker-compose.yml +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/api/core/components.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/api/core/surrogates.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/api/core/translator.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/api/db/client.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/api/db/graph_manager.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/dev-guide/contributing.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/index.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/technical-reference/architecture.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/technical-reference/microservices.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/user-guide/installation.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/docs/user-guide/running-optimization.md +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/mkdocs.yml +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/core/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/db/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/mdo_framework/optimization/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/execution/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/graph/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/src/services/optimization/__init__.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/tests/test_graph_manager.py +0 -0
- {graphmdo-0.1.2 → graphmdo-0.2.0}/uv.lock +0 -0
|
@@ -11,6 +11,21 @@ jobs:
|
|
|
11
11
|
name: Build
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
steps:
|
|
14
|
+
- name: Free Disk Space (Ubuntu)
|
|
15
|
+
uses: jlumbroso/free-disk-space@main
|
|
16
|
+
with:
|
|
17
|
+
# This might take a few minutes, but it frees up ~30GB
|
|
18
|
+
tool-cache: false
|
|
19
|
+
android: true
|
|
20
|
+
dotnet: true
|
|
21
|
+
haskell: true
|
|
22
|
+
large-packages: true
|
|
23
|
+
docker-images: true
|
|
24
|
+
swap-storage: true
|
|
25
|
+
|
|
26
|
+
- name: Setup Docker
|
|
27
|
+
uses: docker/setup-buildx-action@v2
|
|
28
|
+
|
|
14
29
|
- name: Checkout code
|
|
15
30
|
uses: actions/checkout@v3
|
|
16
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: graphmdo
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A dynamic, graph-driven Multidisciplinary Design Optimization (MDO) framework integrating FalkorDB, OpenMDAO, and multi-fidelity surrogate models.
|
|
5
5
|
Author-email: jultou-raa <64092886+jultou-raa@users.noreply.github.com>, google-labs-jules-bot <161369871+google-labs-jules-bot@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -95,7 +95,8 @@ Once the graph is populated, you can run the optimization workflow. You need to
|
|
|
95
95
|
|
|
96
96
|
```python
|
|
97
97
|
from mdo_framework.core.translator import GraphProblemBuilder
|
|
98
|
-
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
98
|
+
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
99
|
+
from mdo_framework.core.evaluators import LocalEvaluator
|
|
99
100
|
from mdo_framework.core.topology import TopologicalAnalyzer
|
|
100
101
|
|
|
101
102
|
# Define tool implementation
|
|
@@ -74,7 +74,8 @@ Once the graph is populated, you can run the optimization workflow. You need to
|
|
|
74
74
|
|
|
75
75
|
```python
|
|
76
76
|
from mdo_framework.core.translator import GraphProblemBuilder
|
|
77
|
-
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
77
|
+
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
78
|
+
from mdo_framework.core.evaluators import LocalEvaluator
|
|
78
79
|
from mdo_framework.core.topology import TopologicalAnalyzer
|
|
79
80
|
|
|
80
81
|
# Define tool implementation
|
|
@@ -43,7 +43,8 @@ Once the graph is populated, you can run the optimization.
|
|
|
43
43
|
|
|
44
44
|
```python
|
|
45
45
|
from mdo_framework.core.translator import GraphProblemBuilder
|
|
46
|
-
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
46
|
+
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
47
|
+
from mdo_framework.core.evaluators import LocalEvaluator
|
|
47
48
|
from mdo_framework.core.topology import TopologicalAnalyzer
|
|
48
49
|
|
|
49
50
|
# 1. Define Tool Implementation
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
from mdo_framework.core.evaluators import LocalEvaluator
|
|
1
2
|
from mdo_framework.core.translator import GraphProblemBuilder
|
|
2
3
|
from mdo_framework.db.graph_manager import GraphManager
|
|
3
|
-
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
4
|
+
from mdo_framework.optimization.optimizer import BayesianOptimizer
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
# --- Sellar Problem Functions ---
|
|
7
8
|
def paraboloid_func(x, y):
|
|
8
|
-
"""
|
|
9
|
-
f(x, y) = (x-3)**2 + xy + (y+4)**2 - 3
|
|
10
|
-
"""
|
|
9
|
+
"""f(x, y) = (x-3)**2 + xy + (y+4)**2 - 3"""
|
|
11
10
|
f_xy = (x - 3.0) ** 2 + x * y + (y + 4.0) ** 2 - 3.0
|
|
12
11
|
c_xy = x - y
|
|
13
12
|
return {"f_xy": f_xy, "c_xy": c_xy}
|
|
@@ -84,7 +83,8 @@ def main():
|
|
|
84
83
|
try:
|
|
85
84
|
result = optimizer.optimize(n_steps=10, n_init=5)
|
|
86
85
|
print("Optimization Complete.")
|
|
87
|
-
print("Best Result:", result)
|
|
86
|
+
print("Best Result:", result["best_parameters"])
|
|
87
|
+
print("Best Objectives:", result["best_objectives"])
|
|
88
88
|
except Exception as e:
|
|
89
89
|
print(f"Optimization failed: {e}")
|
|
90
90
|
|
|
@@ -2,16 +2,16 @@ import openmdao.api as om
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class ToolComponent(om.ExplicitComponent):
|
|
5
|
-
"""
|
|
6
|
-
Generic OpenMDAO component that wraps a Python function.
|
|
7
|
-
"""
|
|
5
|
+
"""Generic OpenMDAO component that wraps a Python function."""
|
|
8
6
|
|
|
9
7
|
def initialize(self):
|
|
10
8
|
self.options.declare("name", types=str, desc="Name of the tool")
|
|
11
9
|
self.options.declare("func", types=object, desc="The function to execute")
|
|
12
10
|
self.options.declare("inputs", types=list, desc="List of input variable names")
|
|
13
11
|
self.options.declare(
|
|
14
|
-
"outputs",
|
|
12
|
+
"outputs",
|
|
13
|
+
types=list,
|
|
14
|
+
desc="List of output variable names",
|
|
15
15
|
)
|
|
16
16
|
self.options.declare(
|
|
17
17
|
"derivatives",
|
|
@@ -52,6 +52,7 @@ class ToolComponent(om.ExplicitComponent):
|
|
|
52
52
|
# If func is: def my_func(x): return {"y": x * 2}
|
|
53
53
|
# This compute block sets outputs["y"] = inputs["x"] * 2
|
|
54
54
|
```
|
|
55
|
+
|
|
55
56
|
"""
|
|
56
57
|
func = self.options["func"]
|
|
57
58
|
# Prepare inputs as a dictionary
|
|
@@ -69,14 +70,13 @@ class ToolComponent(om.ExplicitComponent):
|
|
|
69
70
|
if len(self.options["outputs"]) == 1:
|
|
70
71
|
output_name = self.options["outputs"][0]
|
|
71
72
|
outputs[output_name] = result
|
|
73
|
+
elif isinstance(result, dict):
|
|
74
|
+
for name in self.options["outputs"]:
|
|
75
|
+
outputs[name] = result[name]
|
|
72
76
|
else:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
else:
|
|
77
|
-
# If result is a tuple/list, assume order matches outputs
|
|
78
|
-
for i, name in enumerate(self.options["outputs"]):
|
|
79
|
-
outputs[name] = result[i]
|
|
77
|
+
# If result is a tuple/list, assume order matches outputs
|
|
78
|
+
for i, name in enumerate(self.options["outputs"]):
|
|
79
|
+
outputs[name] = result[i]
|
|
80
80
|
|
|
81
81
|
def compute_partials(self, inputs, partials):
|
|
82
82
|
if self.options["derivatives"]:
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
import openmdao.api as om
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LocalEvaluator:
|
|
7
|
+
"""Evaluates the design parameters locally using an OpenMDAO Problem instance.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
problem: An instantiated OpenMDAO Problem object.
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, problem: om.Problem):
|
|
15
|
+
self.problem = problem
|
|
16
|
+
|
|
17
|
+
def evaluate(
|
|
18
|
+
self,
|
|
19
|
+
parameters: dict[str, Any],
|
|
20
|
+
objectives: list[str],
|
|
21
|
+
) -> dict[str, float]:
|
|
22
|
+
for name, val in parameters.items():
|
|
23
|
+
self.problem.set_val(name, val)
|
|
24
|
+
self.problem.run_model()
|
|
25
|
+
|
|
26
|
+
results = {}
|
|
27
|
+
for obj in objectives:
|
|
28
|
+
results[obj] = (
|
|
29
|
+
float(self.problem.get_val(obj)[0])
|
|
30
|
+
if hasattr(self.problem.get_val(obj), "__iter__")
|
|
31
|
+
else float(self.problem.get_val(obj))
|
|
32
|
+
)
|
|
33
|
+
return results
|
|
@@ -4,9 +4,7 @@ from smt.surrogate_models import KPLS, KRG
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class SMTSurrogate:
|
|
7
|
-
"""
|
|
8
|
-
Wrapper for SMT surrogate models, supporting single and multi-fidelity.
|
|
9
|
-
"""
|
|
7
|
+
"""Wrapper for SMT surrogate models, supporting single and multi-fidelity."""
|
|
10
8
|
|
|
11
9
|
def __init__(self, model_type="KRG", multi_fidelity=False):
|
|
12
10
|
self.model_type = model_type
|
|
@@ -20,14 +18,14 @@ class SMTSurrogate:
|
|
|
20
18
|
x_lf: np.ndarray = None,
|
|
21
19
|
y_lf: np.ndarray = None,
|
|
22
20
|
):
|
|
23
|
-
"""
|
|
24
|
-
Trains the surrogate model.
|
|
21
|
+
"""Trains the surrogate model.
|
|
25
22
|
|
|
26
23
|
Args:
|
|
27
24
|
xt: High-fidelity training inputs.
|
|
28
25
|
yt: High-fidelity training outputs.
|
|
29
26
|
x_lf: Low-fidelity training inputs (for multi-fidelity).
|
|
30
27
|
y_lf: Low-fidelity training outputs (for multi-fidelity).
|
|
28
|
+
|
|
31
29
|
"""
|
|
32
30
|
n_dims = xt.shape[1]
|
|
33
31
|
|
|
@@ -48,7 +46,9 @@ class SMTSurrogate:
|
|
|
48
46
|
# Default n_comp=1 in SMT KPLS.
|
|
49
47
|
n_comp = 1
|
|
50
48
|
self.model = KPLS(
|
|
51
|
-
theta0=[1e-2] * n_comp,
|
|
49
|
+
theta0=[1e-2] * n_comp,
|
|
50
|
+
n_comp=n_comp,
|
|
51
|
+
print_global=False,
|
|
52
52
|
)
|
|
53
53
|
else:
|
|
54
54
|
raise ValueError(f"Unknown model type: {self.model_type}")
|
|
@@ -2,18 +2,17 @@ from typing import Any
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class TopologicalAnalyzer:
|
|
5
|
-
"""
|
|
6
|
-
Analyzes a KADMOS/CMDOWS-style graph schema recursively to extract
|
|
5
|
+
"""Analyzes a KADMOS/CMDOWS-style graph schema recursively to extract
|
|
7
6
|
the independent design variables and sub-graph components required
|
|
8
7
|
to evaluate a specific target output.
|
|
9
8
|
"""
|
|
10
9
|
|
|
11
10
|
def __init__(self, schema: dict[str, Any]):
|
|
12
|
-
"""
|
|
13
|
-
Initializes the analyzer with the provided graph schema.
|
|
11
|
+
"""Initializes the analyzer with the provided graph schema.
|
|
14
12
|
|
|
15
13
|
Args:
|
|
16
14
|
schema: Dictionary representing the full graph tools and variables.
|
|
15
|
+
|
|
17
16
|
"""
|
|
18
17
|
self.schema = schema
|
|
19
18
|
self.tools = {t["name"]: t for t in schema.get("tools", [])}
|
|
@@ -28,10 +27,10 @@ class TopologicalAnalyzer:
|
|
|
28
27
|
self.var_sources[out_var].append(tool_name)
|
|
29
28
|
|
|
30
29
|
def resolve_dependencies(
|
|
31
|
-
self,
|
|
30
|
+
self,
|
|
31
|
+
target_outputs: list[str],
|
|
32
32
|
) -> tuple[list[str], list[dict[str, Any]]]:
|
|
33
|
-
"""
|
|
34
|
-
Recursively resolve all dependencies needed to compute target_outputs.
|
|
33
|
+
"""Recursively resolve all dependencies needed to compute target_outputs.
|
|
35
34
|
Returns a tuple containing:
|
|
36
35
|
1. A list of independent design variables (inputs without any tool source).
|
|
37
36
|
2. A list of tool configurations required for execution.
|
|
@@ -67,9 +66,7 @@ class TopologicalAnalyzer:
|
|
|
67
66
|
return design_vars, req_tools
|
|
68
67
|
|
|
69
68
|
def extract_parameters(self, design_vars: list[str]) -> list[dict[str, Any]]:
|
|
70
|
-
"""
|
|
71
|
-
Formats design variables into Ax-Platform ready parameter structures.
|
|
72
|
-
"""
|
|
69
|
+
"""Formats design variables into Ax-Platform ready parameter structures."""
|
|
73
70
|
parameters = []
|
|
74
71
|
for var_name in design_vars:
|
|
75
72
|
var_data = self.variables.get(var_name)
|
|
@@ -84,7 +81,7 @@ class TopologicalAnalyzer:
|
|
|
84
81
|
"type": "choice",
|
|
85
82
|
"values": var_data.get("choices", []),
|
|
86
83
|
"value_type": var_data.get("value_type", "float"),
|
|
87
|
-
}
|
|
84
|
+
},
|
|
88
85
|
)
|
|
89
86
|
else:
|
|
90
87
|
parameters.append(
|
|
@@ -96,7 +93,7 @@ class TopologicalAnalyzer:
|
|
|
96
93
|
var_data.get("upper", 1.0),
|
|
97
94
|
],
|
|
98
95
|
"value_type": var_data.get("value_type", "float"),
|
|
99
|
-
}
|
|
96
|
+
},
|
|
100
97
|
)
|
|
101
98
|
|
|
102
99
|
return parameters
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any
|
|
2
3
|
|
|
3
4
|
import openmdao.api as om
|
|
4
5
|
|
|
@@ -6,16 +7,14 @@ from mdo_framework.core.components import ToolComponent
|
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class GraphProblemBuilder:
|
|
9
|
-
"""
|
|
10
|
-
Builds an OpenMDAO Problem from a graph schema dictionary.
|
|
11
|
-
"""
|
|
10
|
+
"""Builds an OpenMDAO Problem from a graph schema dictionary."""
|
|
12
11
|
|
|
13
12
|
def __init__(self, schema: dict[str, Any]):
|
|
14
|
-
"""
|
|
15
|
-
Initializes the builder with the given graph schema.
|
|
13
|
+
"""Initializes the builder with the given graph schema.
|
|
16
14
|
|
|
17
15
|
Args:
|
|
18
16
|
schema: Dictionary representing tools, inputs, and outputs.
|
|
17
|
+
|
|
19
18
|
"""
|
|
20
19
|
"""
|
|
21
20
|
Args:
|
|
@@ -25,14 +24,14 @@ class GraphProblemBuilder:
|
|
|
25
24
|
self.schema = schema
|
|
26
25
|
|
|
27
26
|
def build_problem(self, tool_registry: dict[str, Callable]) -> om.Problem:
|
|
28
|
-
"""
|
|
29
|
-
Constructs an OpenMDAO problem from the parsed schema.
|
|
27
|
+
"""Constructs an OpenMDAO problem from the parsed schema.
|
|
30
28
|
|
|
31
29
|
Args:
|
|
32
30
|
tool_registry: Mapping of tool names to Python callables.
|
|
33
31
|
|
|
34
32
|
Returns:
|
|
35
33
|
An instantiated OpenMDAO Problem object.
|
|
34
|
+
|
|
36
35
|
"""
|
|
37
36
|
"""
|
|
38
37
|
Constructs and sets up the OpenMDAO problem.
|
|
@@ -4,22 +4,18 @@ from falkordb import FalkorDB
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class FalkorDBClient:
|
|
7
|
-
"""
|
|
8
|
-
Singleton class to manage the connection to the FalkorDB database.
|
|
9
|
-
"""
|
|
7
|
+
"""Singleton class to manage the connection to the FalkorDB database."""
|
|
10
8
|
|
|
11
9
|
_instance = None
|
|
12
10
|
|
|
13
11
|
def __new__(cls):
|
|
14
12
|
if cls._instance is None:
|
|
15
|
-
cls._instance = super(
|
|
13
|
+
cls._instance = super().__new__(cls)
|
|
16
14
|
cls._instance._initialize()
|
|
17
15
|
return cls._instance
|
|
18
16
|
|
|
19
17
|
def _initialize(self):
|
|
20
|
-
"""
|
|
21
|
-
Initializes the FalkorDB connection.
|
|
22
|
-
"""
|
|
18
|
+
"""Initializes the FalkorDB connection."""
|
|
23
19
|
host = os.getenv("FALKORDB_HOST", "localhost")
|
|
24
20
|
port = int(os.getenv("FALKORDB_PORT", 6379))
|
|
25
21
|
self.client = FalkorDB(host=host, port=port)
|
|
@@ -27,15 +23,10 @@ class FalkorDBClient:
|
|
|
27
23
|
self.graph = self.client.select_graph(self.graph_name)
|
|
28
24
|
|
|
29
25
|
def get_graph(self):
|
|
30
|
-
"""
|
|
31
|
-
Returns the graph object for executing queries.
|
|
32
|
-
"""
|
|
26
|
+
"""Returns the graph object for executing queries."""
|
|
33
27
|
return self.graph
|
|
34
28
|
|
|
35
29
|
def close(self):
|
|
36
|
-
"""
|
|
37
|
-
Closes the connection.
|
|
38
|
-
"""
|
|
30
|
+
"""Closes the connection."""
|
|
39
31
|
# FalkorDB client handles connection pooling, but explicit close might be needed
|
|
40
32
|
# depending on the implementation. For now, we rely on the client's management.
|
|
41
|
-
pass
|
|
@@ -42,6 +42,7 @@ class GraphManager:
|
|
|
42
42
|
gm.add_variable("wing_span", value=10.0, lower=5.0, upper=15.0, param_type="range", description="Wing span variable")
|
|
43
43
|
gm.add_variable("material", value="aluminum", choices=["aluminum", "composite"], param_type="choice", value_type="str")
|
|
44
44
|
```
|
|
45
|
+
|
|
45
46
|
"""
|
|
46
47
|
props = {
|
|
47
48
|
"name": name,
|
|
@@ -78,6 +79,7 @@ class GraphManager:
|
|
|
78
79
|
gm.add_tool("CFD_Solver", fidelity="high", version="1.2.0")
|
|
79
80
|
gm.add_tool("Vortex_Lattice", fidelity="low")
|
|
80
81
|
```
|
|
82
|
+
|
|
81
83
|
"""
|
|
82
84
|
props = {"name": name, "fidelity": fidelity}
|
|
83
85
|
props.update(kwargs)
|
|
@@ -101,13 +103,15 @@ class GraphManager:
|
|
|
101
103
|
```python
|
|
102
104
|
gm.connect_tool_to_output("CFD_Solver", "drag_coefficient")
|
|
103
105
|
```
|
|
106
|
+
|
|
104
107
|
"""
|
|
105
108
|
query = """
|
|
106
109
|
MATCH (t:Tool {name: $tool_name}), (v:Variable {name: $variable_name})
|
|
107
110
|
MERGE (t)-[:OUTPUTS]->(v)
|
|
108
111
|
"""
|
|
109
112
|
self.graph.query(
|
|
110
|
-
query,
|
|
113
|
+
query,
|
|
114
|
+
params={"tool_name": tool_name, "variable_name": variable_name},
|
|
111
115
|
)
|
|
112
116
|
|
|
113
117
|
def connect_input_to_tool(self, variable_name: str, tool_name: str):
|
|
@@ -121,13 +125,15 @@ class GraphManager:
|
|
|
121
125
|
```python
|
|
122
126
|
gm.connect_input_to_tool("wing_span", "CFD_Solver")
|
|
123
127
|
```
|
|
128
|
+
|
|
124
129
|
"""
|
|
125
130
|
query = """
|
|
126
131
|
MATCH (v:Variable {name: $variable_name}), (t:Tool {name: $tool_name})
|
|
127
132
|
MERGE (v)-[:INPUTS_TO]->(t)
|
|
128
133
|
"""
|
|
129
134
|
self.graph.query(
|
|
130
|
-
query,
|
|
135
|
+
query,
|
|
136
|
+
params={"variable_name": variable_name, "tool_name": tool_name},
|
|
131
137
|
)
|
|
132
138
|
|
|
133
139
|
def get_tools(self) -> list[dict[str, Any]]:
|
|
@@ -177,8 +183,7 @@ class GraphManager:
|
|
|
177
183
|
return [r[0] for r in result.result_set]
|
|
178
184
|
|
|
179
185
|
def get_graph_schema(self) -> dict[str, Any]:
|
|
180
|
-
"""
|
|
181
|
-
Returns a serializable dictionary representing the entire graph structure.
|
|
186
|
+
"""Returns a serializable dictionary representing the entire graph structure.
|
|
182
187
|
|
|
183
188
|
Returns:
|
|
184
189
|
A dictionary containing 'tools' and 'variables' lists defining the topology.
|
|
@@ -188,6 +193,7 @@ class GraphManager:
|
|
|
188
193
|
schema = gm.get_graph_schema()
|
|
189
194
|
print(schema["tools"][0]["name"])
|
|
190
195
|
```
|
|
196
|
+
|
|
191
197
|
"""
|
|
192
198
|
variables = self.get_variables()
|
|
193
199
|
|
|
@@ -214,7 +220,7 @@ class GraphManager:
|
|
|
214
220
|
"fidelity": tool_node.properties.get("fidelity", "high"),
|
|
215
221
|
"inputs": inputs,
|
|
216
222
|
"outputs": outputs,
|
|
217
|
-
}
|
|
223
|
+
},
|
|
218
224
|
)
|
|
219
225
|
|
|
220
226
|
return {"tools": tools, "variables": variables}
|