void check_all_equal_lossy(const std::string& startsymbol, const std::vector<std::string>& inputs, int refinementDepth) { int num_grammars = inputs.size(); Parser p; auto eq_tmp = MapEquations(p.free_parser(inputs[0]), [](const FreeSemiring &c) -> LossyFiniteAutomaton { auto srconv = SRConverter<LossyFiniteAutomaton>(); return c.Eval(srconv); }); auto equations_fst = NCEquationsBase<LossyFiniteAutomaton>(eq_tmp.begin(), eq_tmp.end()); VarId S_1; if(startsymbol.compare("") == 0) { S_1 = equations_fst[0].first; } else { S_1 = Var::GetVarId(startsymbol); } Timer timer; timer.Start(); bool all_equal = true; for(int i=1; i<num_grammars; i++) { auto eq_tmp2 = MapEquations(p.free_parser(inputs[i]), [](const FreeSemiring &c) -> LossyFiniteAutomaton { auto srconv = SRConverter<LossyFiniteAutomaton>(); return c.Eval(srconv); }); auto equations = NCEquationsBase<LossyFiniteAutomaton>(eq_tmp2.begin(), eq_tmp2.end()); VarId S_2; if(startsymbol.compare("") == 0) { S_2 = equations[0].first; } else { S_2 = Var::GetVarId(startsymbol); } auto witness = NonCommutativePolynomial<LossyFiniteAutomaton>::refineCourcelle(equations_fst, S_1, equations, S_1, refinementDepth); if(witness != LossyFiniteAutomaton::null()) { if(startsymbol.compare("") == 0) { std::cout << "[DIFF] Difference found for startsymbols (" << equations_fst[0].first << "," << equations[0].first << ")" << std::endl; } else { std::cout << "[DIFF] Difference found for startsymbols (" << S_1 << "," << S_2 << ")" << std::endl; } std::cout << "Witness: " << witness.string() << std::endl; all_equal = false; break; } } if(all_equal) { std::cout << "[EQUIV] All grammars equivalent modulo subword-closure" << std::endl; } timer.Stop(); std::cout << "Total checking time:\t" << timer.GetMilliseconds().count() << " ms" << " (" << timer.GetMicroseconds().count() << "us)" << std::endl; }
void check_all_equal_commutative(const std::string& startsymbol, const std::vector<std::string>& inputs) { Parser p; int num_grammars = inputs.size(); auto nc_equations = p.free_parser(inputs[0]); std::cout << "Eq (non-comm) : " << std::endl; PrintEquations(nc_equations); // Use appropriate semiring (has to be commutative!) auto equations_fst = MakeCommEquationsAndMap(nc_equations, [](const FreeSemiring &c) -> SR { auto srconv = SRConverter<SR>(); return c.Eval(srconv); }); std::cout << "Eq (comm) : " << std::endl; PrintEquations(equations_fst); Timer timer; timer.Start(); ValuationMap<SR> sol_fst = apply_solver<NewtonCL, CommutativePolynomial>(equations_fst, true, false, 0, false); bool all_equal = true; for(int i=1; i<num_grammars; i++) { auto equations = MakeCommEquationsAndMap(p.free_parser(inputs[i]), [](const FreeSemiring &c) -> SR { auto srconv = SRConverter<SR>(); return c.Eval(srconv); }); ValuationMap<SR> sol = apply_solver<NewtonCL, CommutativePolynomial>(equations, true, false, 0, false); if(startsymbol.compare("") == 0) { if(sol[equations[0].first] != sol_fst[equations_fst[0].first]) { std::cout << "[DIFF] Difference found for startsymbols (" << equations_fst[0].first << "," << equations[0].first << ")" << std::endl; std::cout << "0:" << result_string(sol_fst) << std::endl << i << ":" << result_string(sol) << std::endl; all_equal = false; break; } } else { if(sol.find(Var::GetVarId(startsymbol)) == sol.end() || sol_fst.find(Var::GetVarId(startsymbol)) == sol_fst.end()) { std::cout << "[ERROR] startsymbol (" << startsymbol << ") does not occur!"<< std::endl; return; } else if(sol[Var::GetVarId(startsymbol)] != sol_fst[Var::GetVarId(startsymbol)]) { std::cout << "[DIFF] Difference found for startsymbol (" << startsymbol << ")" << std::endl << "0:" << result_string(sol_fst) << std::endl << i << ":" << result_string(sol) << std::endl; all_equal = false; break; } } } if(all_equal) { std::cout << "[EQUIV] All grammars equivalent modulo commutativity" << std::endl; } timer.Stop(); std::cout << "Total checking time:\t" << timer.GetMilliseconds().count() << " ms" << " (" << timer.GetMicroseconds().count() << "us)" << std::endl; }
// CCD via the local separating axis method. This seeks progression // by computing the largest time at which separation is maintained. void TimeOfImpact(TOIOutput* output, const TOIInput* input) { Timer timer; ++b2_toiCalls; output->state = TOIOutput::e_unknown; output->t = input->tMax; const DistanceProxy* proxyA = &input->proxyA; const DistanceProxy* proxyB = &input->proxyB; Sweep sweepA = input->sweepA; Sweep sweepB = input->sweepB; // Large rotations can make the root finder fail, so we normalize the // sweep angles. sweepA.Normalize(); sweepB.Normalize(); float32 tMax = input->tMax; float32 totalRadius = proxyA->m_radius + proxyB->m_radius; float32 target = Max(linearSlop, totalRadius - 3.0f * linearSlop); float32 tolerance = 0.25f * linearSlop; assert(target > tolerance); float32 t1 = 0.0f; const int32 k_maxIterations = 20; // TODO_ERIN b2::Settings int32 iter = 0; // Prepare input for distance query. SimplexCache cache; cache.count = 0; DistanceInput distanceInput; distanceInput.proxyA = input->proxyA; distanceInput.proxyB = input->proxyB; distanceInput.useRadii = false; // The outer loop progressively attempts to compute new separating axes. // This loop terminates when an axis is repeated (no progress is made). for(;;) { Transform xfA, xfB; sweepA.GetTransform(&xfA, t1); sweepB.GetTransform(&xfB, t1); // Get the distance between shapes. We can also use the results // to get a separating axis. distanceInput.transformA = xfA; distanceInput.transformB = xfB; DistanceOutput distanceOutput; Distance(&distanceOutput, &cache, &distanceInput); // If the shapes are overlapped, we give up on continuous collision. if (distanceOutput.distance <= 0.0f) { // Failure! output->state = TOIOutput::e_overlapped; output->t = 0.0f; break; } if (distanceOutput.distance < target + tolerance) { // Victory! output->state = TOIOutput::e_touching; output->t = t1; break; } // Initialize the separating axis. SeparationFunction fcn; fcn.Initialize(&cache, proxyA, sweepA, proxyB, sweepB, t1); #if 0 // Dump the curve seen by the root finder { const int32 N = 100; float32 dx = 1.0f / N; float32 xs[N+1]; float32 fs[N+1]; float32 x = 0.0f; for (int32 i = 0; i <= N; ++i) { sweepA.GetTransform(&xfA, x); sweepB.GetTransform(&xfB, x); float32 f = fcn.Evaluate(xfA, xfB) - target; std::printf("%g %g\n", x, f); xs[i] = x; fs[i] = f; x += dx; } } #endif // Compute the TOI on the separating axis. We do this by successively // resolving the deepest point. This loop is bounded by the number of vertices. bool done = false; float32 t2 = tMax; int32 pushBackIter = 0; for (;;) { // Find the deepest point at t2. Store the witness point indices. int32 indexA, indexB; float32 s2 = fcn.FindMinSeparation(&indexA, &indexB, t2); // Is the final configuration separated? if (s2 > target + tolerance) { // Victory! output->state = TOIOutput::e_separated; output->t = tMax; done = true; break; } // Has the separation reached tolerance? if (s2 > target - tolerance) { // Advance the sweeps t1 = t2; break; } // Compute the initial separation of the witness points. float32 s1 = fcn.Evaluate(indexA, indexB, t1); // Check for initial overlap. This might happen if the root finder // runs out of iterations. if (s1 < target - tolerance) { output->state = TOIOutput::e_failed; output->t = t1; done = true; break; } // Check for touching if (s1 <= target + tolerance) { // Victory! t1 should hold the TOI (could be 0.0). output->state = TOIOutput::e_touching; output->t = t1; done = true; break; } // Compute 1D root of: f(x) - target = 0 int32 rootIterCount = 0; float32 a1 = t1, a2 = t2; for (;;) { // Use a mix of the secant rule and bisection. float32 t; if (rootIterCount & 1) { // Secant rule to improve convergence. t = a1 + (target - s1) * (a2 - a1) / (s2 - s1); } else { // Bisection to guarantee progress. t = 0.5f * (a1 + a2); } ++rootIterCount; ++b2_toiRootIters; float32 s = fcn.Evaluate(indexA, indexB, t); if (Abs(s - target) < tolerance) { // t2 holds a tentative value for t1 t2 = t; break; } // Ensure we continue to bracket the root. if (s > target) { a1 = t; s1 = s; } else { a2 = t; s2 = s; } if (rootIterCount == 50) { break; } } b2_toiMaxRootIters = Max(b2_toiMaxRootIters, rootIterCount); ++pushBackIter; if (pushBackIter == maxPolygonVertices) { break; } } ++iter; ++b2_toiIters; if (done) { break; } if (iter == k_maxIterations) { // Root finder got stuck. Semi-victory. output->state = TOIOutput::e_failed; output->t = t1; break; } } b2_toiMaxIters = Max(b2_toiMaxIters, iter); float32 time = timer.GetMilliseconds(); b2_toiMaxTime = Max(b2_toiMaxTime, time); b2_toiTime += time; }