├── .gitattributes ├── .gitignore ├── BlackStar2.pdf ├── README.md ├── Read ├── palantir.jpg └── shot.png ├── Samples ├── .dockerignore ├── BlackStar.Bom │ ├── BlackStar.Bom.csproj │ └── Program.cs ├── BlackStar.GA │ ├── BlackStar.GA.csproj │ ├── GlobalUsings.cs │ └── Program.cs ├── BlackStar.SceneDefinition │ ├── BlackStar.SceneDefinition.csproj │ ├── GlobalUsings.cs │ ├── Program.cs │ ├── bom.json │ ├── bom.xml │ ├── scene.json │ └── scene.xml ├── BlackStar.View │ ├── App.config │ ├── App.xaml │ ├── App.xaml.cs │ ├── AssemblyInfo.cs │ ├── BlackStar.View.csproj │ ├── BlackStar.View.csproj.user │ ├── Case5k.cs │ ├── CaseBom.cs │ ├── CaseBoolNoBom.cs │ ├── CaseColorSwitch.cs │ ├── CaseDig.cs │ ├── CaseIntNoBom.cs │ ├── CaseLight.cs │ ├── DescendendWindow.xaml │ ├── DescendendWindow.xaml.cs │ ├── Dig.jpg │ ├── GlobalUsings.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── Menu.xaml │ ├── Menu.xaml.cs │ ├── Trace │ │ └── log4net.config │ ├── blackstar desc.ico │ ├── blackstar gantt.ico │ ├── desc.png │ ├── gantt-chart.png │ ├── 模拟11台设备45种产品.xlsx │ └── 资料.xlsx ├── Samples.sln └── Samples.slnx ├── UIDCheckCore.rar ├── UIDCheckWin.rar └── simulation.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | *.cs linguist-language=C# 2 | *.sln linguist-language=C# 3 | *.csproj linguist-language=C# 4 | *.usl linguist-language=C# 5 | *.bs linguist-language=C# 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 3 | ################################################################################ 4 | /Samples/HelloBlackStar/obj 5 | /Samples/SolutionLoadRun/obj/Release/netcoreapp3.1 6 | /Samples/SolutionLoadRun/obj/Debug/netcoreapp3.1 7 | /.vs 8 | /Samples/SolutionLoadRun/obj 9 | /Samples/.vs/Samples/v16 10 | /Samples/HelloBlackStar/bin/Debug/netcoreapp3.1 11 | /Samples/.vs/Samples/DesignTimeBuild 12 | /Samples/SolutionLoadRun/bin/Debug/netcoreapp3.1 13 | /Samples/RuleInjectionCall/bin 14 | /Samples/RuleInjectionCall/obj 15 | /Samples/RuleInjectionRule/obj 16 | /Samples/RuleInjectionRule/bin 17 | /Samples/HelloBlackStar/bin/Release/net5.0 18 | /Samples/SolutionLoadRun/bin/Release/net5.0 19 | /Samples/HelloBlackStar/bin/Debug/net5.0 20 | /Samples/SolutionLoadRun/bin/Debug/net5.0 21 | /Samples/MaxUserate/bin/Debug/net5.0 22 | /Samples/MaxUserate/bin/Release/net5.0 23 | /Samples/MaxUserate/obj 24 | /Samples/CustomAction/bin/Debug/netstandard2.0 25 | /Samples/CustomAction/obj 26 | /Samples/.vs/Samples/v17 27 | /Samples/CustomActionCallingRule/bin/Debug/netstandard2.0 28 | /Samples/CustomActionCallingRule/obj 29 | /Samples/CustomAction/bin/Release/netstandard2.0 30 | /Samples/CustomActionCallingRule/bin/Release/netstandard2.0 31 | /Samples/HelloBlackStar/bin/Release/net6.0 32 | /Samples/MaxUserate/bin/Release/net6.0 33 | /Samples/SolutionLoadRun/bin 34 | /Samples/.vs 35 | /Samples/HelloBlackStar/bin/Debug/net6.0 36 | /Samples/MaxUserate/bin/Debug/net6.0 37 | /Samples/USLInjection/obj 38 | /Samples/USLInjection/bin/Debug/netstandard2.0 39 | /Samples/HelloBlackStar/bin/Debug/net7.0 40 | /Samples/MaxUserate/bin/Debug/net7.0 41 | /Samples/USLInjection/bin/Debug/net7.0 42 | /Samples/CustomActionCallingRule/bin/Debug/net7.0 43 | /Samples/CustomAction/bin/Debug/net7.0 44 | /push.cmd 45 | /Samples/CustomAction/bin/Debug/net8.0 46 | /Samples/CustomActionCallingRule/bin/Debug/net8.0 47 | /Samples/HelloBlackStar/bin/Debug/net8.0 48 | /Samples/USLInjection/bin/Debug/net8.0 49 | /Samples/MaxUserate/bin/Debug/net8.0 50 | /Samples/BlackStar.Bom/bin 51 | /Samples/BlackStar.Bom/obj 52 | /Samples/BlackStar.GA/bin 53 | /Samples/BlackStar.GA/obj 54 | /Samples/BlackStar.SceneDefinition/bin/Debug/net8.0 55 | /Samples/BlackStar.SceneDefinition/obj 56 | /Samples/BlackStar.View/bin 57 | /Samples/BlackStar.View/obj 58 | /Samples/CaseBom/bin/Debug/net8.0-windows 59 | /Samples/CaseBom/obj 60 | /Samples/CaseIntResource/bin 61 | /Samples/CaseIntResource/obj 62 | /Samples/CaseLightModule/bin 63 | /Samples/CaseLightModule/obj 64 | /Samples/CaseLightModule - 副本/obj/Release/net8.0-windows 65 | /Samples/CaseNoBom/bin/Debug/net8.0-windows 66 | /Samples/CaseNoBom/obj 67 | /Samples/CaseProduceRoute/bin 68 | /Samples/CaseProduceRoute/obj 69 | /Samples/CaseBom/bin/Debug/bom.rar 70 | /Samples/CaseNoBom/bin/Debug/no bom.rar 71 | *.blic 72 | /Samples/CaseNoBom/bin/Release/net8.0-windows 73 | /Samples/CaseBom/bin/Release/net8.0-windows 74 | /Samples/BlackStar.SceneDefinition/bin/Release/net8.0 75 | /Samples/BlackStar.SceneDefinition/bin/Debug/net9.0 76 | /Samples/CaseBom/bin/Debug/net9.0-windows 77 | /Samples/CaseNoBom/bin/Debug/net9.0-windows/runtimes/win/lib/net8.0 78 | /Samples/CaseNoBom/bin/Debug/net9.0-windows 79 | /Samples/Case5k/obj 80 | /Samples/Case5k/bin/Debug/net9.0-windows 81 | /Samples/CaseDig/bin/Debug/net9.0-windows 82 | /Samples/CaseDig/obj 83 | /.idea/.idea.folder.dir/.idea 84 | /Samples/.idea/.idea.Samples/.idea 85 | /Samples/BlackStar.SceneDefinition/bin/Release/net9.0 86 | /Samples/Case5k/bin/Release/net9.0-windows 87 | /Samples/CaseBom/bin/Release/net9.0-windows 88 | /Samples/CaseDig/bin/Release/net9.0-windows 89 | /Samples/CaseNoBom/bin/Release/net9.0-windows 90 | /.idea/.gitignore 91 | /.idea/encodings.xml 92 | /.idea/indexLayout.xml 93 | /.idea/vcs.xml 94 | -------------------------------------------------------------------------------- /BlackStar2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnakinCN/BlackStar-APS/49df8e7fb3b8e7fe3858b58acaf6072e1fb77680/BlackStar2.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | charset: utf-8 3 | --- 4 | 5 |

BlackStar, the Planning & Scheduling Solver

6 | 7 | BlackStar is a general APS (advanced planning & scheduling) model and algorithm solution for various industries including aerospace mission planning, unmanned systems planning, vehicle fleet dispatching and manufactory planning. BlackStar uses a continuous time model to support any time precisions. 8 | 9 | Contact Wechat official '真知科技' for license application, you should send the UID of your machine that can be queried by: 10 | 11 | - UID Checker Linux (the running command is: `dotnet BlackStar.UIDCheckCore.dll`,you need dotnet 8 runtime for Linux) 12 | - UID Checker Win (directly run BlackStar.UIDCheckWin.exe, which needs dotnet 8 runtime Windows Desktop) 13 | 14 | 15 |

