53 bool negation,
const char* matcher_name,
54 const std::vector<const char*>& param_names,
const Strings& param_values) {
56 if (param_values.size() >= 1) {
59 return negation ?
"not (" + result +
")" : result;
128 left_(graph_->LhsSize(), kUnused),
129 right_(graph_->RhsSize(), kUnused) {}
134 ::std::vector<char> seen;
147 for (
size_t ilhs = 0; ilhs < graph_->LhsSize(); ++ilhs) {
150 GTEST_CHECK_(left_[ilhs] == kUnused)
151 <<
"ilhs: " << ilhs <<
", left_[ilhs]: " << left_[ilhs];
153 seen.assign(graph_->RhsSize(), 0);
154 TryAugment(ilhs, &seen);
156 ElementMatcherPairs result;
157 for (
size_t ilhs = 0; ilhs < left_.size(); ++ilhs) {
158 size_t irhs = left_[ilhs];
159 if (irhs == kUnused)
continue;
160 result.push_back(ElementMatcherPair(ilhs, irhs));
166 static const size_t kUnused =
static_cast<size_t>(-1);
184 bool TryAugment(
size_t ilhs, ::std::vector<char>* seen) {
185 for (
size_t irhs = 0; irhs < graph_->RhsSize(); ++irhs) {
186 if ((*seen)[irhs])
continue;
187 if (!graph_->HasEdge(ilhs, irhs))
continue;
200 if (right_[irhs] == kUnused || TryAugment(right_[irhs], seen)) {
210 const MatchMatrix* graph_;
222 ::std::vector<size_t> left_;
223 ::std::vector<size_t> right_;
226const size_t MaxBipartiteMatchState::kUnused;
233 ::std::ostream* stream) {
234 typedef ElementMatcherPairs::const_iterator Iter;
235 ::std::ostream& os = *stream;
237 const char* sep =
"";
238 for (Iter it = pairs.begin(); it != pairs.end(); ++it) {
240 <<
"element #" << it->first <<
", "
241 <<
"matcher #" << it->second <<
")";
247bool MatchMatrix::NextGraph() {
248 for (
size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
249 for (
size_t irhs = 0; irhs < RhsSize(); ++irhs) {
250 char& b = matched_[SpaceIndex(ilhs, irhs)];
261void MatchMatrix::Randomize() {
262 for (
size_t ilhs = 0; ilhs < LhsSize(); ++ilhs) {
263 for (
size_t irhs = 0; irhs < RhsSize(); ++irhs) {
264 char& b = matched_[SpaceIndex(ilhs, irhs)];
265 b =
static_cast<char>(rand() & 1);
270std::string MatchMatrix::DebugString()
const {
271 ::std::stringstream ss;
272 const char* sep =
"";
273 for (
size_t i = 0; i < LhsSize(); ++i) {
275 for (
size_t j = 0; j < RhsSize(); ++j) {
283void UnorderedElementsAreMatcherImplBase::DescribeToImpl(
284 ::std::ostream* os)
const {
285 switch (match_flags()) {
286 case UnorderedMatcherRequire::ExactMatch:
287 if (matcher_describers_.empty()) {
291 if (matcher_describers_.size() == 1) {
292 *os <<
"has " << Elements(1) <<
" and that element ";
293 matcher_describers_[0]->DescribeTo(os);
296 *os <<
"has " << Elements(matcher_describers_.size())
297 <<
" and there exists some permutation of elements such that:\n";
299 case UnorderedMatcherRequire::Superset:
300 *os <<
"a surjection from elements to requirements exists such that:\n";
302 case UnorderedMatcherRequire::Subset:
303 *os <<
"an injection from elements to requirements exists such that:\n";
307 const char* sep =
"";
308 for (
size_t i = 0; i != matcher_describers_.size(); ++i) {
310 if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
311 *os <<
" - element #" << i <<
" ";
313 *os <<
" - an element ";
315 matcher_describers_[i]->DescribeTo(os);
316 if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
324void UnorderedElementsAreMatcherImplBase::DescribeNegationToImpl(
325 ::std::ostream* os)
const {
326 switch (match_flags()) {
327 case UnorderedMatcherRequire::ExactMatch:
328 if (matcher_describers_.empty()) {
329 *os <<
"isn't empty";
332 if (matcher_describers_.size() == 1) {
333 *os <<
"doesn't have " << Elements(1) <<
", or has " << Elements(1)
335 matcher_describers_[0]->DescribeNegationTo(os);
338 *os <<
"doesn't have " << Elements(matcher_describers_.size())
339 <<
", or there exists no permutation of elements such that:\n";
341 case UnorderedMatcherRequire::Superset:
342 *os <<
"no surjection from elements to requirements exists such that:\n";
344 case UnorderedMatcherRequire::Subset:
345 *os <<
"no injection from elements to requirements exists such that:\n";
348 const char* sep =
"";
349 for (
size_t i = 0; i != matcher_describers_.size(); ++i) {
351 if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
352 *os <<
" - element #" << i <<
" ";
354 *os <<
" - an element ";
356 matcher_describers_[i]->DescribeTo(os);
357 if (match_flags() == UnorderedMatcherRequire::ExactMatch) {
370bool UnorderedElementsAreMatcherImplBase::VerifyMatchMatrix(
371 const ::std::vector<std::string>& element_printouts,
372 const MatchMatrix& matrix, MatchResultListener* listener)
const {
374 ::std::vector<char> element_matched(matrix.LhsSize(), 0);
375 ::std::vector<char> matcher_matched(matrix.RhsSize(), 0);
377 for (
size_t ilhs = 0; ilhs < matrix.LhsSize(); ilhs++) {
378 for (
size_t irhs = 0; irhs < matrix.RhsSize(); irhs++) {
379 char matched = matrix.HasEdge(ilhs, irhs);
380 element_matched[ilhs] |= matched;
381 matcher_matched[irhs] |= matched;
385 if (match_flags() & UnorderedMatcherRequire::Superset) {
387 "where the following matchers don't match any elements:\n";
388 for (
size_t mi = 0; mi < matcher_matched.size(); ++mi) {
389 if (matcher_matched[mi])
continue;
391 if (listener->IsInterested()) {
392 *listener << sep <<
"matcher #" << mi <<
": ";
393 matcher_describers_[mi]->DescribeTo(listener->stream());
399 if (match_flags() & UnorderedMatcherRequire::Subset) {
401 "where the following elements don't match any matchers:\n";
402 const char* outer_sep =
"";
404 outer_sep =
"\nand ";
406 for (
size_t ei = 0; ei < element_matched.size(); ++ei) {
407 if (element_matched[ei])
continue;
409 if (listener->IsInterested()) {
410 *listener << outer_sep << sep <<
"element #" << ei <<
": "
411 << element_printouts[ei];
420bool UnorderedElementsAreMatcherImplBase::FindPairing(
421 const MatchMatrix& matrix, MatchResultListener* listener)
const {
424 size_t max_flow = matches.size();
425 if ((match_flags() & UnorderedMatcherRequire::Superset) &&
426 max_flow < matrix.RhsSize()) {
427 if (listener->IsInterested()) {
428 *listener <<
"where no permutation of the elements can satisfy all "
429 "matchers, and the closest match is "
430 << max_flow <<
" of " << matrix.RhsSize()
431 <<
" matchers with the pairings:\n";
436 if ((match_flags() & UnorderedMatcherRequire::Subset) &&
437 max_flow < matrix.LhsSize()) {
438 if (listener->IsInterested()) {
440 <<
"where not all elements can be matched, and the closest match is "
441 << max_flow <<
" of " << matrix.RhsSize()
442 <<
" matchers with the pairings:\n";
448 if (matches.size() > 1) {
449 if (listener->IsInterested()) {
450 const char* sep =
"where:\n";
451 for (
size_t mi = 0; mi < matches.size(); ++mi) {
452 *listener << sep <<
" - element #" << matches[mi].first
453 <<
" is matched by matcher #" << matches[mi].second;
MaxBipartiteMatchState(const MatchMatrix &graph)
ElementMatcherPairs Compute()
GTEST_API_ std::string ConvertIdentifierNameToWords(const char *id_name)
GTEST_API_ std::string FormatMatcherDescription(bool negation, const char *matcher_name, const std::vector< const char * > ¶m_names, const Strings ¶m_values)
static void LogElementMatcherPairVec(const ElementMatcherPairs &pairs, ::std::ostream *stream)
GTEST_API_ std::string JoinAsKeyValueTuple(const std::vector< const char * > &names, const Strings &values)
GTEST_API_ ElementMatcherPairs FindMaxBipartiteMatching(const MatchMatrix &g)