namespace Diehard
{
    default_random_engine ProblemTweet::random_engine = default_random_engine(random_device()());
    
    ProblemTweet::ProblemTweet()
    : ProblemDot(*GetRandomCapacities()) {}
    
    shared_ptr<list<string> > ProblemTweet::GetTweets() const
    {
        list<const Node*> nodes_route;
        auto node_goal = GetGoalNodeRandomly();
        if (!node_goal) return nullptr;
        
        auto node_ptr = node_goal;
        while (node_ptr)
        {
            nodes_route.push_front(node_ptr);
            if (node_ptr && node_ptr->GetSum() == 0) break;
            node_ptr = GetFromNodeRandomly(node_ptr);
        }
        
        auto tweets = shared_ptr<list<string> >(new list<string>());
        {
            stringstream ss;
            ss << "Capacities: " << GetName();
            ss << " -> ";
            ss << "Request: " << goal_sum;
            tweets->push_back(ss.str());
        }
        for_each(nodes_route.begin(), nodes_route.end(), [&](const Node* node)
                 {
                     stringstream ss;
                     ss << "Bucket: " << node->GetName(false);
                     tweets->push_back(ss.str());
                 });
        {
            stringstream ss;
            ss << "Final result: ";
            for (Dimention d = 0; d < capacities.size(); d++)
            {
                if (d != 0) ss << "+";
                ss << node_goal->volumes[d];
            }
            ss << "=" << node_goal->GetSum();
            tweets->push_back(ss.str());
        }
        
        return tweets;
    }
    
#pragma mark Random generator
    
    const Node* ProblemTweet::GetGoalNodeRandomly() const
    {
        list<const Node*> nodes_goal;
        for (auto& node : nodes)
        {
            if (
                node.is_used &&
                node.cost < Node::cost_max &&
                node.GetSum() == goal_sum)
                nodes_goal.push_back(&node);
        }
        
        return GetLowestCostRandomly(nodes_goal);
    }
    
    const Node* ProblemTweet::GetFromNodeRandomly(const Node* node)
    {
        list<const Node*> nodes_from(node->from.begin(), node->from.end());
        return GetLowestCostRandomly(nodes_from);
    }
    
    const Node* ProblemTweet::GetLowestCostRandomly(const std::list<const Node*>& nodes)
    {
        Node::Cost cost_min = Node::cost_max;
        for_each(nodes.begin(), nodes.end(), [&](const Node* node)
                 {
                     if (node->cost < cost_min) cost_min = node->cost;
                 });
        
        vector<const Node*> nodes_lowcost;
        for_each(nodes.begin(), nodes.end(), [&](const Node* node)
                 {
                     if (node->cost == cost_min) nodes_lowcost.push_back(node);
                 });
        
        if (nodes_lowcost.empty())
        {
            return nullptr;
        }
        else
        {
            uniform_int_distribution<size_t> dist_idx(0, nodes_lowcost.size() - 1);
            return nodes_lowcost[dist_idx(random_engine)];
        }
    }
    
    shared_ptr<vector<Volume> > ProblemTweet::GetRandomCapacities()
    {
        uniform_int_distribution<Volume> dist_capacity(2, 200);
        uniform_int_distribution<Dimention> dist_dimention(2, 4);
        auto rand_capacity = bind(dist_capacity, random_engine);
        auto dimention = dist_dimention(random_engine);
        
        shared_ptr<vector<Volume> > capacities(new vector<Volume>(dimention));
        for (Dimention i = 0; i < dimention; i++)
        {
            (*capacities)[i] = rand_capacity();
        }
        
        return capacities;
    }
    
