Elegant way to write multiple If statements - c++

I have the following Multiple 'if' statements.
Animals and Humans are two enums.
Var a, b;
int c, d, e = 0;
if (a == Humans ::Men) {
c = 1;
}
if (b == Animals ::Cat) {
d= 1;
e= 1;
}
if (b == Animals ::Dog) {
d = 1;
}
if (b == Animals ::Elephant) {
e = 1;
}
How can I write everything in one statement, so that the meaning is still the same.
Thanks in Advance.

You can set up your enum with specific values such that masking is possible. (Men, Cat, Dog, Element have exactly one, but unique, bit set). Bitwise enumerators with masking values are common.
Then you could write
if (b & Animals::d_applies){
d = 1;
}
where, at the very least, d_applies is Animals::Cat | Animals::Dog

Whenever possible, I find that some sort of tabulation based method is the most easily extendable. I'll demonstrate with std::map, but you can use other sorts of bookkeeping data structures. It's simply a matter of defining a mapping from the pairs of possible enumerations values to the triplets of values you intend to assign onto the variables:
using from_type = std::tuple<Humans, Animals>;
using to_type = std::tuple<int, int, int>;
std::map<from_type, to_type> value_getter {
{ from_type{Humans::Men, Animals::Cat}, to_type{0, 1, 1} },
// etc.
};
int c, d, e;
std::tie(c, d, e) = value_getter[from_type{a, b}];
Or, if you feel fancy and your compiler is up to supporting C++17 properly already, you can use the same map with structured bindings:
auto [c, d, e] = value_getter[from_type{a, b}];
So now initialization is part of the declaration, and is good wholesome C++.

You can arrange a container that contains pairs like "predicate, handler". Then you can iterate the container and call the handler if corresponding predicate do matches. std::for_each would be nice one-liner here after all setup code being done.
P.S. Not sure it's worth a bullet, however.

Related

Counting how many decision variables are equal

I'm a beginner user of Google OR-Tools, especially the CP-SAT. I'm using version 9.3, and I'm interested in the C++ version.
I'm modeling a problem where I need to count how many pairs of decision variables have the same (assigned) value. So, let's suppose I have a set of integer variables like this:
std::vector<IntVar> my_vars;
I also have a set of pairs like this:
std::vector<std::pair<size_t, size_t>> my_pairs;
Assume that all bounds are valid, size, etc, are valid. Now, I want to compute how many of these pairs have the same value. Using IBM Ilog Concert, I can do it very straightforward using:
// Using Ilog Concert technology.
IloIntVar count(env, 0, MY_UPPER_BOUND);
IloIntExpr expr_count(env);
for(const auto& [u, v] : my_pairs) {
expr_count += (my_vars[u] == my_vars[v]);
}
model.add(count == expr_count);
Here, count is a decision variable that holds how many pairs have the same value in a given solution. The expression is a sum of boolean values comparing the actual decision variable's values, not the variable objects themselves (i.e., is the object representing variable u is the same object representing variable v).
Using OR-Tools, the equality operator ==, compares whether the variable objects (or representation of them) are equal, not the decision variable values. So, the following fails by generating an empty expression:
// Using Google Or-Tools CP-SAT.
IntVar count = cp_model
.NewIntVar(Domain(0, my_pairs.size()))
.WithName("count");
LinearExpr expr_count;
for(const auto& [u, v] : my_pairs) {
expr_count += (my_vars[u] == my_vars[v]);
}
cp_model.AddEquality(count, expr_count);
Note that, according to Google OR-Tools code (here), we have that:
class IntVar {
//...
bool operator==(const IntVar& other) const {
return other.builder_ == builder_ && other.index_ == index_;
}
//...
};
i.e., comparing if the variables are the same, but not the value assigned to them. Therefore, we cannot compare decision variables directly using CP-SAT, and we need to recur to another method.
Obviously, I can change the model using some big-M notation and linearize such expressions. However, can I do count without to recur to "remodeling"? I.e., is there a construct I can use "more or less" easily so that I address such cases?
I must mention while I only depict one case here, I have quite a few counting variables of several sets like that. So, remodeling using big-M will be a big headache. I would prefer a simpler and straightforward approach like Ilog Concert.
(Update) Little extension
Now, I want do the same but comparing decision variables with scalars. For example:
std::vector<int> my_scalars;
for(size_t i = 0; i < my_scalars.size(); ++i) {
expr_count += (my_vars[i] == my_scalars[i]);
}
While this can be done using Ilog, it even did not compile on OR-Tools.
THanks,
Carlos
here is a tentative code:
IntVar count = model.NewIntVar(0, MY_UPPER_BOUND);
LinearExpr expr_count;
for(const auto& [u, v] : my_pairs) {
BoolVar is_equal = model.NewBoolVar();
model.AddEquality(my_vars[u], my_vars[v]).OnlyEnforceIf(is_equal);
model.AddNotEqual(my_vars[u], my_vars[v]).OnlyEnforceIf(is_equal.Not());
expr_count += is_equal;
}
model.AddEquality(expr_count, count);
With help of #sascha and #Laurent, my solution is this one:
vector<BoolVar> is_equal;
is_equal.reserve(my_pairs.size());
for(const auto& [u, v] : my_pairs) {
is_remainder_equal.push_back(cp_model.NewBoolVar());
cp_model
.AddEquality(my_vars[u], my_vars[v])
.OnlyEnforceIf(is_equal.back());
cp_model
.AddNotEqual(my_vars[u], my_vars[v])
.OnlyEnforceIf(Not(is_equal.back()));
}
cp_model.AddEquality(LinearExpr::Sum(is_equal), count);
It is the same as #Laurent in the very end, but I save the boolean vars for late use.
For scalars, it looks like I don't need to make a constant, just compare directly with the expression.
Thanks, #Laurent and #sascha. You guys were very helpful.

