结合段的范围的算法--帮助创建 - 页 2 12345678 新评论 Dmitry Fedoseev 2021.04.19 18:35 #11 struct SAllVariants{ int m_cut[][2]; int len; int li; void Init(int aLen){ ArrayResize(m_cut,aLen); len=0; } void AddCut(int & a[][2],int i){ m_cut[len][0]=a[i][0]; m_cut[len][1]=a[i][1]; len++; li=i; } void Set(SAllVariants & a){ len=a.len; li=a.li; for(int i=0;i<len;i++){ m_cut[i][0]=a.m_cut[i][0]; m_cut[i][1]=a.m_cut[i][1]; } } }; SAllVariants av[]; int cut[][2]; void OnStart(){ Print("============================================================="); // заполняем массив сотней каких-нибудь отрезков FillArray(cut,100); //=== алгоритм ==================== // поправить все отрезки, чтобы первая координата была меньше второй int itmp; for(int i=0;i<ArrayRange(cut,0);i++){ if(cut[i][0]>cut[i][1]){ itmp=cut[i][0]; cut[i][0]=cut[i][1]; cut[i][1]=itmp; } } // сортировка массива по первой координате ArraySort(cut); ArrayPrint(cut); // удалить отрезки нулевой длины и повтряющиеся отрезки bool ex; int ti=0; for(int i=0;i<ArrayRange(cut,0);i++){ if(cut[i][0]!=cut[i][1]){ ex=false; for(int j=i-1;j>=0 && cut[j][0]==cut[i][0];j--){ if(cut[j][0]==cut[i][0] && cut[j][1]==cut[i][1]){ ex=true; break; } } if(!ex){ cut[ti][0]=cut[i][0]; cut[ti][1]=cut[i][1]; ti++; } } } ArrayResize(cut,ti); // добавить первый отрезок в массив всех вариантов и еще отрезков с наименьшей координатой ArrayResize(av,1); av[0].Init(ArrayRange(cut,0)); // вдруг ряд получится из всех отрезков av[0].AddCut(cut,0); for(int i=1;i<ArrayRange(cut,0);i++){ if(cut[0][0]==cut[i][0]){ ArrayResize(av,ArraySize(av)+1); av[ArraySize(av)-1].Init(ArrayRange(cut,0)); av[ArraySize(av)-1].AddCut(cut,i); } } // добавить в начало еще отрезков, начинающихся чуть позже, но не позднее конца самого длинного из начальных // на сначала найти диапазон int mn=av[0].m_cut[0][0]; int mx=av[0].m_cut[0][1]; for(int i=1;i<ArraySize(av);i++){ mx=MathMax(mx,av[i].m_cut[0][1]); } // добавить for(int i=1;i<ArrayRange(cut,0);i++){ if(cut[i][0]>mn && cut[i][0]<mx){ ArrayResize(av,ArraySize(av)+1); av[ArraySize(av)-1].Init(ArrayRange(cut,0)); av[ArraySize(av)-1].AddCut(cut,i); } } // а теперь самое интересное double r; bool n; for(int i=0;i<ArraySize(av) && !IsStopped();i++){ // для каждого варианта //Comment(i," ",ArraySize(av)); // найти ближайшее расстояние до следующего отрезка r=DBL_MAX; for(int j=av[i].li+1;j<ArrayRange(cut,0);j++){ if(cut[j][0]>=av[i].m_cut[av[i].len-1][1]){ r=MathMin(r,cut[j][0]-av[i].m_cut[av[i].len-1][1]); // потому что допускаются пропуски (важнее составить ряд, чем чтобы он был непрерывным) } } if(r!=DBL_MAX){ n=false; for(int j=av[i].li+1;j<ArrayRange(cut,0);j++){ if(cut[j][0]-av[i].m_cut[av[i].len-1][1]==r){ if(!n){ n=true; av[i].AddCut(cut,j); } else{ ArrayResize(av,ArraySize(av)+1); av[ArraySize(av)-1].Init(ArrayRange(cut,0)); av[ArraySize(av)-1].Set(av[i]); av[ArraySize(av)-1].AddCut(cut,j); } } } if(n){ i--; } } } string str=""; for(int i=0;i<ArraySize(av) && !IsStopped();i++){ str=""; for(int j=0;j<av[i].len;j++){ str=str+(string)av[i].m_cut[j][0]+"-"+(string)av[i].m_cut[j][1]+" "; } Print("Вариант ",i," - ",str); } } //+------------------------------------------------------------------+ void FillArray(int & a[][2],int cutCnt){ ArrayResize(a,cutCnt); for(int i=0;i<cutCnt;i++){ a[i][0]=MathRand()%30; a[i][1]=a[i][0]+MathRand()%15; } } 不知何故... Aleksey Vyazmikin 2021.04.19 21:15 #12 Dmitry Fedoseev:不知何故... 谢谢你!你马上就能看到大师的手!我明天会试一下,看看会有什么结果。 Aleksey Vyazmikin 2021.04.20 21:56 #13 Dmitry Fedoseev:不知何故... 开始尝试代码,创建了一个人造的例子--填入数组中 FillArray(cut,4); cut[0][0]=0; cut[0][1]=1; cut[1][0]=3; cut[1][1]=6; cut[2][0]=2; cut[2][1]=5; cut[3][0]=7; cut[3][1]=9; 明白了。 2021.04.21 00:52:08.328 Q_Podbor (Si-6.21,W1) [,0][,1] 2021.04.21 00:52:08.328 Q_Podbor (Si-6.21,W1) [0,] 0 1 2021.04.21 00:52:08.328 Q_Podbor (Si-6.21,W1) [1,] 2 5 2021.04.21 00:52:08.328 Q_Podbor (Si-6.21,W1) [2,] 3 6 2021.04.21 00:52:08.328 Q_Podbor (Si-6.21,W1) [3,] 7 9 2021.04.21 00:52:08.328 Q_Podbor (Si-6.21,W1) Вариант 0 - 0-1 2-5 7-9 也就是说,我们得到了一个变体,但我们也在期待着另一个变体。 Вариант 1 - 0-1 3-6 7-9 有没有可能也教给算法去寻找它? Dmitry Fedoseev 2021.04.21 02:32 #14 Aleksey Vyazmikin:开始尝试代码,创建了一个人造的例子--填入数组中明白了。也就是说,我们得到了一个变体,但我们也在期待着另一个变体。算法也能学会找到它吗? 而变体 "0-1 3-6 7-9 "并不比变体 "0-0-1 2-5 7-9 "好--两者都是从0到1,各有两个长度为1的跳动。 在这种情况下出现了两个选项。 1 - 做同样的事情,但要从这组跳绳的终点开始。 2 - 立即寻找不是最接近的那一段,而是要有一个宽容度。但在这种情况下,如果有大量的数据和大量的对接序列,就会有更多。 然而,在变体1之后,你会想从所有可能的起始位置开始建立链条。这是正确的,但算法的工作量却大大增加。 是的!有必要从初始集的每个片段开始构建变体,并继续构建到开始和结束。 Aleksey Vyazmikin 2021.04.21 04:37 #15 Dmitry Fedoseev:而 "0-1 3-6 7-9 "的选项并不比 "0-0-1 2-5 7-9 "的选项好--两者都是从0到1,各有两个长度为1的跳过。 在这种情况下,它们是相等的,我同意,但它们是不同的,根据问题的条款,我们将需要估计它们的分数之和,在我们建立一条线之前,我们将不知道所有线段的综合分数。 德米特里-费多塞耶夫。 然而,在选项1之后,会有一种从所有可能的起始位置开始构建字符串的愿望。这是正确的,但算法的工作量却大大增加。 是的!有必要从初始集的每个片段开始构建变体,并继续构建到开始和结束。 在我看来,这也是比较正确的策略!然而,我认为可能有重复的变体。 你能通过写一些代码来帮助吗? Dmitry Fedoseev 2021.04.21 07:51 #16 struct SAllVariants{ int m_cut[][2]; int len; int m_cut1[][2]; // к концу int len1; int li1; int m_cut2[][2]; // с началу int len2; int li2; bool isDopel; void Init(int aLen){ ArrayResize(m_cut1,aLen); len1=0; ArrayResize(m_cut2,aLen); len2=0; } void AddCut1(int & a[][2],int i){ m_cut1[len1][0]=a[i][0]; m_cut1[len1][1]=a[i][1]; len1++; li1=i; } void AddCut2(int & a[][2],int i){ m_cut2[len2][0]=a[i][0]; m_cut2[len2][1]=a[i][1]; len2++; li2=i; } void Set(SAllVariants & a){ len1=a.len1; li1=a.li1; for(int i=0;i<len1;i++){ m_cut1[i][0]=a.m_cut1[i][0]; m_cut1[i][1]=a.m_cut1[i][1]; } len2=a.len2; li2=a.li2; for(int i=0;i<len2;i++){ m_cut2[i][0]=a.m_cut2[i][0]; m_cut2[i][1]=a.m_cut2[i][1]; } } bool Eq(SAllVariants & a){ if(len1!=a.len1 || len2!=a.len2){ return(false); } for(int i=0;i<len1;i++){ if(m_cut1[i][0]!= a.m_cut1[i][0] || m_cut1[i][1]!= a.m_cut1[i][1]){ return(false); } } for(int i=0;i<len2;i++){ if(m_cut2[i][0]!= a.m_cut2[i][0] || m_cut2[i][1]!= a.m_cut2[i][1]){ return(false); } } return(true); } void Combine(){ len=len1+len2-1; ArrayResize(m_cut,len); int j=0; for(int i=len2-1;i>0;i--){ m_cut[j][0]=m_cut2[i][0]; m_cut[j][1]=m_cut2[i][1]; j++; } for(int i=0;i<len1;i++){ m_cut[j][0]=m_cut1[i][0]; m_cut[j][1]=m_cut1[i][1]; j++; } } }; SAllVariants av[]; int cut[][2]; void OnStart(){ Print("============================================================="); // заполняем массив сотней каких-нибудь отрезков FillArray(cut,100); //=== алгоритм ==================== // поправить все отрезки, чтобы первая координата была меньше второй int itmp; for(int i=0;i<ArrayRange(cut,0);i++){ if(cut[i][0]>cut[i][1]){ itmp=cut[i][0]; cut[i][0]=cut[i][1]; cut[i][1]=itmp; } } // сортировка массива по первой координате ArraySort(cut); ArrayPrint(cut); // удалить отрезки нулевой длины и повтряющиеся отрезки bool ex; int ti=0; for(int i=0;i<ArrayRange(cut,0);i++){ if(cut[i][0]!=cut[i][1]){ ex=false; for(int j=i-1;j>=0 && cut[j][0]==cut[i][0];j--){ if(cut[j][0]==cut[i][0] && cut[j][1]==cut[i][1]){ ex=true; break; } } if(!ex){ cut[ti][0]=cut[i][0]; cut[ti][1]=cut[i][1]; ti++; } } } ArrayResize(cut,ti); // добавить каждый отрезок в массив всех вариантов ArrayResize(av,ArrayRange(cut,0)); for(int i=0;i<ArrayRange(cut,0);i++){ av[i].Init(ArrayRange(cut,0)); av[i].AddCut1(cut,i); // в массив, идущий к концу av[i].AddCut2(cut,i); // в массив, идущий к началу } // а теперь самое интересное // к концу double r; bool n; for(int i=0;i<ArraySize(av) && !IsStopped();i++){ // для каждого варианта // найти ближайшее расстояние до следующего отрезка r=DBL_MAX; for(int j=av[i].li1+1;j<ArrayRange(cut,0);j++){ if(cut[j][0]>=av[i].m_cut1[av[i].len1-1][1]){ r=MathMin(r,cut[j][0]-av[i].m_cut1[av[i].len1-1][1]); // потому что допускаются пропуски (важнее составить ряд, чем чтобы он был непрерывным) } } if(r!=DBL_MAX){ n=false; for(int j=av[i].li1+1;j<ArrayRange(cut,0);j++){ if(cut[j][0]-av[i].m_cut1[av[i].len1-1][1]==r){ if(!n){ n=true; av[i].AddCut1(cut,j); } else{ ArrayResize(av,ArraySize(av)+1); av[ArraySize(av)-1].Init(ArrayRange(cut,0)); av[ArraySize(av)-1].Set(av[i]); av[ArraySize(av)-1].AddCut1(cut,j); } } } if(n){ i--; } } } // к началу for(int i=0;i<ArraySize(av) && !IsStopped();i++){ // для каждого варианта // найти ближайшее расстояние до следующего отрезка r=DBL_MAX; for(int j=av[i].li2-1;j>=0;j--){ if(cut[j][1]<=av[i].m_cut2[av[i].len2-1][0]){ r=MathMin(r,av[i].m_cut2[av[i].len2-1][0]-cut[j][1]); // потому что допускаются пропуски (важнее составить ряд, чем чтобы он был непрерывным) } } if(r!=DBL_MAX){ n=false; for(int j=av[i].li2-1;j>=0;j--){ if(av[i].m_cut2[av[i].len2-1][0]-cut[j][1]==r){ if(!n){ n=true; av[i].AddCut2(cut,j); } else{ ArrayResize(av,ArraySize(av)+1); av[ArraySize(av)-1].Init(ArrayRange(cut,0)); av[ArraySize(av)-1].Set(av[i]); av[ArraySize(av)-1].AddCut2(cut,j); } } } if(n){ i--; } } } // пометить дубли for(int i=0;i<ArraySize(av);i++){ av[i].isDopel=false; for(int j=0;j<i;j++){ if(av[i].Eq(av[j])){ av[i].isDopel=true; break; } } } // соединить два массива в 1 for(int i=0;i<ArraySize(av);i++){ if(!av[i].isDopel){ av[i].Combine(); } } // вывод int h=FileOpen("Выстраивание отрезков.txt",FILE_TXT|FILE_WRITE); for(int i=0;i<ArrayRange(cut,0);i++){ FileWrite(h,(string)cut[i][0]+"-"+(string)cut[i][1]); } FileWrite(h,""); string str=""; int vn=0; for(int i=0;i<ArraySize(av) && !IsStopped();i++){ if(!av[i].isDopel){ str=""; for(int j=0;j<av[i].len;j++){ str=str+(string)av[i].m_cut[j][0]+"-"+(string)av[i].m_cut[j][1]+" "; } Print("Вариант ",vn," - ",str); FileWrite(h,"Вариант ",vn," - ",str); vn++; } } FileClose(h); } //+------------------------------------------------------------------+ void FillArray(int & a[][2],int cutCnt){ ArrayResize(a,cutCnt); for(int i=0;i<cutCnt;i++){ a[i][0]=MathRand()%30; a[i][1]=a[i][0]+MathRand()%15; } } 由于现在每个变体都将片段存储在两个数组中,为了更方便,可以用Combine() 方法将它们合并成一个数组。 Aleksey Vyazmikin 2021.04.22 14:01 #17 Dmitry Fedoseev:我没有从数组中筛选出重复的部分,我只标记了它们。 因为现在每个变体都将片段存储在两个数组中,我可以用Combine() 方法将它们合并成一个数组,这样就更方便了。 德米特里,谢谢你的新算法 是的,确实有很多副本。 2021.04.22 16:55:43.829 Q_Podbor_02 (Si-6.21,M1) Вариант 0 - 0-1 2-5 7-9 2021.04.22 16:55:43.829 Q_Podbor_02 (Si-6.21,M1) Вариант 1 - 0-1 2-5 7-9 2021.04.22 16:55:43.829 Q_Podbor_02 (Si-6.21,M1) Вариант 2 - 0-1 3-6 7-9 2021.04.22 16:55:43.829 Q_Podbor_02 (Si-6.21,M1) Вариант 3 - 0-1 3-6 7-9 根据我的理解,它们不能被计算在内。我还没能等到1000个元素的组合--我的上网本开始耗尽内存了:( 还有,在增加一段时,是否有可能不使用所有的组合,而只使用当前步骤中可能的一定数量的组合,例如,最好的10个? Dmitry Fedoseev 2021.04.22 14:25 #18 Aleksey Vyazmikin:德米特里,谢谢你的新算法是的,确实有很多副本。根据我的理解,你不能计算它们。我无法等待1000个元素的组合--我的上网本开始耗尽内存了:(在增加一段时,是否可以不使用所有的组合,而只使用当前步骤中可能的一定数量,例如,最好的10个组合? 要知道它们是最好的,你必须与其他人进行比较,也就是说,你必须先得到所有的东西。另一件事是以某种方式优化算法,但我没有一个目标将我的生命投入到这个算法中)。 也许决定充分性的标准,首先得到所有的选项,只从一个片段开始,随机选择,以此类推,直到出现一个满意的选项。 而第二种选择可以加速--用变体来扩展数组,不是一次一个元素,而是一次几十个元素,最后再修剪一下。 Aleksey Vyazmikin 2021.04.22 15:48 #19 Dmitry Fedoseev:要知道它们是最好的,你必须与其他人进行比较,也就是说,你必须先得到所有的东西。另一件事是以某种方式优化算法,但我没有将我的生命投入到这个算法的目标)。 我说的是一个单一的片段,比方说它有一个系数来评估它的质量,那么在每次迭代之后,我们的分支,比如说,只在这些系数的前10名上。 Dmitry Fedoseev: 也许决定一个充分性标准,首先得到所有的变体,只从一个片段开始,随机选择,如此反复,直到出现一个满意的变体。 不幸的是,"充分性 "在这里很难估计--这里需要知道一个标准,然后从它可以定义一个公差,而我没有一个标准。 德米特里-费多塞耶夫。 而第二个选项可以加速--用选项来扩展数组,不是一次一个元素,而是几十个元素,最后再把它对齐。 我不太清楚你说的使用OpenCL进行并行计算是什么意思? Dmitry Fedoseev 2021.04.22 16:24 #20 Aleksey Vyazmikin:1.我说的是一个单一的片段,比方说它有一个系数来评估它的质量,那么在每次迭代之后,我们都会分支到,比方说,只有这些系数中的前10名。2.不幸的是,"充分性 "在这里很难估计--你需要知道基准,然后你可以根据它来确定公差,而我没有基准。3.我不太清楚你说的使用OpenCL进行并行计算是什么意思? 1.这个系数在哪里? 2.第1点怎么说? 3.不,这更简单。好的,我明天会试着加快速度。 12345678 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
不知何故...
不知何故...
谢谢你!你马上就能看到大师的手!我明天会试一下,看看会有什么结果。
不知何故...
开始尝试代码,创建了一个人造的例子--填入数组中
明白了。
也就是说,我们得到了一个变体,但我们也在期待着另一个变体。
有没有可能也教给算法去寻找它?
开始尝试代码,创建了一个人造的例子--填入数组中
明白了。
也就是说,我们得到了一个变体,但我们也在期待着另一个变体。
算法也能学会找到它吗?
而变体 "0-1 3-6 7-9 "并不比变体 "0-0-1 2-5 7-9 "好--两者都是从0到1,各有两个长度为1的跳动。
在这种情况下出现了两个选项。
1 - 做同样的事情,但要从这组跳绳的终点开始。
2 - 立即寻找不是最接近的那一段,而是要有一个宽容度。但在这种情况下,如果有大量的数据和大量的对接序列,就会有更多。
然而,在变体1之后,你会想从所有可能的起始位置开始建立链条。这是正确的,但算法的工作量却大大增加。
是的!有必要从初始集的每个片段开始构建变体,并继续构建到开始和结束。
而 "0-1 3-6 7-9 "的选项并不比 "0-0-1 2-5 7-9 "的选项好--两者都是从0到1,各有两个长度为1的跳过。
在这种情况下,它们是相等的,我同意,但它们是不同的,根据问题的条款,我们将需要估计它们的分数之和,在我们建立一条线之前,我们将不知道所有线段的综合分数。
然而,在选项1之后,会有一种从所有可能的起始位置开始构建字符串的愿望。这是正确的,但算法的工作量却大大增加。
是的!有必要从初始集的每个片段开始构建变体,并继续构建到开始和结束。
在我看来,这也是比较正确的策略!然而,我认为可能有重复的变体。
你能通过写一些代码来帮助吗?
由于现在每个变体都将片段存储在两个数组中,为了更方便,可以用Combine() 方法将它们合并成一个数组。
我没有从数组中筛选出重复的部分,我只标记了它们。 因为现在每个变体都将片段存储在两个数组中,我可以用Combine() 方法将它们合并成一个数组,这样就更方便了。
德米特里,谢谢你的新算法
是的,确实有很多副本。
根据我的理解,它们不能被计算在内。我还没能等到1000个元素的组合--我的上网本开始耗尽内存了:(
还有,在增加一段时,是否有可能不使用所有的组合,而只使用当前步骤中可能的一定数量的组合,例如,最好的10个?
德米特里,谢谢你的新算法
是的,确实有很多副本。
根据我的理解,你不能计算它们。我无法等待1000个元素的组合--我的上网本开始耗尽内存了:(
在增加一段时,是否可以不使用所有的组合,而只使用当前步骤中可能的一定数量,例如,最好的10个组合?
要知道它们是最好的,你必须与其他人进行比较,也就是说,你必须先得到所有的东西。另一件事是以某种方式优化算法,但我没有一个目标将我的生命投入到这个算法中)。
也许决定充分性的标准,首先得到所有的选项,只从一个片段开始,随机选择,以此类推,直到出现一个满意的选项。
而第二种选择可以加速--用变体来扩展数组,不是一次一个元素,而是一次几十个元素,最后再修剪一下。
要知道它们是最好的,你必须与其他人进行比较,也就是说,你必须先得到所有的东西。另一件事是以某种方式优化算法,但我没有将我的生命投入到这个算法的目标)。
我说的是一个单一的片段,比方说它有一个系数来评估它的质量,那么在每次迭代之后,我们的分支,比如说,只在这些系数的前10名上。
也许决定一个充分性标准,首先得到所有的变体,只从一个片段开始,随机选择,如此反复,直到出现一个满意的变体。
不幸的是,"充分性 "在这里很难估计--这里需要知道一个标准,然后从它可以定义一个公差,而我没有一个标准。
而第二个选项可以加速--用选项来扩展数组,不是一次一个元素,而是几十个元素,最后再把它对齐。
我不太清楚你说的使用OpenCL进行并行计算是什么意思?
1.我说的是一个单一的片段,比方说它有一个系数来评估它的质量,那么在每次迭代之后,我们都会分支到,比方说,只有这些系数中的前10名。
2.不幸的是,"充分性 "在这里很难估计--你需要知道基准,然后你可以根据它来确定公差,而我没有基准。
3.我不太清楚你说的使用OpenCL进行并行计算是什么意思?
1.这个系数在哪里?
2.第1点怎么说?
3.不,这更简单。好的,我明天会试着加快速度。