    Volume ProblemTweet::GetRandomGoal()
    {
        Volume sum = 0;
        for_each(capacities.begin(), capacities.end(), [&](Volume v) { sum += v; });
        
        uniform_int_distribution<Volume> dist_goal(1, sum);
        return dist_goal(random_engine);
    }
    
}
std::vector<int> KMeansMethod::getInitialClusterOfInputs(const std::vector<std::vector<double>> &inputs, int dim, int countOfCluster) {
    // メルセンヌツイスタの初期化
    std::random_device random_device;
    std::mt19937 mt(random_device());

    std::vector<int> indexOfCluster;
    // まず最初に乱数で一つだけ追加
    std::uniform_int_distribution<int> score(0, inputs.size() - 1);
    indexOfCluster.push_back(score(mt));

    while (indexOfCluster.size() < countOfCluster) {
        std::vector<double> distances;
        for (int i = 0; i < inputs.size(); i++) {
            std::vector<double> input = inputs[i];

            // 一番近いクラスタとの距離
            double minD = std::numeric_limits<double>::max();
            for (int j = 0; j < indexOfCluster.size(); j++) {
                int index = indexOfCluster[j];
                std::vector<double> cluster = inputs[index];

                double d = 0;
                for (int k = 0; k < dim; k++) {
                    d += pow(cluster[k] - input[k], 2.0);
                }
                if (d < minD) {
                    minD = d;
                }
            }

            distances.push_back(minD);
        }

        // 重み付き確率計算のために距離を範囲に変換
        double index = 0;
        for (int i = 0; i < distances.size(); i++) {
            index += distances[i];
            distances[i] = index;
        }
        // 0 ~ 最大値までの乱数生成
        std::uniform_real_distribution<double> score(0.0, index);
        double random = score(mt);
        // 乱数がどこに含まれるかを探索
        int result = -1;
        for (int i = 0; i < distances.size(); i++) {
            if (distances[i] >= random) {
                result = i;
                break;
            }
        }
        // 選択されたクラスタを追加
        if (result >= 0) {
            indexOfCluster.push_back(result);
        }
    }

    std::vector<int> clusterOfInputs;
    // 入力をそれぞれ一番近いクラスタに付与
    for (int i = 0; i < inputs.size(); i++) {
        std::vector<double> input = inputs[i];

        double minD = std::numeric_limits<double>::max();
        int minIndex = 0;
        // 一番近いクラスタを検索
        for (int j = 0; j < countOfCluster; j++) {
            int index = indexOfCluster[j];
            std::vector<double> cluster = inputs[index];

            double d = 0;
            for (int k = 0; k < dim; k++) {
                d += pow(input[k] - cluster[k], 2.0);
            }
            if (d < minD) {
                minD = d;
                minIndex = j;
            }
        }

        clusterOfInputs.push_back(minIndex);
    }
    return clusterOfInputs;
}
Beispiel #3
0
int main()
{
    std::vector<int> vec(10);

	std::cout << "iota:" << '\n';
	boost::iota(vec, 1);
	for (auto e : vec) std::cout << e << " ";
	std::cout << '\n';

	std::cout << "reversed:" << '\n';
	for (auto e : vec | boost::adaptors::reversed) std::cout << e << " ";
	std::cout << '\n';

	std::cout << "sums:" << '\n';
	std::vector<int> sums(10);
	boost::partial_sum(vec, begin(sums));
	for (auto e : sums) std::cout << e << " ";
	std::cout << '\n';

	// perhaps as exercise?
	std::cout << "evens:" << '\n';
	std::vector<int> evens(10);
	boost::fill(evens, 2); // std::vector<int> evens(10, 2);
	boost::partial_sum(evens, begin(evens));
	for (auto e : evens) std::cout << e << " ";
	std::cout << '\n';

	boost::partial_sum(evens | boost::adaptors::reversed, begin(evens));
	for (auto e : evens) std::cout << e << " ";
	std::cout << '\n';

	// perhaps as exercise?
	std::cout << "factorials:" << '\n';
	std::vector<int> factorials(10);
	boost::partial_sum(vec, begin(factorials), std::multiplies<int>());
	for (auto e : factorials) std::cout << e << " ";
	std::cout << '\n';

	std::cout << "die:" << '\n';
	std::random_device random_device;
	std::default_random_engine random_engine(random_device());
	int a = 1, b = 6;
	std::uniform_int_distribution<int> uniform_distribution(a, b);
	auto die = std::bind(uniform_distribution, random_engine);
	std::cout << die() << '\n';

	std::cout << "die throws:" << '\n';
	std::vector<int> die_throws(10);
	boost::generate(die_throws, die); // readability: "generate die_throws using die [duh]"
	for (auto e : die_throws) std::cout << e << " ";
	std::cout << '\n';

	std::cout << "die throws, from #2 to #5:" << '\n';
	for (auto e : die_throws | boost::adaptors::sliced(2, 5)) std::cout << e << " ";
	std::cout << '\n';

	auto count_unique_low = boost::count_if( die_throws | boost::adaptors::uniqued, [](int result) { return result <= 3; } );
	auto count_unique_high = boost::count_if( die_throws | boost::adaptors::uniqued, [](int result) { return result > 3; } );
	std::cout << "count_unique_low = " << count_unique_low << '\n';
	std::cout << "count_unique_high = " << count_unique_high << '\n';

	/*
	std::vector<int> v;
	boost::push_front(v, boost::istream_range<int>(std::cin));
	for (auto e : v) std::cout << e << " ";
	std::cout << '\n';
	*/
	std::vector<int> v;
	boost::push_back(v, boost::irange(100, 200, 3)); // first, last, step-size
	for (auto e : v) std::cout << e << " ";
	std::cout << '\n';

}