Is there any way to assign multiple variable at once with Dlang?

With using Ruby, we can do this.
s = "split by space"
A,B,C = s.split(" ").map(&:to_i)
With using D-lang, it's compile error.
string s = "split by space";
int A,B,C = s.split(" ").map!(x => x.to!int);
Jonathan is mostly right, but there is in fact a way to split a tuple into
its constituent parts, albeit more verbose than in Ruby, and without any handy
type inference:
import std.meta : AliasSeq;
import std.typecons : tuple;
auto foo() { return tuple(42, 29, "hello"); }
unittest {
int a, b;
string c;
AliasSeq!(a, b, c) = foo(); // Look ma, magic!
assert(a == 42);
assert(b == 29);
assert(c == "hello");
}
While there's no built-in way to do this with ranges like your example, it's
possible to implement in a library:
import std.meta : AliasSeq, Repeat;
import std.typecons : Tuple, tuple;
import std.algorithm : map;
import std.conv : to;
import std.string : split;
import std.range : isInputRange, ElementType;
unittest {
string s = "1 2 3";
int A,B,C;
AliasSeq!(A,B,C) = s.split(" ").map!(x => x.to!int).tuplify!3;
assert(A == 1);
assert(B == 2);
assert(C == 3);
}
auto tuplify(size_t n, R)(R r) if (isInputRange!R) {
Tuple!(Repeat!(n, ElementType!R)) result;
static foreach (i; 0..n) {
result[i] = r.front;
r.popFront();
}
assert(r.empty);
return result;
}
No, there is no way to do that. There has been talk off-and-on about possibly adding tuple support to the language such that you could something like
int a;
int b;
string c;
(a, b, c) = foo();
and maybe that will happen someday, but it's not possible right now. The closest would be using something like std.typecons.Tuple/tuple so that you can do something like
Tuple!(int, int, string) foo() { return tuple(42, 29, "hello"); }
Tuple!(int, int, string) result = foo();
or more likely
auto foo() { return tuple(42, 29, "hello"); }
auto result = foo();
but Tuple is ultimately just a struct, and you can't magically split it out at the other end. You have to access its members via indices such as result[0] or result[1], or if you declare Tuple with names - e.g. Tuple!(int, "x", int, "y", string, "str") - then you can access the members by name - e.g. result.x. So, Tuple/tuple allows you to return multiple values without explicitly declaring a struct type just for that, but it's still creating a struct type just for that, and while it allows you to easily pack values to return, it does not allow you to automatically unpack them on the other end. That would require compiler support of some kind that we don't have.
However, even if we had better tuple support in the language so that something like
(a, b, c) = foo();
worked, I doubt that what you're trying to do would work, since map specifically returns a range. So, it's an object with member functions, not a tuple of any kind to be split up. It just so happens to represent a list of values that can be extracted with the right set of function calls. And the number of values that it has is not known at compile time, so even if you assume that the compiler understands the range primitives well enough to get a list out of them for you, it can't guarantee at compile time that there are enough values to put into the variables you're trying to assign to, let alone that there are exactly that number of values. So, while it wouldn't be impossible to make something like that work (e.g. if it threw an Error at compile time if there weren't enough values in the range), I'd be surprised if that were implemented. D is a statically typed language and that would effectively be making a piece of it dynamic, so it would be pretty out-of-character for it to be in the language. Ruby is a dynamic language, so it's a very different beast.
Regardless, any improvements with tuples would be improvements to the language and would have to go through the DIP process and get approved, and nothing like that has happened yet.

C++ class design: dynamic typing alternative to template argument?

I would like to build a space-efficient modular arithmetic class. The idea is that the modulus M is an immutable attribute that gets fixed during instantiation, so if we have a large array (std::vector or another container) of values with the same M, M only needs to be stored once.
If M can be fixed at compile time, this can be done using templates:
template <typename num, num M> class Mod_template
{
private:
num V;
public:
Mod_template(num v=0)
{
if (M == 0)
V = v;
else
{
V = v % M;
if (V < 0)
V += M;
}
}
// ...
};
Mod_template<int, 5> m1(2); // 2 mod 5
However, in my application, we should be able to express M runtime. What I have looks like this:
template <typename num> class Mod
{
private:
const num M;
num V;
public:
Mod(num m, num v=0): M(abs(m))
{
if (M == 0)
V = v;
else
{
V = v % M;
if (V < 0)
V += M;
}
}
// ...
};
Mod<int> m2(5, 2); // 2 mod 5
Mod<int> m3(3); // 0 mod 3
This works, but a large vector of mod M values uses 2x the space it needs to.
I think the underlying conceptual problem is that Mod's of different moduli are syntactically of the same type even though they "should" be different types. For example, a statement like
m2 = m3;
should raise a runtime error "naturally" (in my version, it does so "manually": check is built into the copy constructor, as well as every binary operator I implement).
So, is there a way to implement some kind of dynamic typing so that the Mod object's type remembers the modulus? I'd really appreciate any idea how to solve this.
This is a recurring problem for me with various mathematical structures (e.g. storing many permutations on the same set, elements of the same group, etc.)
EDIT: as far as I understand,
templates are types parametrized by a class or literal.
what I want: a type parametrized by a const object (const num in this case, const Group& or const Group *const for groups, etc.).
Is this possible?
It will be difficult to do it in zero storage space if the class needs to know what M should be without any outside help. Likely the best you can do is store a pointer to a shared M, which may be a little better depending on how large num is. But it's not as good as free.
It will be easier to design if M is a passed-in value to all the functions that need it. Then you can do things like make a pool of objects that all share the same M (there are plenty of easy ways to design this; e.g. map<num, vector<num> >) and only store M once for the pool. The caller will need to know which pool the Mod object came from, but that's probably something it knows anyway.
It's hard to answer this question perfectly in isolation... knowing more about the calling code would definitely help you get better answers.

Lambda closure vs simple argument?

For lambda expressions, I don't quite get the usefulness of closures in C++11.
auto f = [] (int n, int m) { return n + m };
std::cout << f(2,2);
versus.
int n = 2;
auto f = [n] (int m) { return n + m };
std::cout << f(2);
This is a very basic and primitive example. I'm guessing that closures play an important part in other kinds of statements, but my C++ book doesn't clarify this (so far).
Why not include the closure as a parameter?
OK, a simple example, remove all the x's from a string
char x = 'x';
std::string s = "Text to remove all 'x's from";
s.erase(std::remove_if(s.begin(), s.end(), [x](char c) {return x == c;}), s.end());
Borrowed and modifed from http://en.cppreference.com/w/cpp/algorithm/remove
In this example, remove_if() only takes a single parameter, but I need two values for the comparison.
Closures are not always called immediately. They are objects which can be stored and called later when the data necessary to successfully execute the lambda function may no longer be in scope or easily accessible from the call site.
It's possible to to store any necessary data along with the closure but it's so much simpler for the closure to grab anything it needs when it's created and use it when it's eventually called. It provides a form of encapsulation.
This also decreases code coupling because if you were to store the data along with the code then the caller could only work with the specific objects you decided to store. Since a closure carries its own data along with it, it can work with any data it needs.
Here's an greatly oversimplified real-life example. I built a database server which needed to support fields with multiple values. The problem was that when results were displayed, it was important to highlight which values actually caused a record to match the search criteria. So, the query parser would spit out a predicate in the form of a closure which would indicate whether or not it was a matching value.
It looked something like this:
std::function< bool(int value) > parser::match_int(int search_val) {
return [=](int value) { value == search_val; };
}
That closure got stored in a collection. When it was time to render the record, I could easily determine which values needed to be highlighted. Keep in mind that the parser and any associated data is now gone:
void render_values(std::function< bool(int value) > pred, std::vector<int> values) {
for (int value : values) {
if (pred(value))
render_highlight(value);
else
render_normal(value);
}
}

C++ array operator overhead

