Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
0a7c633
i need to check that this actually works when it's not 10pm
rachaelalfant Jun 12, 2026
c5a3ef2
Checking that I can work on the mrp branch that Rachael created
natasha-patnaik-321 Jun 12, 2026
9bf519b
fixed typo in model_data
rachaelalfant Jun 15, 2026
1c4d4b2
fixed a bunch of typos in create_scen_distr
rachaelalfant Jun 15, 2026
c0c0655
Working example for facilityloc, uses data that was sampled from dist…
natasha-patnaik-321 Jun 15, 2026
fb485d2
ScenarioDistribution Class & use empirical distribution of the Monte …
natasha-patnaik-321 Jun 15, 2026
f177d59
Check git push/ pull from laptop
natasha-patnaik-321 Jun 18, 2026
62798f4
Saveing Basic Farmers Example that matches mpisppy tutorial.
natasha-patnaik-321 Jun 22, 2026
2b3d5ff
Merge branch 'mrp' of https://github.com/sandialabs/sparow_examples i…
natasha-patnaik-321 Jun 22, 2026
4829ee6
Classic Farmers in SPAROW
natasha-patnaik-321 Jun 25, 2026
080b691
In-progress: need to check that this standard MRP sparow code runs fo…
natasha-patnaik-321 Jun 30, 2026
d32235d
Code for grid experiments
natasha-patnaik-321 Jul 1, 2026
4792fcb
adding mrp_discrete_facility_loc
rachaelalfant Jul 2, 2026
2dcfc1d
Sampling with vs without replacement and seeding experiments
natasha-patnaik-321 Jul 6, 2026
37d50f4
Merge branch 'mrp' of https://github.com/sandialabs/sparow_examples i…
natasha-patnaik-321 Jul 6, 2026
deec323
Write population scenarios to file from command line
natasha-patnaik-321 Jul 7, 2026
9a43903
Saving in-progress ACVMRP work
natasha-patnaik-321 Jul 10, 2026
64e6d44
Single-run ACVMRP code is running for discrete facilityloc, but need …
natasha-patnaik-321 Jul 13, 2026
fd918c0
ACVMRP Grid experiment results for discrete facilityloc
natasha-patnaik-321 Jul 14, 2026
9146341
NEED TO CHECK: Draft of p-center models
natasha-patnaik-321 Jul 15, 2026
69d16d5
Floating point errors in p-center problem - gives negative true optim…
natasha-patnaik-321 Jul 16, 2026
ef1975c
Discrete facilityloc with manually created suboptimal candidate
natasha-patnaik-321 Jul 17, 2026
e0f8126
Prelim results suggest bug in active fidelity state
natasha-patnaik-321 Jul 17, 2026
b157705
Ready to run ACVMRP grid experiments on discrete facilityloc for testing
natasha-patnaik-321 Jul 17, 2026
6b09c3b
Fixed nested scenario sampling for ACVMRP + discrete facilityloc exam…
natasha-patnaik-321 Jul 20, 2026
a54e165
Common initialization with super().__init__(). Need to check this wo…
natasha-patnaik-321 Jul 20, 2026
2b86a76
Saving changes to MRPFarmers and mrp_discrete_facilityloc examples.
natasha-patnaik-321 Jul 22, 2026
78954e7
PyApprox tutorial for Multi-Fidelity Estimation
natasha-patnaik-321 Jul 22, 2026
55fbd61
Only print if verbose = True
natasha-patnaik-321 Jul 23, 2026
8630f68
Better plot for relative margin of error
natasha-patnaik-321 Jul 24, 2026
e5d64f3
Cleaning up before creating PR
natasha-patnaik-321 Jul 24, 2026
fb9ce9c
Auto apply black [skip ci]
invalid-email-address Jul 24, 2026
09c8f1e
Saving grid experiment results before any other major code changes/ a…
natasha-patnaik-321 Jul 27, 2026
6550c6e
Auto apply black [skip ci]
invalid-email-address Jul 27, 2026
a7d4c3c
PyApprox seems to be working with discrete facilityloc!!!
natasha-patnaik-321 Jul 27, 2026
2ad387c
Auto apply black [skip ci]
invalid-email-address Jul 27, 2026
fd4ba64
True optimality gap w.r.t. HF model... but variance reduction is not …
natasha-patnaik-321 Jul 28, 2026
0d60184
Costs make a difference! Variance Reduction Achieved!
natasha-patnaik-321 Jul 28, 2026
cc9c8dd
Saving code with cost adjustment
natasha-patnaik-321 Jul 28, 2026
89185ae
Sanity check using HF model with artificially increased cost
natasha-patnaik-321 Jul 28, 2026
bc62f3c
Saving code for benchmarking against boot_sp (will organize later)
natasha-patnaik-321 Jul 30, 2026
246ed02
Auto apply black [skip ci]
invalid-email-address Jul 30, 2026
325b84b
Saving minor changes before refactor
natasha-patnaik-321 Aug 3, 2026
da811e5
Auto apply black [skip ci]
invalid-email-address Aug 3, 2026
bdf3270
Update .gitignore to exclude .npy, .png (any experiment results writt…
natasha-patnaik-321 Aug 4, 2026
c1bcd7e
Merge branch 'mrp' of https://github.com/sandialabs/sparow_examples i…
natasha-patnaik-321 Aug 4, 2026
7fc506b
Changed subdirectory name from ci to conf_intervals
natasha-patnaik-321 Aug 4, 2026
b8dd3d9
Ignore log files
natasha-patnaik-321 Aug 5, 2026
92598dd
Updating relative filepaths in PyApprox demo
natasha-patnaik-321 Aug 6, 2026
b008465
Save in-progress protocol-based refactor for MRP and ACV-MRP
natasha-patnaik-321 Aug 11, 2026
ccc6beb
Auto apply black [skip ci]
invalid-email-address Aug 11, 2026
50af795
Fixed typo in dev_environment.yml
natasha-patnaik-321 Aug 11, 2026
44c0c3a
Renaming env for testing
whart222 Aug 11, 2026
83b219f
Merge branch 'mrp' of https://github.com/sandialabs/sparow_examples i…
natasha-patnaik-321 Aug 11, 2026
278ae96
Added UQ and PyApprox Demos
natasha-patnaik-321 Aug 12, 2026
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
4 changes: 2 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
auto-update-conda: true
python-version: ${{ matrix.python-version }}
channels: conda-forge,defaults
activate-environment: conin_dev
activate-environment: sparow_examples_dev
environment-file: dev_environment.yml
use-mamba: true

Expand Down Expand Up @@ -145,7 +145,7 @@ jobs:
auto-update-conda: true
python-version: 3.13
channels: conda-forge,defaults
activate-environment: conin_dev
activate-environment: sparow_examples_dev
environment-file: dev_environment.yml
use-mamba: true

Expand Down
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
__pycache__
*.egg-info
.coverage

.DS_Store

*.npy
*.png

*.log

# Ignore Python byte-compiled files
__pycache__/
*.py[cod]
Empty file added __init__.py
Empty file.
2 changes: 2 additions & 0 deletions dev_environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ dependencies:
- black
- pip:
- mpi-sppy
- matplotlib
- highspy
179 changes: 178 additions & 1 deletion sparow_examples/farmers/MFfarmers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ class GlobalData:
if GlobalData.num_scens < 3:
raise RuntimeError(f"Number of scenarios must be >= 3")

#
# List of possible scenarios for basic farmers problem
# No notion of seperate plots... use this to compare against mpisppy code outputs
#
Basic_scendata = {
"scenarios": [
{
"ID": "scen_0",
"Yield": {"WHEAT": 2.0, "CORN": 2.4, "SUGAR_BEETS": 16.0},
"Probability": 1.0 / 3.0,
},
{
"ID": "scen_1",
"Yield": {"WHEAT": 2.5, "CORN": 3.0, "SUGAR_BEETS": 20.0},
"Probability": 1.0 / 3.0,
},
{
"ID": "scen_2",
"Yield": {"WHEAT": 3.0, "CORN": 3.6, "SUGAR_BEETS": 24.0},
"Probability": 1.0 / 3.0,
},
]
}

#
# list of possible per-plot scenarios for LF model:
#
Expand Down Expand Up @@ -317,10 +341,152 @@ def scenario_generator(self, num_plots, num_scens):
HF_data = HFScen_object.scenario_generator(GlobalData.num_plots, GlobalData.num_scens)

app_data = {"num_plots": GlobalData.num_plots}
model_data = {"LF": LF_scendata, "HF": HF_data}
model_data = {"Basic": Basic_scendata, "LF": LF_scendata, "HF": HF_data}
# print(HF_data)


#
# Construct Basic farmers problem model:
#
def Basic_model_builder(data, args):
model = pyo.ConcreteModel(data["ID"])

### PARAMETERS
model.TOTAL_ACREAGE = 500.0

def crops_init(m):
return ["WHEAT", "CORN", "SUGAR_BEETS"]

model.CROPS = pyo.Set(initialize=crops_init)

def _data(indict):
return {crop: indict[crop] for crop in ["WHEAT", "CORN", "SUGAR_BEETS"]}

model.PriceQuota = _data(
{"WHEAT": 100000.0, "CORN": 100000.0, "SUGAR_BEETS": 6000.0}
)

model.SubQuotaSellingPrice = _data( # favorable selling prices
{"WHEAT": 170.0, "CORN": 150.0, "SUGAR_BEETS": 36.0}
)

model.SuperQuotaSellingPrice = _data( # unfavorable selling prices
{"WHEAT": 0.0, "CORN": 0.0, "SUGAR_BEETS": 10.0}
)

model.CattleFeedRequirement = _data( # right hand sides of demand constraints
{"WHEAT": 200.0, "CORN": 240.0, "SUGAR_BEETS": 0.0}
)

model.PurchasePrice = (
_data( # purchasing costs.... cannot purchase sugar beets, so use dummy value
{"WHEAT": 238.0, "CORN": 210.0, "SUGAR_BEETS": 100000.0}
)
)

model.PlantingCostPerAcre = _data( # planting costs
{"WHEAT": 150.0, "CORN": 230.0, "SUGAR_BEETS": 260.0}
)

### STOCHASTIC DATA
def Yield_init(m, cropname):
return data["Yield"][cropname]

model.Yield = pyo.Param(
model.CROPS,
within=pyo.NonNegativeReals,
initialize=Yield_init,
mutable=True,
)

### VARIABLES
if args.get("use_integer", False): # stage-1 vars integer
model.DevotedAcreage = pyo.Var(
model.CROPS,
within=pyo.NonNegativeIntegers,
bounds=(0.0, model.TOTAL_ACREAGE),
)
else:
model.DevotedAcreage = pyo.Var( # stage-1 vars continuous
model.CROPS,
bounds=(0.0, model.TOTAL_ACREAGE),
)

model.QuantitySubQuotaSold = pyo.Var(
model.CROPS, bounds=(0.0, None)
) # qnty sold at favorable price
model.QuantitySuperQuotaSold = pyo.Var(
model.CROPS, bounds=(0.0, None)
) # qnty sold at unfavorable price
model.QuantityPurchased = pyo.Var(model.CROPS, bounds=(0.0, None)) # qnty purchased

### CONSTRAINTS
def ConstrainTotalAcreage_rule(model):
return sum(model.DevotedAcreage[c] for c in model.CROPS) <= model.TOTAL_ACREAGE

model.ConstrainTotalAcreage = pyo.Constraint(rule=ConstrainTotalAcreage_rule)

def EnforceCattleFeedRequirement_rule(model, c):
return model.CattleFeedRequirement[c] <= (
model.Yield[c] * model.DevotedAcreage[c]
+ model.QuantityPurchased[c]
- model.QuantitySubQuotaSold[c]
- model.QuantitySuperQuotaSold[c]
)

model.EnforceCattleFeedRequirement = pyo.Constraint(
model.CROPS, rule=EnforceCattleFeedRequirement_rule
)

def LimitAmountSold_rule(model, c):
return (
model.QuantitySubQuotaSold[c]
+ model.QuantitySuperQuotaSold[c]
- model.Yield[c] * model.DevotedAcreage[c]
) <= 0.0

model.LimitAmountSold = pyo.Constraint(model.CROPS, rule=LimitAmountSold_rule)

def EnforceQuotas_rule(model, c):
return (0.0, model.QuantitySubQuotaSold[c], model.PriceQuota[c])

model.EnforceQuotas = pyo.Constraint(model.CROPS, rule=EnforceQuotas_rule)

### OBJECTIVE
def ComputeFirstStageCost_rule(model):
return sum(
model.PlantingCostPerAcre[c] * model.DevotedAcreage[c] for c in model.CROPS
)

model.FirstStageCost = pyo.Expression(rule=ComputeFirstStageCost_rule)

def ComputeSecondStageCost_rule(model):
expr = sum(
model.PurchasePrice[c] * model.QuantityPurchased[c] for c in model.CROPS
)
expr -= sum(
model.SubQuotaSellingPrice[c] * model.QuantitySubQuotaSold[c]
for c in model.CROPS
)
expr -= sum(
model.SuperQuotaSellingPrice[c] * model.QuantitySuperQuotaSold[c]
for c in model.CROPS
)
return expr

model.SecondStageCost = pyo.Expression(rule=ComputeSecondStageCost_rule)

def total_cost_rule(model):
return model.FirstStageCost + model.SecondStageCost

model.Total_Cost_Objective = pyo.Objective(
rule=total_cost_rule,
sense=pyo.minimize,
)

return model


#
# Construct LF farmers problem model:
#
Expand Down Expand Up @@ -649,6 +815,17 @@ def total_cost_rule(model):
#


def Basic_farmers():
sp = stochastic_program(first_stage_variables=["DevotedAcreage[*]"])
sp.initialize_application(app_data=app_data)
sp.initialize_model(
name="Basic",
model_data=model_data["Basic"],
model_builder=Basic_model_builder,
)
return sp


def HF_farmers():
sp = stochastic_program(first_stage_variables=["DevotedAcreage[*,*]"])
sp.initialize_application(app_data=app_data)
Expand Down
Loading
Loading