Element-wise multiplication in 2D vectors in C++11 - c++11

I am trying to do element-wise multiplication (.*) between two 2D vectors in C++11 using the code below but I am getting the errors as Error C2664 'int std::multiplies::operator ()(const _Ty &,const _Ty &) const' : cannot convert argument 1 from 'std::vector>' to 'const int &' I could not figure out what the actual problem is?
The code I used is as follows
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
int main()
{
std::vector<std::vector<int32_t>> Route = { { 1,2 },{ 3,4 } };
std::vector<std::vector<int32_t>> Spectrum = { { 2,2 },{ 3,3 } };
std::vector<std::vector<int32_t>> score;
//and do element-wise multiplication of Spectrum and Route i.e. Spectrum .* Route
std::transform(Spectrum.begin() + 1, Spectrum.end(), Route.begin() + 1, std::back_inserter(score), std::multiplies<int32_t>());
std::vector< std::vector<int32_t> >::iterator row;
std::vector<int32_t>::iterator col;
for (row = score.begin(); row != score.end(); row++) {
for (col = row->begin() + 1; col != row->end(); col++) {
std::cout << *col << std::endl;
}
}
}

The elements of Route and Spectrum vectors are instances of std::vector<int32_t>. Your transform calls iterate over the mentioned vectors. Instead of a vector, std::multiplies<int32_t> expects the arguments to be integers. The error message tells you that there is no way to convert from a vector into an integer.
You could instead iterate over the "top" vectors, and transform each subvector into a subvector of the result "top" vector.

Related

Get item closest to a value in a std::vector of doubles

Is there an elegant way in C++ 11 to get the item from a std::vector of doubles which is closest to a certain value?
Code:
#include <iostream>
#include <vector>
double GetClosest(const std::vector<double>& vec, double value) {
// How to get the item closest to "value" from the items in vec. Vec is assumed to be sorted.
}
int main() {
std::vector<double> my_doubles_vec;
my_doubles_vec.push_back(101480.76915103197);
my_doubles_vec.push_back(101480.85708367825);
my_doubles_vec.push_back(101480.93293087184);
my_doubles_vec.push_back(101481.0027936101);
my_doubles_vec.push_back(101481.5625);
my_doubles_vec.push_back(101481.5626);
std::cout.precision(17);
std::cout << GetClosest(my_doubles_vec, 101480.76915103201) << std::endl; // Should output "101480.76915103197"
std::cout << GetClosest(my_doubles_vec, 101480.93293086279) << std::endl; // Should output "101480.93293087184"
std::cout << GetClosest(my_doubles_vec, 101481.5625) << std::endl; // Should output "101481.5625"
return 0;
}
Since its a std::vector of doubles, I think precision comes into play? Or can the logic be made in such a way that one doesn't need to bother about precision?
You could use std::partition_point, std::lower_bound or std::upper_bound on the sorted range.
Example:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if(vec.empty()) throw std::runtime_error("no elements");
// partition_point is the most generic of the three:
auto it = std::partition_point(vec.begin(), vec.end(), [value](double v) {
return v < value;
});
// or auto it = std::lower_bound(vec.begin(), vec.end(), value);
// or auto it = std::upper_bound(vec.begin(), vec.end(), value);
if(it == vec.end()) --it; // value larger than the largest in the vector
else if( it != vec.begin()) { // value not less than first
// check which one of the two around the partition point that is closest
if(std::abs(*std::prev(it) - value) < std::abs(*it - value)) --it;
}
return *it;
}
Since the vector is sorted, you could try something like this:
#include <algorithm>
#include <cmath>
#include <stdexcept>
double GetClosest(const std::vector<double>& vec, double value) {
if (vec.empty()) throw std::invalid_argument("vector cant be empty");
if (vec.size() == 1) return vec[0];
auto iter = std::find_if(vec.begin(), vec.end(),
[=](double d){ return d >= value; }
);
if (iter == vec.begin()) return vec.front();
if (iter == vec.end()) return vec.back();
if (std::abs(value - *(iter-1)) < std::abs(value - *iter)) --iter;
return *iter;
}

Boost Geometry: segments intersection not yet implemented?

I am trying a simple test: compute the intersection of 2 segments with Boost Geometry. It does not compile. I also tried with some variations (int points instead of float points, 2D instead of 3D) with no improvement.
Is it really possible that boost doesn't implement segment intersection ? Or what did I do wrong ? Missing some hpp ? Confusion between algorithms "intersects" & "intersection" ?
The code is very basic:
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
typedef boost::geometry::model::point<float, 3, boost::geometry::cs::cartesian> testPoint;
typedef boost::geometry::model::segment<testPoint> testSegment;
testSegment s1(
testPoint(-1.f, 0.f, 0.f),
testPoint(1.f, 0.f, 0.f)
);
testSegment s2(
testPoint(0.f, -1.f, 0.f),
testPoint(0.f, 1.f, 0.f)
);
std::vector<testPoint> output;
bool intersectionExists = boost::geometry::intersects(s1, s2, output);
But I got the following errors at compile time by Visual:
- Error C2039 'apply' n'est pas membre de 'boost::geometry::dispatch::disjoint<Geometry1,Geometry2,3,boost::geometry::segment_tag,boost::geometry::segment_tag,false>' CDCadwork C:\Program Files\Boost\boost_1_75_0\boost\geometry\algorithms\detail\disjoint\interface.hpp 54
- Error C2338 This operation is not or not yet implemented. CDCadwork C:\Program Files\Boost\boost_1_75_0\boost\geometry\algorithms\not_implemented.hpp 47
There are indeed two problems:
you're intersecting 3D geometries. That's not implemented
Instead you can do the same operation on a projection.
you're passing an "output" geometry to intersects (which indeed only returns the true/false value as your chosen name intersectionExists suggested). In the presence of a third parameter, it would be used as a Strategy - a concept for which output obviously doesn't satisfy.
Note intersection always returns true: What does boost::geometry::intersection return - although that's not part of the documented interface
Since your geometries are trivially projected onto 2d plane Z=0:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgm = bg::model;
using Point = bgm::point<float, 2, bg::cs::cartesian>;
using Segment = bgm::segment<Point>;
int main() {
Segment s1{{-1, 0}, {1, 0}};
Segment s2{{0, -1}, {0, 1}};
bool exists = bg::intersects(s1, s2);
std::vector<Point> output;
/*bool alwaysTrue = */ bg::intersection(s1, s2, output);
std::cout << bg::wkt(s1) << "\n";
std::cout << bg::wkt(s2) << "\n";
for (auto& p : output) {
std::cout << bg::wkt(p) << "\n";
}
return exists? 0:1;
}
Prints
LINESTRING(-1 0,1 0)
LINESTRING(0 -1,0 1)
POINT(0 0)

bad_function_call when using lambda function on boost:heap

I want to create a heap data structure to be able to update the value .
but my simple code below throw an exception. why it gives the following:
109 : 3 terminate called after throwing an instance of 'std::bad_function_call' what(): bad_function_call
#include <set>
#include <algorithm>
#include <functional>
#include <boost/heap/fibonacci_heap.hpp>
int main() {
// Creating & Initializing a map of String & Ints
std::map<int, vector<int> > mapOfWordCount = { { 1000, {0,1,10,8} }, { 10001, {1,5,99} }, { 1008, {7,4,1} } , { 109, {1,5,3} }};
// Declaring the type of Predicate that accepts 2 pairs and return a bool
typedef std::function<bool(std::pair<int, vector<int> > v1, std::pair<int, vector<int> > v2)> Comparator;
// Defining a lambda function to compare two pairs. It will compare two pairs using second field
Comparator compFunctor =
[](std::pair<int, vector<int> > elem1 ,std::pair<int, vector<int> > elem2)
{
return elem1.second.size() > elem2.second.size();
};
boost::heap::fibonacci_heap <std::pair<int, vector<int> >, boost::heap::compare<Comparator> > pq;
typedef boost::heap::fibonacci_heap< std::pair<int, vector<int> >, boost::heap::compare<Comparator> >::handle_type handle_t;
handle_t* tab_handle = new handle_t [mapOfWordCount.size()];
unsigned iter(0);
for( auto& element : mapOfWordCount) {
tab_handle[iter++]=pq.push(element);
std::cout << element.first << " : " << element.second.size() << std::endl;
}
}
std::bad_function_call exception is caused (in this case) when calling a std::function that is empty.
I have made this work by making Comparator a functor.
struct Comparator
{
bool operator()(std::pair<int, std::vector<int> > elem1, std::pair<int, std::vector<int> > elem2) const
{
return elem1.second.size() > elem2.second.size();
}
};
This can then be used in the declarations of pq and handle_t.
Output:
109 : 3
1000 : 4
1008 : 3
10001 : 3
See demo here.
You can figure out how to make it work with a lambda.
Hint: It involves using the lambda compFunctor as an argument for construction.