I remember reading a while back some code that allowed the compiler to do some work and simplify an expression like this one:
// edit: yes the parameters where meant to be passed by reference
// and maintain constness sorry !
template< typename T >
std::vector<T> operator+( const std::vector<T>& a, const std::vector<T>& b )
{
assert( a.size() == b.size() );
std::vector<T> o; o.reserve( a.size() );
for( std::vector<T>::size_type i = 0; i < a.size(); ++i )
o[i] = a[i] + b[i];
return o;
}
// same for operator* but a[i] * b[i] instead
std::vector<double> a, b, c, d, e;
// do some initialization of the vectors
e = a * b + c * d
Where normally a new vector would be created and allocated for each operator instead the compiler would instead only create one copy and do all the operations onto it.
What is this technique?
As #Agnew mentioned very early, the technique you're describing is expression templates.
This is typically done with the mathematical concept of a vector1, not a std::vector.
The broad strokes are:
Don't have math operations on your vectors return the result. Instead, have them return a proxy object that represents the operation that eventually needs to be done. a * b could return a "multiplication proxy" object that just holds const references to the two vectors that should be multiplied.
Write math operations for these proxies too, allowing them to be chained together, so a * b + c * d becomes (TempMulProxy) + (TempMulProxy) becomes (TempAddProxy), all without doing any of the math or copying any vectors.
Write an assignment operator that takes your proxy object for the right-side object. This operator can see the entire expression a * b + c * d and do that operation efficiently on your vector, while knowing the destination. All without creating multiple temporary vector objects.
1 or matrix or quaternion, etc...*
I don't see a question here. However, my crystal ball tells me that you want to know the better method of two methods you came up with in order to perform component-wise arithmetic operations on vectors like a * b + c * d where a, b, c, d are vectors (std::vector<T>) having the same size:
For each operation to be done, loop over the elements, perform the calculation and return a resulting vector. Put these operations together in a formula on vectors.
For each element in the input vectors, calculate the whole expression and write it into one single final resulting vector.
There are two things to consider:
Performance: Here, the second option is ahead, since the processor will not allocate unnecessary temporary vectors.
Re-usability: Clearly, it's nice to implement algorithmic operations for vectors and re-use them by simply expressing your target formula on vectors.
However, there is a nice option to implement the second option which looks very pretty:
std::vector<int> a, b, c, d, e;
// fill a, b, c, d with data
auto expression = [](int a, int b, int c, int d){ return a * b + c * d; };
assert (a.size() == b.size() && b.size() == c.size() && c.size() == d.size());
e.reserve(a.size());
for(auto _a = a.begin(), _b = b.begin(), _c = c.begin(), _d = d.begin(), _e = e.begin();
_a != a.end();
++_a, ++_b, ++_c, ++_d, ++_e)
{
*_e = expression(*_a, *_b, *_c, *_d);
}
This way, you can separate the expression from the logic to evaluate it:
void componentWise4(std::function<int(int,int,int,int)> f,
const std::vector<int> & a,
const std::vector<int> & b,
const std::vector<int> & c,
const std::vector<int> & d,
std::vector<int> & result)
{
assert (a.size() == b.size() && b.size() == c.size() && c.size() == d.size());
result.reserve(a.size());
for(auto _a = a.begin(), _b = b.begin(), _c = c.begin(), _d = d.begin(), _result = result.begin();
_a != a.end();
++_a, ++_b, ++_c, ++_d, ++_result)
{
*_result = expression(*_a, *_b, *_c, *_d);
}
}
Which is then called like that:
std::vector<int> a, b, c, d, e;
// fill a, b, c, d with data
componentWise4([](int a, int b, int c, int d){ return a * b + c * d; },
a, b, c, d, e);
I'm sure this "expression evaluator" can be extended using C++11 new feature "variadic templates" to support arbitrary numbers of arguments within the expression as well as even different types. I couldn't manage to get it working (the variadic template thing), you can try to finish my attempt here: http://ideone.com/w88kuG (I'm new to variadic templates, so I don't know the syntax).
What do you want is in „The C++ Programming Language”. Third Edition by Bjarne Stroustrup in 22.4.7 Temporaries, Copying, and Loops [num.matrix]. It is always a good idea to read the book.
If you dont have it, basically we have two option:
First: we write a set of function for direct calculation of some of the most expected combination ( For example mul_add_and_assign(&U,&M,&V,&W)to calcule U =M*V+W) and led the user to select self what function is he most convenient.
Second: we can introduce some auxiliary classes (for example VxV, VplusV, etc.) that only keep a reference to the arguments of each operation and define an operator conversion to vector. Now we create overloads of the operators + and * that take two vectors by reference and just return an object of the corresponding type. We can create classes of the type VxVplusVxV to calculate more complex operations. Now we can overload operator= to assing VxVplusVxV to a vector. And in this last overload we made all calculation, using the references to the arguments keeped in the auxiliary classes objects, with no or minimal temporary vectors created.