AI智能
改变未来

随机算法解决生产调度问题 C# Oracle

解决这样一个问题,设想机器有500台(注塑机),工单有3000张,每张工单只能分配到特定范围的机器(按照注塑机吨位分配),并且每张工单可以用日产能算出需要多少天,如何一次分配,既使每张工单都能分到机器,又让每台机器都分到工单,并且尽量保证注塑机效率最高(效率最高的意思是开机率最高)。
另外,注塑机出产品可以一个模具出不同的产品,所以很多时候需要考虑给一张工单搭配一个生产数量差不多的联产品,以保证效率。

using Oracle.ManagedDataAccess.Client;using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Runtime.InteropServices;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.Windows.Forms.DataVisualization.Charting;namespace GAInJobShop{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){MachineQuery();}private void MachineQuery(){string sql;sql = @\"SELECT eci01 machine,machine_ton,machine_down FROM injection_plan_machine ORDER BY eci01\";DataTable dt= OracleHelper.ExecuteDataTable(sql);dt.Columns.Add(\"Select\",typeof(bool));dt.Columns[\"Select\"].SetOrdinal(0);dataGridView1.DataSource = dt;//dt.Columns[\"Select\"].DefaultValue = false;for (int i = 0; i < dataGridView1.RowCount; i++){dataGridView1.Rows[i].Cells[\"Select\"].Value = false;if (dataGridView1.Rows[i].Cells[\"machine_down\"].Value.ToString() == \"Y\"){dataGridView1.Rows[i].Cells[\"Select\"].Value = true;}}}private void GA(){string sql;//更新需要排的工單sql = \"TRUNCATE TABLE injection_plan\";OracleHelper.ExecuteNonQuery(sql);sql = @\"insert into injection_plan SELECT CAST(0 AS INT) Ver,SFB01 job_num,SFB102 machine,SFB13 start_date,SFB15 end_date,SFB05 partnum,SFB08 prod_qty,SFB09 complete_qty,sfb08-sfb09 uncomplete_qty,A1 daily_plan_qty,CEIL((sfb08-sfb09)/A1) need_qty,get_forward_date(CEIL((sfb08-sfb09)/A1)) estimate_complete_date,TA_IMA001 suggestion_workshop,TC_MMJ09 ton,gong_mu,tc_mmi01 moldFROM SFB_FILELEFT JOIN IMA_FILEON IMA01 = SFB05LEFT JOIN OEB_FILEON OEB01 = SFB22AND OEB03 = SFB221LEFT JOIN mu_ju_zui_da_chan_neng2ON sfb05=tc_mmj03WHERE SFB04 <> \'8\'AND SFB01 LIKE \'%511-%\'AND SFB02 NOT IN (\'7\', \'8\')AND SFB08 <> SFB09AND sfb13>get_forward_date(-45)AND A1 IS NOT NULLORDER BY sfb102,sfb13\";OracleHelper.ExecuteNonQuery(sql);//MessageBox.Show(\"已經更新工單!!!!\");//產生第二代,為了把沒有機台的隨機排到機台sql = @\"insert into injection_plan SELECT 1 Ver,job_num,machine,start_date,end_date,partnum,prod_qty,complete_qty,uncomplete_qty,daily_plan_qty,need_days,estimate_complete_date,suggestion_workshop,ton,gong_mu,moldFROM injection_planwhere Ver=0 and need_days>\" + NeedDays.Text + \" \";OracleHelper.ExecuteNonQuery(sql);//MessageBox.Show(\"產生第二代!!!!\");//sql = @\"SELECT job_num,ton,gong_mu,mold FROM injection_plan WHERE ver=1 ORDER BY machine\";//DataTable NotScheduleJobNumDt = OracleHelper.ExecuteDataTable(sql);DataTable NotScheduleJobNumDt = new DataTable();DataTable NotScheduleMachineDt = new DataTable();Random rd = new Random(int.Parse(DateTime.Now.ToString(\"ss\")) + 20);Random rd2 = new Random(int.Parse(DateTime.Now.ToString(\"ss\")));Random rd3 = new Random(int.Parse(DateTime.Now.ToString(\"ss\")) + 30);Random rd4 = new Random(int.Parse(DateTime.Now.ToString(\"ss\")) + 40);int randkey, randkey2, randkey3, randkey4;OracleConnection conn = new OracleConnection(OracleHelper.connStr);conn.Open();OracleCommand cmd = conn.CreateCommand();OracleDataAdapter adapter = new OracleDataAdapter(cmd);//MessageBox.Show(\"二代已隨機更新生產線!!!!\");//產生第二代,為了把沒有機台的隨機排到機台sql = @\"insert into injection_plan SELECT 2 Ver,job_num,machine,start_date,end_date,partnum,prod_qty,complete_qty,uncomplete_qty,daily_plan_qty,need_days,estimate_complete_date,suggestion_workshop,ton,gong_mu,moldFROM injection_planwhere Ver=1 \";cmd.CommandText = sql;cmd.ExecuteNonQuery();//MessageBox.Show(\"三代已隨機更新生產線!!!!\");//開始變異/*sql = @\"SELECT ECI01 FROM eci_file WHERE eci03 IN (\'INJA\',\'INJB\',\'INJC\',\'INJD\',\'INJE\')AND eci01 LIKE \'%J%\' AND eciacti=\'Y\' AND eci01<>\'JL01\'AND eci03 IN (\'INJA\',\'INJB\')AND LENGTH(ECI01)=5UNION ALLSELECT ECI01 FROM eci_file WHERE eci03 IN (\'INJA\',\'INJB\',\'INJC\',\'INJD\',\'INJE\')AND eci01 LIKE \'%J%\' AND eciacti=\'Y\' AND eci01<>\'JL01\'AND eci03 NOT IN (\'INJA\',\'INJB\') AND LENGTH(ECI01)=4order by eci01\";cmd.CommandText = sql;DataTable datatable4 = new DataTable();adapter.Fill(datatable4);NotScheduleMachineDt.Clear();NotScheduleMachineDt = datatable4;*///fitnesssql = @\"TRUNCATE TABLE injection_plan_fitness\";cmd.CommandText = sql;cmd.ExecuteNonQuery();sql = @\"insert into injection_plan_fitness(ver,dev_days)SELECT ver,ROUND(STDDEV(need_days),3) dev_daysFROM (SELECT ver,machine,SUM(need_days) need_days FROM injection_plan WHERE ver>=0GROUP BY ver,machine) GROUP BY ver\";cmd.CommandText = sql;cmd.ExecuteNonQuery();//已發料的工單不再進行重新排機sql = @\"TRUNCATE TABLE CanScheduleJobnum\";cmd.CommandText = sql;cmd.ExecuteNonQuery();sql = @\"  insert into CanScheduleJobnum SELECT job_num FROM injection_plan WHERE  ver=2and job_num not in ( SELECT DISTINCT job_num FROM (SELECT sfa06, injection_plan.* FROM injection_planLEFT JOIN sfa_file ON job_num = sfa01WHERE ver = 2 AND sfa06> 0))\";cmd.CommandText = sql;cmd.ExecuteNonQuery();//計算每次變異的工單張數sql = @\"SELECT CEIL(COUNT(*)*(\" + P.Text + \"/100)) FROM injection_plan WHERE ver=2\";int MutationJobQty = int.Parse(OracleHelper.ExecuteDataTable(sql).Rows[0][0].ToString());for (int i = 0; i < int.Parse(Generation.Text); i++){label14.BeginInvoke(new Action(() => { label14.Text=i.ToString(); }));//遺傳使用精英模式int Mutation = int.Parse(EliteGeneration.Text);Mutation = int.Parse(EliteGeneration.Text) - i / 10000 * 15;//進化壓力,越到後面壓力越大,利於收斂if (Mutation < 30){Mutation = 30;}sql = @\"SELECT ver,dev_days FROM (select ver,dev_days from injection_plan_fitness order by dev_days) WHERE ROWNUM<=\" + Mutation + \"  \";cmd.CommandText = sql;DataTable datatable53 = new DataTable();adapter.Fill(datatable53);if (datatable53.Rows.Count == Mutation){if (decimal.Parse(datatable53.Rows[0][1].ToString()) == decimal.Parse(datatable53.Rows[Mutation - 1][1].ToString())){//收斂退出條件break;}}randkey4 = rd4.Next(0, datatable53.Rows.Count);sql = @\"insert into injection_plan SELECT \" + (i + 3) + @\" Ver,job_num,machine,start_date,end_date,partnum,prod_qty,complete_qty,uncomplete_qty,daily_plan_qty,need_days,estimate_complete_date,suggestion_workshop,ton,gong_mu,moldFROM injection_planwhere Ver=\" + datatable53.Rows[randkey4][0] + \" \"; //精英模式複製cmd.CommandText = sql;cmd.ExecuteNonQuery();if (i <= 1000){/*sql = @\" SELECT job_num,PartNum,ton,gong_mu,mold FROM injection_plan WHEREjob_num in ( SELECT job_num FROM CanScheduleJobnum) and ver=\" + (i + 3) + @\"and machine IS NULL \";*/sql = @\" SELECT t0.job_num,PartNum,prod_qty,ton,gong_mu,mold FROM injection_plan t0left join  CanScheduleJobnum t1 on t0.job_num=t1.job_numwhere t1.job_num is not nulland ver=\" + (i + 3) + @\"and machine IS NULL \";}else{/*sql = @\" SELECT job_num,PartNum,ton,gong_mu,mold FROM injection_plan WHEREjob_num in ( SELECT job_num FROM CanScheduleJobnum) and ver=\" + (i + 3) + @\"and (machine is null or (machine IN (SELECT machine FROM (SELECT machine,SUM(need_days) need_days FROM injection_planWHERE ver=\" + (i + 3) + @\" GROUP BY machine) WHERE need_days>=\" + int.Parse(Days.Text) + @\" AND machine IS NOT NULL )))\";*/sql = @\"SELECT t0.job_num,t0.PartNum,t0.prod_qty,t0.ton,t0.gong_mu,t0.mold FROM injection_plan t0LEFT JOIN (SELECT machine FROM (SELECT machine,SUM(need_days/gong_mu) need_days FROM injection_planWHERE ver=\" + (i + 3) + @\" GROUP BY machine) WHERE need_days>=\" + int.Parse(Days.Text) + @\" AND machine IS NOT NULL) t1 ON t0.machine=t1.machineLEFT JOIN CanScheduleJobnum t3 ON t0.job_num=t3.job_numWHERE t3.job_num IS NOT NULLAND ver=\" + (i + 3) + @\"and (t0.machine is NULL OR t1.machine IS NOT NULL) \";}cmd.CommandText = sql;DataTable datatable51 = new DataTable();adapter.Fill(datatable51);NotScheduleJobNumDt.Clear();NotScheduleJobNumDt = datatable51;if (NotScheduleJobNumDt.Rows.Count == 0){continue;}//對1%的進行變異for (int j = 0; j < MutationJobQty - 1; j++){randkey = rd.Next(0, NotScheduleJobNumDt.Rows.Count);//工單只排對應噸位的注塑機if (NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString().Length == 0){NotScheduleJobNumDt.Rows[randkey][\"ton\"] = 200;}if (i <= 1000){sql = @\"select * from injection_plan_machineWHERE  machine_ton>=\" + int.Parse(NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString()) + @\"and machine_ton<=\" + (int.Parse(NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString()) + int.Parse(Ton.Text)) + @\"and MACHINE_DOWN=\'N\' \";cmd.CommandText = sql;DataTable datatable6 = new DataTable();adapter.Fill(datatable6);NotScheduleMachineDt.Clear();NotScheduleMachineDt = datatable6;}else{/*sql = @\"select * from injection_plan_machineWHERE  machine_ton>=\" + int.Parse(NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString()) + @\"and machine_ton<=\" + (int.Parse(NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString()) + int.Parse(Ton.Text))+@\"and ECI01 IN (SELECT machine FROM (SELECT machine,SUM(need_days) need_days FROM injection_planWHERE ver=\" + (i + 3) + @\" GROUP BY machine) WHERE need_days<\" + int.Parse(Days.Text) + @\" AND machine IS NOT NULL)union allselect * from injection_plan_machine where eci01 not in(select machine from injection_plan wheremachine is not null and ver=\"+(i+3)+\") \";*/sql = @\"select t0.* from injection_plan_machine t0LEFT JOIN (SELECT machine FROM (SELECT machine,SUM(need_days/gong_mu) need_days FROM injection_planWHERE ver=\" + (i + 3) + @\" GROUP BY machine) WHERE need_days<\" + int.Parse(Days.Text) + @\" AND machine IS NOT NULL) t1 ON t0.eci01=t1.machineWHERE  machine_ton>=\" + int.Parse(NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString()) + @\"and machine_ton<=\" + (int.Parse(NotScheduleJobNumDt.Rows[randkey][\"ton\"].ToString()) + int.Parse(Ton.Text)) + @\"AND t1.machine IS NOT NULL and t0.MACHINE_DOWN=\'N\'union allselect t00.* from injection_plan_machine t00LEFT JOIN (select machine from injection_plan wheremachine is not null and ver=\" + (i + 3) + @\") t01 ON t00.eci01=t01.machineWHERE  t01.machine IS NULL and t00.MACHINE_DOWN=\'N\' \";cmd.CommandText = sql;DataTable datatable6 = new DataTable();adapter.Fill(datatable6);NotScheduleMachineDt.Clear();NotScheduleMachineDt = datatable6;}if (NotScheduleMachineDt.Rows.Count == 0){continue;}randkey2 = rd2.Next(0, NotScheduleMachineDt.Rows.Count);sql = @\"update injection_plan set machine=\'\" + NotScheduleMachineDt.Rows[randkey2][\"ECI01\"] + @\"\'where job_num=\'\" + NotScheduleJobNumDt.Rows[randkey][\"job_num\"].ToString() + \"\' and ver=\" + (i + 3) + \" \";cmd.CommandText = sql;cmd.ExecuteNonQuery();//現在考慮1個模具出2個膠件的情況,找到剛才這張工單使用的模具,找到應模具使用的料號,//找到料號對應的工單,更新之//先處理2個料號共模具 其他的暫時不處理 2020年1月10日10:19:40if (NotScheduleJobNumDt.Rows[randkey][\"gong_mu\"].ToString() == \"2\"){//找出共模的料號sql = @\"SELECT tc_mmj03 FROM tc_mmj_file WHERE tc_mmj01=\'\" + NotScheduleJobNumDt.Rows[randkey][\"mold\"] + @\"\'AND tc_mmj03<>\'\" + NotScheduleJobNumDt.Rows[randkey][\"PartNum\"] + \"\' \";cmd.CommandText = sql;DataTable datatable211 = new DataTable();adapter.Fill(datatable211);//用這個料號去找一個可以排的工單號//sql = @\"SELECT job_num FROM injection_plan//    WHERE partnum=\'\" + datatable211.Rows[0][0].ToString() + @\"\'//    and ver=1 and job_num<>\'\" + NotScheduleJobNumDt.Rows[randkey][\"job_num\"].ToString() + @\"\'//    and job_num in (select job_num from CanScheduleJobnum) \";//可以排的工單號/*sql = @\"SELECT job_num FROM injection_planWHERE partnum=\'\" + datatable211.Rows[0][0].ToString() + @\"\'and ver=1 and job_num<>\'\" + NotScheduleJobNumDt.Rows[randkey][\"job_num\"].ToString() + @\"\'and exists (select * from CanScheduleJobnum t0,injection_plan t1where t0.job_num=t1.job_num) AND ROWNUM=1ORDER BY ABS(prod_qty-\" + NotScheduleJobNumDt.Rows[randkey][\"prod_qty\"] + \") ASC \";//可以排的工單號 //排數量跟他最接近的那個共模工單*/sql = @\"select job_num from (SELECT row_number() OVER (ORDER BY ABS(prod_qty-\" + NotScheduleJobNumDt.Rows[randkey][\"prod_qty\"] + @\") ASC) seq,job_num FROM injection_planWHERE partnum=\'\" + datatable211.Rows[0][0].ToString() + @\"\'and ver=1 and job_num<>\'\" + NotScheduleJobNumDt.Rows[randkey][\"job_num\"].ToString() + @\"\'and exists (select * from CanScheduleJobnum t0,injection_plan t1where t0.job_num=t1.job_num) ) where seq=1 \";cmd.CommandText = sql;DataTable datatable212 = new DataTable();adapter.Fill(datatable212);//找不到共模的工單號,就不處理了,繼續下一次循環if (datatable212.Rows.Count == 0){continue;}//更新這個工單號的機台randkey3 = 0;sql = @\"update injection_plan set machine=\'\" + NotScheduleMachineDt.Rows[randkey2][\"ECI01\"] + @\"\'where job_num=\'\" + datatable212.Rows[randkey3][\"job_num\"].ToString() + \"\' and ver=\" + (i + 3) + \" \";cmd.CommandText = sql;cmd.ExecuteNonQuery();}}sql = @\"insert into injection_plan_fitness(ver,dev_days,max_days,min_days)SELECT ver,ROUND(STDDEV(need_days),5) dev_days,max(need_days) max_days,min(need_days) min_daysFROM (SELECT ver,machine,round(SUM(need_days/gong_mu),2) need_days FROM injection_plan WHERE ver=\" + (i + 3) + @\"GROUP BY ver,machine) GROUP BY ver\";cmd.CommandText = sql;cmd.ExecuteNonQuery();ClearMemory();}conn.Close();label11.BeginInvoke(new Action(() => { label11.Text = \"~~~計算完畢~~~\"; }));label11.BeginInvoke(new Action(() => { label18.Text = DateTime.Now.ToString(\"yyyy-MM-dd HH:mm:ss\"); }));}private void button1_Click(object sender, EventArgs e){label18.Text = \"結束時間\";if (label11.Text == \"正在計算中。。。。。。\"){MessageBox.Show(\"正在計算中,請不要再次點擊\");return;}label10.Text = DateTime.Now.ToString(\"yyyy-MM-dd HH:mm:ss\");var t1 = Task.Run(() => GA());label11.Text = \"正在計算中。。。。。。\";}[DllImport(\"kernel32.dll\", EntryPoint = \"SetProcessWorkingSetSize\")]public static extern int SetProcessWorkingSetSize(IntPtr process, int minSize, int maxSize);/// <summary>/// 释放内存/// </summary>public static void ClearMemory(){GC.Collect();GC.WaitForPendingFinalizers();if (Environment.OSVersion.Platform == PlatformID.Win32NT){SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);}}private void button2_Click(object sender, EventArgs e){}private void button2_Click_1(object sender, EventArgs e){}private void button2_Click_2(object sender, EventArgs e){string sql;for (int i = 0; i < dataGridView1.Rows.Count; i++){if ((Convert.ToBoolean(dataGridView1.Rows[i].Cells[\"Select\"].Value) == true)){string machine = \"\";machine = dataGridView1.Rows[i].Cells[\"machine\"].Value.ToString();sql = @\"update injection_plan_machine set MACHINE_DOWN=\'Y\'where eci01=\'\" + machine + \"\' \";OracleHelper.ExecuteNonQuery(sql);}else{string machine = \"\";machine = dataGridView1.Rows[i].Cells[\"machine\"].Value.ToString();sql = @\"update injection_plan_machine set MACHINE_DOWN=\'N\'where eci01=\'\" + machine + \"\' \";OracleHelper.ExecuteNonQuery(sql);}}MachineQuery();}private void button3_Click(object sender, EventArgs e){string sql;sql = @\"SELECT * FROM (SELECT * FROM injection_plan_fitness ORDER BY dev_days)WHERE ROWNUM<100\";dataGridView2.DataSource = OracleHelper.ExecuteDataTable(sql);}private void button4_Click(object sender, EventArgs e){string sql;sql = @\"SELECT ROWNUM,t0.* FROM (SELECT machine,ROUND(SUM(need_days/gong_mu),0) need_days,COUNT(*) job_qty,MAX(ton) tonFROM injection_planWHERE ver=\"+GenerationQuery.Text+@\"AND machine NOT IN(\'FC31\',\'FBC09\',\'JB22\',\'JB02\')GROUP BY machineORDER BY NEED_DAYS ASC) t0\";dataGridView3.DataSource = OracleHelper.ExecuteDataTable(sql);}private void button5_Click(object sender, EventArgs e){string sql = @\"select * from injection_plan where ver=\"+InjectionG.Text+\" \";dataGridView4.DataSource = OracleHelper.ExecuteDataTable(sql);}private void button6_Click(object sender, EventArgs e){if (label18.Text == \"結束時間\"){DateTime startTime = Convert.ToDateTime(label10.Text);DateTime endTime = DateTime.Now;TimeSpan ts = endTime - startTime;//int seconds = (int)ts.TotalSecond;int sec = (int)ts.TotalSeconds;label16.Text = (Math.Round(float.Parse(label14.Text) / sec, 2)).ToString(\"0.00\");}else{DateTime startTime = Convert.ToDateTime(label10.Text);DateTime endTime = Convert.ToDateTime(label18.Text);TimeSpan ts = endTime - startTime;//int seconds = (int)ts.TotalSecond;int sec = (int)ts.TotalSeconds;label16.Text = (Math.Round(float.Parse(label14.Text) / sec, 2)).ToString(\"0.00\");}}private void button7_Click(object sender, EventArgs e){string sql = @\"select * from injection_plan where ver=\" + InjectionG.Text + \" \";ExcelHelper.ToExcel(OracleHelper.ExecuteDataTable(sql));}private void button8_Click(object sender, EventArgs e){if ((Convert.ToBoolean(dataGridView1.Rows[0].Cells[0].Value) == false)){for (int i = 0; i < dataGridView1.Rows.Count; i++){if ((Convert.ToBoolean(dataGridView1.Rows[i].Cells[0].Value) == false)){dataGridView1.Rows[i].Cells[0].Value = \"True\";}}}else{for (int i = 0; i < dataGridView1.Rows.Count; i++){if ((Convert.ToBoolean(dataGridView1.Rows[i].Cells[0].Value) == true)){dataGridView1.Rows[i].Cells[0].Value = \"False\";}}}}private void button9_Click(object sender, EventArgs e){mychart.ChartAreas.Clear(); //图表区mychart.Titles.Clear(); //图表标题mychart.Series.Clear(); //图表序列mychart.Legends.Clear(); //图表图例//新建chart图表要素mychart.ChartAreas.Add(new ChartArea(\"chartArea\"));mychart.ChartAreas[\"chartArea\"].AxisX.IsMarginVisible = false;mychart.ChartAreas[\"chartArea\"].Area3DStyle.Enable3D = false;mychart.Series.Add(\"均方差回歸\");//mychart.Titles.Add(\"均方差回歸\"); //标题//mychart.Titles[0].Font = new Font(\"宋体\", 12);mychart.Series[\"均方差回歸\"].ChartType = SeriesChartType.Point; //图标类型mychart.Series[\"均方差回歸\"][\"PieLineColor\"] = \"Black\";//mychart.Legends.Add(new Legend(\"legend\"));mychart.Palette = ChartColorPalette.BrightPastel;mychart.ChartAreas[\"chartArea\"].AxisY.LabelStyle.IsStaggered = true;Legend tu_li = new Legend();mychart.Legends.Add(tu_li);tu_li.Alignment = StringAlignment.Center;tu_li.Docking = Docking.Top;tu_li.Font= new Font(\"宋体\", 24); ;string sql3 = \"SELECT ver,dev_days FROM injection_plan_fitness ORDER BY ver\";DataTable dt2;dt2 = OracleHelper.ExecuteDataTable(sql3);mychart.Series[\"均方差回歸\"].Points.DataBind(dt2.AsEnumerable(), \"VER\", \"DEV_DAYS\", \"\");mychart.Series[\"均方差回歸\"].LabelForeColor = Color.Blue;}}}
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 随机算法解决生产调度问题 C# Oracle