How does std::distance() work?

I am very much new to C++11 and learning about the STL Libraries. I have written a code which is like this,
#include <bits/stdc++.h>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
void Print( const vector<int> &arrays )
{
for ( int x : arrays ) cout << x << ' ';
}
int main() {
int citys, cityPairs, fv, lv, w;
vector <int> fvarr;
vector <int> lvarr;
vector <int> warr;
vector <int> warr_temp;
vector <int> disjoint_pairs;
scanf("%d%d", &citys, &cityPairs);
for(int nr = 0; nr < cityPairs; nr++){
scanf("%d%d%d", &fv, &lv, &w);
fvarr.push_back(fv);
lvarr.push_back(lv);
warr.push_back(w);
warr_temp = warr;
}
for (int j = 0; j < citys; j++){
auto result = min_element(begin(warr_temp), end(warr_temp));
auto pos_temp = distance(begin(warr_temp), result);
cout << pos_temp;
auto pos = distance(begin(warr), result);
cout << pos;
disjoint_pairs.push_back(fvarr[pos]);
disjoint_pairs.push_back(lvarr[pos]);
warr_temp.erase(warr_temp.begin() + pos_temp);
}
// Print(disjoint_pairs);
}
What i am doing in this code is i am taking 3 vectors and 1 vector to copy the last one warr_temp = warr;. Then i am checking the minimum value in vectorwarr_temp and storing it's index in pos_temp, next i am storing that min value's index from vector warr into pos.
Now the problem is the first cout which is pos_temp giving me correct values but the second one which is pos giving me the output something like this,
-61-62-63-64
why is this happening? what are these numbers? are they pointers? I know that distance is a template so what is the right way to implement this?
If anyone can clear my doubts that would be very helpfull.
Sorry if stupid question!!!
The root cause of the problem is auto pos = distance(begin(warr), result); line. It gives unpredictable results because result and begin(warr) belong to different vectors.
result is iterator pointing to warr_temp element, it cannot be mixed with iterators pointing to warr elements like begin(warr).
To get element position in warr vector use std::find(begin(warr), end(warr), *result) instead:
auto warr_res = std::find(begin(warr), end(warr), *result);
auto pos = distance(begin(warr), warr_res);

Eigen boolean matrix plus

I would like to do the boolean matrix plus. How could I do it in Eigen?
My following example only gives a scalar +.
#include "Eigen/Dense"
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
Eigen::Matrix<bool, 4, 4> m;
m << 0,1,1,1,
1,0,1,0,
1,1,0,0,
1,1,1,0;
cout << m + m; //should be logical_and here
}
How could I use the logical_and here?
Eigen does not seem to provide specific functions to work on boolean matrices. However you can use the fact that booleans are converted to 0 (false) and 1 (true) reliably (see bool to int conversion). Noting that 0=0*0=0*1=1*0 and 1*1=1 it is obvious that multiplication of the booleans as integers is the same (up to type) as logical and. Therefore the following should work:
#include "Eigen/Dense"
#include <iostream>
using namespace std;
using namespace Eigen;
int main()
{
Eigen::Matrix<bool, 4, 4> m;
m << 0,1,1,1,
1,0,1,0,
1,1,0,0,
1,1,1,0;
Eigen::Matrix<bool, 4, 4> result = m.cwiseProduct(m);
cout << result;
}

Resources