efficient loop of a map within a map c++ - loops

I am attempting to find an efficient loop over a map data structure.
The map structure maps the following integers:
1 2, 2 3, 3 1, 4 1, 4 5, 5 3, 5 6, 5 7, 5 8, 6 4, 7 6, 8 9, 9 10
The resulting map looks as follows:
1| 2
2| 3
3| 1
4| 1 5
5| 3 6 7 8
6| 4
7| 6
8| 9
9| 10
Start : 4
Result :
1(1) 2(2) 5(1) 3(2) 6(2) 7(2) 8(2)
Can anybody suggest how to efficiently loop (possibly recursive method) so that, given a start of say 4, the result would be
1(1), 2(2), 5(1), 3(2), 6(2), 7(2), 8(2), 9(3), 10(4)
So the idea is to use each inner key, as an outer key, starting with a given outer key. With outer 4 for example, the inner keys are 5 and 1. So use 5 and 1 as outer keys to obtain inner keys (3 6 7 8) and (2), the process should continue mapping the inner keys to outer keys. A running total should be kept per "jump". So it probably resolves to a recursive problem rather than a loop.
The process should stop if either you reach the starting point, 4 in the above scenario, or there are no more inner keys, for example, 10 has no mapping.
The loop starting at line 44, only performs the above, up to two levels, which is inadequate.
#include <iostream>
#include <map>
#include <sstream>
int digit_count(int number) {
int digits = 0;
if (number < 0) digits = 1; // remove this line if '-' counts as a digit
while (number) {
number /= 10;
digits++;
}
return digits;
}
int main() {
int v1, v2;
std::map< int, std::map< int, int> > m;
std::istringstream stm {"1 2 2 3 3 1 4 1 4 5 5 3 5 6 5 7 5 8 6 4 7 6 8 9 9 10"};
while (stm >> v1 >> v2) {
m[v1];
m[v1][v2] = 1;
}
std::cout << "Map layout " << "\n";
std::string ss = "";
int dc = digit_count(m.rbegin()->first); // equals max number
for (const auto & p : m) {
std::cout << p.first << ss.append(" ", (dc - digit_count(p.first))) << "| ";
for (const auto & val : p.second)
std::cout << val.first << " ";
ss = "";
std::cout << "\n";
}
int start {4};
std::cout << "\nStart : " << start << "\n";
std::cout << "Result : " << "\n";
// efficient loop
for (const auto & e : m[start]) {
std::cout << e.first << "(" << e.second << ") ";
for (const auto & x : m[e.first])
std::cout << x.first << "(" << (e.second + x.second) << ") ";
}
std::cout << "\n";
return 0;
}
Any help would be much appreciated.

Took me a while, but I've answered my own question, and thought I'd update the post. The only way I could think of finding a solution was to create a recursive function. I don't think it is possible to achieve with loops. I didn't select Dijkstra's algorithm, since there are no weights to consider and the results of this recursive function serve as input to a red black tree where each node of the red black tree holds a hash table (unordered_map).
So the result of the query on the combined red black tree/hash table is Log n, to find the shortest path. The problem is providing the input, as you can see from below, is recursive and inefficient.
#include <iostream>
#include <map>
#include <sstream>
#include <set>
#include <vector>
#include <fstream>
int digit_count(int number) {
int digits = 0;
if (number < 0) digits = 1; // remove this line if '-' counts as a digit
while (number) {
number /= 10;
digits++;
}
return digits;
}
struct vertex {
int point;
mutable bool visited{false};
int id;
};
void clear_visited(std::map<int, vertex>& verteces) {
for (const auto & e : verteces) {
e.second.visited = false;
}
}
void traverse_graph(std::map<int, vertex>& verteces, const vertex & v, std::map< vertex, std::map< vertex, int> >& graph, int& counter) {
if (verteces[v.id].visited)
return;
++counter;
verteces[v.id].visited = true;
std::cout << v.point << "(" << counter << ") ";
for (const auto & e : graph[v]) {
traverse_graph(verteces, e.first, graph, counter);
}
}
void start_traverse_graph(std::map<int, vertex>& verteces, const vertex & v, std::map< vertex, std::map< vertex, int> >& graph) {
if (verteces[v.id].visited)
return;
verteces[v.id].visited = true;
for (const auto & e : graph[v]) {
int counter{0};
clear_visited(verteces);
verteces[v.id].visited = true;
traverse_graph(verteces, e.first, graph, counter);
}
}
bool operator<(vertex a, vertex b) { return a.point < b.point; }
int main (int argc, char *argv[]) {
vertex v1, v2;
std::map< vertex, std::map< vertex, int> > m;
std::istringstream stm {"1 2 2 3 3 1 4 1 4 5 5 3 5 6 5 7 5 8 6 4 7 6 8 9 9 10"};
std::set<vertex> vertecesSet;
std::map<int, vertex> verteces;
while (stm >> v1.point >> v2.point) {
v1.id = v1.point;
v2.id = v2.point;
m[v1];
m[v1][v2] = 1;
vertecesSet.insert({v1.point, false, v1.point});
vertecesSet.insert({v2.point, false, v2.point});
}
for(auto & el : vertecesSet)
verteces[el.id] = std::move(el); // dont need set objects anymore so move them
std::cout << "Map layout " << "\n";
std::string ss = "";
int dc = digit_count(m.rbegin()->first.point); // equals max number
for (const auto & p : m) {
std::cout << p.first.point << ss.append(" ", (dc - digit_count(p.first.point))) << "| ";
for (const auto & val : p.second)
std::cout << val.first.point << " ";
ss = "";
std::cout << "\n";
}
vertex start {5,false,5};
std::cout << "\nStart : " << start.point << "\n";
start_traverse_graph( verteces, start, m);
std::cout << "\n";
return 0;
}

