libgsjj  1
Deterministic finite automata learning library
MethodFactory.cpp
Go to the documentation of this file.
1 #include <algorithm>
2 #include <iostream>
3 #include <stdexcept>
4 #include <future>
5 #include <cmath>
6 
8 #include "gsjj/passive/utils.h"
9 
10 std::atomic_bool falseStopTrigger(false);
11 std::chrono::seconds noLimit(0);
13 
14 namespace gsjj {
15  namespace passive {
16  // We initialise the static map
17  std::map<std::string, MethodFactory::MethodConstructor> MethodFactory::s_methodsMap;
18 
19  bool MethodFactory::registerMethod(const std::string &name, MethodConstructor const &constructor) {
20  // If "name" is not yet registered, we register it (it's really simple)
21  auto itr = s_methodsMap.find(name);
22  if (itr == s_methodsMap.end()) {
23  s_methodsMap.emplace(name, constructor);
24  return true;
25  }
26  else {
27  return false;
28  }
29  }
30 
31  MethodFactory::MethodPtr MethodFactory::create(const std::string &name, unsigned int n, const std::set<std::string> &Sp, const std::set<std::string> &Sm, const std::set<std::string> &S, const std::set<std::string> &prefixes, const std::set<char> &alphabet) {
32  auto itr = s_methodsMap.find(name);
33  if (itr == s_methodsMap.end()) {
34  return nullptr;
35  }
36  else {
37  return itr->second(Sp, Sm, S, prefixes, alphabet, n);
38  }
39  }
40 
41  std::unique_ptr<Method> constructMethodTrigger(const std::string &name, unsigned int n, const std::set<std::string> &Sp, const std::set<std::string> &Sm, const std::set<std::string> &S, const std::set<std::string> &prefixes, const std::set<char> &alphabet, const std::chrono::seconds &timeLimit, std::atomic_bool &stopTrigger, const bool *stopPointer) {
42  std::unique_ptr<Method> method = MethodFactory::create(name, n, Sp, Sm, S, prefixes, alphabet);
43  if (!method) {
44  throw std::invalid_argument("Unknown method type: " + name);
45  }
46  method->setStopTrigger(timeLimit, stopTrigger, stopPointer);
47  return method;
48  }
49 
50  std::unique_ptr<Method> constructMethod(const std::string &method, unsigned int n, const std::set<std::string> &Sp, const std::set<std::string> &Sm) {
51  std::set<std::string> S = computeS(Sp, Sm);
52  std::set<std::string> prefixes = computePrefixes(S);
53  std::set<char> alphabet = computeAlphabet(S);
54 
55  return std::move(constructMethod(method, n, Sp, Sm, S, prefixes, alphabet));
56  }
57 
58  std::unique_ptr<Method> constructMethod(const std::string &method, unsigned int n, const std::set<std::string> &Sp, const std::set<std::string> &Sm, const std::set<std::string> &S, const std::set<std::string> &prefixes, const std::set<char> &alphabet) {
59  return std::move(constructMethodTrigger(method, n, Sp, Sm, S, prefixes, alphabet, noLimit, falseStopTrigger, &falseStopBool));
60  }
61 
62  std::pair<std::unique_ptr<Method>, bool> constructMethod(const std::string &method, const std::set<std::string> &Sp, const std::set<std::string> &Sm, const std::chrono::seconds &timeLimit, long double *timeTaken) {
63  std::set<std::string> S = computeS(Sp, Sm);
64  std::set<std::string> prefixes = computePrefixes(S);
65  std::set<char> alphabet = computeAlphabet(S);
66 
67  return constructMethod(method, Sp, Sm, S, prefixes, alphabet, timeLimit, timeTaken);
68  }
69 
70  std::pair<std::unique_ptr<Method>, bool> constructMethod(const std::string &method, const std::set<std::string> &Sp, const std::set<std::string> &Sm, const std::set<std::string> &S, const std::set<std::string> &prefixes, const std::set<char> &alphabet, const std::chrono::seconds &timeLimit, long double *timeTaken) {
71  std::atomic_bool stopTrigger(false);
72  bool stopBool(false);
73 
74  std::chrono::seconds remainingTime(timeLimit);
75 
76  std::unique_ptr<Method> bestPossible = nullptr;
77 
78  // We use a thread to be able to stop the method when the time limit is reached
79  std::packaged_task<void()> task([&]() {
80  unsigned int n = 1;
81  bool cont = true;
82  while (cont && !stopTrigger) {
83  std::unique_ptr<Method> toTry = constructMethodTrigger(method, n, Sp, Sm, S, prefixes, alphabet, remainingTime, stopTrigger, &stopBool);
84 
85  bool success = toTry->solve();
86  if (timeTaken) {
87  *timeTaken += toTry->timeToSolve();
88  }
89  remainingTime -= std::chrono::seconds(int(std::floor(toTry->timeToSolve())));
90  // To make sure CVC4 does not think it has an unlimited available time
91  if (remainingTime.count() <= 0) {
92  if (timeLimit == std::chrono::seconds(0)) {
93  remainingTime = std::chrono::seconds(0);
94  }
95  else {
96  remainingTime = std::chrono::seconds(1);
97  }
98  }
99 
100  if (success) {
101  bestPossible = std::move(toTry);
102  cont = false;
103  }
104  n++;
105  }
106  });
107 
108  std::future<void> future = task.get_future();
109  std::thread t(std::move(task));
110 
111  // If there is no limit, we just start the thread and join
112  if (timeLimit <= std::chrono::seconds(0)) {
113  future.wait();
114  t.join();
115  future.get(); // Allows to retrieve any thrown exception
116  return std::make_pair(std::move(bestPossible), true);
117  }
118  else {
119  // We use wait_for to wait for the thread to finish or for the timeLimit to be reached
120  // If the thread had enough time, we simply join (to make sure everything is ready to be destroyed) and we return the built model
121  // If the time limit is reached, we set the stopping flags to ask the thread to finish as soon as possible and we join
122  std::future_status status = future.wait_for(timeLimit);
123  if (status == std::future_status::ready) {
124  t.join();
125  future.get(); // Allows to retrieve any thrown exception
126  return std::make_pair(std::move(bestPossible), true);
127  }
128  else {
129  stopTrigger.store(true);
130  stopBool = true;
131  t.join();
132  future.get(); // Allows to retrieve any thrown exception
133  return std::make_pair(std::move(bestPossible), false);
134  }
135  }
136  }
137  }
138 }
std::unique_ptr< Method > constructMethodTrigger(const std::string &name, unsigned int n, const std::set< std::string > &Sp, const std::set< std::string > &Sm, const std::set< std::string > &S, const std::set< std::string > &prefixes, const std::set< char > &alphabet, const std::chrono::seconds &timeLimit, std::atomic_bool &stopTrigger, const bool *stopPointer)
bool falseStopBool
The namespace of the library.
Definition: binary.h:11
std::chrono::seconds noLimit(0)
static MethodPtr create(const std::string &name, unsigned int n, const std::set< std::string > &Sp, const std::set< std::string > &Sm, const std::set< std::string > &S, const std::set< std::string > &prefixes, const std::set< char > &alphabet)
Creates a unique_ptr to a method.
std::set< std::string > computePrefixes(const std::set< std::string > &S)
Computes .
Definition: utils.cpp:17
static bool registerMethod(const std::string &name, MethodConstructor const &constructor)
Registers a method.
std::atomic_bool falseStopTrigger(false)
std::unique_ptr< Method > constructMethod(const std::string &name, unsigned int n, const std::set< std::string > &Sp, const std::set< std::string > &Sm)
Computes the alphabet and the prefixes set from Sp and Sm and constructs a method for a fixed number ...
std::unique_ptr< Method > MethodPtr
The type the function create will return.
Definition: MethodFactory.h:24
std::set< std::string > computeS(const std::set< std::string > &Sp, const std::set< std::string > &Sm)
Computes .
Definition: utils.cpp:11
std::function< MethodPtr(const std::set< std::string > &Sp, const std::set< std::string > &Sm, const std::set< std::string > &S, const std::set< std::string > &prefixes, const std::set< char > &alphabet, unsigned int n)> MethodConstructor
The type of the constructor the registerMethod must receive.
Definition: MethodFactory.h:35
std::set< char > computeAlphabet(const std::set< std::string > &S)
Computes the alphabet from the words in .
Definition: utils.cpp:27