Пример #1
0
    double weakBoundDistance(const VList & oldV, const VList & newV) {
        // Here we implement a weak bound (can also be seen in Cassandra's code)
        // This is mostly because a strong bound is more costly (it requires performing
        // multiple LPs) and also the code at the moment does not support it cleanly, so
        // I prefer waiting until I have a good implementation of an LP class that hides
        // complexity from here.
        //
        // The logic of the weak bound is the following: the variation between the old
        // VList and the new one is equal to the maximum distance between a ValueFunction
        // in the old VList with its closest match in the new VList. So the farthest from
        // closest.
        //
        // We define distance between two ValueFunctions as the maximum between their
        // element-wise difference.
        if ( !oldV.size() ) return 0.0;

        double distance = 0.0;
        for ( const auto & newVE : newV ) {
            // Initialize closest distance for newVE as infinity
            double closestDistance = std::numeric_limits<double>::infinity();
            for ( const auto & oldVE : oldV ) {
                // Compute the distance, we pick the max
                double distance = (newVE.values - oldVE.values).cwiseAbs().maxCoeff();

                // Keep the closest, we pick the min
                closestDistance = std::min(closestDistance, distance);
            }
            // Keep the maximum distance between a new VList and its closest old VList
            distance = std::max(distance, closestDistance);
        }
        return distance;
    }
Пример #2
0
        VList IncrementalPruning::crossSum(const VList & l1, const VList & l2, size_t a, bool order) {
            VList c;

            if ( ! ( l1.size() && l2.size() ) ) return c;

            // We can get the sizes of the observation vectors
            // outside since all VEntries for our input VLists
            // are guaranteed to be sized equally.
            const auto O1size  = std::get<OBS>(l1[0]).size();
            const auto O2size  = std::get<OBS>(l2[0]).size();
            for ( const auto & v1 : l1 ) {
                auto O1begin = std::begin(std::get<OBS>(v1));
                auto O1end   = std::end  (std::get<OBS>(v1));
                for ( const auto & v2 : l2 ) {
                    auto O2begin = std::begin(std::get<OBS>(v2));
                    auto O2end   = std::end  (std::get<OBS>(v2));
                    // Cross sum
                    auto v = std::get<VALUES>(v1) + std::get<VALUES>(v2);

                    // This step now depends on which order the two lists
                    // are. This function is only used in this class, so we
                    // know that the two lists are "adjacent"; however one
                    // is after the other. `order` tells us which one comes
                    // first, and we join the observation vectors accordingly.
                    VObs obs; obs.reserve(O1size + O2size);
                    if ( order ) {
                        obs.insert(std::end(obs),O1begin, O1end);
                        obs.insert(std::end(obs),O2begin, O2end);
                    } else {
                        obs.insert(std::end(obs),O2begin, O2end);
                        obs.insert(std::end(obs),O1begin, O1end);
                    }
                    c.emplace_back(std::move(v), a, std::move(obs));
                }
            }

            return c;
        }