Related

Most efficient way to find an intersection between two sets of numbers encoded with bitwise operations

Given two sets of numbers encoded with bitwise operations (using 6 bits for number):
a = {12,20,21,24,31}
b = {13,18,24,28,35}
Intersection -> a ∩ b = {24}
unsigned int a = 0;
a |= (12 | 20 << 6 | 21 << 12 | 24 << 18 | 31 << 24);
unsigned int b = 0;
b |= (13 | 18 << 6 | 24 << 12 | 28 << 18 | 35 << 24);
What is the fastest way to find out, if there is at least one number in common between the sets?
This is just an example, but you can have common numbers in any position.
#include <stdint.h>
#include <limits.h>
typedef unsigned int SetType;
#define FieldWidth 6 // Number of bits per field.
#define NumberOfFields (sizeof(SetType) * CHAR_BIT / FieldWidth)
// Return non-zero iff some element is in both a and b.
int IsIntersectionNonEmpty(SetType a, SetType b)
{
// Create masks with a bit set for each element an input set.
uint64_t A = 0, B = 0;
for (int i = 0; i < NumberOfFields; ++i)
{
A |= UINT64_C(1) << (a >> i*6 & 0x3f);
B |= UINT64_C(1) << (b >> i*6 & 0x3f);
/* ">> i*6" moves field i to the low bits.
"& 0x3f" isolates that six-bit field.
"UINT64_C(1) << …" generates a 1 bit in that position.
*/
}
/* Bitwise AND A and B to see if they have a bit in common, then
convert that to 1 or 0.
*/
return !! (A & B);
}
Maybe not the absolute fastest, but I'd XOR a with b, and see if the result has any six-bit all-zeros pattern in any of your 5 positions. Then shift one of them by 6 bits and repeat up to 4 more times if needed.
Here's a somewhat faster version of my solution above; instead of shifting left and right, just rotate:
int leftRotate(unsigned int n, unsigned int d)
{
return (n << d)|(n >> (32 - d));
}
// Return non-zero iff some element is in both a and b.
int IsIntersectionNonEmpty(unsigned int a, unsigned int b)
{
for (int i = 0; i < 5; i++) {
unsigned int matches = leftRotate(a, i*6) ^ b;
for (int j = 0; j < 5; j++) {
unsigned int testval = 0x3f << j*6;
if (matches & testval == testval)
return 1; // success
}
}
return 0;
}
5 instructions in the outer loop, 3 in the inner * 5, so 20 total, times 5 loops, around 100 instructions total -- but as soon as it finds a match it returns. So if there are frequent matches it'll likely be faster than the #eric-postpischil version, but with no matches it'll be slower. On the other hand, his solution is likely auto-vectorizable with a smart compiler.
Well, thanks to everyone, but thank to the guy that posted the EL code, I do not know why he withdrew it.
Here we go, as fast as light:
#define EL(x) (UINT64_C(1) << (x))
unsigned int a = 0;
a |= (12 | 20 << 6 | 21 << 12 | 24 << 18 | 31 << 24);
unsigned int b = 0;
b |= (13 | 18 << 6 | 24 << 12 | 28 << 18 | 35 << 24);
unsigned int aa = EL(a & 0x00000003F) | EL((a & 0x000000FC0) >> 6) | EL((a & 0x3F000) >> 12) | EL((a & 0xFC0000) >> 18) | EL((a & 0x3F000000) >> 24);
unsigned int bb = EL(b & 0x00000003F) | EL((b & 0x000000FC0) >> 6) | EL((b & 0x3F000) >> 12) | EL((b & 0xFC0000) >> 18) | EL((b & 0x3F000000) >> 24);
anb = !! (aa & bb); // intersection

