Skip to content

Commit 8c98cfa

Browse files
SDoE: implementing input type dependent ordering capability (#1194)
* implementing difficulty column and ordering depending on input difficulty. * remove order.py * add test for order_blocks function * add difficulty to config files so tests pass * save one final design * fix test_order * Format files with Black --------- Co-authored-by: Ludovico Bianchi <lbianchi@lbl.gov>
1 parent fbda808 commit 8c98cfa

8 files changed

Lines changed: 146 additions & 135 deletions

File tree

foqus_lib/framework/sdoe/order.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

foqus_lib/framework/sdoe/sdoe.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from dask.distributed import get_client
2525
import numpy as np
2626
import pandas as pd
27+
from python_tsp.exact import solve_tsp_dynamic_programming
2728

2829
from foqus_lib.framework.uq.Common import Common
2930
from foqus_lib.framework.uq.ResponseSurfaces import ResponseSurfaces
@@ -71,6 +72,10 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
7172
min_vals = [float(s) for s in config["INPUT"]["min_vals"].split(",")]
7273

7374
types = [s.strip() for s in config["INPUT"]["types"].split(",")]
75+
difficulty = [s.strip() for s in config["INPUT"]["difficulty"].split(",")]
76+
type_idx = types.index("Index")
77+
diff_no_idx = difficulty.copy()
78+
del diff_no_idx[type_idx]
7479
# 'Input' columns
7580
idx = [x for x, t in zip(include, types) if t == "Input"]
7681
# 'Index' column (should only be one)
@@ -202,6 +207,10 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
202207
"dmat": os.path.join(outdir, "nusf_dmat_{}.npy".format(suffix)),
203208
}
204209
save(fnames[mwr], results[mwr], elapsed_time)
210+
if all(x == "Hard" for x in diff_no_idx):
211+
rank(fnames[mwr])
212+
elif any(x == "Hard" for x in diff_no_idx):
213+
order_blocks(fnames[mwr], difficulty)
205214

206215
if sf_method == "usf":
207216
suffix = "d{}_n{}_{}".format(nd, nr, "+".join(include))
@@ -210,6 +219,10 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
210219
"dmat": os.path.join(outdir, "usf_dmat_{}.npy".format(suffix)),
211220
}
212221
save(fnames, results, elapsed_time)
222+
if all(x == "Hard" for x in diff_no_idx):
223+
rank(fnames)
224+
elif any(x == "Hard" for x in diff_no_idx):
225+
order_blocks(fnames, difficulty)
213226