BlackStar计划调度排产求解器

16 | 17 | BlackStar是一个通用的先进计划排程APS模型和算法解决方案,支持航天任务、无人系统、车队调度、制造排产等诸多领域。BlackStar使用连续时间模型,可支持任意精度的时间。详见技术白皮书。 18 | 19 | 请联系微信公众号“真知科技”申请证书,之前需要检查机器的UID,请使用UID检查工具,并将显示的UID序列号发送过来: 20 | 21 | 22 | 23 | - UID Checker Linux (运行命令为 `dotnet BlackStar.UIDCheckCore.dll`,需要dotnet 9 Linux运行时 ) 24 | - UID Checker Win(直接运行BlackStar.UIDCheckWin.exe文件,需要dotnet 9 Windows桌面运行时 ) 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Read/palantir.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnakinCN/BlackStar-APS/49df8e7fb3b8e7fe3858b58acaf6072e1fb77680/Read/palantir.jpg -------------------------------------------------------------------------------- /Read/shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnakinCN/BlackStar-APS/49df8e7fb3b8e7fe3858b58acaf6072e1fb77680/Read/shot.png -------------------------------------------------------------------------------- /Samples/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /Samples/BlackStar.Bom/BlackStar.Bom.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | enable 7 | enable 8 | 2.0.0.0 9 | x64 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Samples/BlackStar.Bom/Program.cs: -------------------------------------------------------------------------------- 1 | using BlackStar.Model; 2 | 3 | var mainBOM = new Bom("Main Bom"); 4 | var screwsBOM = new Bom("Screws"); 5 | var nutsBOM = new Bom("Nuts"); 6 | var washersBOM = new Bom("Washers"); 7 | 8 | mainBOM.AddSubBom(screwsBOM,1); 9 | mainBOM.AddSubBom(nutsBOM, 1); 10 | mainBOM.AddSubBom(washersBOM, 1); 11 | 12 | var smallScrewsBOM = new Bom("Small Screws"); 13 | var largeScrewsBOM = new Bom("Large Screws"); 14 | 15 | screwsBOM.AddSubBom(smallScrewsBOM, 1); 16 | screwsBOM.AddSubBom(largeScrewsBOM, 1); 17 | 18 | mainBOM.Display(); -------------------------------------------------------------------------------- /Samples/BlackStar.GA/BlackStar.GA.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | enable 7 | enable 8 | Preview 9 | 2.0.0.0 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Samples/BlackStar.GA/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.Collections; 3 | global using System.Collections.Generic; 4 | global using System.Collections.Concurrent; 5 | global using System.Linq; 6 | global using System.Text; 7 | global using System.Threading.Tasks; 8 | global using Prism.Events; 9 | global using System.Diagnostics; 10 | global using System.Text.RegularExpressions; 11 | global using BlackStar.Transolution.SortAll; 12 | global using BlackStar.Model; 13 | global using BlackStar.Strategy; 14 | global using BlackStar.Functions; 15 | -------------------------------------------------------------------------------- /Samples/BlackStar.GA/Program.cs: -------------------------------------------------------------------------------- 1 | using Collections.Pooled; 2 | 3 | OptimTest1(50,60); 4 | 5 | void OptimTest1(int nAct, int nResource) 6 | { 7 | DateTime start = new DateTime(2023, 1, 1); 8 | 9 | // 1. Generate 1000 random ActInt 10 | List acts = new(); 11 | for (int i = 0; i < nAct; i++) 12 | { 13 | string name = $"act{i:000}"; 14 | ActBool actInt = new(name) 15 | { 16 | NeedTs = new () { ["BoolService"] = TimeSpan.FromMinutes(0.6 + Random.Shared.NextDouble())}, 17 | }; 18 | //Console.WriteLine($"{name} need {actInt.NeedTs}"); 19 | acts.Add(actInt); 20 | } 21 | Console.WriteLine($"need total {acts.Sum(i=> ((ActBool)i).NeedTs["BoolService"].TotalMinutes)}"); 22 | //Console.WriteLine(); 23 | 24 | // 2. Generate 2000 Resource with State 25 | PooledDictionary resources = new(); 26 | for (int i = 0; i < nResource; i++) 27 | { 28 | string name = $"res{i:000}"; 29 | Resource resource = new Resource(name); 30 | var statestart = new DateTime(2023, 1, 1) + TimeSpan.FromMinutes(20 * Random.Shared.NextDouble()); 31 | var stateend = statestart + TimeSpan.FromMinutes(2 + 2.5 * Random.Shared.NextDouble()); 32 | State state = new State("BoolService", statestart, stateend, true); 33 | resource.States = new PooledList> { state }; 34 | //Console.WriteLine($"{name} provide {state.To- state.From}"); 35 | resources.TryAdd(name, resource); 36 | } 37 | var provideTotal = resources.Sum( 38 | i => ((Resource)i.Value).States 39 | .Sum(j => (j.To - j.From).TotalMinutes)); 40 | Console.WriteLine($"provides total {provideTotal}"); 41 | Console.WriteLine(); 42 | SortAllTransolution solver = new(acts, resources); 43 | var scene = solver.Solve(); 44 | 45 | } -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/BlackStar.SceneDefinition.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net9.0 6 | enable 7 | enable 8 | 2.0.0.0 9 | x64 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | PreserveNewest 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.Collections.Generic; 3 | global using System.Linq; 4 | global using System.Text; 5 | global using System.Threading.Tasks; 6 | global using System; 7 | global using System.Collections.Generic; 8 | global using System.Linq; 9 | global using System.Text; 10 | global using System.Threading.Tasks; 11 | global using System.Windows; 12 | global using BlackStar; 13 | global using BlackStar.Transolution.SortAll; 14 | global using BlackStar.Model; 15 | global using MoreLinq.Extensions; 16 | global using BlackStar.Functions; 17 | global using System.Buffers.Text; 18 | global using System.Diagnostics; 19 | global using System.IO; 20 | global using Newtonsoft.Json.Linq; 21 | global using System.Configuration; 22 | global using BlackStar.Transolution.SortBom; 23 | global using Newtonsoft.Json; 24 | -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/Program.cs: -------------------------------------------------------------------------------- 1 | Scene scene1 = Scene.LoadXML("scene.xml"); 2 | Scene scene2 = Scene.LoadJSON("scene.json"); 3 | 4 | Bom bom1 = Bom.LoadXML("bom.xml"); 5 | Bom bom2 = Bom.LoadJSON("bom.json"); 6 | 7 | Debug.WriteLine(""); 8 | -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/bom.json: -------------------------------------------------------------------------------- 1 | { 2 | "Name": "成品", 3 | "Subs": [ 4 | { 5 | "Name": "SMT半成品B", 6 | "Ammount": 1, 7 | "Subs": [ 8 | { 9 | "Name": "SMT半成品A", 10 | "Ammount": 1 11 | } 12 | ] 13 | }, 14 | { 15 | "Name": "DIP半成品", 16 | "Ammount": 1 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/bom.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 成品 4 | 5 | 6 | SMT半成品B 7 | 1 8 | 9 | 10 | SMT半成品A 11 | 1 12 | 13 | 14 | 15 | 16 | DIP半成品 17 | 1 18 | 19 | 20 | -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/scene.json: -------------------------------------------------------------------------------- 1 | { 2 | "Scene": { 3 | "Name": "Scene1", 4 | 5 | "Resources": [ 6 | { 7 | "Name": "Machine01", 8 | "Type": "bool", 9 | 10 | "States": [ 11 | { 12 | "Type": "bool", 13 | "Name": "Manufacture", 14 | "From": "2023-1-1", 15 | "To": "2023-1-2", 16 | 17 | "Value": true 18 | } 19 | ], 20 | "Variables": [ 21 | { 22 | "Name": "VariableBool", 23 | "Value": true 24 | } 25 | ] 26 | 27 | } 28 | ] 29 | } 30 | } -------------------------------------------------------------------------------- /Samples/BlackStar.SceneDefinition/scene.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | Scene1 4 | 5 | 6 | Machine01 7 | bool 8 | 9 | 10 | bool 11 | Manufacture 12 | 2023-1-1 13 | 2023-1-2 14 | True 15 | 16 | 17 | 18 | 19 | VariableBool 20 | True 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Data; 3 | using System.Windows; 4 | 5 | namespace BlackStar.View 6 | { 7 | /// 8 | /// Interaction logic for App.xaml 9 | /// 10 | public partial class App : Application 11 | { 12 | } 13 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/BlackStar.View.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net9.0-windows 6 | enable 7 | enable 8 | true 9 | Preview 10 | blackstar gantt.ico 11 | preview-all 12 | blackstar desc.ico 13 | 2.0.0.0 14 | x64 15 | 16 | 17 | 18 | 19 | 20 | 21 | PreserveNewest 22 | Trace\log4net.config 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | PreserveNewest 40 | 41 | 42 | PreserveNewest 43 | 44 | 45 | 46 | 47 | 48 | PreserveNewest 49 | 50 | 51 | True 52 | \ 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/BlackStar.View.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Designer 7 | 8 | 9 | 10 | 11 | Code 12 | 13 | 14 | Code 15 | 16 | 17 | 18 | 19 | Designer 20 | 21 | 22 | Designer 23 | 24 | 25 | Designer 26 | 27 | 28 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/Case5k.cs: -------------------------------------------------------------------------------- 1 | namespace BlackStar.View; 2 | 3 | internal class Case5k 4 | { 5 | const int STAGNATION = 20; 6 | const int POP = 2; 7 | private static int NREQUIRE = 50; 8 | static DateTime baseDt = new(2023, 1, 1); 9 | private static DateTime to; 10 | 11 | public static async IAsyncEnumerable Optim5k() 12 | { 13 | Reset(); 14 | TimeSpan last = TimeSpan.FromDays(365); 15 | to = baseDt + last; 16 | 17 | //get the nRequire option in App.config 18 | var bom = createBom(2, 5); 19 | //NREQUIRE = int.Parse(ConfigurationManager.AppSettings["nRequire"]); //输入成品数 20 | 21 | var solver = new SortBomTransolution(bom, NREQUIRE, needs, resources, switches: null, population: POP, stagnation: STAGNATION); 22 | await foreach(Scene scene in solver.Solve()) 23 | { 24 | yield return scene; 25 | }; 26 | } 27 | 28 | private static void Reset() 29 | { 30 | needs = new(); 31 | resources = new(); 32 | } 33 | 34 | private static PooledList needs = new(); 35 | private static PooledDictionary resources = new(); 36 | private static Random random = new(); 37 | 38 | private static Bom createBom(int maxWidth, int maxDeep) 39 | { 40 | // 随机生成当前BOM的名称 41 | var bom = new Bom($"0"); 42 | addNeedForBom(bom); 43 | 44 | // 随机确定当前BOM的子节点数量(不超过宽度) 45 | int width = random.Next(1, maxWidth + 1); 46 | 47 | for (int iwidth = 0; iwidth < width; iwidth++) 48 | { 49 | var subBom = createSubBom(bom, iwidth, 1, maxWidth, maxDeep); 50 | if (subBom != null) 51 | { 52 | bom.AddSubBom(subBom); 53 | } 54 | } 55 | 56 | return bom; 57 | } 58 | 59 | private static Bom createSubBom(Bom parenet, int iwidth, int ideep, int maxWidth, int maxDeep) 60 | { 61 | if (ideep == maxDeep) return null; 62 | 63 | // 随机生成当前BOM的名称 64 | var bom = new Bom($"{parenet.Name}-{iwidth}"); 65 | addNeedForBom(bom); 66 | 67 | // 随机确定当前BOM的子节点数量(不超过宽度) 68 | int width = random.Next(1, maxWidth + 1); 69 | 70 | for (int isubwidth = 0; isubwidth < width; isubwidth++) 71 | { 72 | var subBom = createSubBom(bom, isubwidth, ideep + 1, maxWidth, maxDeep); 73 | if (subBom != null) 74 | { 75 | bom.AddSubBom(subBom); 76 | } 77 | } 78 | 79 | return bom; 80 | } 81 | 82 | private static void addNeedForBom(Bom bom) 83 | { 84 | //int num = random.Next(3); 85 | //for (int i = 1; i < num; i++) 86 | //{ 87 | string resourcename = "机" + bom.Name; 88 | string ability = "造" + bom.Name; 89 | resources.TryAdd(resourcename, new Resource(resourcename) 90 | { 91 | States = new() { new State(ability, baseDt, to, true) }, 92 | Variables = new() { ["NeedSwitch"] = new Variable(false) }, 93 | }); 94 | needs.Add( 95 | new ServiceAbility( 96 | bom.Name, ability, TimeSpan.FromSeconds(random.Next(50)) 97 | )); 98 | //} 99 | } 100 | 101 | private static PooledDictionary createSwitches() 102 | { 103 | PooledDictionary switches = new() 104 | { 105 | ["SMT半成品A"] = TimeSpan.FromMinutes(3), 106 | ["SMT半成品B"] = TimeSpan.FromMinutes(3), 107 | ["DIP半成品"] = TimeSpan.FromMinutes(2), 108 | ["成品"] = TimeSpan.FromMinutes(3), 109 | }; 110 | return switches; 111 | } 112 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/CaseBom.cs: -------------------------------------------------------------------------------- 1 | namespace BlackStar.View; 2 | 3 | static class CaseBom 4 | { 5 | static int NACT = 100; 6 | static int NRESOURCE = 6; 7 | static int STAGNATION = 10; 8 | static int POP = 20; 9 | static DateTime baseDt = new (2023, 1, 1); 10 | 11 | public async static IAsyncEnumerable OptimBoolBom() 12 | { 13 | var bom = createBom(); 14 | var needs = createNeeds(); 15 | var resources = createResources(); 16 | var solver = new SortBomTransolution(bom, NACT, needs, resources, population: POP, stagnation: STAGNATION); 17 | await foreach(Scene scene in solver.Solve()) 18 | yield return scene; 19 | } 20 | 21 | private static PooledDictionary createResources() 22 | { 23 | PooledDictionary resources = new(); 24 | TimeSpan last = TimeSpan.FromHours(24); 25 | DateTime to = baseDt + last; 26 | for (int i = 0; i < NRESOURCE; i++) 27 | { 28 | 29 | resources.Add($"PhoneMachine{i}", new Resource($"PhoneMachine{i}") { States = new() { new State("BuildPhone", baseDt, to, true) } }); 30 | resources.Add($"ScreenMachine{i*2+1}", new Resource($"ScreenMachine{i*2+1}") {States = new() { new State("BuildScreen", baseDt, to, true)}}); 31 | resources.Add($"ScreenMachine{i*2+2}", new Resource($"ScreenMachine{i*2+2}") {States = new() { new State("BuildScreenHigh", baseDt, to, true)}}); 32 | resources.Add($"BatteryMachine{i*2+1}", new Resource($"BatteryMachine{i*2+1}") {States = new() { new State("BuildBattery", baseDt, to, true)}}); 33 | resources.Add($"BatteryMachine{i*2+2}", new Resource($"BatteryMachine{i*2+2}") {States = new() { new State("BuildBatteryHigh", baseDt, to, true)}}); 34 | resources.Add($"CommunicationMachine{i}", new Resource($"CommunicationMachine{i}") {States = new() { new State("BuildCommunication", baseDt, to, true)}}); 35 | resources.Add($"AntennaMachine{i}", new Resource($"AntennaMachine{i}") {States = new() { new State("BuildAntenna", baseDt, to, true)}}); 36 | resources.Add( $"BaseBandMachine{i}", new Resource($"BaseBandMachine{i}") {States = new() { new State("BuildBaseBand", baseDt, to, true)}}); 37 | } 38 | return resources; 39 | } 40 | 41 | /// 42 | /// 生产零件能力,物料名-机器名 43 | /// 44 | /// 45 | public static PooledList createNeeds() 46 | { 47 | return new() 48 | { 49 | new ServiceAbility("batch", "BuildBatch", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 50 | new ServiceAbility("Phone", "BuildPhone", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 51 | new ServiceAbility("Screen", "BuildScreen", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 52 | new ServiceAbility("Screen", "BuildScreenHigh", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 53 | new ServiceAbility("Battery", "BuildBattery", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 54 | new ServiceAbility("Battery", "BuildBatteryHigh", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 55 | new ServiceAbility("Communication", "BuildCommunication", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 56 | new ServiceAbility("Antenna", "BuildAntenna", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 57 | new ServiceAbility("BaseBand", "BuildBaseBand", TimeSpan.FromMinutes(1+ 4 * Random.Shared.NextDouble())), 58 | }; 59 | } 60 | 61 | public static Bom createBom() 62 | { 63 | var bomMain = new Bom("Phone"); 64 | var bomScreen = new Bom("Screen"); 65 | var bomBat = new Bom("Battery"); 66 | var bomCom = new Bom("Communication"); 67 | 68 | bomMain.AddSubBom(bomScreen); 69 | bomMain.AddSubBom(bomBat); 70 | bomMain.AddSubBom(bomCom); 71 | 72 | var bomAntenna = new Bom("Antenna"); 73 | var bomBaseBand = new Bom("BaseBand"); 74 | 75 | bomCom.AddSubBom(bomAntenna); 76 | bomCom.AddSubBom(bomBaseBand); 77 | 78 | //bomMain.Display(); 79 | print(bomMain); 80 | 81 | return bomMain; 82 | } 83 | 84 | private static void print(Bom bomMain) 85 | { 86 | JObject root = new() 87 | { 88 | ["Name"] = bomMain.Name, 89 | }; 90 | if (bomMain.SubBoms.Count > 0) 91 | { 92 | JArray subs = new(); 93 | foreach (var pair in bomMain.SubBoms.Span) 94 | { 95 | subs.Add(pairToJo(pair)); 96 | } 97 | root["Subs"] = subs; 98 | } 99 | 100 | File.WriteAllText("bom.json", root.ToString()); 101 | } 102 | 103 | private static JObject pairToJo(BomPair pair) 104 | { 105 | JObject jo = new() 106 | { 107 | ["Name"] = pair.Bom.Name, 108 | ["Amount"] = pair.Amount 109 | }; 110 | if (pair.Bom.SubBoms.Count > 0) 111 | { 112 | JArray subs = new(); 113 | foreach (var subpair in pair.Bom.SubBoms.Span) 114 | { 115 | subs.Add(pairToJo(subpair)); 116 | } 117 | jo["Subs"] = subs; 118 | } 119 | 120 | return jo; 121 | } 122 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/CaseBoolNoBom.cs: -------------------------------------------------------------------------------- 1 | namespace BlackStar.View; 2 | 3 | public static class CaseBoolNoBom 4 | { 5 | const int NACT = 1000; 6 | const int NRESOURCE = 700; 7 | const int STAGNATION = 10; 8 | const int POP = 20; 9 | static DateTime baseDt = new (2023, 1, 1); 10 | 11 | /// 12 | /// 无bom 13 | /// 14 | /// 15 | public static async IAsyncEnumerable OptimBoolNoBom() 16 | { 17 | // 1. Generate 1000 random ActInt 18 | PooledList acts = new(); 19 | JArray root = new(); 20 | for (int i = 0; i < NACT; i++) 21 | { 22 | string name = $"act{i:000}"; 23 | TimeSpan needTs = TimeSpan.FromMinutes(0.6 + Random.Shared.NextDouble()); 24 | ActBool actInt = new(name) {NeedTs = new() { ["BoolService"] = needTs, }}; 25 | //Console.WriteLine($"{name} need {actInt.NeedTs}"); 26 | acts.Add(actInt); 27 | root.Add(new JObject 28 | { 29 | ["需求名称"] = name, 30 | ["需求加工时间"] = needTs.TotalMinutes, 31 | }); 32 | } 33 | Console.WriteLine($"need total {acts.Sum(i => ((ActBool)i).NeedTs["BoolService"].TotalMinutes)}"); 34 | 35 | File.WriteAllText("require.json", root.ToString()); 36 | 37 | // 2. Generate 2000 Resource with State 38 | PooledDictionary resources = new(); 39 | root = new(); 40 | for (int i = 0; i < NRESOURCE; i++) 41 | { 42 | string name = $"res{i:000}"; 43 | Resource resource = new Resource(name); 44 | var statestart = baseDt + TimeSpan.FromMinutes(20 * Random.Shared.NextDouble()); 45 | var stateend = statestart + TimeSpan.FromMinutes(2 + 2.5 * Random.Shared.NextDouble()); 46 | State state = new State("BoolService", statestart, stateend, true); 47 | resource.States = new PooledList> { state }; 48 | //Console.WriteLine($"{name} provide {state.To- state.From}"); 49 | resources.TryAdd(name, resource); 50 | root.Add(new JObject() 51 | { 52 | ["机器名称"] = name, 53 | ["可用时间开始"] = statestart, 54 | ["可用时间结束"] = stateend, 55 | }); 56 | } 57 | var provideTotal = resources.Sum( 58 | i => ((Resource)i.Value).States 59 | .Sum(j => (j.To - j.From).TotalMinutes)); 60 | Console.WriteLine($"provides total {provideTotal}"); 61 | Console.WriteLine(); 62 | File.WriteAllText("machine.json", root.ToString()); 63 | SortAllTransolution transolution = new(acts, resources, pop: POP, stagnation: STAGNATION); 64 | 65 | await foreach(Scene scene in transolution.Solve()) 66 | { 67 | if(scene!=null) 68 | Debug.WriteLine($"use resources {scene.Deploys.Select(i => i.UseResource).Distinct().Count()}"); 69 | yield return scene; 70 | }; 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/CaseColorSwitch.cs: -------------------------------------------------------------------------------- 1 | using Color = System.Drawing.Color; 2 | 3 | namespace BlackStar.View; 4 | 5 | internal class CaseColorSwitch 6 | { 7 | const int STAGNATION = 40; 8 | const int POP = 4; 9 | const int GENERATION = 100; 10 | private static int NREQUIRE = 1; 11 | static DateTime baseDt = new(2023, 1, 1); 12 | 13 | public static async IAsyncEnumerable OptimColorSwitch() 14 | { 15 | var bom = createBom(); 16 | var needs = createNeeds(); //读入机器能力 17 | var resources = createResources(); //读入机器排班表 18 | var switches = createSwitches(); //读入物料切换时间 19 | MainWindow.Colors = createColors(); 20 | var solver = new SortBomTransolution(bom, NREQUIRE, needs, resources, switches: switches, population: POP, generation: GENERATION, stagnation: STAGNATION); 21 | await foreach(Scene scene in solver.Solve()) 22 | yield return scene; 23 | } 24 | 25 | private static PooledDictionary createColors() 26 | { 27 | PooledDictionary colors = new(); 28 | colors.Add("Switch", ScottPlot.Colors.Orange); 29 | colors.Add("白绿产品染色白", ScottPlot.Colors.White); 30 | colors.Add("白绿产品染色绿", ScottPlot.Colors.LightGreen); 31 | colors.Add("蓝绿产品染色蓝", ScottPlot.Colors.Blue); 32 | colors.Add("蓝绿产品染色绿", ScottPlot.Colors.Green); 33 | return colors; 34 | } 35 | 36 | private static PooledDictionary createResources() 37 | { 38 | PooledDictionary resources = new(); 39 | TimeSpan last = TimeSpan.FromHours(4800); 40 | DateTime to = baseDt + last; 41 | 42 | resources.Add("染缸1", new Resource("染缸1") 43 | { 44 | States = new() { new State("染色", baseDt, to, true) }, //服务能力 45 | Variables = new() 46 | { 47 | ["Current"] = new(""), 48 | ["Color"] = new Variable(Color.White), 49 | ["NeedSwitch"] = new(true) 50 | }, 51 | Decides = new() 52 | { 53 | ["Switch"] = ColorSwitchAction //定制的颜色切换行为 54 | }, 55 | }); 56 | resources.Add("染缸2", new Resource("染缸2") 57 | { 58 | States = new() { new State("染色", baseDt, to, true) }, 59 | Variables = new() 60 | { 61 | ["Current"] = new(""), 62 | ["Color"] = new Variable(Color.White), 63 | ["NeedSwitch"] = new(true), 64 | }, 65 | Decides = new() 66 | { 67 | ["Switch"] = ColorSwitchAction 68 | }, 69 | }); 70 | resources.Add("收纳线", new Resource("收纳线") 71 | { 72 | States = new() { new State("收纳", baseDt, to, true) }, 73 | Variables = new() 74 | { 75 | ["Current"] = new(""), 76 | ["NeedSwitch"] = new(false), 77 | }, 78 | Decides = new() 79 | { 80 | ["Switch"] = Delegates.DefaultSwitchAction 81 | }, 82 | }); 83 | 84 | return resources; 85 | } 86 | 87 | public static Delegates.SwitchByResourceBom ColorSwitchAction = (resource, nextBom) => 88 | { 89 | var considerSwitch = resource.Scene.Variables["ConsiderSwitch"].GetBoolValue(); 90 | if (!considerSwitch) 91 | return false; 92 | 93 | if (nextBom.Variables == null) 94 | return false; 95 | 96 | Color currentColor = (Color)resource.Variables["Color"].GetObjectValue(); //当前加工颜色R 97 | Color nextColor = (Color)nextBom.Variables["Color"].GetObjectValue(); //下一个加工颜色R 98 | 99 | if(currentColor.R + currentColor.G + currentColor.B < 255 * 1.5 //深色 100 | && nextColor.R + nextColor.G + nextColor.B > 255 * 1.5) //浅色 101 | return true; 102 | 103 | return false; 104 | }; 105 | 106 | private static PooledList createNeeds() 107 | { 108 | return 109 | [ 110 | new ServiceAbility("默认批次", "收纳", TimeSpan.FromSeconds(0)), 111 | new ServiceAbility("蓝绿产品", "收纳", TimeSpan.FromSeconds(0)), 112 | new ServiceAbility("白绿产品", "收纳", TimeSpan.FromSeconds(0)), 113 | new ServiceAbility("蓝绿产品染色蓝", "染色", TimeSpan.FromSeconds(34)), 114 | new ServiceAbility("白绿产品染色白", "染色", TimeSpan.FromSeconds(30)), 115 | new ServiceAbility("蓝绿产品染色绿", "染色", TimeSpan.FromSeconds(40)), 116 | new ServiceAbility("白绿产品染色绿", "染色", TimeSpan.FromSeconds(40)), 117 | ]; 118 | } 119 | 120 | private static Bom createBom() 121 | { 122 | var batch = new Bom("默认批次"); 123 | 124 | var bomBlueGreen = new Bom("蓝绿产品"); 125 | 126 | var bom蓝绿1 = new Bom("蓝绿产品染色蓝"){ 127 | Variables = new() 128 | { 129 | ["Color"] = new Variable(Color.Blue), 130 | } 131 | }; 132 | var bom蓝绿2 = new Bom("蓝绿产品染色绿"){ 133 | Variables = new() 134 | { 135 | ["Color"] = new Variable(Color.Green), 136 | } 137 | }; 138 | bom蓝绿2.AddSubBom(bom蓝绿1); 139 | bomBlueGreen.AddSubBom(bom蓝绿2); 140 | 141 | var bomWhiteGreen = new Bom("白绿产品"); 142 | var bom白绿1 = new Bom("白绿产品染色白") 143 | { 144 | Variables = new() 145 | { 146 | ["Color"] = new Variable(Color.White), 147 | } 148 | };; 149 | var bom白绿2 = new Bom("白绿产品染色绿") 150 | { 151 | Variables = new() 152 | { 153 | ["Color"] = new Variable(Color.Green), 154 | } 155 | }; 156 | bom白绿2.AddSubBom(bom白绿1); 157 | bomWhiteGreen.AddSubBom(bom白绿2); 158 | 159 | batch.AddSubBom(bomBlueGreen, 10); 160 | batch.AddSubBom(bomWhiteGreen, 30); 161 | return batch; 162 | } 163 | 164 | private static PooledDictionary createSwitches() 165 | { 166 | PooledDictionary switches = new() 167 | { 168 | ["默认批次"] = TimeSpan.FromMinutes(0), 169 | ["蓝绿产品"] = TimeSpan.FromMinutes(0), 170 | ["白绿产品"] = TimeSpan.FromMinutes(0), 171 | ["蓝绿产品染色蓝"] = TimeSpan.FromMinutes(10), //清洗时间,如果有 172 | ["白绿产品染色白"] = TimeSpan.FromMinutes(10), //清洗时间,如果有 173 | ["蓝绿产品染色绿"] = TimeSpan.FromMinutes(10), //清洗时间,如果有 174 | ["白绿产品染色绿"] = TimeSpan.FromMinutes(10), //清洗时间,如果有 175 | }; 176 | return switches; 177 | } 178 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/CaseDig.cs: -------------------------------------------------------------------------------- 1 | namespace BlackStar.View; 2 | 3 | internal class CaseDig 4 | { 5 | const int STAGNATION = 10; 6 | const int POP = 10; 7 | private static int NREQUIRE = 1; 8 | static DateTime baseDt = new(2023, 1, 1, 8, 0, 0); 9 | 10 | public static async IAsyncEnumerable OptimDig() 11 | { 12 | var bom = createBom(); 13 | var needs = createNeeds(); //读入机器能力 14 | var resources = createResources(); //读入机器排班表 15 | var solver = new SortBomTransolution(bom, NREQUIRE, needs, resources, switches: null, population: POP, 16 | stagnation: STAGNATION); 17 | 18 | //Scene scene = null; 19 | await foreach(Scene scene in solver.Solve()) 20 | { 21 | yield return scene; 22 | }; 23 | //yield return scene; 24 | } 25 | 26 | private static PooledList createNeeds() 27 | { 28 | return new() 29 | { 30 | new ServiceAbility("group", "批次", TimeSpan.FromMinutes(0)), 31 | new ServiceAbility("D1G1", "工序A", TimeSpan.FromMinutes(5)), 32 | new ServiceAbility("D1G2", "工序B", TimeSpan.FromMinutes(10)), 33 | new ServiceAbility("D1G3", "工序D", TimeSpan.FromMinutes(4)), 34 | new ServiceAbility("D2G1", "工序B", TimeSpan.FromMinutes(20)), 35 | new ServiceAbility("D2G2", "工序C", TimeSpan.FromMinutes(50)), 36 | new ServiceAbility("D3G2", "工序A", TimeSpan.FromMinutes(5)), 37 | new ServiceAbility("D3G3", "工序C", TimeSpan.FromMinutes(30)), 38 | new ServiceAbility("D3G1", "工序D", TimeSpan.FromMinutes(4)), 39 | }; 40 | } 41 | 42 | private static PooledDictionary createResources() 43 | { 44 | PooledDictionary resources = new() 45 | { 46 | {"MachineGroup", new Resource("MachineGroup")}, 47 | {"MachineA", new Resource("MachineA")}, 48 | {"MachineB1", new Resource("MachineB1")}, 49 | {"MachineB2", new Resource("MachineB2")}, 50 | {"MachineC", new Resource("MachineC")}, 51 | {"MachineC1", new Resource("MachineC1")}, 52 | {"MachineC2", new Resource("MachineC2")}, 53 | {"MachineD", new Resource("MachineD")}, 54 | }; 55 | 56 | TimeSpan last = TimeSpan.FromHours(8); 57 | for (int iday = 0; iday < 300; iday++) 58 | { 59 | DateTime from = baseDt + TimeSpan.FromDays(iday); 60 | DateTime to = from + last; 61 | (resources["MachineGroup"] as Resource).States.Add(new State("批次", from, to, true)); 62 | (resources["MachineA"] as Resource).States.Add( new State("工序A", from, to, true)); 63 | (resources["MachineB1"] as Resource).States.Add(new State("工序B", from, to, true)); 64 | (resources["MachineB2"] as Resource).States.Add(new State("工序B", from, to, true)); 65 | (resources["MachineC"] as Resource).States.Add(new State("工序C", from, to, true)); 66 | (resources["MachineC1"] as Resource).States.Add(new State("工序C", from, to, true)); 67 | (resources["MachineC2"] as Resource).States.Add(new State("工序C", from, to, true)); 68 | (resources["MachineD"] as Resource).States.Add(new State("工序D", from, to, true)); 69 | } 70 | 71 | return resources; 72 | } 73 | 74 | /// 75 | /// 深度定制的场景化bom 76 | /// 77 | /// 78 | private static Bom createBom() 79 | { 80 | const int N1 = 1; 81 | const int N2 = 2; 82 | const int N3 = 3; 83 | 84 | var bomMain = new Bom("group"); 85 | 86 | var bD1G1 = new Bom("D1G1"); 87 | var bD1G2 = new Bom("D1G2"); 88 | var bD1G3 = new Bom("D1G3"); 89 | bD1G2.AddSubBom(bD1G1); 90 | bD1G2.SceneCondition = scene => 91 | scene.Variables.TryGetValue("Count_D1G1", out Variable getVar) && getVar == N1; 92 | bD1G3.AddSubBom(bD1G2); 93 | bD1G3.SceneCondition = scene => 94 | scene.Variables.TryGetValue("Count_D1G2", out Variable getVar) && getVar == N1; 95 | 96 | var bD2G1 = new Bom("D2G1"); 97 | var bD2G2 = new Bom("D2G2"); 98 | bD2G2.AddSubBom(bD2G1); 99 | bD2G2.SceneCondition = scene => 100 | scene.Variables.TryGetValue("Count_D2G1", out Variable getVar) && getVar == N2; 101 | 102 | var bD3G1 = new Bom("D3G1"); 103 | var bD3G2 = new Bom("D3G2"); 104 | var bD3G3 = new Bom("D3G3"); 105 | bD3G2.AddSubBom(bD3G1); 106 | bD3G2.SceneCondition = scene => 107 | scene.Variables.TryGetValue("Count_D3G1", out Variable getVar) && getVar == N3; 108 | bD3G3.AddSubBom(bD3G2); 109 | bD3G3.SceneCondition = scene => //D3G2的数量达到要求,才能进行D3G3 110 | scene.Variables.TryGetValue("Count_D3G2", out Variable getVar) && getVar == N3; 111 | 112 | //指定工序的满足条件 113 | bD3G3.BopCondition = bop => 114 | { 115 | DateTime childReady = bop.GetChildrenReady(baseDt); //子工序完成时间 116 | TimeSpan ten = TimeSpan.FromMinutes(10); //必要的静置间隔 117 | TimeSpan veryLong = TimeSpan.FromDays(1000); 118 | return (childReady + ten, veryLong); //返回可开始时间和最大延迟时间 119 | }; 120 | 121 | // 如果负数,则不考虑,如果正数则由小到大依次选择 122 | bD3G3.ResourcePreference = new Resource.ResourcePreferenceDelegate( 123 | (resource, bop) => resource.Name switch 124 | { 125 | "MachineC" => -1.0f, //不使用MachineC 126 | "MachineC1" => 1.0f, //使用MachineC1,优先级最高 127 | "MachineC2" => 2.0f, //使用MachineC2,但是优先级低于C1 128 | _ => -1.0f, 129 | }); 130 | 131 | bomMain.AddSubBom(bD1G3, N1); 132 | bomMain.AddSubBom(bD2G2, N2); 133 | bomMain.AddSubBom(bD3G3, N3); 134 | 135 | IO.PrintBom(bomMain); 136 | 137 | return bomMain; 138 | } 139 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/CaseIntNoBom.cs: -------------------------------------------------------------------------------- 1 | namespace BlackStar.View; 2 | 3 | public class CaseIntNoBom 4 | { 5 | const int NACT = 200; 6 | const int NRESOURCE = 140; 7 | const int STAGNATION = 5; 8 | const int POP = 10; 9 | static DateTime baseDt = new (2023, 1, 1); 10 | 11 | /// 12 | /// 无bom 13 | /// 14 | /// 15 | public async static IAsyncEnumerable OptimIntNoBom() 16 | { 17 | // 1. Generate 1000 random ActInt 18 | PooledList acts = new(); 19 | JArray root = new(); 20 | for (int i = 0; i < NACT; i++) 21 | { 22 | string name = $"act{i:000}"; 23 | TimeSpan needTs = TimeSpan.FromMinutes(0.6 + Random.Shared.NextDouble()); 24 | ActInt actInt = new(name) { NeedTs = new() { ["IntService"] = needTs, } }; 25 | //Console.WriteLine($"{name} need {actInt.NeedTs}"); 26 | acts.Add(actInt); 27 | root.Add(new JObject 28 | { 29 | ["需求名称"] = name, 30 | ["需求加工时间"] = needTs.TotalMinutes, 31 | }); 32 | } 33 | Console.WriteLine($"need total {acts.Sum(i => i.NeedTs["IntService"].TotalMinutes)}"); 34 | //Console.WriteLine(); 35 | 36 | File.WriteAllText("require.json", root.ToString()); 37 | 38 | // 2. Generate 2000 Resource with State 39 | PooledDictionary resources = new(); 40 | root = new(); 41 | for (int i = 0; i < NRESOURCE; i++) 42 | { 43 | string name = $"res{i:000}"; 44 | Resource resource = new Resource(name); 45 | var statestart = baseDt + TimeSpan.FromMinutes(20 * Random.Shared.NextDouble()); 46 | var stateend = statestart + TimeSpan.FromMinutes(2 + 2.5 * Random.Shared.NextDouble()); 47 | State state = new State("IntService", statestart, stateend, 4); 48 | resource.States = new PooledList> { state }; 49 | //Console.WriteLine($"{name} provide {state.To- state.From}"); 50 | resources.TryAdd(name, resource); 51 | root.Add(new JObject 52 | { 53 | ["机器名称"] = name, 54 | ["可用时间开始"] = statestart, 55 | ["可用时间结束"] = stateend, 56 | }); 57 | } 58 | var provideTotal = resources.Sum( 59 | i => ((Resource)i.Value).States 60 | .Sum(j => (j.To - j.From).TotalMinutes)); 61 | Console.WriteLine($"provides total {provideTotal}"); 62 | Console.WriteLine(); 63 | File.WriteAllText("machine.json", root.ToString()); 64 | SortAllTransolution transolution = new(acts, resources, pop: POP, stagnation: STAGNATION); 65 | 66 | 67 | await foreach(Scene scene in transolution.Solve()) 68 | { 69 | yield return scene; 70 | Debug.WriteLine($"use resources {scene.Deploys.Select(i => i.UseResource).Distinct().Count()}"); 71 | }; 72 | } 73 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/CaseLight.cs: -------------------------------------------------------------------------------- 1 | namespace BlackStar.View; 2 | 3 | public class CaseLight 4 | { 5 | const int STAGNATION = 20; 6 | const int POP = 40; 7 | const int GENERATION = 200; 8 | private static int NREQUIRE = 40; 9 | static DateTime baseDt = new(2023, 1, 1); 10 | 11 | public static async IAsyncEnumerable OptimLight() 12 | { 13 | //get the nRequire option in App.config 14 | var bom = createBom(); 15 | //NREQUIRE = int.Parse(ConfigurationManager.AppSettings["nRequire"]); //输入成品数 16 | 17 | var needs = createNeeds(); //读入机器能力 18 | var resources = createResources(); //读入机器排班表 19 | var switches = createSwitches(); //读入物料切换时间 20 | var solver = new SortBomTransolution(bom, NREQUIRE, needs, resources, switches: switches, population: POP, generation: GENERATION, stagnation: STAGNATION); 21 | 22 | //Scene scene = null; 23 | await foreach(Scene scene in solver.Solve()) 24 | { 25 | yield return scene; 26 | }; 27 | //yield return scene; 28 | } 29 | 30 | private static PooledDictionary createResources() 31 | { 32 | PooledDictionary resources = new(); 33 | TimeSpan last = TimeSpan.FromHours(4800); 34 | DateTime to = baseDt + last; 35 | 36 | resources.Add("GY0034阴阳板1", new Resource("GY0034阴阳板1") 37 | { 38 | States = new() { new State("治具", baseDt, to, true) }, 39 | Variables = new() 40 | { 41 | ["Current"] = new(""), 42 | ["NeedSwitch"] = new(false) 43 | }, 44 | Decides = new() 45 | { 46 | ["Switch"] = Delegates.DefaultSwitchAction 47 | }, 48 | }); 49 | resources.Add("GY0034阴阳板2", new Resource("GY0034阴阳板2") 50 | { 51 | States = new() { new State("治具", baseDt, to, true) }, 52 | Variables = new() 53 | { 54 | ["Current"] = new(""), 55 | ["NeedSwitch"] = new(false), 56 | }, 57 | Decides = new() 58 | { 59 | ["Switch"] = Delegates.DefaultSwitchAction 60 | }, 61 | }); 62 | 63 | resources.Add("SMT01线", new Resource("SMT01线") 64 | { 65 | States = new() { new State("SMT01", baseDt, to, true) }, 66 | Variables = new() 67 | { 68 | ["Current"] = new(""), 69 | ["NeedSwitch"] = new(true) 70 | }, 71 | Decides = new() 72 | { 73 | ["Switch"] = Delegates.DefaultSwitchAction 74 | }, 75 | }); 76 | resources.Add("SMT02线", new Resource("SMT02线") 77 | { 78 | States = new() { new State("SMT02", baseDt, to, true) }, 79 | Variables = new() 80 | { 81 | ["Current"] = new(""), 82 | ["NeedSwitch"] = new(true) 83 | }, 84 | Decides = new() 85 | { 86 | ["Switch"] = Delegates.DefaultSwitchAction 87 | }, 88 | }); 89 | //{"SMT03线", new Resource("SMT03线") {States = new() { new State("SMT03", baseDt, to, true)}}}, 90 | 91 | resources.Add("插件01线", new Resource("插件01线") 92 | { 93 | States = new() { new State("DIP01", baseDt, to, true) }, 94 | Variables = new() 95 | { 96 | ["Current"] = new(""), 97 | ["NeedSwitch"] = new(true) 98 | }, 99 | Decides = new() 100 | { 101 | ["Switch"] = Delegates.DefaultSwitchAction 102 | }, 103 | }); 104 | resources.Add("插件02线", new Resource("插件02线") 105 | { 106 | States = new() { new State("DIP02", baseDt, to, true) }, 107 | Variables = new() 108 | { 109 | ["Current"] = new(""), 110 | ["NeedSwitch"] = new(true) 111 | }, 112 | Decides = new() 113 | { 114 | ["Switch"] = Delegates.DefaultSwitchAction 115 | }, 116 | }); 117 | 118 | resources.Add("组装01线", new Resource("组装01线") 119 | { 120 | States = [new State("组装", baseDt, to, true)], 121 | Variables = new() 122 | { 123 | ["Current"] = new(""), 124 | ["NeedSwitch"] = new(true), 125 | }, 126 | Decides = new() 127 | { 128 | ["Switch"] = Delegates.DefaultSwitchAction 129 | }, 130 | }); 131 | //{"组装02线", new Resource("组装02线") {States = new() { new State("组装", baseDt, to, true)}}}, 132 | 133 | 134 | return resources; 135 | } 136 | 137 | private static PooledList createNeeds() 138 | { 139 | return 140 | [ 141 | new ServiceAbilityCompound("SMT半成品A", ["治具", "SMT01"], TimeSpan.FromSeconds(23)), //SMTA面 142 | new ServiceAbilityCompound("SMT半成品A", ["治具", "SMT02"], TimeSpan.FromSeconds(30.3)), //SMTA面 143 | new ServiceAbility("SMT半成品B", "SMT01", TimeSpan.FromSeconds(64)), //SMTB面 144 | new ServiceAbility("DIP半成品", "DIP01", TimeSpan.FromSeconds(86.4)), //插件 145 | new ServiceAbility("DIP半成品", "DIP02", TimeSpan.FromSeconds(100.3)), //插件 146 | new ServiceAbility("成品", "组装", TimeSpan.FromSeconds(300)) //组装 147 | ]; 148 | } 149 | 150 | private static Bom createBom() 151 | { 152 | var bomMain = new Bom("成品"); 153 | var bomA = new Bom("SMT半成品A"); 154 | var bomB = new Bom("SMT半成品B"); 155 | var bomDIP = new Bom("DIP半成品"); 156 | bomB.AddSubBom(bomA); 157 | bomMain.AddSubBom(bomB); 158 | bomMain.AddSubBom(bomDIP); 159 | 160 | IO.PrintBom(bomMain); 161 | 162 | return bomMain; 163 | } 164 | 165 | private static PooledDictionary createSwitches() 166 | { 167 | PooledDictionary switches = new() 168 | { 169 | ["SMT半成品A"] = TimeSpan.FromMinutes(3), 170 | ["SMT半成品B"] = TimeSpan.FromMinutes(3), 171 | ["DIP半成品"] = TimeSpan.FromMinutes(2), 172 | ["成品"] = TimeSpan.FromMinutes(3), 173 | }; 174 | return switches; 175 | } 176 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/DescendendWindow.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/DescendendWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using ScottPlot.Plottables; 2 | using static log4net.Appender.FileAppender; 3 | 4 | namespace BlackStar.View; 5 | 6 | 7 | public partial class DescendendWindow : Window 8 | { 9 | //ScottPlot.Plottables.DataStreamer Streamer1; 10 | public DescendendWindow() 11 | { 12 | InitializeComponent(); 13 | 14 | initDrawDescendence(); 15 | 16 | MessageOP.MessageOf().Subscribe(OnDualMessage); 17 | } 18 | 19 | private void OnDualMessage((string, string) message) 20 | { 21 | if(message.Item1!="Sample") 22 | return; 23 | this.Clear(); 24 | } 25 | 26 | private void Clear() 27 | { 28 | xList = new(); 29 | yList = new(); 30 | this.WpfPlot1.Plot.Clear(); 31 | } 32 | 33 | private void initDrawDescendence() 34 | { 35 | 36 | WpfPlot1.Plot.XLabel("Generation"); 37 | WpfPlot1.Plot.YLabel("Finish ( minutes )"); 38 | //Streamer1 = WpfPlot1.Plot.Add.DataStreamer(20); 39 | WpfPlot1.Refresh(); 40 | } 41 | 42 | PooledList xList = new(); 43 | PooledList yList = new(); 44 | private Scatter scatter; 45 | public void AddDraw(int x, TimeSpan y) 46 | { 47 | xList.Add(x); 48 | yList.Add(y.TotalMinutes); 49 | double[] xs = xList.ToArray(); 50 | double[] ys = yList.ToArray(); 51 | if(scatter!=null) 52 | WpfPlot1.Plot.Remove(scatter); 53 | scatter = WpfPlot1.Plot.Add.Scatter(xs, ys); 54 | scatter.MarkerShape = MarkerShape.FilledSquare; 55 | scatter.MarkerSize = 5; 56 | scatter.LinePattern = LinePattern.DenselyDashed; 57 | scatter.LineWidth = 1.5f; 58 | //scatter.Smooth = true; 59 | //scatter.SmoothTension = 2f; 60 | WpfPlot1.Plot.Axes.AutoScale(); 61 | WpfPlot1.Refresh(); 62 | } 63 | 64 | private void BtFit_OnClick(object sender, RoutedEventArgs e) 65 | { 66 | WpfPlot1.Plot.Axes.AutoScale(); 67 | WpfPlot1.Refresh(); 68 | } 69 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/Dig.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnakinCN/BlackStar-APS/49df8e7fb3b8e7fe3858b58acaf6072e1fb77680/Samples/BlackStar.View/Dig.jpg -------------------------------------------------------------------------------- /Samples/BlackStar.View/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using System; 2 | global using System.Collections.Generic; 3 | global using System.Linq; 4 | global using System.Text; 5 | global using System.Threading.Tasks; 6 | global using System.Windows; 7 | global using System.Windows.Controls; 8 | global using System.Windows.Data; 9 | global using System.Windows.Documents; 10 | global using System.Windows.Input; 11 | global using System.Windows.Media; 12 | global using System.Windows.Media.Imaging; 13 | global using System.Windows.Shapes; 14 | global using System; 15 | global using System.Collections.Generic; 16 | global using ScottPlot; 17 | global using System.Windows; 18 | global using BlackStar; 19 | global using BlackStar.Transolution.SortAll; 20 | global using BlackStar.Model; 21 | global using MoreLinq.Extensions; 22 | global using BlackStar.Functions; 23 | global using System.Buffers.Text; 24 | global using System.Diagnostics; 25 | global using System.IO; 26 | global using Newtonsoft.Json; 27 | global using Newtonsoft.Json.Linq; 28 | global using System.Configuration; 29 | global using BlackStar.Transolution.SortBom; 30 | global using BlackStar.Message; 31 | global using Collections.Pooled; -------------------------------------------------------------------------------- /Samples/BlackStar.View/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Samples/BlackStar.View/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using Colors = ScottPlot.Colors; 2 | 3 | namespace BlackStar.View; 4 | 5 | public partial class MainWindow 6 | { 7 | static DateTime baseDt = new (2023, 1, 1); 8 | private DescendendWindow decentWind; 9 | public static PooledDictionary Colors { get; set; } = new(); 10 | 11 | public MainWindow() 12 | { 13 | InitializeComponent(); 14 | 15 | MessageOP.Initialize(); 16 | MessageOP.MessageOf().Subscribe(OnIntTsEvent); 17 | MessageOP.MessageOf().Subscribe(OnNotifyEvent); 18 | MessageOP.MessageOf().Subscribe(OnDualMessage); 19 | initDescendendWindow(); 20 | //RunSample(); 21 | 22 | BlackStar.View.Menu menu = new(); 23 | menu.Show(); 24 | } 25 | 26 | delegate IAsyncEnumerable Optim(); 27 | private async void OnDualMessage((string, string) message) 28 | { 29 | if (message.Item1 != "Sample") 30 | return; 31 | this.Clear(); 32 | Optim optim = message.Item2 switch 33 | { 34 | "布尔模型无Bom" => CaseBoolNoBom.OptimBoolNoBom, 35 | "整数模型无Bom" => CaseIntNoBom.OptimIntNoBom, 36 | "布尔模型有Bom" => CaseBom.OptimBoolBom, 37 | "DIG:资源偏好定制" => CaseDig.OptimDig, 38 | "光模块工艺" => CaseLight.OptimLight, 39 | "SMT工艺" => Case5k.Optim5k, 40 | "染料切换" => CaseColorSwitch.OptimColorSwitch, 41 | _ => null 42 | }; 43 | 44 | if (optim == null) 45 | return; 46 | await Task.Run(async () => 47 | { 48 | await foreach (Scene scene in optim()) 49 | { 50 | this.Draw(scene); 51 | Report(scene); 52 | } 53 | }); 54 | MessageOP.MessageOf().Publish("Done"); 55 | } 56 | 57 | private void Clear() 58 | { 59 | this.GanttChart.Plot.Clear(); 60 | } 61 | 62 | /// 63 | /// 绘下降曲线图 64 | /// 65 | /// 66 | private void OnIntTsEvent(IntTimespanMessage message) 67 | { 68 | this.Dispatcher.BeginInvoke(() => this.decentWind.AddDraw(message.IntValue, message.TsValue)); 69 | } 70 | 71 | private void OnNotifyEvent(string message) 72 | { 73 | switch (message) 74 | { 75 | case "nolic": 76 | this.nolic.Visibility = Visibility.Visible; 77 | break; 78 | } 79 | } 80 | 81 | private void Report(Scene scene) 82 | { 83 | if (scene is null) 84 | return; 85 | 86 | JArray root = new(); 87 | 88 | foreach (var deploy in scene.Deploys.Span) 89 | { 90 | root.Add(new JObject 91 | { 92 | ["需求名称"] = deploy.Name, 93 | ["承担机器"] = deploy.UseResource, 94 | ["加工开始"] = deploy.From, 95 | ["加工结束"] = deploy.To, 96 | ["加工时长"] = deploy.To - deploy.From, 97 | }); 98 | } 99 | File.WriteAllText("plan.json", root.ToString()); 100 | } 101 | 102 | private void initDescendendWindow() 103 | { 104 | decentWind = new(); 105 | decentWind.Show(); 106 | } 107 | 108 | private void Draw(Scene scene) 109 | { 110 | if (scene is null) 111 | return; 112 | 113 | const double TASKHEIGHT = 10d; 114 | const double LINEHEIGHT = 20d; 115 | const double halfHeight = TASKHEIGHT / 2; 116 | 117 | PooledDictionary rows = new(); 118 | PooledDictionary rowLables = new(); 119 | int row = 0; 120 | foreach (var resource in scene.Resources) 121 | { 122 | if(rows.TryAdd(resource.Key, row)) 123 | { 124 | rowLables.Add(row, resource.Key); 125 | row++; 126 | } 127 | } 128 | 129 | GanttChart.Plot.XLabel("Time"); 130 | GanttChart.Plot.YLabel("Resource"); 131 | #region 资源轴 132 | ScottPlot.TickGenerators.NumericManual yticks = new(); 133 | int ipair = 0; 134 | foreach (var pair in rows) 135 | { 136 | var tick = new Tick(ipair * LINEHEIGHT, pair.Key); 137 | yticks.Add(tick); 138 | ipair++; 139 | } 140 | GanttChart.Plot.Axes.Left.TickGenerator = yticks; 141 | GanttChart.Plot.Axes.Left.TickLabelStyle.FontName = "微软雅黑"; 142 | #endregion 143 | #region 时间轴 144 | // ScottPlot.TickGenerators.NumericManual xticks = new(); 145 | // for (int i = 0; i < (scene.Deploys.Select(i=>i.To).Max() - baseDt).TotalMinutes; i += 10) 146 | // { 147 | // var tick = new Tick(i, TimeSpan.FromMinutes(i * 10d).ToString("HH:mm")); 148 | // xticks.Add(tick); 149 | // } 150 | // GanttChart.Plot.Axes.Bottom.TickGenerator = xticks; 151 | // GanttChart.Plot.Axes.Bottom.TickLabelStyle.FontName = "微软雅黑"; 152 | #endregion 153 | 154 | foreach (var task in scene.Deploys.Span) 155 | { 156 | int line = rows[task.UseResource]; 157 | var y = line * LINEHEIGHT; 158 | var x1 = (task.From - baseDt).TotalMinutes; 159 | var x2 = (task.To - baseDt).TotalMinutes; 160 | var y1 = y - halfHeight; 161 | var y2 = y + halfHeight; 162 | 163 | var rect = GanttChart.Plot.Add.Rectangle(x1, x2, y1, y2); 164 | string bomname = StringOP.TrimLastUnderline(task.Name); 165 | if(Colors!=null && Colors.TryGetValue(bomname, out var color)) 166 | rect.FillColor = color; 167 | if (scene.Deploys.Count <= 100) 168 | { 169 | var text = GanttChart.Plot.Add.Text(task.Name, x1, y); 170 | text.LabelFontName = "微软雅黑"; 171 | text.LabelFontSize = 12; 172 | text.LabelFontColor = ScottPlot.Colors.Black; 173 | } 174 | } 175 | GanttChart.Plot.Axes.AutoScale(); 176 | GanttChart.Refresh(); 177 | } 178 | 179 | private void BtFit_OnClick(object sender, RoutedEventArgs e) 180 | { 181 | // GanttChart.Plot.AxisAuto(); 182 | GanttChart.Plot.Axes.AutoScale(); 183 | GanttChart.Refresh(); 184 | } 185 | 186 | private void btDir_OnClick(object sender, RoutedEventArgs e) 187 | { 188 | string folder = System.IO.Path.Join(".", "Log", "Trace"); 189 | Process.Start("explorer", folder); 190 | } 191 | } -------------------------------------------------------------------------------- /Samples/BlackStar.View/Menu.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |