1

I'm trying to change this Python code into C++, but unwanted zeros are keep appearing when I compile. Why is this happening, and how could I fix this issue?

p = [0.2, 0.2, 0.2, 0.2, 0.2]
world = ['green', 'red', 'red', 'green', 'green']
measurements = ['red', 'green']
motions = [1,1]
pHit = 0.6
pMiss = 0.2
pExact = 0.8
pOvershoot = 0.1
pUndershoot = 0.1

def sense(p, Z):
    q=[]
    for i in range(len(p)):
        hit = (Z == world[i])
        q.append(p[i] * (hit * pHit + (1-hit) * pMiss))
    s = sum(q)
    for i in range(len(q)):
        q[i] = q[i] / s
    return q

def move(p, U):
    q = []
    for i in range(len(p)):
        s = pExact * p[(i-U) % len(p)]
        s = s + pOvershoot * p[(i-U-1) % len(p)]
        s = s + pUndershoot * p[(i-U+1) % len(p)]
        q.append(s)
    return q

for k in range(len(measurements)):
    p = sense(p, measurements[k])
    p = move(p, motions[k])

print p

and here are my C++ implementation codes:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

vector<float> p (5);
vector<string> world (5);
vector<string> measurements (2);
vector<int> motions (2);
float pHit;
float pMiss;
float pExact;
float pOvershoot;
float pUndershoot;
vector<float> sense(vector<float> p, string Z);
vector<float> move(vector<float> p, int U);

int main(){
    vector<float> p (5, 0.2);

    world.push_back("green");
    world.push_back("red");
    world.push_back("red");
    world.push_back("green");
    world.push_back("green");

    measurements.push_back("red");
    measurements.push_back("green");

    pHit = 0.6;
    pMiss = 0.2;
    pExact = 0.8;
    pOvershoot = 0.1;
    pUndershoot = 0.1;

    vector<int> motions (2, 1);

    for(int i=0; i<measurements.size(); i++){
        p = sense(p, measurements[i]);
        p = move(p, motions[i]);
    }

    for(int i=0; i<p.size(); i++){
        cout << p[i] << " ";
    }

    return 0;
}

vector<float> sense(vector<float> p, string Z){
    vector<float> q (p.size());
    for(int i=0; i<p.size(); i++){
        bool hit = (Z == world[i]);
        q.push_back(p[i] * (hit * pHit + (1-hit) * pMiss));
    }

    float s = 0.0;
    for(int i=0; i<q.size(); i++){
        s += q[i];
    }

    for(int i=0; i<q.size(); i++){
        q[i] /= s;
    }

    return q;
}

vector<float> move(vector<float> p, int U){
    vector<float> q (p.size());
    for(int i=0; i<p.size(); i++){
        float s = pExact * p[(i-U) % p.size()];
        s = s + pOvershoot * p[(i-U-1) % p.size()];
        s = s + pUndershoot * p[(i-U+1) % p.size()];
        q.push_back(s);
    }
    return q;
}

*desired output: [0.21157894736842103, 0.1515789473684211, 0.08105263157894739, 0.16842105263157897, 0.3873684210526316]

*my output: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000205128 0.00494872 0.0406154 0.119872 0.054359 0.00994872 0.00166667 0.0108205 0.0657692 0.190641 0.243051 0.211974 0.0435641 0.0025641 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Program ended with exit code: 0

  • You have a `std::vector p` in the global scope and locally in `main`. I don't know if that's the cause of the problem, but it should be addressed. – François Andrieux Oct 12 '17 at 18:57
  • Be aware that you are copying your vectors every time you pass them to a function. Consider changing your functions to take `const` references instead. – François Andrieux Oct 12 '17 at 18:58
  • One problem, repeated in couple of functions, is that you are using `vector q (p.size());` followed by `q.push_back(...)`. That keeps on increasing the size of the vector. You can use `vector q;` to remove that error. However, I was not able to follow your logic clearly to figure out how to get the desired values in the output. – R Sahu Oct 12 '17 at 19:10

