diff --git a/v1/cicd_runner_allocation/README.md b/v1/cicd_runner_allocation/README.md index 42ff6bef..6b147032 100644 --- a/v1/cicd_runner_allocation/README.md +++ b/v1/cicd_runner_allocation/README.md @@ -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 diff --git a/v1/cicd_runner_allocation/pyproject.toml b/v1/cicd_runner_allocation/pyproject.toml index 24f3b7bc..cc0fa9d6 100644 --- a/v1/cicd_runner_allocation/pyproject.toml +++ b/v1/cicd_runner_allocation/pyproject.toml @@ -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", ] diff --git a/v1/factory_production/README.md b/v1/factory_production/README.md index f508325f..73bdd679 100644 --- a/v1/factory_production/README.md +++ b/v1/factory_production/README.md @@ -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 diff --git a/v1/factory_production/pyproject.toml b/v1/factory_production/pyproject.toml index a5518b50..af921e4a 100644 --- a/v1/factory_production/pyproject.toml +++ b/v1/factory_production/pyproject.toml @@ -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", ] diff --git a/v1/supplier_reliability/README.md b/v1/supplier_reliability/README.md index f774f111..bf90708a 100644 --- a/v1/supplier_reliability/README.md +++ b/v1/supplier_reliability/README.md @@ -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 diff --git a/v1/supplier_reliability/pyproject.toml b/v1/supplier_reliability/pyproject.toml index 1dd217e7..ccedd7e0 100644 --- a/v1/supplier_reliability/pyproject.toml +++ b/v1/supplier_reliability/pyproject.toml @@ -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", ] diff --git a/v1/telco_network_recovery/README.md b/v1/telco_network_recovery/README.md index b7504419..2e860022 100644 --- a/v1/telco_network_recovery/README.md +++ b/v1/telco_network_recovery/README.md @@ -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 @@ -366,7 +366,7 @@ The bundled subscriber data has 50 enterprise (~$300K LTV avg) vs. 1,150 consume
Gurobi unavailable / unlicensed -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")`.
diff --git a/v1/telco_network_recovery/pyproject.toml b/v1/telco_network_recovery/pyproject.toml index 0236cb09..2d661e90 100644 --- a/v1/telco_network_recovery/pyproject.toml +++ b/v1/telco_network_recovery/pyproject.toml @@ -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", ] diff --git a/v1/telco_network_recovery/telco_network_recovery.py b/v1/telco_network_recovery/telco_network_recovery.py index cc8af1f4..03789064 100644 --- a/v1/telco_network_recovery/telco_network_recovery.py +++ b/v1/telco_network_recovery/telco_network_recovery.py @@ -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( @@ -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( @@ -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( @@ -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