Build a new matrix made of some source matrix rows given a row index vector

I want to build a new matrix made of some source matrix rows given a vector of non consecutive indexes.
Namely, I'd like a row() function which take a list of indexes and returns the list of rows stored in a new matrix :
VectorXi v = VectorXi::LinSpaced( 4, 10, 13);
MatrixXi m = v.rowwise().replicate( 4 );
VectorXi r1 ( ( VectorXi(3) << 0, 3, 1 ).finished() );
// Here is some pseudo code to create the desired matrix N :
MatrixXi N = m.row(r1);
cout << "m = " << m << endl;
cout << "r1 = " << r1 << endl;
cout << "N = " << N << endl;
Desired output :
m =
10 10 10 10
11 11 11 11
12 12 12 12
13 13 13 13
r1 =
0
3
1
N =
10 10 10 10
13 13 13 13
11 11 11 11
Thanks a lot for helping.
Sylvain
With the development branch and (at least) C++11 enabled, you can write:
Eigen::MatrixXi N = m(r1,Eigen::all);
This is similar to the Matlab syntax:
N = m(r1, :);
You can also pass {x,...}-lists directly, or anything that behaves like an std::vector<int> (must provide a size() function and an operator[] and return an integral type), e.g.:
std::vector<int> c2{{3,0}};
std::cout << "m({2,1},c2) = \n" << m({2,1}, c2) << '\n';
These expressions are writable (assuming m itself is writable):
m({2,1}, c2) = Eigen::Matrix2i{{1,2},{3,4}};
std::cout << m << '\n';
Godbolt demo: https://godbolt.org/z/cjacOY

Finding closest power of 2 for any float at compile time

I need to scale all floats to [-1,1] range by dividing with closest higher power of 2. The code needs to be Q0.31 fixed-point, so no floats.
For example, 10.75 would be divided by 16, 20.91 by 32, 1000.17 by 1024, etc, all the way to 2^31.
I'd need the scaling to be done at compilation time.
For example:
#define PARAMETER1 10.0f // this could be changed in various builds
#define PARAMETER1_SCALE ( CALC_SCALE(PARAMETER1) )
#define float_to_fixed(x) ( (int)( (float)(x)*(float)0x80000000 ) )
int main()
{
int par1 = float_to_fixed( PARAMETER1/PARAMETER1_SCALE );
// use par1 here
// ...
// then descale using PARAMETER1_SCALE again
}
Is there a C macro CALC_SCALE which would calculate this?
How about this:
#include <math.h>
#define collapse(value) (value < 0 ? value / pow(2, ceil(log2(value * -1))) : value / pow(2, ceil(log2(value))))
int main() {
cout << collapse(10.75) << endl;
cout << collapse(20.91) << endl;
cout << collapse(-1) << endl;
cout << collapse(-2.5) << endl;
cout << collapse(5.7) << endl;
}
Output is:
0.671875
0.653438
-1
-0.625
0.7125
This does it:
#define CALC_SCALE ( x > 16 ? 32 : x > 8 ? 16 : x > 4 ? 8 : x > 2 ? 4 : x > 1 ? 2 : 1 )
At compile time:
int x = CALC_SCALE( 13 );
is compiled to:
int x = 16;
This can easily be changed to support floats.

Finding the max and min values in array of five times