214227
if sf_method == "irsf":
215228
fnames = {}
@@ -230,6 +243,47 @@ def run(config_file: str, nd: int, test: bool = False) -> Tuple[Dict, Dict, floa
230243
return fnames, results, elapsed_time
231244

232245

246+
def rank(fnames):
247+
"""return fnames ranked"""
248+
dist_mat = np.load(fnames["dmat"])
249+
250+
permutation, _distance = solve_tsp_dynamic_programming(dist_mat)
251+
252+
# retrieve ranked list
253+
cand = load(fnames["cand"])
254+
ranked_cand = cand.loc[permutation]
255+
256+
# save the output
257+
fname_ranked = fnames["cand"]
258+
259+
write(fname_ranked, ranked_cand)
260+
261+
return fname_ranked
262+
263+
264+
def order_blocks(fnames, difficulty):
265+
# load candidate set
266+
cand = load(fnames["cand"])
267+
cols = list(cand.columns)
268+
269+
diff_arr = np.array(difficulty)
270+
diff_idx_arr = np.where(diff_arr == "Hard")[0]
271+
diff_idx = list(diff_idx_arr)
272+
273+
col_order = []
274+
for i in diff_idx:
275+
col_order.append(cols[i])
276+
277+
sorted_cand = cand.sort_values(col_order)
278+
279+
# save the output
280+
fname_blocks = fnames["cand"]
281+
282+
write(fname_blocks, sorted_cand)
283+
284+
return fname_blocks
285+
286+
233287
def dataImputation(fname: str, y: int, rsMethodName: str, eval_fname: str) -> str:
234288
"""
235289
args: fname, y, rsMethodName, eval_fname

foqus_lib/framework/sdoe/test/config_irsf.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ min_vals = 0.0,0.0,0.0,0.0
1010
max_vals = 440.0,1.0,1.0,1.0
1111
include = __id,V1,V2,Y
1212
types = Index,Input,Input,Response
13+
difficulty = Easy,Easy,Easy,Easy
1314

1415
[SF]
1516
sf_method = irsf

foqus_lib/framework/sdoe/test/config_nusf.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ min_vals = 0.0,3004.0,1000.0,0.12,0.1,4.33
1010
max_vals = 372.0,11675.0,2750.0,0.18,0.3,9.3
1111
include = __id,L,G,w,lldg,CI Width Prior
1212
types = Index,Input,Input,Input,Input,Weight
13+
difficulty = Easy,Easy,Easy,Easy,Easy,Easy
1314

1415
[WEIGHT]
1516
weight_mode = by_user

foqus_lib/framework/sdoe/test/config_usf.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ min_vals = 0.0,0.12,1000.0,0.1,3020.0
1111
max_vals = 241.0,0.18,2700.0,0.3,11392.0
1212
include = __id,w,G,lldg,L
1313
types = Index,Input,Input,Input,Input
14+
difficulty = Easy,Easy,Easy,Easy,Easy
1415

1516
[SF]
1617
sf_method = usf

foqus_lib/framework/sdoe/test/test_order.py

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,11 @@
2424
import numpy as np
2525
import pandas as pd
2626

27-
from foqus_lib.framework.sdoe import df_utils, order
28-
29-
30-
def test_mat2tuples():
31-
"""Test mat2tuples"""
32-
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
33-
lte = order.mat2tuples(arr)
34-
assert lte == [(1, 0, 4), (2, 0, 7), (2, 1, 8)]
27+
from foqus_lib.framework.sdoe import df_utils, sdoe
3528

3629

3730
def test_rank():
38-
"""Call to order.rank() using hard-coded data written to temp files"""
31+
"""Call to sdoe.rank() using hard-coded data written to temp files"""
3932

4033
# candidate dataframe to write to cand file
4134
cand_df = pd.DataFrame(
@@ -137,11 +130,11 @@ def test_rank():
137130
dmat_fn = pl.Path(sys.path[0], "tmp_dmat.npy")
138131
np.save(dmat_fn, dmat)
139132

140-
# file name dict to be passed to order.rank()
133+
# file name dict to be passed to sdoe.rank()
141134
fnames = {"cand": str(cand_fn), "dmat": str(dmat_fn)}
142135

143136
# Make the actual call
144-
fname_ranked = order.rank(fnames)
137+
fname_ranked = sdoe.rank(fnames)
145138

146139
# Ranked results as a dataframe
147140
ret_ranked_df = df_utils.load(fname_ranked)
@@ -161,6 +154,50 @@ def test_rank():
161154
# Clean up tmp files
162155
cand_fn.unlink()
163156
dmat_fn.unlink()
164-
pl.Path(fname_ranked).unlink()
157+
158+
assert test_results
159+
160+
161+
def test_order_blocks():
162+
"""Call to sdoe.order_blocks() using hard-coded data written to temp files"""
163+
164+
# candidate dataframe to write to cand file
165+
cand_df = pd.DataFrame(
166+
{
167+
"w": [0.15, 0.15, 0.15, 0.175, 0.175, 0.15, 0.15, 0.15],
168+
"G": [2700, 2500, 2000, 2500, 2500, 1500, 1500, 2000],
169+
"lldg": [0.15, 0.15, 0.25, 0.25, 0.3, 0.15, 0.15, 0.3],
170+
"L": [10039, 9060, 7519, 7358, 6185, 3100, 3454, 8529],
171+
}
172+
)
173+
cand_fn = pl.Path(sys.path[0], "tmp_cand.csv")
174+
df_utils.write(cand_fn, cand_df)
175+
176+
# file name dict to be passed to sdoe.order_blocks()
177+
fnames = {"cand": str(cand_fn)}
178+
179+
# difficulty list
180+
difficulty = ["Hard", "Hard", "Easy", "Easy"]
181+
182+
# Make the actual call
183+
fname_blocks = sdoe.order_blocks(fnames, difficulty)
184+
185+
# Ranked results as a dataframe
186+
ret_blocks_df = df_utils.load(fname_blocks)
187+
188+
# Expected ranked results as dataframe
189+
blocks_df = pd.DataFrame(
190+
{
191+
"w": [0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.175, 0.175],
192+
"G": [1500, 1500, 2000, 2000, 2500, 2700, 2500, 2500],
193+
"lldg": [0.15, 0.15, 0.25, 0.3, 0.15, 0.15, 0.25, 0.3],
194+
"L": [3100, 3454, 7519, 8529, 9060, 10039, 7358, 6185],
195+
}
196+
)
197+
198+
test_results = ret_blocks_df.equals(blocks_df)
199+
200+
# Clean up tmp files
201+
cand_fn.unlink()
165202

166203
assert test_results

0 commit comments

Comments
 (0)