<ahref="matchers_8h.html">Go to the documentation of this file.</a><divclass="fragment"><divclass="line"><aid="l00001"name="l00001"></a><spanclass="lineno"> 1</span><spanclass="comment">// Copyright 2010-2021 Google LLC</span></div>
<divclass="line"><aid="l00002"name="l00002"></a><spanclass="lineno"> 2</span><spanclass="comment">// Licensed under the Apache License, Version 2.0 (the "License");</span></div>
<divclass="line"><aid="l00003"name="l00003"></a><spanclass="lineno"> 3</span><spanclass="comment">// you may not use this file except in compliance with the License.</span></div>
<divclass="line"><aid="l00004"name="l00004"></a><spanclass="lineno"> 4</span><spanclass="comment">// You may obtain a copy of the License at</span></div>
<divclass="line"><aid="l00008"name="l00008"></a><spanclass="lineno"> 8</span><spanclass="comment">// Unless required by applicable law or agreed to in writing, software</span></div>
<divclass="line"><aid="l00009"name="l00009"></a><spanclass="lineno"> 9</span><spanclass="comment">// distributed under the License is distributed on an "AS IS" BASIS,</span></div>
<divclass="line"><aid="l00010"name="l00010"></a><spanclass="lineno"> 10</span><spanclass="comment">// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></div>
<divclass="line"><aid="l00011"name="l00011"></a><spanclass="lineno"> 11</span><spanclass="comment">// See the License for the specific language governing permissions and</span></div>
<divclass="line"><aid="l00012"name="l00012"></a><spanclass="lineno"> 12</span><spanclass="comment">// limitations under the License.</span></div>
<divclass="line"><aid="l00016"name="l00016"></a><spanclass="lineno"> 16</span><spanclass="comment">// The matchers defined here are useful for writing unit tests checking that the</span></div>
<divclass="line"><aid="l00017"name="l00017"></a><spanclass="lineno"> 17</span><spanclass="comment">// result of Solve(), absl::StatusOr<SolveResult>, meets expectations. We give</span></div>
<divclass="line"><aid="l00018"name="l00018"></a><spanclass="lineno"> 18</span><spanclass="comment">// some examples below. All code is assumed with the following setup:</span></div>
<divclass="line"><aid="l00021"name="l00021"></a><spanclass="lineno"> 21</span><spanclass="comment">// using ::testing::status::IsOkAndHolds;</span></div>
<divclass="line"><aid="l00029"name="l00029"></a><spanclass="lineno"> 29</span><spanclass="comment">// Example 1.a: result is OK, optimal, and objective value approximately 42.</span></div>
<divclass="line"><aid="l00037"name="l00037"></a><spanclass="lineno"> 37</span><spanclass="comment">// Example 2: result is OK, optimal, and best solution is x=1, y=0.</span></div>
<divclass="line"><aid="l00042"name="l00042"></a><spanclass="lineno"> 42</span><spanclass="comment">// Note: the second ASSERT ensures that if the solution is not optimal, then</span></div>
<divclass="line"><aid="l00043"name="l00043"></a><spanclass="lineno"> 43</span><spanclass="comment">// result.variable_value() will not run (the function will crash if the solver</span></div>
<divclass="line"><aid="l00044"name="l00044"></a><spanclass="lineno"> 44</span><spanclass="comment">// didn't find a solution). Further, MathOpt guarantees there is a solution</span></div>
<divclass="line"><aid="l00045"name="l00045"></a><spanclass="lineno"> 45</span><spanclass="comment">// when the termination reason is optimal.</span></div>
<divclass="line"><aid="l00047"name="l00047"></a><spanclass="lineno"> 47</span><spanclass="comment">// Example 3: result is OK, check the solution without specifying termination.</span></div>
<divclass="line"><aid="l00052"name="l00052"></a><spanclass="lineno"> 52</span><spanclass="comment">// Example 4: multiple possible termination reason, primal ray optional:</span></div>
<divclass="line"><aid="l00063"name="l00063"></a><spanclass="lineno"> 63</span><spanclass="comment">// Tips on writing good tests:</span></div>
<divclass="line"><aid="l00064"name="l00064"></a><spanclass="lineno"> 64</span><spanclass="comment">// * Use ASSERT_OK_AND_ASSIGN(const SolveResult result, Solve(...)) to ensure</span></div>
<divclass="line"><aid="l00065"name="l00065"></a><spanclass="lineno"> 65</span><spanclass="comment">// the test terminates immediately if Solve() does not return OK.</span></div>
<divclass="line"><aid="l00066"name="l00066"></a><spanclass="lineno"> 66</span><spanclass="comment">// * If you ASSERT_THAT(result, IsOptimal()), you can assume that you have a</span></div>
<divclass="line"><aid="l00067"name="l00067"></a><spanclass="lineno"> 67</span><spanclass="comment">// feasible primal solution afterwards. Otherwise, make no assumptions on</span></div>
<divclass="line"><aid="l00068"name="l00068"></a><spanclass="lineno"> 68</span><spanclass="comment">// the contents of result (e.g. do not assume result contains a primal ray</span></div>
<divclass="line"><aid="l00069"name="l00069"></a><spanclass="lineno"> 69</span><spanclass="comment">// just because the termination reason was UNBOUNDED).</span></div>
<divclass="line"><aid="l00070"name="l00070"></a><spanclass="lineno"> 70</span><spanclass="comment">// * For problems that are infeasible, the termination reasons INFEASIBLE and</span></div>
<divclass="line"><aid="l00071"name="l00071"></a><spanclass="lineno"> 71</span><spanclass="comment">// DUAL_INFEASIBLE are both possible. Likewise, for unbounded problems, you</span></div>
<divclass="line"><aid="l00072"name="l00072"></a><spanclass="lineno"> 72</span><spanclass="comment">// can get both UNBOUNDED and DUAL_INFEASIBLE. See TerminatesWithOneOf()</span></div>
<divclass="line"><aid="l00073"name="l00073"></a><spanclass="lineno"> 73</span><spanclass="comment">// below to make assertions in this case. Note also that some solvers have</span></div>
<divclass="line"><aid="l00074"name="l00074"></a><spanclass="lineno"> 74</span><spanclass="comment">// solver specific parameters to ensure that DUAL_INFEASIBLE will not be</span></div>
<divclass="line"><aid="l00075"name="l00075"></a><spanclass="lineno"> 75</span><spanclass="comment">// returned (e.g. for Gurobi, use DualReductions or InfUnbdInfo).</span></div>
<divclass="line"><aid="l00076"name="l00076"></a><spanclass="lineno"> 76</span><spanclass="comment">// * The objective value and variable values should always be compared up to</span></div>
<divclass="line"><aid="l00077"name="l00077"></a><spanclass="lineno"> 77</span><spanclass="comment">// a tolerance, even if your decision variables are integer. The matchers</span></div>
<divclass="line"><aid="l00078"name="l00078"></a><spanclass="lineno"> 78</span><spanclass="comment">// defined have a configurable tolerance with default value 1e-5.</span></div>
<divclass="line"><aid="l00079"name="l00079"></a><spanclass="lineno"> 79</span><spanclass="comment">// * Primal and dual rays are unique only up to a constant scaling. The</span></div>
<divclass="line"><aid="l00080"name="l00080"></a><spanclass="lineno"> 80</span><spanclass="comment">// matchers provided rescale both expected and actual before comparing.</span></div>
<divclass="line"><aid="l00081"name="l00081"></a><spanclass="lineno"> 81</span><spanclass="comment">// * Take care on problems with multiple optimal solutions. Do not rely on a</span></div>
<divclass="line"><aid="l00082"name="l00082"></a><spanclass="lineno"> 82</span><spanclass="comment">// particular solution being returned in your test, as the test will break</span></div>
<divclass="line"><aid="l00083"name="l00083"></a><spanclass="lineno"> 83</span><spanclass="comment">// when we upgrade the solver.</span></div>
<divclass="line"><aid="l00085"name="l00085"></a><spanclass="lineno"> 85</span><spanclass="comment">// This file also defines functions to let gunit print various MathOpt types.</span></div>
<divclass="line"><aid="l00087"name="l00087"></a><spanclass="lineno"> 87</span><spanclass="comment">// To see the error messages these matchers generate, run</span></div>
<divclass="line"><aid="l00088"name="l00088"></a><spanclass="lineno"> 88</span><spanclass="comment">// blaze test experimental/users/rander/math_opt:matchers_error_messages</span></div>
<divclass="line"><aid="l00089"name="l00089"></a><spanclass="lineno"> 89</span><spanclass="comment">// which is a fork of matchers_test.cc where the assertions are all negated</span></div>
<divclass="line"><aid="l00090"name="l00090"></a><spanclass="lineno"> 90</span><spanclass="comment">// (note that every test should fail).</span></div>
<divclass="line"><aid="l00109"name="l00109"></a><spanclass="lineno"> 109</span><spanclass="comment">// Matchers for IdMap<Variable,double> and IdMap<LinearConstraint, double></span></div>
<divclass="line"><aid="l00112"name="l00112"></a><spanclass="lineno"> 112</span><spanclass="comment">// Checks that the maps have identical keys and values within tolerance.</span></div>
<divclass="line"><aid="l00116"name="l00116"></a><spanclass="lineno"> 116</span><spanclass="comment">// Checks that the keys of actual are a subset of the keys of expected, and that</span></div>
<divclass="line"><aid="l00117"name="l00117"></a><spanclass="lineno"> 117</span><spanclass="comment">// for all shared keys, the values are within tolerance.</span></div>
<divclass="line"><aid="l00121"name="l00121"></a><spanclass="lineno"> 121</span><spanclass="comment">// Checks that the maps have identical keys and values within tolerance.</span></div>
<divclass="line"><aid="l00126"name="l00126"></a><spanclass="lineno"> 126</span><spanclass="comment">// Checks that the keys of actual are a subset of the keys of expected, and that</span></div>
<divclass="line"><aid="l00127"name="l00127"></a><spanclass="lineno"> 127</span><spanclass="comment">// for all shared keys, the values are within tolerance.</span></div>
<divclass="line"><aid="l00147"name="l00147"></a><spanclass="lineno"> 147</span><spanclass="comment">// Checks variables match and variable/objective values are within tolerance and</span></div>
<divclass="line"><aid="l00148"name="l00148"></a><spanclass="lineno"> 148</span><spanclass="comment">// feasibility statuses are identical.</span></div>
<divclass="line"><aid="l00152"name="l00152"></a><spanclass="lineno"> 152</span><spanclass="comment">// Checks dual variables, reduced costs and objective are within tolerance and</span></div>
<divclass="line"><aid="l00153"name="l00153"></a><spanclass="lineno"> 153</span><spanclass="comment">// feasibility statuses are identical.</span></div>
<divclass="line"><aid="l00163"name="l00163"></a><spanclass="lineno"> 163</span><spanclass="comment">// Checks variables match and that after rescaling, variable values are within</span></div>
<divclass="line"><aid="l00168"name="l00168"></a><spanclass="lineno"> 168</span><spanclass="comment">// Checks variables match and that after rescaling, variable values are within</span></div>
<divclass="line"><aid="l00174"name="l00174"></a><spanclass="lineno"> 174</span><spanclass="comment">// Checks that dual variables and reduced costs are defined for the same</span></div>
<divclass="line"><aid="l00175"name="l00175"></a><spanclass="lineno"> 175</span><spanclass="comment">// set of Variables/LinearConstraints, and that their rescaled values are within</span></div>
<divclass="line"><aid="l00184"name="l00184"></a><spanclass="lineno"> 184</span><spanclass="comment">// Checks the following:</span></div>
<divclass="line"><aid="l00185"name="l00185"></a><spanclass="lineno"> 185</span><spanclass="comment">// * The termination reason is optimal.</span></div>
<divclass="line"><aid="l00186"name="l00186"></a><spanclass="lineno"> 186</span><spanclass="comment">// * If expected_objective contains a value, there is at least one feasible</span></div>
<divclass="line"><aid="l00187"name="l00187"></a><spanclass="lineno"> 187</span><spanclass="comment">// solution and that solution has an objective value within tolerance of</span></div>
<divclass="line"><aid="l00202"name="l00202"></a><spanclass="lineno"> 202</span><spanclass="comment">// Checks the following:</span></div>
<divclass="line"><aid="l00203"name="l00203"></a><spanclass="lineno"> 203</span><spanclass="comment">// * The result has the expected termination reason.</span></div>
<divclass="line"><aid="l00206"name="l00206"></a><spanclass="lineno"> 206</span><spanclass="comment">// Checks that the result has one of the allowed termination reasons.</span></div>
<divclass="line"><aid="l00210"name="l00210"></a><spanclass="lineno"> 210</span><spanclass="comment">// Checks the following:</span></div>
<divclass="line"><aid="l00211"name="l00211"></a><spanclass="lineno"> 211</span><spanclass="comment">// * The result has termination reason kFeasible or kNoSolutionFound.</span></div>
<divclass="line"><aid="l00212"name="l00212"></a><spanclass="lineno"> 212</span><spanclass="comment">// * The limit is expected, or is kUndetermined if allow_limit_undetermined.</span></div>
<divclass="line"><aid="l00216"name="l00216"></a><spanclass="lineno"> 216</span><spanclass="comment">// Checks the following:</span></div>
<divclass="line"><aid="l00217"name="l00217"></a><spanclass="lineno"> 217</span><spanclass="comment">// * The result has termination reason kFeasible.</span></div>
<divclass="line"><aid="l00218"name="l00218"></a><spanclass="lineno"> 218</span><spanclass="comment">// * The limit is expected, or is kUndetermined if allow_limit_undetermined.</span></div>
<divclass="line"><aid="l00223"name="l00223"></a><spanclass="lineno"> 223</span><spanclass="comment">// * The result has termination reason kNoSolutionFound.</span></div>
<divclass="line"><aid="l00224"name="l00224"></a><spanclass="lineno"> 224</span><spanclass="comment">// * The limit is expected, or is kUndetermined if allow_limit_undetermined.</span></div>
<divclass="line"><aid="l00228"name="l00228"></a><spanclass="lineno"> 228</span><spanclass="comment">// SolveResult has a primal solution matching expected within tolerance.</span></div>
<divclass="line"><aid="l00232"name="l00232"></a><spanclass="lineno"> 232</span><spanclass="comment">// SolveResult has a dual solution matching expected within</span></div>
<divclass="line"><aid="l00237"name="l00237"></a><spanclass="lineno"> 237</span><spanclass="comment">// Actual SolveResult contains a primal ray that matches expected within</span></div>
<divclass="line"><aid="l00242"name="l00242"></a><spanclass="lineno"> 242</span><spanclass="comment">// Actual SolveResult contains a primal ray with variable values equivalent to</span></div>
<divclass="line"><aid="l00243"name="l00243"></a><spanclass="lineno"> 243</span><spanclass="comment">// (under L_inf scaling) expected_vars up to tolerance.</span></div>
<divclass="line"><aid="l00248"name="l00248"></a><spanclass="lineno"> 248</span><spanclass="comment">// Actual SolveResult contains a dual ray that matches expected within</span></div>
<divclass="line"><aid="l00260"name="l00260"></a><spanclass="lineno"> 260</span><spanclass="comment">// If the expected result has termination reason kInfeasible, kUnbounded, or</span></div>
<divclass="line"><aid="l00261"name="l00261"></a><spanclass="lineno"> 261</span><spanclass="comment">// kDualInfeasasible, the primal solution, dual solution, and basis are</span></div>
<divclass="line"><aid="l00262"name="l00262"></a><spanclass="lineno"> 262</span><spanclass="comment">// ignored unless check_solutions_if_inf_or_unbounded is true.</span></div>
<divclass="line"><aid="l00264"name="l00264"></a><spanclass="lineno"> 264</span><spanclass="comment">// TODO(b/201099290): this is perhaps not a good default. Gurobi as</span></div>
<divclass="line"><aid="l00265"name="l00265"></a><spanclass="lineno"> 265</span><spanclass="comment">// implemented is returning primal solutions for both unbounded and</span></div>
<divclass="line"><aid="l00266"name="l00266"></a><spanclass="lineno"> 266</span><spanclass="comment">// infeasible problems. We need to add unit tests that inspect this value</span></div>
<divclass="line"><aid="l00267"name="l00267"></a><spanclass="lineno"> 267</span><spanclass="comment">// and turn them on one solver at a time with a new parameter on</span></div>
<divclass="line"><aid="l00272"name="l00272"></a><spanclass="lineno"> 272</span><spanclass="comment">// In linear programming, the following outcomes are all possible</span></div>
<divclass="line"><aid="l00281"name="l00281"></a><spanclass="lineno"> 281</span><spanclass="comment">// (Above "Optimal" means that an optimal solution exists. This is a statement</span></div>
<divclass="line"><aid="l00282"name="l00282"></a><spanclass="lineno"> 282</span><spanclass="comment">// about the existence of optimal solutions and certificates of</span></div>
<divclass="line"><aid="l00283"name="l00283"></a><spanclass="lineno"> 283</span><spanclass="comment">// infeasibility/unboundedness, not about the outcome of applying any</span></div>
<divclass="line"><aid="l00286"name="l00286"></a><spanclass="lineno"> 286</span><spanclass="comment">// When writing your unit test, you can typically tell which case of 1-4 you</span></div>
<divclass="line"><aid="l00287"name="l00287"></a><spanclass="lineno"> 287</span><spanclass="comment">// are in, but in cases 3-4 you do not know which termination reason will be</span></div>
<divclass="line"><aid="l00288"name="l00288"></a><spanclass="lineno"> 288</span><spanclass="comment">// returned. In some situations, it may not be clear if you are in case 1 or</span></div>
<divclass="line"><aid="l00289"name="l00289"></a><spanclass="lineno"> 289</span><spanclass="comment">// case 4 as well.</span></div>
<divclass="line"><aid="l00291"name="l00291"></a><spanclass="lineno"> 291</span><spanclass="comment">// When inf_or_unb_soft_match=false, the matcher must exactly specify the</span></div>
<divclass="line"><aid="l00292"name="l00292"></a><spanclass="lineno"> 292</span><spanclass="comment">// status returned by the solver. For cases 3-4, this is implementation</span></div>
<divclass="line"><aid="l00293"name="l00293"></a><spanclass="lineno"> 293</span><spanclass="comment">// dependent and we do not recommend this. When</span></div>
<divclass="line"><aid="l00295"name="l00295"></a><spanclass="lineno"> 295</span><spanclass="comment">// * kInfeasible can also match kInfeasibleOrUnbounded</span></div>
<divclass="line"><aid="l00296"name="l00296"></a><spanclass="lineno"> 296</span><spanclass="comment">// * kUnbounded can also match kInfeasibleOrUnbounded</span></div>
<divclass="line"><aid="l00297"name="l00297"></a><spanclass="lineno"> 297</span><spanclass="comment">// * kInfeasibleOrUnbounded can also match kInfeasible and kUnbounded.</span></div>
<divclass="line"><aid="l00298"name="l00298"></a><spanclass="lineno"> 298</span><spanclass="comment">// For case 2, inf_or_unb_soft_match has no effect.</span></div>
<divclass="line"><aid="l00300"name="l00300"></a><spanclass="lineno"> 300</span><spanclass="comment">// To build the strongest possible matcher (accepting the minimal set of</span></div>
<divclass="line"><aid="l00302"name="l00302"></a><spanclass="lineno"> 302</span><spanclass="comment">// * If you know you are in case 1, se inf_or_unb_soft_match=false</span></div>
<divclass="line"><aid="l00304"name="l00304"></a><spanclass="lineno"> 304</span><spanclass="comment">// * For case 3, use inf_or_unb_soft_match=false and</span></div>
<divclass="line"><aid="l00306"name="l00306"></a><spanclass="lineno"> 306</span><spanclass="comment">// * For case 4 (or if you are unsure of case 1 vs case 4), use</span></div>
<divclass="line"><aid="l00309"name="l00309"></a><spanclass="lineno"> 309</span><spanclass="comment">// * If you cannot tell if you are in case 3 or case 4, use</span></div>
<divclass="line"><aid="l00310"name="l00310"></a><spanclass="lineno"> 310</span><spanclass="comment">// inf_or_unb_soft_match=true and termination reason</span></div>
<divclass="line"><aid="l00313"name="l00313"></a><spanclass="lineno"> 313</span><spanclass="comment">// If the above is too complicated, always setting</span></div>
<divclass="line"><aid="l00314"name="l00314"></a><spanclass="lineno"> 314</span><spanclass="comment">// inf_or_unb_soft_match=true and using any of the expected MathOpt</span></div>
<divclass="line"><aid="l00315"name="l00315"></a><spanclass="lineno"> 315</span><spanclass="comment">// termination reasons from the above table will give a matcher that is</span></div>
<divclass="line"><aid="l00316"name="l00316"></a><spanclass="lineno"> 316</span><spanclass="comment">// slightly too lenient.</span></div>
<divclass="line"><aid="l00320"name="l00320"></a><spanclass="lineno"> 320</span><spanclass="comment">// Tests that two SolveResults are equivalent. Basic use:</span></div>
<divclass="line"><aid="l00327"name="l00327"></a><spanclass="lineno"> 327</span><spanclass="comment">// Equivalence is defined as follows:</span></div>
<divclass="line"><aid="l00328"name="l00328"></a><spanclass="lineno"> 328</span><spanclass="comment">// * The termination reasons are the same.</span></div>
<divclass="line"><aid="l00329"name="l00329"></a><spanclass="lineno"> 329</span><spanclass="comment">// - For infeasible and unbounded problems, see</span></div>
<divclass="line"><aid="l00331"name="l00331"></a><spanclass="lineno"> 331</span><spanclass="comment">// * The solve stats are ignored.</span></div>
<divclass="line"><aid="l00332"name="l00332"></a><spanclass="lineno"> 332</span><spanclass="comment">// * For both primal and dual solutions, either expected and actual are</span></div>
<divclass="line"><aid="l00333"name="l00333"></a><spanclass="lineno"> 333</span><spanclass="comment">// both empty, or their first entries satisfy IsNear() at options.tolerance.</span></div>
<divclass="line"><aid="l00334"name="l00334"></a><spanclass="lineno"> 334</span><spanclass="comment">// - Not checked if options.check_solutions_if_inf_or_unbounded and the</span></div>
<divclass="line"><aid="l00335"name="l00335"></a><spanclass="lineno"> 335</span><spanclass="comment">// problem is infeasible or unbounded (default).</span></div>
<divclass="line"><aid="l00336"name="l00336"></a><spanclass="lineno"> 336</span><spanclass="comment">// - If options.first_solution_only is false, check the entire list of</span></div>
<divclass="line"><aid="l00337"name="l00337"></a><spanclass="lineno"> 337</span><spanclass="comment">// solutions matches in the same order.</span></div>
<divclass="line"><aid="l00338"name="l00338"></a><spanclass="lineno"> 338</span><spanclass="comment">// - Dual solution is not checked if options.check_dual=false</span></div>
<divclass="line"><aid="l00339"name="l00339"></a><spanclass="lineno"> 339</span><spanclass="comment">// * For both the primal and dual rays, either expected and actual are both</span></div>
<divclass="line"><aid="l00340"name="l00340"></a><spanclass="lineno"> 340</span><spanclass="comment">// empty, or any ray in expected IsNear() any ray in actual (which is up</span></div>
<divclass="line"><aid="l00341"name="l00341"></a><spanclass="lineno"> 341</span><spanclass="comment">// to a rescaling) at options.tolerance.</span></div>
<divclass="line"><aid="l00342"name="l00342"></a><spanclass="lineno"> 342</span><spanclass="comment">// - Not checked if options.check_rays=false</span></div>
<divclass="line"><aid="l00343"name="l00343"></a><spanclass="lineno"> 343</span><spanclass="comment">// - If options.first_solution_only is false, check the entire list of</span></div>
<divclass="line"><aid="l00344"name="l00344"></a><spanclass="lineno"> 344</span><spanclass="comment">// solutions matches in the same order.</span></div>
<divclass="line"><aid="l00345"name="l00345"></a><spanclass="lineno"> 345</span><spanclass="comment">// * The basis is not checked by default. If enabled, checked with BasisIs().</span></div>
<divclass="line"><aid="l00346"name="l00346"></a><spanclass="lineno"> 346</span><spanclass="comment">// - Enable with options.check_basis</span></div>
<divclass="line"><aid="l00348"name="l00348"></a><spanclass="lineno"> 348</span><spanclass="comment">// This function is symmetric in that:</span></div>
<divclass="line"><aid="l00351"name="l00351"></a><spanclass="lineno"> 351</span><spanclass="comment">// agree on matching, they only differ in strings produced. Per gmock</span></div>
<divclass="line"><aid="l00352"name="l00352"></a><spanclass="lineno"> 352</span><spanclass="comment">// conventions, prefer the former.</span></div>
<divclass="line"><aid="l00354"name="l00354"></a><spanclass="lineno"> 354</span><spanclass="comment">// For problems with either primal or dual infeasibility, see</span></div>
<divclass="line"><aid="l00355"name="l00355"></a><spanclass="lineno"> 355</span><spanclass="comment">// SolveResultMatcherOptions::inf_or_unb_soft_match for guidance on how to</span></div>
<divclass="line"><aid="l00356"name="l00356"></a><spanclass="lineno"> 356</span><spanclass="comment">// best set the termination reason and inf_or_unb_soft_match.</span></div>
<divclass="line"><aid="l00364"name="l00364"></a><spanclass="lineno"> 364</span><spanclass="comment">// Actual UpdateResult.did_update is true.</span></div>
<divclass="line"><aid="l00371"name="l00371"></a><spanclass="lineno"> 371</span><spanclass="comment">// TODO(b/200835670): use the << operator on Termination instead once it</span></div>
<divclass="line"><aid="l00372"name="l00372"></a><spanclass="lineno"> 372</span><spanclass="comment">// supports quoting/escaping on termination.detail.</span></div>
<divclass="line"><aid="l00382"name="l00382"></a><spanclass="lineno"> 382</span><spanclass="comment">// We do not want to rely on ::testing::internal::ContainerPrinter because we</span></div>
<divclass="line"><aid="l00383"name="l00383"></a><spanclass="lineno"> 383</span><spanclass="comment">// want to sort the keys.</span></div>
<divclass="line"><aid="l00389"name="l00389"></a><spanclass="lineno"> 389</span><spanclass="keywordflow">for</span> (<spanclass="keyword">const</span> K k : id_map.<aclass="code hl_function"href="classoperations__research_1_1math__opt_1_1_id_map.html#a32c71b1e0da0f6dda942729e686ff021">SortedKeys</a>()) {</div>
<divclass="ttc"id="aclassoperations__research_1_1math__opt_1_1_id_map_html_a32c71b1e0da0f6dda942729e686ff021"><divclass="ttname"><ahref="classoperations__research_1_1math__opt_1_1_id_map.html#a32c71b1e0da0f6dda942729e686ff021">operations_research::math_opt::IdMap::SortedKeys</a></div><divclass="ttdeci">std::vector< K > SortedKeys() const</div><divclass="ttdef"><b>Definition:</b><ahref="id__map_8h_source.html#l00579">id_map.h:579</a></div></div>
<divclass="ttc"id="aclassoperations__research_1_1math__opt_1_1_id_map_html_ab2a3f17d02b118e3876034e67fdef6d3"><divclass="ttname"><ahref="classoperations__research_1_1math__opt_1_1_id_map.html#ab2a3f17d02b118e3876034e67fdef6d3">operations_research::math_opt::IdMap::at</a></div><divclass="ttdeci">const V & at(const K &k) const</div><divclass="ttdef"><b>Definition:</b><ahref="id__map_8h_source.html#l00480">id_map.h:480</a></div></div>
<divclass="ttc"id="anamespaceoperations__research_html"><divclass="ttname"><ahref="namespaceoperations__research.html">operations_research</a></div><divclass="ttdoc">Collection of objects used to extend the Constraint Solver library.</div><divclass="ttdef"><b>Definition:</b><ahref="dense__doubly__linked__list_8h_source.html#l00021">dense_doubly_linked_list.h:21</a></div></div>