2 Answers2

2

in Python sense:

def sense(p, Z):
    q=[]

you're declaring an empty list.

but in C++ sense:

vector<float> sense(vector<float> p, string Z){
    vector<float> q (p.size());

you're declaring a vector with a given size, then you're usng push_back on it. Which changes the size, and leaves zeroed values at the start.

Just do:

    vector<float> q;

then you could reserve memory with

q.reserve(p.size());

(reserve is not resize, it allocates internally but doesn't change .size()) so push_back wouldn't need so many reallocations.

Once you've fixed that you can apply exactly the same fix to your move function which has exactly the same issue.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 1
    Also same issue in `move`. OP might be better off learning to pass by reference instead, too. – AndyG Oct 12 '17 at 19:04
  • passing by reference isn't really required with modern compilers and _copy elision_. edited with `move` fix. – Jean-François Fabre Oct 12 '17 at 19:05
  • My old reflexes tend to pass the inputs as constant references (cannot hurt, yes). But return values are better off left as return values. At least we know that it's an output, not an input/output (and copy elision ensures that there's no copy from callee variable to caller variable, that wasn't the case a few years ago) – Jean-François Fabre Oct 12 '17 at 19:08
  • Revisting it, perhaps fine to leave input vector as a by-value and then call with `std::move(p)`. – AndyG Oct 12 '17 at 19:13
  • @AndyG yes, transfer of memory. I read about that but never really practized it. check there: seems automatic in C++ 11: https://stackoverflow.com/questions/22655059/why-it-is-ok-to-return-vector-from-function – Jean-François Fabre Oct 12 '17 at 19:14
0

With c++17 you can make the code look a lot like the python counterpart:

#include <initializer_list>
#include <vector>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>

using namespace std::literals;

auto p = std::vector{0.2, 0.2, 0.2, 0.2, 0.2};
auto world = std::vector{"green"s, "red"s, "red"s, "green"s, "green"s};
auto measurements = std::vector{"red"s, "green"s};
auto motions = std::vector{1,1};
auto pHit = 0.6;
auto pMiss = 0.2;
auto pExact = 0.8;
auto pOvershoot = 0.1;
auto pUndershoot = 0.1;

auto sum = [](auto&& cont)
{
    using value_type = std::decay_t<decltype(*std::begin(cont))>;
    return std::accumulate(std::begin(cont), std::end(cont),
                           value_type(0), std::plus<>());
};

auto divide_all = [](auto&& container, auto&& divisor)
{
    for(auto&& val : container)
        val /= divisor;
};

auto sense = [](auto p, auto && Z)
{
    for(auto&& val : p)
    {
        auto i = std::distance(&p[0], &val); 
        auto hit = double(Z == world[i]);
        val *= (hit * pHit + (1-hit) * pMiss);
    }
    divide_all(p, sum(p));
    return p;
};

auto move = [](auto p, auto&& U)
{
    auto size = std::size(p);
    for(std::size_t i = 0 ; i < size ; ++i)
    {
        auto s = pExact * p[(i-U) % size];
        s = s + pOvershoot * p[(i-U-1) % size];
        s = s + pUndershoot * p[(i-U+1) % size];
        p[i] = s;
    }
    return p;
};

template<class Container>
void print(Container&& cont)
{
    std::cout << "[";
    const char* sep = " ";
    for (auto&& x : cont) {
        std::cout << sep << x;
        sep = ", ";
    }
    std::cout << " ]" << std::endl;
}

int main()
{

    for(std::size_t k = 0 ; k < std::size(measurements) ; ++k)
    {
        p = move(sense(p, measurements[k]), motions[k]);
    }
    std::cout << __TIMESTAMP__ << std::endl;
    print(p);
}

Although I'm getting slightly different results. I may have missed something in translation:

Thu Oct 12 21:37:26 2017
[ 0.231391, 0.217253, 0.207143, 0.216875, 0.223073 ]

http://coliru.stacked-crooked.com/a/f973d6c5eab3c746

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142