diff --git a/docs/source/chapt_sdoe/basics-runorder.rst b/docs/source/chapt_sdoe/basics-runorder.rst index 75ca82bcd..04aa9cfc7 100644 --- a/docs/source/chapt_sdoe/basics-runorder.rst +++ b/docs/source/chapt_sdoe/basics-runorder.rst @@ -34,7 +34,7 @@ A pop up window confirms the location of the newly ordered file (see below). Cli Both design files (located in the designated folder) are saved in the csv format, which can be opened with your preferred application (e.g. Microsoft Excel). You can produce a scatterplot of the ordered design file either using FOQUS or any other external application. -The ordering scheme provides a method for the user to design the experimental run order that follows the minimal path distance to traverse from one design point to another, i.e., minimal changes the the experimental processes. This standardizes the range of each input factor t to be between 0 and 1, and then minimizes the sum of the Euclidean distances between all of the points. Often this would be a preferred operational implementation to increase the efficiency of the experiment, by reducing the time for the process to reach equilibrium. The implementation provided uses the TSP (travelling sales person) algorithm as implemented in the 'mlrose' library in scikit-learn package for ordering/ranking the design points. +The ordering scheme provides a method for the user to design the experimental run order that follows the minimal path distance to traverse from one design point to another, i.e., minimal changes the the experimental processes. This standardizes the range of each input factor t to be between 0 and 1, and then minimizes the sum of the Euclidean distances between all of the points. Often this would be a preferred operational implementation to increase the efficiency of the experiment, by reducing the time for the process to reach equilibrium. The implementation provided uses the TSP (travelling sales person) algorithm as implemented in the 'python-tsp' library package for ordering/ranking the design points. An alternative to this approach is a simple sequential ordering (ascending or descending) of the most expensive input factor. This is easily implemented by the user, and can be efficient for the running of the experiment, but should be used cautiously because the run order might confound other changes in the system during the implementation of the experiment. diff --git a/foqus_lib/framework/sdoe/order.py b/foqus_lib/framework/sdoe/order.py index d16987388..6ef8c931f 100644 --- a/foqus_lib/framework/sdoe/order.py +++ b/foqus_lib/framework/sdoe/order.py @@ -13,16 +13,13 @@ # "https://github.com/CCSI-Toolset/FOQUS". ################################################################################# """ -Candidate ordering by TSP Optimization - -Code adopted from: -https://mlrose.readthedocs.io/en/stable/source/tutorial2.html - +Candidate ordering by TSP Optimization using python-tsp +https://pypi.org/project/python-tsp/ """ import logging import os import numpy as np -import mlrose_hiive as mlrose +from python_tsp.exact import solve_tsp_dynamic_programming from .df_utils import load, write _log = logging.getLogger("foqus." + __name__) @@ -40,26 +37,15 @@ def mat2tuples(mat): return lte -def rank(fnames, ga_max_attempts=25): +def rank(fnames): """return fnames ranked""" dist_mat = np.load(fnames["dmat"]) - dist_list = mat2tuples(dist_mat) - - # define fitness function object - fitness_dists = mlrose.TravellingSales(distances=dist_list) - - # define optimization problem object - n_len = dist_mat.shape[0] - problem_fit = mlrose.TSPOpt(length=n_len, fitness_fn=fitness_dists, maximize=False) - # solve problem using the genetic algorithm - best_state = mlrose.genetic_alg( - problem_fit, mutation_prob=0.2, max_attempts=ga_max_attempts, random_state=2 - )[0] + permutation, _distance = solve_tsp_dynamic_programming(dist_mat) # retrieve ranked list cand = load(fnames["cand"]) - ranked_cand = cand.loc[best_state] + ranked_cand = cand.loc[permutation] # save the output fname, ext = os.path.splitext(fnames["cand"]) diff --git a/foqus_lib/framework/sdoe/test/test_order.py b/foqus_lib/framework/sdoe/test/test_order.py index 9c0d14806..77151e248 100644 --- a/foqus_lib/framework/sdoe/test/test_order.py +++ b/foqus_lib/framework/sdoe/test/test_order.py @@ -142,7 +142,7 @@ def test_rank(): fnames = {"cand": str(cand_fn), "dmat": str(dmat_fn)} # Make the actual call - fname_ranked = order.rank(fnames, ga_max_attempts=5) + fname_ranked = order.rank(fnames) # Ranked results as a dataframe ret_ranked_df = df_utils.load(fname_ranked) @@ -151,9 +151,9 @@ def test_rank(): ranked_df = pd.DataFrame( { "w": [0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.175, 0.175], - "G": [2000, 2000, 1500, 1500, 2500, 2700, 2500, 2500], - "lldg": [0.3, 0.25, 0.15, 0.15, 0.15, 0.15, 0.25, 0.3], - "L": [8529, 7519, 3100, 3454, 9060, 10039, 7358, 6185], + "G": [2700, 2500, 1500, 1500, 2000, 2000, 2500, 2500], + "lldg": [0.15, 0.15, 0.15, 0.15, 0.25, 0.3, 0.3, 0.25], + "L": [10039, 9060, 3454, 3100, 7519, 8529, 6185, 7358], } ) diff --git a/setup.py b/setup.py index 16d4b4886..36149d733 100644 --- a/setup.py +++ b/setup.py @@ -92,7 +92,7 @@ "boto3", "cma", "matplotlib<3.6", - "mlrose_hiive==2.1.3", + "python-tsp==0.3.1", "joblib<1.3", # CCSI-Toolset/FOQUS#1154 "mplcursors", "numpy",