{"id":21241154,"url":"https://github.com/ccsi-toolset/measurement-optimization","last_synced_at":"2026-02-16T23:10:32.993Z","repository":{"id":220407087,"uuid":"511971308","full_name":"CCSI-Toolset/measurement-optimization","owner":"CCSI-Toolset","description":"Code for Measure This, Not That: Optimizing the Cost and Model-Based Informa- tion Content of Measurements","archived":false,"fork":false,"pushed_at":"2025-01-14T21:24:30.000Z","size":10373,"stargazers_count":2,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-14T01:54:39.695Z","etag":null,"topics":["applied-statistics","convex-optimization","data-science","design-of-experiments","pyomo"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CCSI-Toolset.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-07-08T17:13:53.000Z","updated_at":"2025-01-14T21:24:36.000Z","dependencies_parsed_at":"2024-02-25T05:22:23.771Z","dependency_job_id":"2b72d322-f55a-4229-a58b-60e21d225740","html_url":"https://github.com/CCSI-Toolset/measurement-optimization","commit_stats":null,"previous_names":["dowlinglab/measurement-opt","dowlinglab/measurement-optimization","ccsi-toolset/measurement-optimization"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CCSI-Toolset%2Fmeasurement-optimization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CCSI-Toolset%2Fmeasurement-optimization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CCSI-Toolset%2Fmeasurement-optimization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CCSI-Toolset%2Fmeasurement-optimization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CCSI-Toolset","download_url":"https://codeload.github.com/CCSI-Toolset/measurement-optimization/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248809032,"owners_count":21164895,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["applied-statistics","convex-optimization","data-science","design-of-experiments","pyomo"],"created_at":"2024-11-21T00:54:49.536Z","updated_at":"2026-02-16T23:10:27.948Z","avatar_url":"https://github.com/CCSI-Toolset.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# *Measurement This, Not That: Optimizing the Cost and Model-Based Information Content of Measurements*\n\nAuthors: Jialu Wang, Zedong Peng, Ryan Hughes, Debangsu Bhattacharyya, David E. Bernal Neira, Alexander W. Dowling \n\nThis repository contains code and results for the paper: *Measure This, Not That: Optimizing the Cost and Model-based Information Content of Measurements* \n\nQuestions: Please contact Prof. Alex Dowling (adowling@nd.edu). This repository is primarily to archive the code. It may not be maintained. The version of software packages used to generate results are given in the paper.\n\n## Installation instructions \n\nThe following instructions assume you have anaconda installed. We suggest creating an environment with the following commands to run code: \n\n### Step 1: create a new environment \n- create new environment, called for e.g. `measurement_optimization`, with `conda` with `Python` version 3.8\nUpdate on May 14: Python 3.8 is not necessary (sometimes even causing problem.) Let's switch to the most updated Python. This is tested to have no problems. \n\n`conda create --name measurement_optimization`\n\n`conda activate measurement_optimization`\n   \n### Step 2 (optional): install `IDAES-PSE`\n- this step provides `Ipopt` solver, but this solver is not necessary for reproducing paper results if you already have `Ipopt`. If step 2 is conducted, step 3 can be skipped\n\n`pip install idaes-pse` \n\n`idaes get-extensions`\n\n### Step 3: install `numpy`, `scipy`, `pandas`, `matplotlib` \n- If not installing `IDAES-PSE`, the following packages are needed: \n  \n`conda install numpy`\n\n`conda install scipy`\n\n`conda install pandas`\n\n`conda install matplotlib`\n   \n### Step 4: install `Pyomo` from specified branches\n- install from the following branch for a generalization version of Mindtpy:\n\n`pip install git+https://github.com/ZedongPeng/pyomo.git@add_mindtpy_callback`\n\n   \n### Step 5: install `GurobiPy`\n- this is needed only for solving mixed-integer problems\n\n  `conda install -c gurobi gurobi`\n\n  (By Feb. 25 2024) ND CRC users: CRC hasn't updated their gurobi license to version 11. If you install gurobi without specifying version 10, it will pop an error about not having license for version 11. To specify a version for CRC:\n\n  `conda install -c gurobi gurobi==10.0.3`\n   \n### Step 6: install `CyIpopt`\n- this is needed only for D-optimality problems with grey-box modules\n\n   `conda install -c conda-forge cyipopt`\n\n### Step 7: install `jupyter notebook`\n- this is needed only for the draw_figure.ipynb notebook\n\n  `conda install jupyter notebook`\n\n### (Optional) Build `PyNumero`\n\nIf you get errors related to the ASL library, AmplInterface, etc., you may need to [rebuild PyNumero](https://pyomo.readthedocs.io/en/latest/explanation/solvers/pynumero/installation.html).\n\n### (Optional) `Cvxpy` environment setting\n- this is needed only for constructing and solving the problem with `cvxpy`. \n\n  Step 1: same as step 1 above to create the environment\n\n  Step 2: same as step 3 above to install dependencies\n\n  Step 3: install cvxpy with: \n\n  `conda install -c conda-forge cvxpy`\n\n  Step 4: install `Mosek`. You need to validate a license for using this solver, see the link: https://docs.mosek.com/latest/install/installation.html\n\n### Software versions we use for the results \n\n`Python`: 3.8\n\n`IDAES-PSE`: 2.2.0\n\n`Pyomo`: 6.7.0 dev 0\n\n`GurobiPy`: 10.0.3\n\n`CyIpopt`: 1.3.0\n\n`Cvxpy`: 1.2.1\n\n## Code \n\n- `measure_optimize.py`: Measurement optimization optimization framework\n\n- `greybox_generalize.py`: Grey-box generalization \n\n- `kinetics_MO.py`: Kinetics case study\n\n- `rotary_bed_MO.py`: Rotary bed case study\n\n- `draw_figure.ipynb`: Generates all results figures in the manuscript\n\n- `cvxpy_problem.py`: Kinetics case study implemented with `Cvxpy`\n\n## Example to run code and reproduce figures for case studies\n\nSetup the scripts to reproduce result files and figures from the paper: \n\n### Kinetics case study \n\n- Step 1: run `kinetics_MO.py`\n- Step 2: with `mip_option` and `objective`, choose to run the A-optimality or D-optimality, mixed-integer or relaxed problem \n- Step 3: with `rerun_all_paper_results`, set up the budget ranges as you want to try. \n\n  If `rerun_all_paper_results`: we use the budget range [1000, 5000] with a 400 discretization,\n  i.e. [1000, 1400, 1800, ..., 5000] for mixed-integer problems.\n\n  Otherwise, we use three budget [1000, 2200, 3800] to do a test run.\n  \n- Step 4: with `linear_solver_opt`, choose the linear solver for `CyIpopt`. If not specified, it will use the default linear solver, which is `ma27` if you have HSL, otherwise `mumps`. \n\n- Step 5: with `initializer_option` and `curr_results`, select initial solutions to initialize the problem, and provide file paths for these solutions\n\n  You can choose from: A- and D-optimality, with mixed-integer or continuous options. In the paper, both objective functions and both mixed-integer and continuous frameworks are considered and solved. Refer to Eq. (11) in section 2.3 for the MO problem with mixed-integer and continuous options, Eq. (12), (13) in section 2.4 for A- and D-optimality. \n  \n- Step 6: store results for drawing figures\n\n  To do this, define the param `file_store_name` with a string you given, for e.g., \"MINLP_result_\".\n\n  Then both the solutions and the FIM of the results are stored separately.\n\n  For e.g., if running in the range [1000, 5000], the stored files will be:\n\n  MINLP_result_1000, MINLP_result_fim_1000,\n\n  ...\n\n  MINLP_result_5000, MINLP_result_fim_5000,\n  \n- Step 7: use draw_figure.ipynb to read stored FIM and solutions\n\n  - `read_fim` receives the string name, for.e.g. `MINLP_result_`, and budget ranges, returns a list of A- and D-optimality values of the given FIMs\n \n  - `plot_data` receives both the A- and D-optimality of all four optimization strategies, and draw two figures like Fig. 3 in paper\n \n  - `read_solution` receives the string name, for e.g. `MINLP_result_`, and budget ranges, returns 6 lists: CA, CB, CC solutions as SCM and DCM,\n    each list contains four lists as results from four strategies\n \n  - `plot_one_solution` receives and draws the solution of one measurement under four strategies. To reproduce result figure like Fig. S-2 in paper, call it 6 times to draw all 6 figures and combine to a panel figure. \n\n\n### Kinetics case study with Cvxpy \n\n- Step 1: run `cvxpy_problem.py`\n- Step 2: with `mip_option` and `objective`, choose to run the A-optimality or D-optimality, mixed-integer or relaxed problem \n- Step 3: with `test`, set up the budget ranges as you want to try. \n\n  If `test` is False: we use the budget range [1000, 5000] with a 400 discretization,\n  i.e. [1000, 1400, 1800, ..., 5000] for mixed-integer problems.\n\n  Otherwise, we use three budget [3000, 5000] to do a test run.\n  \n- Step 4: store results for drawing figures\n\n  To do this, define the param `file_store_name` with a string you given, for e.g., \"MINLP_result_\".\n\n  Then both the solutions and the FIM of the results are stored separately.\n\n  For e.g., if running in the range [1000, 5000], the stored files will be:\n\n  MINLP_result_1000, MINLP_result_fim_1000,\n\n  ...\n\n  MINLP_result_5000, MINLP_result_fim_5000,\n  \n- Step 7: use draw_figure.ipynb to read stored FIM and solutions\n\n  - `read_fim` receives the string name, for.e.g. `MINLP_result_`, and budget ranges, returns a list of A- and D-optimality values of the given FIMs\n \n  - `plot_data` receives the Cvxpy solution and Pyomo solution, and draws them on the same figure\n\n### Rotary bed case study \n\n- Step 1: run `rotary_bed_MO.py`\n- Step 2: with `mip_option` and `objective`, choose to run the A-optimality or D-optimality, mixed-integer or relaxed problem \n- Step 3: with `rerun_all_paper_results`, set up the budget ranges as you want to try. \n\n  If `rerun_all_paper_results`: In our results, we use the budget range [1000, 25000] with a 1000 discretization,\n  i.e. [1000, 11000, ..., 25000], for relaxed problems\n\n  Otherwise, we use three budget [1000, 5000, 15000] to do a test run.\n\n- Step 4: with `linear_solver_opt`, choose the linear solver for `CyIpopt`. If not specified, it will use the default linear solver, which is `ma27` if you have HSL, otherwise `mumps`.\n  \n- Step 5: with `initializer_option` and `curr_results`, select initial solutions to initialize the problem, and provide file paths for these solutions\n\n  You can choose from: A- and D-optimality, with mixed-integer or continuous options. \n  \n- Step 6: store results for drawing figures\n\n  To do this, define the param `file_store_name` with a string you given, for e.g., \"MINLP_result_\".\n\n  Then both the solutions and the FIM of the results are stored separately.\n\n  For e.g., if running in the range [1000, 25000], the stored files will be:\n\n  MINLP_result_1000, MINLP_result_fim_1000,\n\n  ...\n\n  MINLP_result_25000, MINLP_result_fim_25000,\n  \n- Step 7: use draw_figure.ipynb to read stored FIM and solutions\n\n  - `read_fim` receives the string name, for.e.g. `MINLP_result_`, and budget ranges, returns a list of A- and D-optimality values of the given FIMs\n \n  - `plot_data` receives both the A- and D-optimality of all four optimization strategies, and draw two figures like Fig. 6 in paper\n\n\n## Source files\n\n### Kinetics case study \n\n- `./kinetics_source_data/reactor_kinetics.py`: kinetics case study model  \n- `./kinetics_source_data/Q_drop0.csv`: contain Jacobian for this case study, data structure as the following:\n  \n  0   |  A1  |  A2  |  E1  |  E2  |\n  \n  1   |  num | num  | num  | num  |\n\n  ...\n\n  24  |  num | num  | num  | num  |\n\n  Rows: measurements (C_A, C_B, C_C, each measurement has 8 time points)\n  Columns: parameters (4 parameters)\n\n### Rotary bed case study \n\n- `./rotary_source_data/RotaryBed-DataProcess.ipynb`: process rotary bed measurements data from `Aspen Custom Modeler`, generate Jacobian\n- `./rotary_source_data/Q110_scale.csv`: contain Jacobian for this case study, data structure as the following:\n\n  0   |  MTC  |  HTC  |  DH  |  ISO1  |  ISO2 |\n   \n  1   |  num | num  | num  | num  | num |\n\n  ...\n\n  1540  |  num | num  | num  | num  | num |\n\n  Rows: measurements (14 measurements, each has 110 time points)\n  Columns: parameters (5 parameters)\n\n\n## Result files \n\n### Kinetics case study\n\nAt each budget, the FIM result and the optimal solution are stored separately in `pickle` files. \nComputational details including solver time and numbers of operations are also stored separately in `pickle` files.\n\n#### FIM of final results \n\nAn example name: `LP_fim_1000_a`, the results of A-optimality LP problem of a budget of 1000 \n\nData file type: `pickle`, storing a numpy array of FIM of the shape Np*Np, Np is the number of parameters \n\nTo replicate the results, iterate in the given budget range to retrieve the FIM stored in each data file\n\n- A-optimality LP results: `kinetics_results/LP_fim_x_a`, x in the range [1000, 1100, 1200, ..., 5000]\n\n- A-optimality MILP results: `kinetics_results/MILP_fim_x_a`, x in the range [1000, 1400, 1800, ..., 5000]\n\n- D-optimality NLP results: `kinetics_results/NLP_fim_x_d`, x in the range [1000, 1100, 1200, ..., 5000]\n\n- D-optimality MINLP results: `kinetics_results/MINLP_fim_x_d_mip`, x in the range [1000, 1400, 1800, ..., 5000]\n\n- Operating cost results: `kinetics_results/Operate_fim_x_d_mip`, x in the range [1000, 1400, 1800, ..., 5000]\n\n#### Optimal solutions\n\nAn example name: `LP_1000_a`, the results of A-optimality LP problem of a budget of 1000 \n\nData file type: `pickle`, storing a numpy array of the solutions of the shape Nm*Nm, Nm is the number of all measurements\n\n- A-optimality LP results: `kinetics_results/LP_x_a`, x in the range [1000, 1100, 1200, ..., 5000]\n\n- A-optimality MILP results: `kinetics_results/MILP_x_a`, x in the range [1000, 1400, 1800, ..., 5000]\n\n- D-optimality NLP results: `kinetics_results/NLP_x_d`, x in the range [1000, 1100, 1200, ..., 5000]\n\n- D-optimality MINLP results: `kinetics_results/MINLP_x_d`, x in the range [1000, 1400, 1800, ..., 5000]\n\n- Operating cost results: `kinetics_results/Operate_x_d_mip`, x in the range [1000, 1400, 1800, ..., 5000]\n\n#### Computational details \n\nThe computational details are stored separately. \n\nFor A-optimality LP and MILP problems, the `pickle` files store a numpy array of the solver time of each budget \n\nFor D-optimality NLP and MINLP problems, the `pickle` files store a dictionary, where the keys are the budgets. An example is: \n\n`nlp_time={1000: {\"t\": 0.01, \"n\": 10}, ..., \"5000\": {\"t\": 0.01, \"n\": 10}}`\n\nFor each budget, the value is a dictionary where the key `t` stores the solver time, `n` stores the number of iterations\n\n- A-optimality LP solver time: \"kinetics_time_lp\"\n\n- A-optimality MILP solver time: \"kinetics_time_milp\"\n\n- D-optimality NLP iterations and solver time: \"kinetics_time_iter_nlp\"\n\n- D-optimality MINLP iterations and solver time: \"kinetics_time_iter_minlp\"\n\n\n### Rotary bed case study \n\nAt each budget, the FIM result and the optimal solution are stored separately in `pickle` files. \nComputational details including solver time and numbers of operations are also stored separately in `pickle` files.\n\n\n#### FIM of optimal solutions\n\nAn example name: `LP_fim_1000_a`, the results of A-optimality LP problem of a budget of 1000 \n\nData file type: `pickle`, storing a numpy array of FIM of the shape Np*Np, Np is the number of parameters \n\nTo replicate the results, iterate in the given budget range to retrieve the FIM stored in each data file\n\n- A-optimality LP results: `rotary_results/LP_fim_x_a`, x in the range [1000, 2000, 3000, ..., 25000]\n\n- A-optimality MILP results: `rotary_results/MILP_FIM_A_mip_x`, x in the range [1000, 2000, 3000, ..., 25000]\n\n- D-optimality NLP results: `rotary_results/NLP_fim_x_d`, x in the range [1000, 2000, 3000, ..., 25000]\n\n- D-optimality MINLP results: `rotary_results/MILP_fim_x_d_mip`, x in the range [1000, 2000, 3000, ..., 25000]\n\n#### Optimal solutions\n\nAn example name: `LP_1000_a`, the results of A-optimality LP problem of a budget of 1000 \n\nData file type: `pickle`, storing a numpy array of the solutions of the shape Nm*Nm, Nm is the number of all measurements\n\n\n- A-optimality LP results: `rotary_results/LP_x_a`, x in the range [1000, 2000, 3000, ..., 25000]\n\n- A-optimality MILP results: `rotary_results/MILP_A_mip_x`, x in the range [1000, 2000, 3000, ..., 25000]\n\n- D-optimality NLP results: `rotary_results/NLP_x_d`, x in the range [1000, 2000, 3000, ..., 25000]\n\n- D-optimality MINLP results: `rotary_results/MILP_x_d_mip`, x in the range [1000, 2000, 3000, ..., 25000]\n\n#### Computational details \n\nThe computational details are stored separately. \n\nFor A-optimality LP and MILP problems, the `pickle` files store a numpy array of the solver time of each budget \n\nFor D-optimality NLP and MINLP problems, the `pickle` files store a dictionary, where the keys are the budgets. An example is: \n\n`nlp_time={1000: {\"t\": 0.01, \"n\": 10}, ..., \"5000\": {\"t\": 0.01, \"n\": 10}}`\n\nFor each budget, the value is a dictionary where the key `t` stores the solver time, `n` stores the number of iterations\n\n- A-optimality LP solver time: `rotary_time_lp`\n\n- A-optimality MILP solver time: `rotary_time_milp`\n\n- D-optimality NLP iterations and solver time: `rotary_time_iter_nlp`\n\n- D-optimality MINLP iterations and solver time: `rotary_time_iter_minlp`\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fccsi-toolset%2Fmeasurement-optimization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fccsi-toolset%2Fmeasurement-optimization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fccsi-toolset%2Fmeasurement-optimization/lists"}