Skip to content

Commit 9ea2149

Browse files
sotorrio1ksbeattie
andauthored
SDoE: Adding MaxPro functionality to USF designs (#1266)
* UI changes to accommodate MaxPro option within USF designs * adding maxpro base code and starting to hook things up * implementing maxpro backend functionalities * running black * fix import order error * fix index type for pylint * fix SDoE tests because of change in config file * implementing maxpro augmented design * adjusting time estimates and plotting for maxpro * adding couple quick maxpro tests * adding maxpro criterion test * removing print statements used for debugging * adding more maxpro and plot_utils tests * removing this test, issue with temp file --------- Co-authored-by: Keith Beattie <ksbeattie@lbl.gov>
1 parent 11b5fa4 commit 9ea2149

18 files changed

Lines changed: 8596 additions & 134 deletions

foqus_lib/framework/sdoe/maxpro.py

Lines changed: 1686 additions & 0 deletions
Large diffs are not rendered by default.

foqus_lib/framework/sdoe/plot_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ def plot_candidates(
412412
labels.append(scatter_label)
413413
if nImpPts > 0:
414414
labels.append("Imputed points")
415-
if cand is not None:
415+
if cand is not None and len(cand) > 0:
416416
labels.append("Candidate data points")
417417
if hf is not None:
418418
labels.append("Previous data points")

foqus_lib/framework/sdoe/sdoe.py

Lines changed: 86 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,33 @@
3131
from .df_utils import load, write
3232

3333

34-
def save(fnames: Dict, results: Dict, elapsed_time: float, irsf: bool = False):
34+
def save(
35+
fnames: Dict,
36+
results: Dict,
37+
elapsed_time: float,
38+
irsf: bool = False,
39+
maxpro: bool = False,
40+
):
3541
if irsf:
3642
write(fnames["des"], results["des"])
3743
print("Designs saved to {}".format(fnames["des"]))
3844
write(fnames["pf"], results["pareto_front"])
3945
print("Pareto Front saved to {}".format(fnames["pf"]))
4046

47+
elif maxpro:
48+
write(fnames["cand"], results["design"])
49+
print("Design saved to {}".format(fnames["cand"]))
50+
print(
51+
(
52+
"d={}, p={}: measure={}, elapsed_time={}s".format(
53+
results["design"].shape[0],
54+
results["design"].shape[1],
55+
results["measure"],
56+
elapsed_time,
57+
)
58+
)
59+
)
60+
4161
else:
4262
write(fnames["cand"], results["best_cand"], index=True)
4363
print("Candidates saved to {}".format(fnames["cand"]))
@@ -61,20 +81,24 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
6181
config.read(config_file)
6282

6383
mode = config["METHOD"]["mode"]
64-
nr = int(config["METHOD"]["number_random_starts"])
84+
if mode == "maxpro":
85+
max_iter = int(config["METHOD"]["max_iter"])
86+
else:
87+
nr = int(config["METHOD"]["number_random_starts"])
6588

66-
hfile = config["INPUT"]["history_file"]
89+
hfile = config["INPUT"]["prev_data_file"]
6790
cfile = config["INPUT"]["candidate_file"]
6891
include = [s.strip() for s in config["INPUT"]["include"].split(",")]
6992

7093
max_vals = [float(s) for s in config["INPUT"]["max_vals"].split(",")]
7194
min_vals = [float(s) for s in config["INPUT"]["min_vals"].split(",")]
7295

7396
types = [s.strip() for s in config["INPUT"]["types"].split(",")]
74-
difficulty = [s.strip() for s in config["INPUT"]["difficulty"].split(",")]
75-
type_idx = types.index("Index")
76-
diff_no_idx = difficulty.copy()
77-
del diff_no_idx[type_idx]
97+
if mode != "maxpro":
98+
difficulty = [s.strip() for s in config["INPUT"]["difficulty"].split(",")]
99+
type_idx = types.index("Index")
100+
diff_no_idx = difficulty.copy()
101+
del diff_no_idx[type_idx]
78102
# 'Input' columns
79103
idx = [x for x, t in zip(include, types) if t == "Input"]
80104
# 'Index' column (should only be one)
@@ -102,6 +126,22 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
102126
)
103127
pass
104128

129+
# create outdir as needed
130+
if not os.path.exists(outdir):
131+
os.makedirs(outdir)
132+
133+
# load candidates
134+
if cfile:
135+
cand = load(cfile, index=id_)
136+
if len(include) == 1 and include[0] == "all":
137+
include = list(cand)
138+
139+
# load history
140+
if hfile != "":
141+
hist = load(hfile, index=id_)
142+
else:
143+
hist = None
144+
105145
if sf_method == "nusf":
106146
# 'Weight' column (should only be one)
107147
idw = [x for x, t in zip(include, types) if t == "Weight"]
@@ -143,7 +183,19 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
143183
if use_dask:
144184
from .usf_dask import criterion
145185
else:
146-
from .usf import criterion
186+
if mode != "maxpro":
187+
from .usf import criterion
188+
else:
189+
from .maxpro import criterion
190+
191+
min_scl = pd.Series(min_vals, index=include)
192+
max_scl = pd.Series(max_vals, index=include)
193+
args = {
194+
"icol": id_,
195+
"xcols": idx,
196+
"min_scale_factors": min_scl,
197+
"max_scale_factors": max_scl,
198+
}
147199

148200
if sf_method == "irsf":
149201
args = {
@@ -155,22 +207,6 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
155207
}
156208
from .irsf import criterion
157209

158-
# create outdir as needed
159-
if not os.path.exists(outdir):
160-
os.makedirs(outdir)
161-
162-
# load candidates
163-
if cfile:
164-
cand = load(cfile, index=id_)
165-
if len(include) == 1 and include[0] == "all":
166-
include = list(cand)
167-
168-
# load history
169-
if hfile != "":
170-
hist = load(hfile, index=id_)
171-
else:
172-
hist = None
173-
174210
# do a quick test to get an idea of runtime
175211
if test:
176212
if sf_method == "irsf":
@@ -181,6 +217,9 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
181217
results = criterion(cand, args, nr, nd, mode=mode, hist=hist, test=True)
182218
# pylint: enable=unexpected-keyword-arg
183219
return results["t1"], results["t2"]
220+
elif mode == "maxpro":
221+
results = criterion(cand, args, nd, max_iter, hist=hist, test=True)
222+
return results["elapsed_time"]
184223
else:
185224
t0 = time.time()
186225
criterion(cand, args, nr, nd, mode=mode, hist=hist)
@@ -193,7 +232,12 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
193232

194233
# otherwise, run sdoe for real
195234
t0 = time.time()
196-
results = criterion(cand, args, nr, nd, mode=mode, hist=hist)
235+
236+
if mode != "maxpro":
237+
results = criterion(cand, args, nr, nd, mode=mode, hist=hist)
238+
else:
239+
results = criterion(cand, args, nd, max_iter, hist=hist)
240+
197241
elapsed_time = time.time() - t0
198242

199243
# save the output
@@ -212,16 +256,23 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
212256
order_blocks(fnames[mwr], difficulty)
213257

214258
if sf_method == "usf":
215-
suffix = "d{}_n{}_{}".format(nd, nr, "+".join(include))
216-
fnames = {
217-
"cand": os.path.join(outdir, "usf_{}.csv".format(suffix)),
218-
"dmat": os.path.join(outdir, "usf_dmat_{}.npy".format(suffix)),
219-
}
220-
save(fnames, results, elapsed_time)
221-
if all(x == "Hard" for x in diff_no_idx):
222-
rank(fnames)
223-
elif any(x == "Hard" for x in diff_no_idx):
224-
order_blocks(fnames, difficulty)
259+
if mode != "maxpro":
260+
suffix = "d{}_n{}_{}".format(nd, nr, "+".join(include))
261+
fnames = {
262+
"cand": os.path.join(outdir, "usf_{}.csv".format(suffix)),
263+
"dmat": os.path.join(outdir, "usf_dmat_{}.npy".format(suffix)),
264+
}
265+
save(fnames, results, elapsed_time)
266+
if all(x == "Hard" for x in diff_no_idx):
267+
rank(fnames)
268+
elif any(x == "Hard" for x in diff_no_idx):
269+
order_blocks(fnames, difficulty)
270+
else:
271+
suffix = "d{}_p{}_{}".format(nd, len(args["xcols"]), "+".join(include))
272+
fnames = {
273+
"cand": os.path.join(outdir, "maxpro_{}.csv".format(suffix)),
274+
}
275+
save(fnames, results, results["elapsed_time"], maxpro=True)
225276

226277
if sf_method == "irsf":
227278
fnames = {}

0 commit comments

Comments
 (0)