Sorting Network Search
Backtracking for Small Sorting Networks
Main.cpp
Go to the documentation of this file.
1
8
9// MIT License
10//
11// Copyright (c) 2023 Ian Parberry
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to
15// deal in the Software without restriction, including without limitation the
16// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
17// sell copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29// IN THE SOFTWARE.
30
31#ifdef _DEBUG
32 #include <vld.h> //Visual Leak Detector from http://vld.codeplex.com/
33#endif
34
35#include <iostream>
36#include <fstream>
37#include <stdexcept>
38
39#include "Nearsort2.h"
40
41#include "ThreadManager.h"
42#include "Task.h"
43#include "Timer.h"
44
45#include "TernaryGrayCode.h"
46
52
53size_t getn(const std::string& strBanner){
54 std::cout << strBanner << std::endl << "> ";
55 std::string strLine;
56 std::getline(std::cin, strLine);
57
58 return (size_t)std::stoi(strLine);
59} //getn
60
70
71bool CheckParams(const size_t n, const size_t d){
72 bool ok = false;
73
74 switch(n){
75 case 3: case 4: ok = d == 2 || d == 3; break;
76 case 5: case 6: ok = d == 4 || d == 5; break;
77 case 7: case 8: ok = d == 5 || d == 6; break;
78 case 9: case 10: ok = d == 6 || d == 7; break;
79 case 11: case 12: ok = d == 7 || d == 8; break;
80 default: ok = false;
81 } //switch
82
83 if(!ok){
84 std::cout << "Depth must be ";
85
86 switch(n){
87 case 3: case 4: std::cout << "2 or 3"; break;
88 case 5: case 6: std::cout << "4 or 5"; break;
89 case 7: case 8: std::cout << "5 or 6"; break;
90 case 9: case 10: std::cout << "6 or 7"; break;
91 case 11: case 12: std::cout << "7 or 8"; break;
92 } //switch
93
94 std::cout << std::endl;
95 } //if
96
97 return ok;
98} //CheckParams
99
105
106void ReadParams(size_t& n, size_t& d){
107 bool ok = false; //for loop control
108
109 //read the width and make sure it is within range
110
111 while(!ok){
112 n = getn("Enter number of inputs. Must be at least 3 and at most 12.");
113 ok = n >= 3 && n <= 12;
114 if(!ok)std::cout << "Out of range" << std::endl;
115 } //while
116
117 //read the depth and make sure it is within range for the width chosen
118
119 ok = false;
120
121 while(!ok){
122 d = getn("Enter depth.");
123 ok = d >= 3 && d <= 8;
124 if(!ok)std::cout << "Out of range" << std::endl;
125 ok = ok && CheckParams(n, d);
126 } //while
127} //ReadParams
128
134
135void ReadParams(bool& bNearsort2, const size_t d){
136 if(d >= 5){ //deep enough for nearsort2 heuristic
137 std::cout << "Use nearsort2 heuristic? [yn]" << std::endl << "> ";
138 std::string strLine;
139 std::getline(std::cin, strLine);
140 bNearsort2 = strLine[0] == 'y' || strLine[0] == 'Y';
141 } //if
142} //ReadParams
143
149
150void SaveSummary(const std::string s){
151 std::cout << s << std::endl; //print to console
152
153 //append to log file
154
155 std::ofstream logfile("log.txt", std::ios::app);
156 logfile << s << std::endl;
157 logfile.close();
158} //SaveSummary
159
169
170void Search(CThreadManager* p, const size_t nDepth, const bool bNearsort2){
171 CLevel2Search* pLevel2Search = new CLevel2Search(); //for level 2 matchings
172 auto L2Matchings = pLevel2Search->GetMatchings(); //get level 2 matchings
173 size_t i = 0; //index of current matching
174
175 //insert search tasks to task queue
176
177 for(auto matching: L2Matchings){ //for each level2 matching
178 CSearchable* pSearch = nullptr; //for the searchable sorting network
179
180 switch(nDepth){ //choose optimization depending on depth
181 case 2: pSearch = new C2NF(matching, i++); break;
182 case 3: pSearch = new CAutocomplete(matching, i++); break;
183 case 4: pSearch = new CNearsort(matching, i++); break;
184 default: //depth 5 or greater
185 if(bNearsort2)
186 pSearch = new CNearsort2(matching, i++);
187 else pSearch = new CNearsort(matching, i++);
188 break;
189 } //switch
190
191 p->Insert(new CTask(pSearch)); //insert search task
192 } //for
193
194 //perform multi-threaded backtracking search
195
196 p->Spawn(); //spawn threads
197 p->Wait(); //wait for threads to finish
198 p->Process(); //process results
199
200 delete pLevel2Search;
201} //Search
202
208
209int main(){
210 size_t nWidth = 0; //sorting network width (number of inputs)
211 size_t nDepth = 0; //sorting network depth (number of layers)
212 ReadParams(nWidth, nDepth); //read from stdin
213 CSettings::SetWidth(nWidth); //distribute width to all classes
214 CSettings::SetDepth(nDepth); //distribute depth to all classes
215
216 bool bFastGrayCode = false; //use fast Gray code flag
217 bool bNearsort2 = false; //use nearsort2 flag
218 ReadParams(bNearsort2, nDepth); //read from stdin
219
220 CTimer* pTimer = new CTimer; //timer for elapsed and CPU time
221
222 //print header to console and log file
223
224 std::cout << "Start " << pTimer->GetTimeAndDate() << std::endl;
225
226 std::string strSummary = "Searching for " +
227 std::to_string(nWidth) + "-input sorting networks of depth " +
228 std::to_string(nDepth);
229
230 SaveSummary(strSummary);
231
232 //multithreaded search
233
234 CThreadManager* pThreadManager = new CThreadManager; //thread manager
235
236 pTimer->Start(); //start timing CPU and elapsed time
237 Search(pThreadManager, nDepth, bNearsort2); //this is where the search happens
238
239 //print results to console and log file
240
241 std::cout << "Finish " << pTimer->GetTimeAndDate() << std::endl;
242
243 strSummary = std::to_string(pThreadManager->GetCount()) + " found in " +
244 pTimer->GetElapsedTime() + " using " +
245 pTimer->GetCPUTime() + " CPU time over " +
246 std::to_string(pThreadManager->GetNumThreads()) + " threads";
247
248 SaveSummary(strSummary);
249
250 //clean up and exit
251
252 delete pThreadManager;
253 delete pTimer;
254
255 return 0;
256} //main
void SaveSummary(const std::string s)
Save summary string.
Definition: Main.cpp:150
size_t getn(const std::string &strBanner)
Get size_t from input.
Definition: Main.cpp:53
void Search(CThreadManager *p, const size_t nDepth, const bool bNearsort2)
Multi-threaded search.
Definition: Main.cpp:170
bool CheckParams(const size_t n, const size_t d)
Check that depth is reasonable for width.
Definition: Main.cpp:71
void ReadParams(size_t &n, size_t &d)
Read parameters for search.
Definition: Main.cpp:106
int main()
Main.
Definition: Main.cpp:209
Header for the task class CTask.
Interface for the ternary reflected Gray code generator CTernaryGrayCode.
Header for the thread manager CThreadManager.
Second normal form searchable sorting network.
Definition: 2NF.h:38
Searchable second normal form sorting network with autocomplete.
Definition: Autocomplete.h:41
Level 2 search.
Definition: Level2Search.h:80
const std::vector< CMatching > & GetMatchings() const
Get matching vector.
Searchable sorting network with nearsort2.
Definition: Nearsort2.h:37
Searchable sorting network with nearsort.
Definition: Nearsort.h:38
Searchable sorting network.
Definition: Searchable.h:39
static void SetWidth(const size_t)
Set width.
Definition: Settings.cpp:34
static void SetDepth(const size_t)
Set depth.
Definition: Settings.cpp:41
Task.
Definition: Task.h:38
Thread manager.
Definition: ThreadManager.h:40
const size_t GetCount() const
Get count.