I'm supposed to find the minimum and maximum values in the array, but I can't seem to figure out why the answers aren't correct. For example if I entered "1 2 3 4 5" as my five times, it told me 1 was my maximum and 0 was the minimum. For some reason, whatever the first number is, it calls it the max and it also assigns 0 as the min.
#include <iostream>
using namespace std;
int find_distance(int j); //a function that returns a distance based on the choice j
int intmax, intmin;
int main( )
{
int i =0;
int distance[6];
double data[6][5];
for(int j = 0; j < 6; j++)
{
distance[j] = find_distance(j);
cout << "\nEnter 5 of your best running times for \n " << distance[j] << " m \n";
for(int i = 0; i < 5; i++)
{
cout << "Enter a time \n"; cin >> data[j][i];
}
}
cout << "Here is your best 5 times: ";
for(int j = 0; j < 6; j++)
{
cout << "\nDistance : " << distance[j] << " m \n";
for(int i = 0; i < 5; i++)
{
system ("pause");
cout << data[j][i] << "\t"; } cout << endl;
if (data[j][i] < intmin)
intmin = data[j][i];
else if (data[j][i] > intmax)
intmax = data[j][i];
cout << "The maximum time is: " << intmax << endl;
cout << "The minimum time is: "<< intmin << endl;
}
return 0;
}
int find_distance(int j)
{
switch (j)
{ case 0: // 100 meter
return 100;
break;
case 1: // 150 meter
return 150;
break;
case 2: // 200 meter
return 200;
break;
case 3: // 400 meter
return 400;
break;
case 4: // 500 meter
return 800;
break;
default: // 1600 meter
return 1600;
}
}
The minimum value is 0 because when you initialize intmin, it is set to 0 by default. You never enter a negative time, so in your comparisons it is always less than the compared value.
The maximum value is off because your for loop ends in an odd place and the comparison code is improperly executed. Change this code:
for(int j = 0; j < 6; j++)
{
cout << "\nDistance : " << distance[j] << " m \n";
for(int i = 0; i < 5; i++)
{
system ("pause");
cout << data[j][i] << "\t"; } cout << endl; //why does the for loop end here?
if (data[j][i] < intmin)
intmin = data[j][i];
else if (data[j][i] > intmax)
intmax = data[j][i];
//move the end bracket to this line and it should work
cout << "The maximum time is: " << intmax << endl;
cout << "The minimum time is: "<< intmin << endl;
}
Just to practice:
#include <iostream>
#include <algorithm>
#include <string>
#include <boost/regex.hpp>
int main () {
using namespace std;
string input;
boost::regex re("-?\\d+");
vector<int> integers;
cout << "enter sequence of integers: ";
getline(cin, input);
boost::sregex_token_iterator begin(input.begin(), input.end(), re, 0);
boost::sregex_token_iterator end;
while (begin != end) {
integers.push_back(stoi(*begin));
++begin;
}
if (integers.size()) {
auto pair = minmax_element(integers.begin(), integers.end());
cout << "min: " << *pair.first << " max: " << *pair.second << endl;
} else {
cout << "you didn't enter any integers." << endl;
}
return 0;
}
This is how to compile and to run:
$ g++ -o lab_2 -std=c++11 -lboost_regex lab_2.cpp
$ ./lab_2
$ enter sequence of integers: -10 34 75 101 2 43
$ min: -10 max: 101
Requires boost installed because STL regular expressions aren't functional yet.

Generalized Reduced Gradient algorithm in C

