Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion v1/cicd_runner_allocation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Finally, it shows **conflict analysis (infeasibility diagnosis)**. A maintenance

### Tools
- Python >= 3.10
- RelationalAI Python SDK (`relationalai`) >= 1.9.0
- RelationalAI Python SDK (`relationalai`) == 1.11.0

## Quickstart

Expand Down
2 changes: 1 addition & 1 deletion v1/cicd_runner_allocation/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "RelationalAI template: cicd_runner_allocation (PyRel v1)"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"relationalai==1.9.0",
"relationalai==1.11.0",
"pandas>=2.0",
]

Expand Down
2 changes: 1 addition & 1 deletion v1/factory_production/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Because the objective is a **maximization**, the *capacity shadow price* is the

### Tools
- Python >= 3.10
- RelationalAI Python SDK (`relationalai`) >= 1.9.0
- RelationalAI Python SDK (`relationalai`) == 1.11.0

## Quickstart

Expand Down
2 changes: 1 addition & 1 deletion v1/factory_production/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "RelationalAI template: factory_production (PyRel v1)"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"relationalai==1.9.0",
"relationalai==1.11.0",
"pandas",
]

Expand Down
2 changes: 1 addition & 1 deletion v1/supplier_reliability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Finally, the template demonstrates **scenario analysis** by re-solving the probl

### Tools
- Python >= 3.10
- RelationalAI Python SDK (`relationalai`) >= 1.9.0
- RelationalAI Python SDK (`relationalai`) == 1.11.0

## Quickstart

Expand Down
2 changes: 1 addition & 1 deletion v1/supplier_reliability/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "RelationalAI template: supplier_reliability (PyRel v1)"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"relationalai==1.9.0",
"relationalai==1.11.0",
"pandas",
]

Expand Down
6 changes: 3 additions & 3 deletions v1/telco_network_recovery/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ Built using **predictive reasoning** (GNN on a heterogeneous graph), **rules-bas

- A Snowflake account with the RelationalAI native app installed.
- A Snowflake user with permissions on the RAI native app and on `EXP_DATABASE` (the schema for GNN experiment artifacts).
- A gurobi-enabled prescriptive engine for Stage 4 (the script automatically falls back to the bundled HiGHS solver if gurobi is not configured).
- A gurobi-enabled prescriptive engine for Stage 4 (if gurobi is unavailable or unlicensed, the script catches the solver error and falls back to the bundled HiGHS solver automatically).

### Tools

- Python ≥ 3.10.
- RelationalAI Python SDK (`relationalai == 1.8`).
- RelationalAI Python SDK (`relationalai == 1.11.0`).

### One-time Snowflake setup for GNN experiment artifacts

Expand Down Expand Up @@ -366,7 +366,7 @@ The bundled subscriber data has 50 enterprise (~$300K LTV avg) vs. 1,150 consume
<details>
<summary>Gurobi unavailable / unlicensed</summary>

The script attempts the engine's configured solver first. If gurobi is configured but errors at runtime (license, integration), the script catches the failure and retries with `solver="highs"` — no edit needed. To force HiGHS, set the engine's prescriptive solver to `highs` in `raiconfig.yaml`.
The script requests gurobi first. If gurobi errors at runtime (license, integration), it catches the failure and retries with `solver="highs"` — no edit needed. To always use HiGHS, change `problem.solve("gurobi")` to `problem.solve("highs")`.

</details>

Expand Down
2 changes: 1 addition & 1 deletion v1/telco_network_recovery/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description = "RelationalAI template: telco_network_recovery (PyRel v1)"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"relationalai==1.8",
"relationalai==1.11.0",
"pandas>=2.0",
]

Expand Down
34 changes: 13 additions & 21 deletions v1/telco_network_recovery/telco_network_recovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ def _pos_prob(p):
NetworkPerformance.latency_ms = model.Property(f"{NetworkPerformance} has {Float:latency_ms}")
NetworkPerformance.error_rate = model.Property(f"{NetworkPerformance} has {Float:error_rate}")
NetworkPerformance.for_tower = model.Relationship(
f"{NetworkPerformance} for tower {CellTower}", short_name="performance_for_tower"
f"{NetworkPerformance} for tower {CellTower}"
)
src = model.data(network_perf_df)
model.define(NetworkPerformance.new(
Expand Down Expand Up @@ -672,13 +672,13 @@ def _pos_prob(p):
# subscriber PageRank graph and for per-tower customer-impact aggregation.
CallDetailRecord = model.Concept("CallDetailRecord", identify_by={"id": String})
CallDetailRecord.caller = model.Relationship(
f"{CallDetailRecord} has caller {Subscriber}", short_name="cdr_caller"
f"{CallDetailRecord} has caller {Subscriber}"
)
CallDetailRecord.callee = model.Relationship(
f"{CallDetailRecord} has callee {Subscriber}", short_name="cdr_callee"
f"{CallDetailRecord} has callee {Subscriber}"
)
CallDetailRecord.routed_through = model.Relationship(
f"{CallDetailRecord} routed through {CellTower}", short_name="cdr_routed_through"
f"{CallDetailRecord} routed through {CellTower}"
)
src = model.data(cdr_df)
model.define(CallDetailRecord.new(
Expand Down Expand Up @@ -806,7 +806,7 @@ def _pos_prob(p):
TowerUpgradeOption.cost = model.Property(f"{TowerUpgradeOption} has {Float:cost}")
TowerUpgradeOption.install_weeks = model.Property(f"{TowerUpgradeOption} has {Integer:install_weeks}")
TowerUpgradeOption.for_tower = model.Relationship(
f"{TowerUpgradeOption} for tower {CellTower}", short_name="upgrade_for_tower"
f"{TowerUpgradeOption} for tower {CellTower}"
)
src = model.data(upgrade_options_df)
model.define(TowerUpgradeOption.new(
Expand Down Expand Up @@ -879,25 +879,17 @@ def _pos_prob(p):
)
)

# The prescriptive engine's configured solver picks up by default
# (see raiconfig.yaml `reasoners.prescriptive`). If the engine is set
# to gurobi but gurobi errors at runtime (license, integration), the
# except branch catches the failure and retries with HiGHS explicitly.
# Prefer gurobi (typically faster on MIPs where licensed). If the gurobi
# solve fails for any reason -- most often gurobi being unavailable or
# unlicensed on the prescriptive engine -- fall back to the bundled
# open-source HiGHS solver so the template runs on any engine. If HiGHS
# also fails, that error (e.g. a genuine model issue) propagates.
print("\n Solving...")
try:
problem.solve()
problem.solve("gurobi")
except Exception as exc:
# Fall back to the bundled open-source HiGHS solver when gurobi is
# unavailable / unlicensed on the prescriptive engine.
_msg = str(exc).lower()
if "gurobi" in _msg and any(
k in _msg for k in ("licen", "unavailable", "not enabled",
"not found", "disabled", "install")
):
print(f" Gurobi unavailable ({exc}); falling back to solver='highs'.")
problem.solve(solver="highs")
else:
raise
print(f" gurobi solve failed ({exc}); falling back to solver='highs'.")
problem.solve("highs")
problem.display()

# Extract selected upgrades. Cast int128 (returned by RAI select) to
Expand Down
Loading