├── LICENSE ├── Production Scheduling Identification.pdf ├── README.md ├── add_dual_constraints.m ├── add_grid_priori.m ├── add_primal_constraints.m ├── add_varDef_and_initVal.m ├── data_prepare ├── README.md ├── aggregate_get_g.m ├── data_generate_cement.m ├── data_generate_steelpowder.m ├── data_price.m ├── data_price_2.m ├── dataset_cement.mat ├── dataset_steelpowder.mat ├── load_parameters_Golmo_milp.xlsx ├── load_parameters_Lu_milp.xlsx ├── load_primal_problem_milp.m ├── plot_typical_load.m ├── rt_hrl_lmps.xlsx └── rt_hrl_lmps_202208.xlsx ├── inverse_optimization.m ├── main_cement.m ├── main_steelpowder.m ├── results ├── 0226_20_training_set_120 │ ├── test_Lu_gen_10stages_120.mat │ └── test_Lu_gen_12stages_120.mat ├── 0227_no_assumption_e │ ├── test_Lu_gen_10stages_120.mat │ ├── test_Lu_gen_12stages_120.mat │ ├── test_Lu_gen_14stages_120.mat │ ├── test_Lu_gen_16stages_120.mat │ ├── test_Lu_gen_18stages_120.mat │ ├── test_Lu_gen_20stages_120.mat │ ├── test_Lu_gen_22stages_120.mat │ ├── test_Lu_gen_24stages_120.mat │ ├── test_Lu_gen_3stages_120.mat │ ├── test_Lu_gen_5stages_120.mat │ ├── test_Lu_gen_6stages_120.mat │ └── test_Lu_gen_8stages_120.mat ├── 0301_no_assumption_b │ ├── test_Lu_gen_10stages_120.mat │ ├── test_Lu_gen_12stages_120.mat │ ├── test_Lu_gen_14stages_120.mat │ ├── test_Lu_gen_16stages_120.mat │ ├── test_Lu_gen_18stages_120.mat │ ├── test_Lu_gen_20stages_120.mat │ ├── test_Lu_gen_5stages_120.mat │ ├── test_Lu_gen_6stages_120.mat │ └── test_Lu_gen_8stages_120.mat ├── 0301_no_assumption_c │ ├── test_Lu_gen_10stages_120.mat │ ├── test_Lu_gen_12stages_120.mat │ ├── test_Lu_gen_14stages_120.mat │ ├── test_Lu_gen_16stages_120.mat │ ├── test_Lu_gen_18stages_120.mat │ ├── test_Lu_gen_20stages_120.mat │ ├── test_Lu_gen_5stages_120.mat │ ├── test_Lu_gen_6stages_120.mat │ └── test_Lu_gen_8stages_120.mat ├── 0314_10_training_set │ ├── test_Lu_gen_10stages_120.mat │ ├── test_Lu_gen_12stages_120.mat │ ├── test_Lu_gen_14stages_120.mat │ ├── test_Lu_gen_16stages_120.mat │ ├── test_Lu_gen_18stages_120.mat │ ├── test_Lu_gen_20stages_120.mat │ ├── test_Lu_gen_5stages_120.mat │ ├── test_Lu_gen_6stages_120.mat │ └── test_Lu_gen_8stages_120.mat ├── 0314_5_training_set │ ├── test_Lu_gen_10stages_120.mat │ ├── test_Lu_gen_12stages_120.mat │ ├── test_Lu_gen_14stages_120.mat │ ├── test_Lu_gen_16stages_120.mat │ ├── test_Lu_gen_18stages_120.mat │ ├── test_Lu_gen_20stages_120.mat │ ├── test_Lu_gen_5stages_120.mat │ ├── test_Lu_gen_6stages_120.mat │ └── test_Lu_gen_8stages_120.mat ├── README.md ├── accuracy.pdf ├── cal_rmse_ml_cement.m ├── cal_rmse_ml_steelpowder.m ├── cal_rmse_test.m ├── load_primal_problem.m ├── ml_results │ ├── predict_LSTM_20230226.mat │ ├── predict_LSTM_20230226_baseline.mat │ ├── predict_LSTM_20240828.mat │ ├── predict_LSTM_20240828_baseline.mat │ ├── predict_MLP_20230226.mat │ ├── predict_MLP_20230226_baseline.mat │ ├── predict_MLP_20240828.mat │ ├── predict_MLP_20240828_baseline.mat │ ├── predict_SVR_20230226.mat │ ├── predict_SVR_20230226_baseline.mat │ ├── predict_svr_20240828.mat │ └── predict_svr_20240828_baseline.mat ├── plot_box.m ├── plot_rmse_methods.m ├── plot_typical_cement.m ├── plot_typical_steel.m ├── total_table_methods.mat ├── total_table_noftraining_set.mat ├── total_table_removing_priori.mat ├── total_table_wrt_m.mat ├── typical_load.pdf ├── typical_load_cement.pdf ├── typical_load_steel.pdf └── variation.pdf ├── 工业过程建模与参数辨识-0522-PSI.pdf └── 工业过程建模与参数辨识-0522-PSI.pptx /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Ruike Lyu (吕睿可) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Production Scheduling Identification.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/Production Scheduling Identification.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## README 2 | 3 | # Production Scheduling Identification: An Inverse Optimization Approach for Industrial Load Modeling Using Smart Meter Data 4 | 5 | Video: https://www.bilibili.com/video/BV1bXQDYcE8Y/?vd_source=18e4b7b95b505bbe9bf571ca4ff73d55 6 | 7 | 8 | ![image](https://github.com/user-attachments/assets/3392dc91-1d46-48f3-96fa-cc7e0b19fbc9) 9 | 10 | This repository contains data and code for our paper "Production Scheduling Identification: An Inverse Optimization Approach for Industrial Load Modeling Using Smart Meter Data", which has been accepted by IEEE Transactions on Smart Grid. 11 | 12 | If you find this code useful for your research, please consider citing our paper: 13 | ```bibtex 14 | @article{lyu2024production, 15 | title={Production Scheduling Identification: An Inverse Optimization Approach for Industrial Load Modeling Using Smart Meter Data}, 16 | author={Ruike Lyu, Hongye Guo, Qinghu Tang, Qixin Chen, Chongqing Kang}, 17 | journal={IEEE Transactions on Smart Grid}, 18 | year={2024}, 19 | publisher={IEEE} 20 | } 21 | ``` 22 | 23 | ## File Structure Overview 24 | - `data_prepare` folder: Contains code that utilizes PJM electricity price data and a state-task network (STN) model constructed based on parameters from literature for simulating optimal energy utilization results for these two factories on different dates. 25 | - `results` folder: Contains our results and visualization code. 26 | - `main_cement` and `main_steelpowder`: Main programs for fitting industrial assembly line model parameters through inverse optimization on datasets from cement and steel powder plants. These programs call `add_varDef_and_initVal` for variable definition and initialization, use files starting with `add_` to add various constraints for the inverse optimization problem, and apply our proposed iterative algorithm based on zeroth-order stochastic gradient descent to solve the inverse optimization problem (inverse_optimization). 27 | 28 | Please note that this is a standalone research code repository with concise comments (due to my busy Ph.D. schedule). I expect readers to understand the code implementation after reading our paper, rather than solely relying on code comments to grasp the underlying principles. 29 | 30 | # Frequently Asked Questions (FAQ) - English Version 31 | 32 | ## 1. What information is accessible and inaccessible in industrial load modeling? 33 | 34 | Information in industrial load modeling can be categorized into three types: 35 | 36 | 1. **Prior Public Knowledge**: 37 | - Obtainable through internet or expert knowledge 38 | - Independent of specific factory parameters 39 | - Includes standard information like unit energy consumption 40 | 41 | 2. **Specific Facility Parameters** (not directly accessible): 42 | - Rated power of equipment at each production stage 43 | - Material storage space 44 | - Production goals 45 | - Other facility-specific parameters 46 | 47 | 3. **Smart Meter Data**: 48 | - 15-minute or hourly average power readings 49 | - Usually available from grid operators or load aggregators 50 | - Not public but usable for modeling 51 | 52 | ## 2. What are the main innovations of the PSI framework? 53 | 54 | The PSI framework's innovations are threefold: 55 | 56 | 1. **Addressing Incomplete Information**: 57 | - First to propose industrial user modeling using only smart meter data 58 | - Solves the challenge of inaccessible internal parameters due to privacy concerns 59 | 60 | 2. **Improved STN Model**: 61 | - Introduces mSTN model with linear form 62 | - Adopts per-unit parameter system 63 | - Enables task aggregation 64 | 65 | 3. **Practical Algorithm Implementation**: 66 | - Designs appropriate loss function 67 | - Uses iterative approach for multi-day data 68 | - Validates feasibility through numerical results 69 | 70 | ## 3. What does model parameter θ represent? What is its physical interpretation? 71 | 72 | Parameter θ includes: 73 | - Rated power of equipment at each production stage 74 | - Material storage space 75 | - Initial material quantities 76 | - Production targets 77 | - Other facility-specific parameters 78 | 79 | These parameters directly reflect the physical characteristics and operational constraints of industrial facilities. 80 | 81 | ## 4. What are the limitations of the PSI method? 82 | 83 | The PSI method has several limitations: 84 | 85 | 1. **Model Assumptions**: 86 | - Assumes production targets remain constant over time 87 | - Doesn't consider equipment start-stop time constraints 88 | - Doesn't account for ramping constraints 89 | - Doesn't include nonlinear production efficiency 90 | 91 | 2. **Data Requirements**: 92 | - Requires sufficient historical smart meter data 93 | - Needs reliable electricity price data 94 | 95 | 3. **Application Scope**: 96 | - Mainly suitable for industrial loads that can be described by STN model 97 | - May not be applicable to all types of industrial processes 98 | 99 | 100 | ## 中文版README 101 | 102 | # 生产调度识别:利用智能电表数据的工业负荷参数辨识 103 | 104 | 这个代码库包含了与我们发表在 IEEE Transactions on Smart Grid 的论文相关的数据和代码。 105 | 106 | 如果您觉得这些代码对您的研究有帮助,请考虑引用我们的论文。 107 | 108 | 109 | ## 文件结构说明 110 | - `data_prepare` 文件夹: 包含利用PJM电价数据和基于文献中水泥厂和钢厂参数构建的状态-任务网络(STN)模型来模拟这两个工厂在不同日期下的最优能源利用结果的代码。 111 | - `results` 文件夹: 存放了我们的结果和可视化代码。 112 | - `main_cement` 和 `main_steelpowder`: 在水泥厂和钢粉厂数据集上通过逆向优化拟合工业流水线模型参数的主程序。这些程序会调用 `add_varDef_and_initVal` 来定义变量并初始化,调用以 `add_` 开头的几个文件来添加逆向优化问题的不同约束,并应用我们提出的基于零阶随机梯度下降的迭代算法来求解逆向优化问题(inverse_optimization)。 113 | 114 | 请注意,这是一个独立研究的代码库,我的注释相对简略(因为我是一个忙碌的博士生)。我期望读者在阅读我们的论文后能够理解代码实现,而不仅仅依靠代码注释来理解背后的原理。 115 | 116 | # 常见问题解答 (FAQ) - 中文版 117 | 118 | ## 1. 在工业负荷建模中,哪些信息是可获取的,哪些是不可获取的? 119 | 120 | 工业负荷建模中的信息可分为三类: 121 | 122 | 1. **先验公共知识**: 123 | - 可通过互联网或专家知识获取 124 | - 与具体工厂参数无关 125 | - 包括生产过程的单位能耗等标准信息 126 | 127 | 2. **具体设施参数**(不可直接获取): 128 | - 各生产阶段设备的额定功率 129 | - 物料存储空间 130 | - 生产目标 131 | - 其他设施特定参数 132 | 133 | 3. **智能电表数据**: 134 | - 15分钟或每小时的平均功率读数 135 | - 通常可从电网运营商或负荷聚合商处获取 136 | - 虽不公开但可用于建模 137 | 138 | ## 2. PSI框架的主要创新点是什么? 139 | 140 | PSI框架的创新主要体现在三个方面: 141 | 142 | 1. **解决信息不完整问题**: 143 | - 首次提出仅使用智能电表数据进行工业用户建模 144 | - 解决了因隐私问题无法获取内部参数的挑战 145 | 146 | 2. **改进STN模型**: 147 | - 提出mSTN模型,保持线性形式 148 | - 采用参数单位制 149 | - 支持任务聚合 150 | 151 | 3. **实用算法实现**: 152 | - 设计了合适的损失函数 153 | - 采用迭代方式处理多天数据 154 | - 通过数值结果验证了可行性 155 | 156 | ## 3. 模型参数θ代表什么?有什么物理意义? 157 | 158 | 参数θ包括: 159 | - 工厂内各生产阶段设备的额定功率 160 | - 物料存储空间 161 | - 初始物料量 162 | - 生产目标 163 | - 其他设施特定参数 164 | 165 | 这些参数直接反映了工业设施的物理特性和运行约束。 166 | 167 | ## 4. PSI方法的局限性是什么? 168 | 169 | PSI方法存在以下局限: 170 | 171 | 1. **模型假设**: 172 | - 假设生产目标在一段时间内保持不变 173 | - 未考虑设备启停时间约束 174 | - 未考虑爬坡约束 175 | - 未考虑非线性生产效率 176 | 177 | 2. **数据要求**: 178 | - 需要足够的历史智能电表数据 179 | - 需要可靠的电价数据 180 | 181 | 3. **应用范围**: 182 | - 主要适用于可用STN模型描述的工业负荷 183 | - 可能不适用于所有类型的工业过程 184 | 185 | -------------------------------------------------------------------------------- /add_dual_constraints.m: -------------------------------------------------------------------------------- 1 | %% Dual Problem Constraints and Prior Assumptions 2 | Constraints_dual = []; 3 | 4 | % Constraints corresponding to P_t_i 5 | Constraints_dual = [Constraints_dual, repmat(Price * delta_t, 1, NOFMACHINES) - mu_P_min + mu_P_max ... 6 | + lambda_S(2:end, 1:NOFMACHINES) .* repmat(g_td, NOFINTERVALS, 1) ... 7 | - lambda_S(2:end, 2:NOFMACHINES+1) .* repmat(g_td, NOFINTERVALS, 1) == 0]; 8 | 9 | % Constraints corresponding to S_t_i (t ~= T) 10 | Constraints_dual = [Constraints_dual, lambda_S(1:end-1, :) - lambda_S(2:end, :) ... 11 | - mu_S_min(1:end-1, :) + mu_S_max(1:end-1, :) == 0]; 12 | % Constraints corresponding to S_t_i (t = T) 13 | Constraints_dual = [Constraints_dual, -mu_S_T + lambda_S(end, :) ... 14 | - mu_S_min(end, :) + mu_S_max(end, :) == 0]; 15 | 16 | % Non-negativity of dual variables (lambda does not need to be non-negative) 17 | Constraints_dual = [Constraints_dual, mu_P_max >= 0]; 18 | Constraints_dual = [Constraints_dual, mu_P_min >= 0]; 19 | Constraints_dual = [Constraints_dual, mu_S_T >= 0]; 20 | Constraints_dual = [Constraints_dual, mu_S_max >= 0]; 21 | Constraints_dual = [Constraints_dual, mu_S_min >= 0]; 22 | 23 | % Dual Problem Objective Function 24 | g_dual = -sum(mu_P_max * P_max_td') ... 25 | + mu_S_T * (S_0_td + S_tar_td)' ... 26 | - sum(mu_S_max * S_max_td') ... 27 | - sum(lambda_S(1, :) * S_0_td'); 28 | -------------------------------------------------------------------------------- /add_grid_priori.m: -------------------------------------------------------------------------------- 1 | %% Prior Assumptions 2 | M = 1e3; % Large number 3 | Constraints_priori = []; 4 | % Limit variable sizes 5 | % Basic parameter constraints (when there are original problem constraints, non-negativity constraints may not be necessary) 6 | Constraints_priori = [Constraints_priori, P_max_td <= M]; 7 | Constraints_priori = [Constraints_priori, g_td <= M]; 8 | Constraints_priori = [Constraints_priori, S_0_td <= M]; 9 | Constraints_priori = [Constraints_priori, S_max_td <= M]; 10 | 11 | % Dual variable constraints 12 | Constraints_priori = [Constraints_priori, mu_P_max <= M]; 13 | Constraints_priori = [Constraints_priori, mu_P_min <= M]; 14 | Constraints_priori = [Constraints_priori, mu_S_T <= M]; 15 | Constraints_priori = [Constraints_priori, mu_S_max <= M]; 16 | Constraints_priori = [Constraints_priori, mu_S_min <= M]; 17 | 18 | % Material conservation assumption (middle interval target is 0, first and last are negative and positive) 19 | Constraints_priori = [Constraints_priori, S_tar_td(2:end-1) == 0]; 20 | Constraints_priori = [Constraints_priori, S_tar_td(end) >= 0]; 21 | Constraints_priori = [Constraints_priori, S_tar_td(1) == -S_tar_td(end) - 100]; 22 | 23 | % Maximum power previously observed (in historical data on these days) 24 | Constraints_priori = [Constraints_priori, P_max_td * ones(NOFMACHINES, 1) * delta_t == max_E_t]; 25 | -------------------------------------------------------------------------------- /add_primal_constraints.m: -------------------------------------------------------------------------------- 1 | %% Add Constraints from the Original Problem to the Inverse Problem, similar to load_primal_problem 2 | %% Only some parameters from the original problem are now variables 3 | 4 | %% Constraints 5 | Constraints_primal = []; 6 | 7 | % Power range constraints 8 | Constraints_primal = [Constraints_primal, -P <= 0]; 9 | Constraints_primal = [Constraints_primal, P <= repmat(P_max_td, NOFINTERVALS, 1)]; 10 | 11 | % Material target (end of interval) 12 | Constraints_primal = [Constraints_primal, S_0_td + S_tar_td - S(end, :) <= 0]; 13 | 14 | % Material balance constraints (per interval) 15 | % First interval, given initial value 16 | Constraints_primal = [Constraints_primal, S(1, :) == S_0_td]; 17 | % Subsequent intervals 18 | % Intermediate steps (note the dimension difference between P and S by 1) 19 | Constraints_primal = [Constraints_primal, S(2:end, 2:end-1) - S(1:end-1, 2:end-1) - ... 20 | P(:, 1:end-1) .* repmat(g_td(1:end-1), NOFINTERVALS, 1) + ... 21 | P(:, 2:end) .* repmat(g_td(2:end), NOFINTERVALS, 1) == 0]; 22 | 23 | % First step (note the dimension difference between P and S by 1) 24 | Constraints_primal = [Constraints_primal, S(2:end, 1) - S(1:end-1, 1) ... 25 | + P(:, 1) .* repmat(g_td(1), NOFINTERVALS, 1) == 0]; 26 | 27 | % Last step (note the dimension difference between P and S by 1) 28 | Constraints_primal = [Constraints_primal, S(2:end, end) - S(1:end-1, end) - ... 29 | P(:, end) .* repmat(g_td(end), NOFINTERVALS, 1) == 0]; 30 | 31 | % Material storage constraints (can ignore the first and last) 32 | Constraints_primal = [Constraints_primal, -S <= 0]; 33 | 34 | Constraints_primal = [Constraints_primal, S <= repmat(S_max_td, NOFINTERVALS + 1, 1)]; 35 | 36 | %% Objective Function 37 | Z_primal = Price' * (P * ones(NOFMACHINES, 1)) * delta_t; 38 | -------------------------------------------------------------------------------- /add_varDef_and_initVal.m: -------------------------------------------------------------------------------- 1 | %% Variable Definition and Initialization 2 | 3 | % Number of intervals 4 | NOFINTERVALS = 24; 5 | % Length of each interval 6 | delta_t = 24 / NOFINTERVALS; 7 | % Whether to start adaptation 8 | isAdapt = 0; 9 | idx_itr_Adapt = 0; 10 | 11 | %% Variable Setup 12 | 13 | % Machine parameters 14 | P_max_td = sdpvar(1, NOFMACHINES, 'full'); 15 | S_0_td = sdpvar(1, NOFMACHINES + 1, 'full'); 16 | S_tar_td = sdpvar(1, NOFMACHINES + 1, 'full'); 17 | S_max_td = sdpvar(1, NOFMACHINES + 1, 'full'); 18 | 19 | % Other electricity consumption 20 | P_0 = zeros(NOFINTERVALS, 1); 21 | % Machine power 22 | P = sdpvar(NOFINTERVALS, NOFMACHINES, 'full'); 23 | % Material quantity (0 interval is the initial value, set to 0, the following intervals are the values at the end of intervals 1-24) with a dimension one more than the number of machines 24 | S = sdpvar(NOFINTERVALS + 1, NOFMACHINES + 1, 'full'); 25 | 26 | % Dual variables 27 | mu_P_max = sdpvar(NOFINTERVALS, NOFMACHINES, 'full'); 28 | mu_P_min = sdpvar(NOFINTERVALS, NOFMACHINES, 'full'); 29 | mu_S_T = sdpvar(1, NOFMACHINES + 1, 'full'); 30 | lambda_S = sdpvar(NOFINTERVALS + 1, NOFMACHINES + 1, 'full'); % 0 ~ T 31 | mu_S_max = sdpvar(NOFINTERVALS + 1, NOFMACHINES + 1, 'full'); 32 | mu_S_min = sdpvar(NOFINTERVALS + 1, NOFMACHINES + 1, 'full'); 33 | 34 | % Some known information (commented out to indicate to be solved (already defined as variables)) 35 | g_init = g; 36 | g_td = g; 37 | 38 | %% Iterative Parameter Solving 39 | 40 | % Number of days in the data 41 | NOFDAYS = size(E_primal_days_train, 2); 42 | 43 | % Maximum electricity consumption in the data (used for prior determination of the sum of P_max) 44 | max_E_t = max(max(E_primal_days_train)); 45 | 46 | % Initialization 47 | result_S_tar = []; 48 | result_S_max = []; 49 | result_P_max = []; 50 | result_S_0 = []; 51 | result_g = []; 52 | result_Z = 1e3; 53 | result_J_theta = 1e3; 54 | 55 | % Initialization, estimated value is 0 56 | S_tar_ref = zeros(1, NOFMACHINES + 1); 57 | P_max_ref = zeros(1, NOFMACHINES); 58 | S_max_ref = zeros(1, NOFMACHINES + 1); 59 | S_0_ref = zeros(1, NOFMACHINES + 1); 60 | g_ref = zeros(1, NOFMACHINES); 61 | -------------------------------------------------------------------------------- /data_prepare/README.md: -------------------------------------------------------------------------------- 1 | # Data preparation 2 | 3 | This repository contains code that utilizes PJM electricity price data and State-Task Network (STN) models constructed based on parameters from a cement plant and a steel plant as described in the literature. The code simulates the optimal energy usage results for these two factories on different dates. 4 | 5 | - `aggregate_get_g`: Obtains some aggregate parameters for the steel plant (refer to our PSI paper for the rationale behind aggregation). 6 | - `data_generate_cement` and `data_generate_steelpowder`: Main programs to generate data for the corresponding factories. 7 | - `data_price(_2)`: Script to read price data. 8 | - `load_primal_problem_milp`: Uses the STN model to solve for optimal energy usage results. 9 | - `plot_typical_load`: Plots the typical energy usage of the steel plant for a specific day (various equipment). 10 | 11 | The models and data sources are referenced within the code where necessary. For a comprehensive overview, please refer to our PSI paper. 12 | 13 | # 数据准备 14 | 15 | 这个仓库包含的代码主要利用了PJM电价数据和基于文献中水泥厂和钢厂参数构建的状态-任务网络(STN)模型。代码模拟了这两个工厂在不同日期下的最优能源利用结果。 16 | 17 | - `aggregate_get_g`:获取钢厂的一些聚合参数(聚合原因请参考我们的PSI论文)。 18 | - `data_generate_cement` 和 `data_generate_steelpowder`:生成对应工厂数据的主要程序。 19 | - `data_price(_2)`:读取价格数据的脚本。 20 | - `load_primal_problem_milp`:使用STN模型求解最优能源利用结果。 21 | - `plot_typical_load`:绘制钢厂特定日期的典型能源利用情况(各种设备)。 22 | 23 | 模型和数据来源在代码中有相应引用。为了全面了解,请参考我们的PSI论文中的算例设置部分。 24 | -------------------------------------------------------------------------------- /data_prepare/aggregate_get_g.m: -------------------------------------------------------------------------------- 1 | %% Input the number of stages and return the g values for each stage and the bottleneck stage number (for a steel powder plant) 2 | function [g, idx_bottleneck] = aggregate_get_g(NOFMECHINES) 3 | 4 | % Read original parameters 5 | % Original machine parameters (g, P_max, S_max/0/tar) 6 | filename = "load_parameters_Lu.xlsx"; 7 | B = xlsread(filename); 8 | % Material production coefficients 9 | g = B(:, 7)'; 10 | 11 | NOFMECHINES_original = 10; 12 | 13 | % Aggregate or combine some stages based on the number of stages 14 | %% Split stages 15 | if NOFMECHINES > NOFMECHINES_original 16 | % If the number of machines is greater than the actual number of machines, split the stage with the maximum Pmax (except for the bottleneck stage) 17 | % Manually specify the splitting order 18 | idx_disol = [1, 1, 3, 6, 13]; 19 | idx_Key = [8, 9, 10, 11, 11]; 20 | 21 | % Split stages 22 | for idx = 1 : NOFMECHINES - length(g) 23 | g(idx_disol(idx)) = 2 * g(idx_disol(idx)); 24 | g = [g(1 : idx_disol(idx)), g(idx_disol(idx) : end)]; 25 | end 26 | idx_bottleneck = idx_Key(NOFMECHINES - NOFMECHINES_original); 27 | % Bottleneck stage 28 | end 29 | 30 | %% 10 stages: unchanged 31 | if NOFMECHINES == NOFMECHINES_original 32 | idx_bottleneck = 7; 33 | end 34 | 35 | %% Aggregate stages with 3 or more 36 | if NOFMECHINES < NOFMECHINES_original && NOFMECHINES >= 3 37 | idx_agg = [10, 3, 4, 7, 4, 2, 2]; 38 | idx_Key = [7, 6, 5, 5, 4, 3, 2]; 39 | 40 | % Split stages 41 | for idx = 1 : NOFMECHINES_original - NOFMECHINES 42 | g(idx_agg(idx) - 1) = 1 / (1 / g(idx_agg(idx)) + 1 / g(idx_agg(idx) - 1)); 43 | g = [g(1 : idx_agg(idx)-1), g(idx_agg(idx)+1 : end)]; 44 | end 45 | idx_bottleneck = idx_Key(NOFMECHINES_original - NOFMECHINES); 46 | % Bottleneck stage 47 | end 48 | 49 | %% Aggregate stages to less than 3 50 | if NOFMECHINES < 3 51 | [g, ~] = aggregate_get_g(3); 52 | 53 | switch NOFMECHINES 54 | case 2.5 55 | g(2) = 1 / (1 / g(2) + 1 / g(3)); 56 | g = g(1 : 2); 57 | idx_bottleneck = 2; 58 | case 1.5 59 | g(2) = 1 / (1 / g(2) + 1 / g(1)); 60 | g = g(2 : 3); 61 | idx_bottleneck = 1; 62 | case 1 63 | g(2) = 1 / (1 / g(2) + 1 / g(3)); 64 | g(2) = 1 / (1 / g(2) + 1 / g(1)); 65 | g = g(2); 66 | idx_bottleneck = 1; 67 | otherwise 68 | disp('Input error') 69 | end 70 | 71 | end 72 | -------------------------------------------------------------------------------- /data_prepare/data_generate_cement.m: -------------------------------------------------------------------------------- 1 | %% Generate multi-day data of a cement plant for inverse optimization using an existing MILP model from literature 2 | % Assuming that the internal parameters are the same for each day, but the external electricity prices vary, leading to different production schedules. 3 | 4 | % Referencing the paper by Golmohamadi-2020-rubost 5 | filename = "load_parameters_Golmo_milp.xlsx"; 6 | 7 | load_parameter = xlsread(filename); 8 | 9 | %% Parameters related to load, specifics can be found in the documentation 10 | 11 | % Energy consumption coefficients MWh/h 12 | e_np = 1e-3 * load_parameter(:, 2 : 2 : end); 13 | 14 | % Material production coefficients kton/h 15 | g_np = 1e-3 * load_parameter(:, 1 : 2 : end - 1); 16 | 17 | % Material maximum/minimum values (0), raw materials are generally not limited kton 18 | S_max = 1e-3 * load_parameter(:, end); 19 | S_max(end) = 4 * 48; 20 | 21 | % Initial material values 22 | S_0 = 0.5 * S_max; 23 | S_0(end) = 0; 24 | 25 | % Material target values (change) 26 | S_tar = zeros(size(S_max)); 27 | S_tar(end) = 1e-3 * 250 * 23; % The bottleneck stage needs to operate for 23 hours. 28 | 29 | % Read prices 30 | data_price; 31 | 32 | %% Generate electricity usage data 33 | 34 | E_primal_days = []; 35 | 36 | for idx_day = 1 : length(Price_days) 37 | Price = Price_days(:, idx_day); 38 | 39 | load_primal_problem_milp; 40 | 41 | P_val = value(E_hn); 42 | % Record electricity consumption 43 | E_primal = ones(1, NOFMACHINES) * P_val; 44 | E_primal = E_primal'; 45 | 46 | E_primal_days = [E_primal_days, E_primal]; 47 | end 48 | 49 | %% Differentiate training and cross-validation sets 50 | 51 | % First 21 days for training, last 10 days for cross-validation 52 | E_primal_days_train = E_primal_days(:, 1 : 21); 53 | E_primal_days_cv = E_primal_days(:, 22 : end); 54 | Price_days_train = Price_days(:, 1 : 21); 55 | Price_days_cv = Price_days(:, 22 : end); 56 | 57 | %% August data for testing set (load baseline) 58 | 59 | % Read prices 60 | data_price_2; 61 | 62 | Price_days_test_baseline = Price_days(:, 1 : 10); 63 | 64 | % Generate electricity usage data 65 | 66 | E_primal_days_test_baseline = []; 67 | 68 | for idx_day = 1 : size(Price_days_test_baseline, 2) 69 | Price = Price_days_test_baseline(:, idx_day); 70 | 71 | load_primal_problem_milp; 72 | 73 | P_val = value(E_hn); 74 | % Record electricity consumption 75 | E_primal = ones(1, NOFMACHINES) * P_val; 76 | E_primal = E_primal'; 77 | 78 | E_primal_days_test_baseline = [E_primal_days_test_baseline, E_primal]; 79 | end 80 | 81 | %% Save 82 | 83 | save("dataset_psi_add.mat", "E_primal_days_train", "Price_days_train", ... 84 | "E_primal_days_cv", "Price_days_cv", ... 85 | "E_primal_days_test_baseline", "Price_days_test_baseline"); 86 | -------------------------------------------------------------------------------- /data_prepare/data_generate_steelpowder.m: -------------------------------------------------------------------------------- 1 | %% Generate multi-day data for inverse optimization in a steel powder plant using an existing MILP model from literature 2 | % Assuming that the internal parameters are the same for each day, but the external electricity prices vary, leading to different production schedules. 3 | 4 | %% Referencing the paper by Lu-2021-data-driven 5 | filename = "load_parameters_Lu_milp.xlsx"; 6 | 7 | % Using data from Lu-2021 for validation 8 | load_parameter = xlsread(filename); 9 | 10 | % Energy consumption coefficients 11 | e_np = load_parameter(:, [2, 4, 6]); 12 | 13 | % Material production coefficients 14 | g_np = load_parameter(:, [1, 3, 5]); 15 | 16 | % Material maximum/minimum values (0), raw materials are generally not limited 17 | S_max = load_parameter(:, 7); 18 | S_max(end) = 400; 19 | 20 | % Initial material values 21 | S_0 = 0.5 * S_max; 22 | S_0(end) = 0; 23 | 24 | % Material target values (change) 25 | S_tar = zeros(size(S_max)); 26 | S_tar(end) = 10 * 24; % The bottleneck stage needs to operate for 24 hours. 27 | 28 | %% Read prices (July) 29 | data_price; 30 | 31 | %% Generate electricity usage data 32 | 33 | E_primal_days = []; 34 | 35 | for idx_day = 1 : length(Price_days) 36 | Price = Price_days(:, idx_day); 37 | 38 | load_primal_problem_milp; 39 | 40 | P_val = value(E_hn); 41 | % Record electricity consumption 42 | E_primal = ones(1, NOFMACHINES) * P_val; 43 | E_primal = E_primal'; 44 | 45 | E_primal_days = [E_primal_days, E_primal]; 46 | end 47 | 48 | %% Differentiate training and cross-validation sets 49 | 50 | % First 21 days for training, last 10 days for cross-validation 51 | E_primal_days_train = E_primal_days(:, 1 : 21); 52 | E_primal_days_cv = E_primal_days(:, 22 : end); 53 | Price_days_train = Price_days(:, 1 : 21); 54 | Price_days_cv = Price_days(:, 22 : end); 55 | 56 | %% August data for testing set (load baseline) 57 | 58 | % Read prices 59 | data_price_2; 60 | 61 | Price_days_test_baseline = Price_days(:, 1 : 10); 62 | 63 | % Generate electricity usage data 64 | 65 | E_primal_days_test_baseline = []; 66 | 67 | for idx_day = 1 : size(Price_days_test_baseline, 2) 68 | Price = Price_days_test_baseline(:, idx_day); 69 | 70 | load_primal_problem_milp; 71 | 72 | P_val = value(E_hn); 73 | % Record electricity consumption 74 | E_primal = ones(1, NOFMACHINES) * P_val; 75 | E_primal = E_primal'; 76 | 77 | E_primal_days_test_baseline = [E_primal_days_test_baseline, E_primal]; 78 | end 79 | 80 | %% Save 81 | 82 | save("dataset_steelpowder.mat", "E_primal_days_train", "Price_days_train", ... 83 | "E_primal_days_cv", "Price_days_cv", ... 84 | "E_primal_days_test_baseline", "Price_days_test_baseline"); 85 | -------------------------------------------------------------------------------- /data_prepare/data_price.m: -------------------------------------------------------------------------------- 1 | % Read PJM2022 July electricity price data 2 | 3 | %% Market prices and other parameters 4 | % Read system energy price data 5 | % Time interval length, 1 hour 6 | delta_t = 1; 7 | day_price = 1; % Selected number of days 8 | hour_init = 1; % Starting from the first time slot of the day 9 | NOFSLOTS = 24 / delta_t; 10 | 11 | % Read prices for all days of this month (July) 12 | Price_days = []; 13 | for day_price = 1 : 31 14 | 15 | start_row = (day_price-1) * 24 + hour_init + 1; % Starting row 16 | filename = 'rt_hrl_lmps.xlsx'; 17 | sheet = 'rt_hrl_lmps'; % Sheet name 18 | xlRange = "I" + start_row + ":I" + (start_row + NOFSLOTS - 1); % Range 19 | Price = xlsread(filename, sheet, xlRange); % Capacity price, mileage price 20 | Price_days = [Price_days, Price]; 21 | 22 | end 23 | clear Price filename sheet xlRange start_row hour_init day_price NOFSLOTS delta_t 24 | 25 | % Convert prices to $/kWh 26 | Price_days = Price_days * 1e-3; 27 | -------------------------------------------------------------------------------- /data_prepare/data_price_2.m: -------------------------------------------------------------------------------- 1 | %% Read PJM2022 August electricity price data 2 | 3 | %% Market prices and other parameters 4 | % Read system energy price data 5 | % Time interval length, 1 hour 6 | delta_t = 1; 7 | day_price = 1; % Selected number of days 8 | hour_init = 1; % Starting from the first time slot of the day 9 | NOFSLOTS = 24 / delta_t; 10 | 11 | % Read prices for all days of this month (August) 12 | Price_days = []; 13 | for day_price = 1 : 10 14 | 15 | start_row = (day_price-1) * 24 + hour_init + 1; % Starting row 16 | filename = 'rt_hrl_lmps_202208.xlsx'; 17 | sheet = 'sheet1'; % Sheet name 18 | xlRange = "I" + start_row + ":I" + (start_row + NOFSLOTS - 1); % Range 19 | Price = xlsread(filename, sheet, xlRange); % Capacity price, mileage price 20 | Price_days = [Price_days, Price]; 21 | 22 | end 23 | clear Price filename sheet xlRange start_row hour_init day_price NOFSLOTS delta_t 24 | 25 | % Convert prices to $/kWh 26 | Price_days = Price_days * 1e-3; 27 | -------------------------------------------------------------------------------- /data_prepare/dataset_cement.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/data_prepare/dataset_cement.mat -------------------------------------------------------------------------------- /data_prepare/dataset_steelpowder.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/data_prepare/dataset_steelpowder.mat -------------------------------------------------------------------------------- /data_prepare/load_parameters_Golmo_milp.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/data_prepare/load_parameters_Golmo_milp.xlsx -------------------------------------------------------------------------------- /data_prepare/load_parameters_Lu_milp.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/data_prepare/load_parameters_Lu_milp.xlsx -------------------------------------------------------------------------------- /data_prepare/load_primal_problem_milp.m: -------------------------------------------------------------------------------- 1 | %% STN model code implementation (including objective function and solving process) 2 | % Parameters: load_parameter (read from Excel in the upper-level code) 3 | % Input: External electricity prices (read in the upper-level code) 4 | % Output: Optimal solutions for variables in the STN model 5 | % Detailed model reference: lu_Data-driven_2021: R. Lu, R. Bai, Y. Huang, Y. Li, J. Jiang, and Y. Ding, "Data-driven real-time price-based demand response for industrial facilities energy management,” Appl. Energy, vol. 283, p. 116291, Feb. 2021. 6 | 7 | %% Other parameters 8 | 9 | NOFMACHINES = size(load_parameter, 1); 10 | NOFINTERVALS = 24; 11 | NOFPOINTS = (size(load_parameter, 2) - 1) / 2; 12 | 13 | %% Variable Setup 14 | 15 | % Machine operating states 16 | I_hnp = binvar(NOFPOINTS, NOFMACHINES, NOFINTERVALS, 'full'); 17 | 18 | % Machine energy consumption 19 | E_hn = sdpvar(NOFMACHINES, NOFINTERVALS, 'full'); 20 | 21 | % Material quantity (0 time interval for initial value, set to 0, followed by values at time intervals 1-24) 22 | S_hn = sdpvar(NOFMACHINES, NOFINTERVALS + 1, 'full'); 23 | 24 | %% Constraints 25 | Constraints = []; 26 | 27 | % Unique operating states (1) 28 | temp = reshape(sum(I_hnp), NOFMACHINES, NOFINTERVALS); 29 | Constraints = [Constraints, temp == ones(NOFMACHINES, NOFINTERVALS)]; 30 | 31 | % Energy consumption decomposition constraint (2) 32 | temp = reshape(sum(I_hnp .* repmat(e_np', 1, 1, 24)), NOFMACHINES, NOFINTERVALS); 33 | Constraints = [Constraints, E_hn == temp]; 34 | 35 | % Material change constraints (5, 6, 7) 36 | % Initial value given for the first time interval 37 | Constraints = [Constraints, S_hn(:, 1) == S_0]; 38 | % Subsequent time intervals 39 | temp = reshape(sum(I_hnp .* repmat(g_np', 1, 1, 24)), NOFMACHINES, NOFINTERVALS); 40 | % Non-terminal intervals 41 | Constraints = [Constraints, S_hn(1 : end-1, 2 : end) - S_hn(1 : end-1, 1 : end - 1) - ... 42 | temp(1 : end-1, 1 : end) + temp(2 : end, 1 : end) == 0]; 43 | % Terminal intervals (note the dimension difference between P and S) 44 | Constraints = [Constraints, S_hn(end, 2 : end) - S_hn(end, 1 : end-1) - ... 45 | temp(end, 1 : end) == 0]; 46 | 47 | % Material storage constraints (first and last intervals can be ignored) 48 | Constraints = [Constraints, - S_hn <= 0]; 49 | 50 | Constraints = [Constraints, S_hn <= repmat(S_max, 1, NOFINTERVALS + 1)]; 51 | 52 | % Material target (end time interval) 53 | Constraints = [Constraints, S_0 + S_tar - S_hn(:, end) <= 0]; 54 | 55 | %% Objective Function 56 | Z_primal = sum(E_hn) * Price; 57 | 58 | %% Solve 59 | ops = sdpsettings('debug',1,'solver','GUROBI','savesolveroutput',1,'savesolverinput',1); 60 | 61 | sol = optimize(Constraints, Z_primal, ops); 62 | 63 | %% Record variable values 64 | P_val = value(E_hn); 65 | S_val = value(S_hn); 66 | I_val = value(I_hnp); 67 | -------------------------------------------------------------------------------- /data_prepare/plot_typical_load.m: -------------------------------------------------------------------------------- 1 | %% Illustrative Price and Energy Consumption at Various Stages of a Steel Powder Plant on a Certain Day 2 | 3 | % Load parameters 4 | % Referencing the paper by Lu-2021-data-driven 5 | filename = "load_parameters_Lu_milp.xlsx"; 6 | 7 | % Using data from Lu-2021 for validation 8 | load_parameter = xlsread(filename); 9 | 10 | % Energy consumption coefficients 11 | e_np = load_parameter(:, [2, 4, 6]); 12 | 13 | % Material production coefficients 14 | g_np = load_parameter(:, [1, 3, 5]); 15 | 16 | % Material maximum/minimum values (0), raw materials are generally not limited 17 | S_max = load_parameter(:, 7); 18 | S_max(end) = 400; 19 | 20 | % Initial material values 21 | S_0 = 0.5 * S_max; 22 | S_0(end) = 0; 23 | 24 | % Material target values (change) 25 | S_tar = zeros(size(S_max)); 26 | S_tar(end) = 10 * 24; % The bottleneck stage needs to operate for 24 hours. 27 | 28 | % Load prices (August) 29 | data_price_2; 30 | 31 | % First 10 days as the test set 32 | Price_days_test = Price_days(:, 1 : 10); 33 | 34 | % Generate electricity usage data 35 | idx_day = 5; 36 | 37 | Price = Price_days_test(:, idx_day); 38 | 39 | load_primal_problem_milp; 40 | 41 | %% Plot 42 | linewidth = 2; 43 | 44 | % Actual energy consumption 45 | bar(P_val', 0.4,'stacked','DisplayName','P_val'); 46 | hold on; 47 | 48 | y1 = ylabel('Energy Consumption (kWh)','FontSize',13.5,'FontName', 'Times New Roman','FontWeight','bold'); 49 | 50 | yyaxis right 51 | plot(1:24, 1e3 * Price, "-.g", 'linewidth', linewidth); 52 | 53 | ax = gca; 54 | ax.YLim = [0, 300]; 55 | ax.YColor = 'black'; 56 | 57 | legend('Blender','Classifier','Crusher', ... 58 | 'Classifier', ... 59 | 'Crusher', ... 60 | 'Separator', ... 61 | 'Dryer', ... 62 | 'Dehydrator', ... 63 | 'Atomizer', ... 64 | 'Reduction', ... 65 | 'Price', ... 66 | 'fontsize',13.5, ... 67 | 'Location','EastOutside', ... 68 | 'Orientation','vertical', ... 69 | 'FontName', 'Times New Roman'); 70 | 71 | x1 = xlabel('Hour','FontSize',13.5,'FontName', 'Times New Roman','FontWeight','bold'); 72 | y1 = ylabel('Electricity Price ($/MWh)','FontSize',13.5,'FontName', 'Times New Roman','FontWeight','bold'); 73 | 74 | % Figure size 75 | figureUnits = 'centimeters'; 76 | figureWidth = 20; 77 | figureHeight = figureWidth * 1.6 / 4; 78 | set(gcf, 'Units', figureUnits, 'Position', [10 10 figureWidth figureHeight]); 79 | 80 | % Axis properties 81 | ax = gca; 82 | ax.XLim = [0, 25]; 83 | ax.FontSize = 13.5; 84 | ax.XTick = [1:24]; 85 | ax.XTickLabel = {'1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24'}; 86 | ax.FontName = 'Times New Roman'; 87 | set(gcf, 'PaperSize', [19.4, 7.8]); 88 | 89 | saveas(gcf,'typical_load.pdf'); 90 | -------------------------------------------------------------------------------- /data_prepare/rt_hrl_lmps.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/data_prepare/rt_hrl_lmps.xlsx -------------------------------------------------------------------------------- /data_prepare/rt_hrl_lmps_202208.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/data_prepare/rt_hrl_lmps_202208.xlsx -------------------------------------------------------------------------------- /inverse_optimization.m: -------------------------------------------------------------------------------- 1 | %% Fitting Load Model Parameters based on Historical Electricity Data and Prices 2 | 3 | NOFMACHINES = length(g); 4 | 5 | % Variable naming and initialization 6 | add_varDef_and_initVal; 7 | 8 | for idx_itr = 0:210 % 10 * NOFDAYS 9 | % Solve the inverse problem for the idx_day day 10 | idx_day = mod(idx_itr, NOFDAYS) + 1; 11 | 12 | % Read price and electricity consumption information for the day 13 | Price = Price_days_train(:, idx_day); 14 | E_primal = E_primal_days_train(:, idx_day); 15 | 16 | %% Inverse problem constraints 17 | % In the inverse optimization problem to infer factory production model parameters based on meter data, add constraints from the original problem, dual problem constraints (including strong duality conditions) 18 | 19 | Constraints = []; 20 | 21 | % Dual problem variables and constraints 22 | add_dual_constraints; 23 | % Add dual constraints 24 | Constraints = [Constraints, Constraints_dual]; 25 | 26 | % Original problem variables and constraints 27 | add_primal_constraints; 28 | % Add original problem constraints 29 | Constraints = [Constraints, Constraints_primal]; 30 | 31 | % Equality of objective function values (only need the dual function and original function values to be equal, no need to be equal to real data) 32 | Constraints = [Constraints, g_dual == Z_primal]; 33 | 34 | % Prior constraints 35 | add_grid_priori; 36 | Constraints = [Constraints, Constraints_priori]; 37 | 38 | %% Inverse Problem Objective Function 39 | 40 | Z = sum(sum((P_max_td - P_max_ref).^2)) ... 41 | + sum(sum((S_0_td - S_0_ref).^2)) ... 42 | + sum(sum((S_tar_td - S_tar_ref).^2)) ... 43 | + sum(sum((S_max_td - S_max_ref).^2)); 44 | 45 | % New loss function part for faster convergence 46 | J_theta = sum((P * ones(NOFMACHINES, 1) * delta_t - E_primal).^2); 47 | 48 | % Learning rate gradually decreases (adaptive) 49 | if (idx_itr > 3 * NOFDAYS) && isAdapt == 0 50 | isAdapt = 1; 51 | idx_itr_Adapt = idx_itr; 52 | end 53 | 54 | % If adaptation has started, reduce the weight of J_theta 55 | if isAdapt 56 | alpha = (1 / (idx_itr - idx_itr_Adapt + 1))^(0.5); 57 | else 58 | alpha = 1; 59 | end 60 | 61 | % First loop does not need to consider ref values 62 | if idx_itr <= NOFDAYS 63 | Z = 1e3; 64 | end 65 | 66 | Z_total = alpha * J_theta + Z; 67 | 68 | %% Solve 69 | 70 | % Set solving time 71 | TimeLimit = 1; 72 | ops = sdpsettings('debug', 1, 'solver', 'gurobi', ... 73 | 'verbose', 0, ... 74 | 'gurobi.NonConvex', 2, ... 75 | 'allownonconvex', 1, ... 76 | 'gurobi.TimeLimit', TimeLimit, 'usex0', 1); 77 | ops.gurobi.TuneTimeLimit = TimeLimit; 78 | sol = optimize(Constraints, Z_total, ops); 79 | 80 | disp("Iteration " + idx_itr + "; Training Loss Z: " + value(Z) + "; Training Loss J_theta: " + value(J_theta)) 81 | 82 | % Record loss functions 83 | result_Z = [result_Z; value(Z)]; 84 | result_J_theta = [result_J_theta; value(J_theta)]; 85 | 86 | % Record iteration process 87 | result_S_tar = [result_S_tar; value(S_tar_td)]; 88 | result_S_max = [result_S_max; value(S_max_td)]; 89 | result_P_max = [result_P_max; value(P_max_td)]; 90 | result_S_0 = [result_S_0; value(S_0_td)]; 91 | result_g = [result_g; value(g_td)]; 92 | 93 | if idx_itr > NOFDAYS 94 | S_tar_ref = mean(result_S_tar(end - NOFDAYS + 1 : end, :)); 95 | P_max_ref = mean(result_P_max(end - NOFDAYS + 1 : end, :)); 96 | S_max_ref = mean(result_S_max(end - NOFDAYS + 1 : end, :)); 97 | S_0_ref = mean(result_S_0(end - NOFDAYS + 1 : end, :)); 98 | g_ref = mean(result_g(end - NOFDAYS + 1 : end, :)); 99 | else 100 | S_tar_ref = value(S_tar_td); 101 | P_max_ref = value(P_max_td); 102 | S_max_ref = value(S_max_td); 103 | S_0_ref = value(S_0_td); 104 | g_ref = value(g_td); 105 | end 106 | 107 | % Convergence criterion: change in loss function over the past NOFDAYS period 108 | err = 1e-2; 109 | if idx_itr > NOFDAYS && mean(abs(result_Z(end - NOFDAYS + 1 : end))) < err 110 | break; 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /main_cement.m: -------------------------------------------------------------------------------- 1 | %% Main Program (Cement Plant) 2 | clc; clear; 3 | 4 | % Load data, electricity consumption in each time period 5 | load("data_prepare/dataset_cement.mat"); % Cement data from Golmo_2020 6 | 7 | % Original machine parameters (g) 8 | filename = "data_prepare/load_parameters_Golmo_milp.xlsx"; 9 | B = xlsread(filename); 10 | % Material production coefficient 11 | g = B(:, 3)' ./ B(:, 4)'; 12 | NOFSTAGES = length(g); 13 | NOFMECHINES_original = length(g); 14 | idx_bottleneck = 2; % Bottleneck stage index (although not used) 15 | 16 | % Inverse optimization 17 | inverse_optimization; 18 | 19 | save("results/test_Golmo_gen_" + 4 + "stages_120.mat"); 20 | 21 | yalmip('clear'); 22 | -------------------------------------------------------------------------------- /main_steelpowder.m: -------------------------------------------------------------------------------- 1 | %% Test Main Program 2 | clc; clear; 3 | 4 | % Load dataset_steelpowder data, electricity consumption in each time period 5 | load("data_prepare/dataset_steelpowder.mat"); 6 | 7 | % Differentiate models based on the number of machines, 1.5 and 2.5 represent two ways of aggregating 2 stages 8 | for NOFSTAGES = [2.5 3 4 5 6 7 8 9 10] 9 | 10 | % Read stage data 11 | [g, idx_bottleneck] = aggregate_get_g(NOFSTAGES); 12 | 13 | % Inverse optimization 14 | inverse_optimization; 15 | 16 | % Save results 17 | save("results/test_Lu_gen_" + 2 * NOFSTAGES + "stages_120.mat"); 18 | 19 | yalmip('clear'); 20 | 21 | end 22 | -------------------------------------------------------------------------------- /results/0226_20_training_set_120/test_Lu_gen_10stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0226_20_training_set_120/test_Lu_gen_10stages_120.mat -------------------------------------------------------------------------------- /results/0226_20_training_set_120/test_Lu_gen_12stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0226_20_training_set_120/test_Lu_gen_12stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_10stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_10stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_12stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_12stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_14stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_14stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_16stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_16stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_18stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_18stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_20stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_20stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_22stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_22stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_24stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_24stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_3stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_3stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_5stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_5stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_6stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_6stages_120.mat -------------------------------------------------------------------------------- /results/0227_no_assumption_e/test_Lu_gen_8stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0227_no_assumption_e/test_Lu_gen_8stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_10stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_10stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_12stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_12stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_14stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_14stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_16stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_16stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_18stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_18stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_20stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_20stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_5stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_5stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_6stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_6stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_b/test_Lu_gen_8stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_b/test_Lu_gen_8stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_10stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_10stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_12stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_12stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_14stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_14stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_16stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_16stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_18stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_18stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_20stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_20stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_5stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_5stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_6stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_6stages_120.mat -------------------------------------------------------------------------------- /results/0301_no_assumption_c/test_Lu_gen_8stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0301_no_assumption_c/test_Lu_gen_8stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_10stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_10stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_12stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_12stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_14stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_14stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_16stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_16stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_18stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_18stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_20stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_20stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_5stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_5stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_6stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_6stages_120.mat -------------------------------------------------------------------------------- /results/0314_10_training_set/test_Lu_gen_8stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_10_training_set/test_Lu_gen_8stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_10stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_10stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_12stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_12stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_14stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_14stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_16stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_16stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_18stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_18stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_20stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_20stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_5stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_5stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_6stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_6stages_120.mat -------------------------------------------------------------------------------- /results/0314_5_training_set/test_Lu_gen_8stages_120.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/0314_5_training_set/test_Lu_gen_8stages_120.mat -------------------------------------------------------------------------------- /results/README.md: -------------------------------------------------------------------------------- 1 | # Results Visualization Code for PSI in Cement and Steel Powder Plants 2 | 3 | This repository contains code for visualizing the results of PSI (Proposed Method) on datasets from a cement plant and a steel powder plant. The visualizations generated by the code can be referenced in our PSI paper. 4 | 5 | ## Files Description 6 | - Files starting with `cal_` are scripts for auxiliary calculations to compute errors. 7 | - Files starting with `plot_` are scripts for statistical analysis and generating visualizations. 8 | - `plot_box.m`: Generates box plots. 9 | - `plot_rmse_methods.m`: Compiles errors for various methods. 10 | - Files starting with `plot_typical_` provide comparisons between typical load ground truth and model predictions. 11 | 12 | Feel free to explore the code and adapt it to visualize results for the PSI method in your own research projects. If you have any questions or suggestions, please feel free to reach out. Thank you for your interest! 13 | 14 | # 水泥厂和钢粉厂数据集上PSI结果可视化代码 15 | 16 | 该代码库包含了对水泥厂和钢粉厂数据集上PSI(提出的方法)结果进行可视化的代码。生成的可视化结果可以参考我们的PSI论文。 17 | 18 | ## 文件说明 19 | - 以`cal_`开头的文件是用于辅助计算误差的脚本。 20 | - 以`plot_`开头的文件是用于统计分析和生成图像的脚本。 21 | - `plot_box.m`:生成箱线图。 22 | - `plot_rmse_methods.m`:汇总各种方法的误差。 23 | - 以`plot_typical_`开头的文件提供了典型负荷真实值和模型预测结果的对比。 24 | 25 | 欢迎查看代码并根据需要调整,以在您自己的研究项目中可视化PSI方法的结果。如果有任何问题或建议,请随时联系我。感谢您的关注! -------------------------------------------------------------------------------- /results/accuracy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/accuracy.pdf -------------------------------------------------------------------------------- /results/cal_rmse_ml_cement.m: -------------------------------------------------------------------------------- 1 | %% Calculate metrics for machine learning methods' results (% cement) 2 | 3 | J_baseline_test = []; % Load baseline error 4 | J_P_test = []; % Power error 5 | 6 | % Power response error 7 | load("..\data_prepare\dataset_cement.mat"); 8 | 9 | NOFDAYS = size(E_primal_days_test_baseline, 2); 10 | Price_days = Price_days_test_baseline; 11 | E_primal_days = E_primal_days_test_baseline; 12 | 13 | for idx_day = 1:NOFDAYS 14 | % Training set prices 15 | Price = Price_days(:, idx_day); 16 | E_inverse = E_inverse_days(:, idx_day); 17 | 18 | % Energy consumption of the original problem 19 | E_primal = E_primal_days(:, idx_day); 20 | 21 | J_P_test = [J_P_test, mean(mean((E_inverse - E_primal).^2))]; 22 | end 23 | 24 | % Calculate errors 25 | % Mean relative deviation 26 | 27 | % rmse_cement = sqrt((mean(J_P_test))) 28 | 29 | % Daily relative errors 30 | rmse_cement = sqrt(((J_P_test))); 31 | -------------------------------------------------------------------------------- /results/cal_rmse_ml_steelpowder.m: -------------------------------------------------------------------------------- 1 | %% Calculate metrics for machine learning methods' results (steelpowder) 2 | 3 | J_baseline_test = []; % Load baseline error 4 | J_P_test = []; % Power error 5 | 6 | load("..\data_prepare\dataset_steelpowder.mat"); 7 | 8 | NOFDAYS = size(E_primal_days_test_baseline, 2); 9 | Price_days = Price_days_test_baseline; 10 | E_primal_days = E_primal_days_test_baseline; 11 | 12 | for idx_day = 1:NOFDAYS 13 | % Training set prices 14 | Price = Price_days(:, idx_day); 15 | E_inverse = E_inverse_days(:, idx_day); 16 | 17 | % Energy consumption of the original problem 18 | E_primal = E_primal_days(:, idx_day); 19 | 20 | J_baseline_test = [J_baseline_test, mean(mean((E_inverse - E_primal).^2))]; 21 | end 22 | 23 | %% Calculate errors 24 | % Mean relative deviation 25 | 26 | % rmse_steelpowder = sqrt((mean(J_baseline_test))) 27 | 28 | % Daily relative errors 29 | rmse_steelpowder = sqrt(((J_baseline_test))); 30 | -------------------------------------------------------------------------------- /results/cal_rmse_test.m: -------------------------------------------------------------------------------- 1 | %% Given a model, run results on training and testing sets 2 | 3 | %% Run the forward problem with fitted parameters 4 | % (g, P_max, S_max/0/tar) 5 | S_tar = result_S_tar(end, :); 6 | S_max = result_S_max(end, :); 7 | P_max = result_P_max(end, :); 8 | S_0 = result_S_0(end, :); 9 | g = result_g(end, :); 10 | 11 | % Forward problem 12 | J_P_test = []; % Power error 13 | J_baseline_test = []; % Load baseline error 14 | 15 | %% Test set errors, load baseline error 16 | 17 | NOFDAYS = size(E_primal_days_test_baseline, 2); 18 | Price_days = Price_days_test_baseline; 19 | E_primal_days = E_primal_days_test_baseline; 20 | 21 | E_inverse_days = []; 22 | 23 | for idx_day = 1:NOFDAYS 24 | % Training set prices 25 | Price = Price_days(:, idx_day); 26 | % Forward problem 27 | load_primal_problem; 28 | 29 | % Calculate differences 30 | P_val = value(P); 31 | S_val = value(S); 32 | E_inverse = P_val * ones(NOFMACHINES, 1) * delta_t; 33 | E_inverse_days = [E_inverse_days, E_inverse]; 34 | 35 | % Energy consumption of the original problem 36 | E_primal = E_primal_days(:, idx_day); 37 | 38 | J_baseline_test = [J_baseline_test, mean(mean((E_inverse - E_primal).^2))]; 39 | end 40 | 41 | % Calculate errors 42 | % Daily relative error 43 | rmse_baseline = sqrt(((J_baseline_test))); 44 | -------------------------------------------------------------------------------- /results/load_primal_problem.m: -------------------------------------------------------------------------------- 1 | %% Linear Programming Problem Solved by Industrial Users for Production Scheduling per Hour (based on mSTN model) 2 | 3 | % Set parameters 4 | % (g, P_max, S_max/0/tar) 5 | % Load parameters 6 | % load("data_prepare/primal_parameter_Lu.mat"); 7 | % load("data_prepare/primal_parameter_Lu_agg.mat"); 8 | 9 | %% Example Parameters 10 | 11 | % Number of intervals 12 | NOFINTERVALS = 24; 13 | 14 | % Length of each interval 15 | delta_t = 24 / NOFINTERVALS; 16 | 17 | % Number of machines 18 | NOFMACHINES = length(g); 19 | 20 | %% Variable Setup 21 | % Other electricity consumption 22 | P_0 = zeros(NOFINTERVALS, 1); 23 | 24 | %% Variable Setup 25 | % if ~exist('P') 26 | % Machine power 27 | P = sdpvar(NOFINTERVALS, NOFMACHINES, 'full'); 28 | 29 | % Material quantity (0 interval is the initial value, set to 0, the following intervals are the values at the end of intervals 1-24) with a dimension one more than the number of machines 30 | S = sdpvar(NOFINTERVALS + 1, NOFMACHINES + 1, 'full'); 31 | 32 | % Machine parameters 33 | P_max_td = P_max; 34 | g_td = g; 35 | S_0_td = S_0; 36 | S_tar_td = S_tar; 37 | S_max_td = S_max; 38 | S_max_td(end) = S_max_td(end) + 1; 39 | 40 | % Original problem constraints 41 | %% Constraints 42 | Constraints_primal = []; 43 | 44 | % Power range constraints 45 | Constraints_primal = [Constraints_primal, -P <= 0]; 46 | Constraints_primal = [Constraints_primal, P <= repmat(P_max_td, NOFINTERVALS, 1)]; 47 | 48 | % Material target (end of interval) 49 | Constraints_primal = [Constraints_primal, S_0_td + S_tar_td - S(end, :) <= 0]; 50 | 51 | % Material balance constraints (per interval) 52 | % First interval, given initial value 53 | Constraints_primal = [Constraints_primal, S(1, :) == S_0_td]; 54 | % Subsequent intervals 55 | % Intermediate steps (note the dimension difference between P and S by 1) 56 | Constraints_primal = [Constraints_primal, S(2:end, 2:end-1) - S(1:end-1, 2:end-1) - ... 57 | P(:, 1:end-1) .* repmat(g_td(1:end-1), NOFINTERVALS, 1) + ... 58 | P(:, 2:end) .* repmat(g_td(2:end), NOFINTERVALS, 1) == 0]; 59 | 60 | % First step (note the dimension difference between P and S by 1) 61 | Constraints_primal = [Constraints_primal, S(2:end, 1) - S(1:end-1, 1) ... 62 | + P(:, 1) .* repmat(g_td(1), NOFINTERVALS, 1) == 0]; 63 | 64 | % Last step (note the dimension difference between P and S by 1) 65 | Constraints_primal = [Constraints_primal, S(2:end, end) - S(1:end-1, end) - ... 66 | P(:, end) .* repmat(g_td(end), NOFINTERVALS, 1) == 0]; 67 | 68 | % Material storage constraints (can ignore the first and last) 69 | Constraints_primal = [Constraints_primal, -S <= 0]; 70 | 71 | Constraints_primal = [Constraints_primal, S <= repmat(S_max_td, NOFINTERVALS + 1, 1)]; 72 | 73 | %% Objective Function 74 | Z_primal = Price' * (P * ones(NOFMACHINES, 1)) * delta_t; 75 | 76 | %% Solve 77 | ops = sdpsettings('debug', 1, 'solver', 'gurobi', 'savesolveroutput', 1, 'savesolverinput', 1); 78 | 79 | sol = optimize(Constraints_primal, Z_primal, ops); 80 | 81 | %% Record Results 82 | P_val = value(P); 83 | S_val = value(S); 84 | -------------------------------------------------------------------------------- /results/ml_results/predict_LSTM_20230226.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_LSTM_20230226.mat -------------------------------------------------------------------------------- /results/ml_results/predict_LSTM_20230226_baseline.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_LSTM_20230226_baseline.mat -------------------------------------------------------------------------------- /results/ml_results/predict_LSTM_20240828.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_LSTM_20240828.mat -------------------------------------------------------------------------------- /results/ml_results/predict_LSTM_20240828_baseline.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_LSTM_20240828_baseline.mat -------------------------------------------------------------------------------- /results/ml_results/predict_MLP_20230226.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_MLP_20230226.mat -------------------------------------------------------------------------------- /results/ml_results/predict_MLP_20230226_baseline.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_MLP_20230226_baseline.mat -------------------------------------------------------------------------------- /results/ml_results/predict_MLP_20240828.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_MLP_20240828.mat -------------------------------------------------------------------------------- /results/ml_results/predict_MLP_20240828_baseline.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_MLP_20240828_baseline.mat -------------------------------------------------------------------------------- /results/ml_results/predict_SVR_20230226.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_SVR_20230226.mat -------------------------------------------------------------------------------- /results/ml_results/predict_SVR_20230226_baseline.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_SVR_20230226_baseline.mat -------------------------------------------------------------------------------- /results/ml_results/predict_svr_20240828.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_svr_20240828.mat -------------------------------------------------------------------------------- /results/ml_results/predict_svr_20240828_baseline.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rick10119/Production-Scheduling-Identification/bf2dfba7d163be98be3da484083a58fcaf3f5531/results/ml_results/predict_svr_20240828_baseline.mat -------------------------------------------------------------------------------- /results/plot_box.m: -------------------------------------------------------------------------------- 1 | % boxplot: run plot_rmse_methods first 2 | 3 | h = boxplot(total_table' * 100); 4 | 5 | % Set colors for different results 6 | colors = ['r', 'b']; % r for red, b for blue 7 | for i = 1:size(h, 2) 8 | color = colors(mod(i - 1, length(colors)) + 1); % Cycle through colors 9 | set(h(:, i), 'Color', color); 10 | end 11 | 12 | % Axis properties 13 | ax = gca; 14 | ax.XLim = [0, 9]; 15 | ax.YLim = [0, 40]; 16 | 17 | set(gca, "YGrid", "on"); 18 | 19 | % Set ticks 20 | ax.XTick = [1.5:2:7.5]; 21 | 22 | % Set x-axis labels 23 | xticklabels({'PSI', 'MLP', 'LSTM', 'SVR'}); 24 | 25 | % Font settings 26 | ax.FontSize = 13.5; 27 | ax.FontName = 'Times New Roman'; 28 | 29 | hold on 30 | h1 = plot(NaN, NaN, 'r-'); 31 | h2 = plot(NaN, NaN, 'b-'); 32 | legend([h1, h2], "Cement plant", "Steel powder manufactory",... 33 | 'fontsize', 13.5, ... 34 | 'Orientation', 'vertical', ... 35 | 'FontName', 'Times New Roman'); 36 | 37 | % Set y-axis label and title 38 | ylabel('Normalized RMSE (%)', 'FontSize', 13.5, 'FontName', 'Times New Roman', 'FontWeight', 'bold'); 39 | 40 | % Figure size 41 | figureUnits = 'centimeters'; 42 | figureWidth = 10; 43 | figureHeight = figureWidth * 4 / 4; 44 | set(gcf, 'Units', figureUnits, 'Position', [10 10 figureWidth figureHeight]); 45 | 46 | set(gcf, 'PaperSize', [10, 10]); 47 | 48 | saveas(gcf, 'accuracy.pdf'); 49 | -------------------------------------------------------------------------------- /results/plot_rmse_methods.m: -------------------------------------------------------------------------------- 1 | %% Calculate test set errors for different methods 2 | 3 | total_table = []; 4 | 5 | %% Machine Learning Methods 6 | 7 | % MLP 8 | load("ml_results\predict_MLP_20240828_baseline.mat"); E_inverse_days = predict_y; 9 | cal_rmse_ml_cement;% cement 10 | 11 | load("ml_results\predict_MLP_20230226_baseline.mat"); E_inverse_days = predict_y; 12 | cal_rmse_ml_steelpowder;% steelpowder 13 | 14 | total_table = [total_table; rmse_cement; rmse_steelpowder]; 15 | 16 | % LSTM 17 | load("ml_results\predict_LSTM_20240828_baseline.mat"); E_inverse_days = predict_y; 18 | cal_rmse_ml_cement; 19 | 20 | load("ml_results\predict_LSTM_20230226_baseline.mat"); E_inverse_days = predict_y; 21 | cal_rmse_ml_steelpowder; 22 | 23 | total_table = [total_table; rmse_cement; rmse_steelpowder]; 24 | 25 | % SVR 26 | load("ml_results\predict_svr_20240828_baseline.mat"); E_inverse_days = y_predict; 27 | cal_rmse_ml_cement; 28 | 29 | load("ml_results\predict_SVR_20230226_baseline.mat"); E_inverse_days = y_predict; 30 | cal_rmse_ml_steelpowder; 31 | 32 | total_table = [total_table; rmse_cement; rmse_steelpowder]; 33 | 34 | %% Proposed Methods 35 | % Steel powder 36 | NOFSTAGES = 5; 37 | load("0227_no_assumption_e/test_Lu_gen_" + 2*NOFSTAGES + "stages_120.mat"); 38 | load("..\data_prepare\dataset_steelpowder.mat"); 39 | cal_rmse_test; 40 | maxE_steel = max(E_primal); 41 | rmse_steel = rmse_baseline; 42 | 43 | % Cement plant 44 | load('test_Golmo_gen_4stages_120.mat'); 45 | load("..\data_prepare\dataset_cement.mat"); 46 | cal_rmse_test; 47 | maxE_cement = max(E_primal); 48 | rmse_cement = rmse_baseline; 49 | total_table = [rmse_cement; rmse_steel; total_table]; 50 | 51 | % Normalize 52 | total_table(1:2:end, :) = total_table(1:2:end, :) / maxE_cement; 53 | total_table(2:2:end, :) = total_table(2:2:end, :) / maxE_steel; 54 | 55 | save("total_table_methods.mat", 'total_table'); 56 | -------------------------------------------------------------------------------- /results/plot_typical_cement.m: -------------------------------------------------------------------------------- 1 | %% Plot typical load curves for a cement plant 2 | 3 | total_energy_baseline = []; 4 | 5 | index_day = 5; 6 | 7 | %% Machine learning methods 8 | 9 | load("ml_results\predict_MLP_20240828_baseline.mat"); 10 | E_inverse_days = predict_y; 11 | 12 | total_energy_baseline = [total_energy_baseline, reshape(E_inverse_days(:, index_day), 24, 1)]; 13 | total_energy_baseline(18) = 0; 14 | 15 | load("ml_results\predict_LSTM_20240828_baseline.mat"); 16 | E_inverse_days = predict_y; 17 | total_energy_baseline = [total_energy_baseline, reshape(E_inverse_days(:, index_day), 24, 1)]; 18 | 19 | load("ml_results\predict_SVR_20240828_baseline.mat"); 20 | E_inverse_days = y_predict; 21 | total_energy_baseline = [total_energy_baseline, reshape(E_inverse_days(:, index_day), 24, 1)]; 22 | 23 | %% Proposed method 24 | NOFSTAGES = 5; 25 | load('test_Golmo_gen_4stages_120.mat'); 26 | cal_rmse_test_baseline; 27 | total_energy_baseline = [total_energy_baseline, reshape(E_inverse_days(:, index_day), 24, 1)]; 28 | 29 | % True value 30 | load("..\data_prepare\dataset_cement.mat"); 31 | total_energy_baseline = [total_energy_baseline, reshape(E_primal_days_test_baseline(:, index_day), 24, 1)]; 32 | 33 | %% Plot 34 | 35 | linewidth = 1; 36 | plot(1:24, total_energy_baseline(:, 5), "-oblack", 'linewidth', linewidth); hold on; 37 | plot(1:24, total_energy_baseline(:, 1), "-->m", 'linewidth', linewidth); hold on; 38 | plot(1:24, total_energy_baseline(:, 2), "--m", 'linewidth', linewidth); hold on; 38 | plot(1:24, total_energy_baseline(:, 2), "--