I am working on some science project and I need the C language implementation of Generalized Reduced Gradient algorithm for non-linear optimization. Is there any library or just a piece of code for that? Or, please suggest any other solution for non-linear multivariable problems. I am looking to build an optimization model using 4 independent variables and 2 constants: the model is nonlinear.
I have checked with Microsoft Excel's Solver using generalized reduced gradient (GRG) is solving this model perfectly, but I need this in the C language for my simulations.
Here is my excel solution:
http://speedy.sh/SEdZj/eof-cs-rest.xlsm
I have used Microsoft Excel Solver with GRG algorithm to search for a minimum value of SS and the output are values of Const_a and Const_b.
CONOPT as distributed by GAMS seems an established implementation of GRG, but is not free (although demo may be sufficient for you).
Alglib has an implementation of non-linear Levenberg-Marquardt algorithm here and is GPL / commercial licensed.
Sample code using alglib below:
/*
* Simple optimiser example
*
* nl_opt.cpp
*
* Compile with eg 'g++ -I../tools/alglib/src ../tools/alglib/src/ap.cpp ../tools/alglib/src/alglibinternal.cpp ../tools/alglib/src/linalg.cpp ../tools/alglib/src/alglibmisc.cpp ../tools/alglib/src/solvers.cpp ../tools/alglib/src/optimization.cpp nl_opt.cpp -o opt'
*
*/
#include "stdafx.h"
#include <iostream>
#include <cmath>
#include "optimization.h"
using namespace std;
double fn(double a1, double a2, double a3, double x, double A, double B)
{
return A * exp(-x*(a1*B*B+a2*B+a3));
}
struct problem
{
double *m_a1s;
double *m_a2s;
double *m_a3s;
double *m_xs;
double *m_ys;
int m_n;
problem(double *a1s, double *a2s, double *a3s, double *xs, double *ys, int n)
: m_a1s(a1s), m_a2s(a2s), m_a3s(a3s), m_xs(xs), m_ys(ys), m_n(n)
{
}
void fn_vec(const alglib::real_1d_array &c_var, alglib::real_1d_array &fi, void *ptr)
{
double sum = 0.0;
for(int i = 0; i < m_n; ++i)
{
double yhat = fn(m_a1s[i], m_a2s[i], m_a3s[i], m_xs[i], c_var[0], c_var[1]);
double err_sq = (m_ys[i] - yhat) * (m_ys[i] - yhat);
sum += err_sq;
}
fi[0] = sum;
}
};
problem *g_p;
void fn_vec(const alglib::real_1d_array &c_var, alglib::real_1d_array &fi, void *ptr)
{
g_p->fn_vec(c_var, fi, ptr);
}
int main()
{
cout << "Testing non-linear optimizer..." << endl;
int n = 5;
double a1s[] = {2.42, 4.78, 7.25, 9.55, 11.54};
double a2s[] = {4.25, 5.27, 6.33, 7.32, 8.18};
double a3s[] = {3.94, 4.05, 4.17, 4.28, 4.37};
double xs[] = {0.024, 0.036, 0.048, 0.06, 0.072};
double ys[] = {80, 70, 50, 40, 45};
double initial[] = {150, 1.75};
double ss_init = 0.0;
cout << "Initial problem:" << endl;
for(int i = 0; i < n; ++i)
{
double yhat = fn(a1s[i], a2s[i], a3s[i], xs[i], initial[0], initial[1]);
double err_sq = (ys[i] - yhat) * (ys[i] - yhat);
ss_init += err_sq;
cout << a1s[i] << "\t" << a2s[i] << "\t" << a3s[i] << "\t"
<< xs[i] << "\t" << ys[i] << "\t" << yhat << "\t" << err_sq << endl;
}
cout << "Error: " << ss_init << endl;
// create problem
problem p(a1s, a2s, a3s, xs, ys, n);
g_p = &p;
// setup solver
alglib::real_1d_array x = "[150.0, 1.75]";
double epsg = 0.00000001;
double epsf = 0;
double epsx = 0;
alglib::ae_int_t maxits = 0;
alglib::minlmstate state;
alglib::minlmreport report;
alglib::minlmcreatev(2, x, 0.0001, state);
alglib::minlmsetcond(state, epsg, epsf, epsx, maxits);
// optimize
alglib::minlmoptimize(state, fn_vec);
alglib::minlmresults(state, x, report);
cout << "Results:" << endl;
cout << report.terminationtype << endl;
cout << x.tostring(2).c_str() << endl;
double ss_end = 0.0;
for(int i = 0; i < n; ++i)
{
double yhat = fn(a1s[i], a2s[i], a3s[i], xs[i], x[0], x[1]);
double err_sq = (ys[i] - yhat) * (ys[i] - yhat);
ss_end += err_sq;
cout << a1s[i] << "\t" << a2s[i] << "\t" << a3s[i] << "\t"
<< xs[i] << "\t" << ys[i] << "\t" << yhat << "\t" << err_sq << endl;
}
cout << "Error: " << ss_end << endl;
return 0;
}
This gives sample output:
./opt
Testing non-linear optimizer...
Initial problem:
2.42 4.25 3.94 0.024 80 95.5553 241.968
4.78 5.27 4.05 0.036 70 54.9174 227.485
7.25 6.33 4.17 0.048 50 24.8537 632.338
9.55 7.32 4.28 0.06 40 9.3038 942.257
11.54 8.18 4.37 0.072 45 3.06714 1758.36
Error: 3802.41
Results:
2
[92.22,0.57]
2.42 4.25 3.94 0.024 80 77.6579 5.48528
4.78 5.27 4.05 0.036 70 67.599 5.76475
7.25 6.33 4.17 0.048 50 56.6216 43.8456
9.55 7.32 4.28 0.06 40 46.0026 36.0314
11.54 8.18 4.37 0.072 45 36.6279 70.0922
Error: 161.219

Resources