Avoiding NANs for expressions that are partly imaginary in c++ - c++

I have an expression whose outcome is a real number, but is composed of imaginary terms (that cancel one another). A significantly more simple example than the one I am considering would be something like,
z = a + 1/[sqrt(a-b) - a] - f[sqrt(a-b)] = a
where a and b are real numbers and f is some function that statisfies the above expression. It would not surprise you that in some cases, say for b > a (which does not always occur, but could occur in some cases), the above expression returns nan, since some of its terms are imaginary.
Sometimes, it is possible to work out the algebra and write out this not-really-complex expression using real numbers only. However, in my case, the algebra is very messy (so messy that even Matlab's symbolic package and Mathematica are unable to trivially simplify).
I am wondering if there is some other way to work out expressions you know to be real, but are partly imaginary.
PS: not important for this question, but for more info about the expression I am dealing with, please see another question I previously asked.

tl;dr for the comment thread:
If you know you're doing something that will involve imaginary numbers, just use std::complex.
You can't avoid getting NaN if you insist on asking for a real result to something (sqrt, say) that you know will have an imaginary component. There is no real answer it can give you.
At the end of your computation, if imag(result) is zero (or within a suitable epsilon), then your imaginary parts cancelled out and you have a real(result).
As a concrete example:
#include <complex>
#include <iostream>
int main()
{
std::complex<double> a{-5, 0}; // -5 + 0i
std::complex<double> b{ 5, 0}; // +5 + 0i
auto z = b + sqrt(a) - sqrt(a);
std::cout << "z = " << real(z) << " + " << imag(z) << "i\n";
}
prints
z = 5 + 0i
With your new example
z = a + 1/(sqrt(a-b) - a) - f(sqrt(a-b)) = a
it'll be useful to make a of type std::complex in the first place, and to use a complex 1+0i for the numerator as well. This is because of the way overloaded operators are resolved:
using cx = std::complex<double>;
cx f(cx); // whatever this does, it also needs to handle complex inputs
cx foo(cx a, cx b)
{
return a + cx{1}/(sqrt(a-b) - a) - f(sqrt(a-b));
}
auto

Related

Broadcasting Row and Column Vector in Eigen C++

I have following Python Code written in NumPy:
> r = 3
> y, x = numpy.ogrid[-r : r + 1, -r : r + 1]
> mask = numpy.sqrt(x**2 + y**2)
> mask
array([[4.24264, 3.60555, 3.16228, 3.00000, 3.16228, 3.60555, 4.24264],
[3.60555, 2.82843, 2.23607, 2.00000, 2.23607, 2.82843, 3.60555],
[3.16228, 2.23607, 1.41421, 1.00000, 1.41421, 2.23607, 3.16228],
[3.00000, 2.00000, 1.00000, 0.00000, 1.00000, 2.00000, 3.00000],
[3.16228, 2.23607, 1.41421, 1.00000, 1.41421, 2.23607, 3.16228],
[3.60555, 2.82843, 2.23607, 2.00000, 2.23607, 2.82843, 3.60555],
[4.24264, 3.60555, 3.16228, 3.00000, 3.16228, 3.60555, 4.24264]])
Now, I am making the mask in Eigen where I need to broadcast row and column vector. Unfortunately, it is not allowed so I made the following workaround:
int len = 1 + 2 * r;
MatrixXf mask = MatrixXf::Zero(len, len);
ArrayXf squared_yx = ArrayXf::LinSpaced(len, -r, r).square();
mask = (mask.array().colwise() + squared_yx) +
(mask.array().rowwise() + squared_yx.transpose());
mask = mask.cwiseSqrt();
cout << "mask" << endl << mask << endl;
4.24264 3.60555 3.16228 3 3.16228 3.60555 4.24264
3.60555 2.82843 2.23607 2 2.23607 2.82843 3.60555
3.16228 2.23607 1.41421 1 1.41421 2.23607 3.16228
3 2 1 0 1 2 3
3.16228 2.23607 1.41421 1 1.41421 2.23607 3.16228
3.60555 2.82843 2.23607 2 2.23607 2.82843 3.60555
4.24264 3.60555 3.16228 3 3.16228 3.60555 4.24264
It works. But I wonder if there is another and shorter way to do it. Therefore my question is how to broadcast Row and Column Vector in Eigen C++?
System Info
Tool
Version
Eigen
3.3.7
GCC
9.4.0
Ubuntu
20.04.4 LTS
I think the easiest approach (as in: most readable), is replicate.
int r = 3;
int len = 1 + 2 * r;
const auto& squared_yx = Eigen::ArrayXf::LinSpaced(len, -r, r).square();
const auto& bcast = squared_yx.replicate(1, len);
Eigen::MatrixXf mask = (bcast + bcast.transpose()).sqrt();
Note that what you do is numerically unstable (for large r) and the hypot function exists to work around these issues. So even your python code could be better:
r = 3
y, x = numpy.ogrid[-r : r + 1, -r : r + 1]
mask = numpy.hypot(x, y)
To achieve the same in Eigen, do something like this:
const auto& yx = Eigen::ArrayXf::LinSpaced(len, -r, r);
const auto& bcast = yx.replicate(1, len);
Eigen::MatrixXf mask = bcast.binaryExpr(bcast.transpose(),
[](float x, float y) noexcept -> float {
return std::hypot(x, y);
});
Eigen's documentation on binaryExpr is currently broken, so this is hard to find.
To be fair, you will probably never run into stability issues in this particular case because you will run out of memory first. However, it'd still like to point this out because seeing a naive sqrt(x**2 + y**2) is always a bit of a red flag. Also, in Python hypot might still worth it from a performance point because it reduces the number of temporary memory allocations and function calls.
BinaryExpr
The documentation on binaryExpr is missing, I assume because the parser has trouble with Eigen's C++ code. In any case, one can find it indirectly as CwiseBinaryOp and similarly CwiseUnaryOp, CwiseNullaryOp and CwiseTernaryOp.
The use looks a bit weird but is pretty simple. It takes a functor (either a struct with operator(), a function pointer, or a lambda) and applies this element-wise.
The unary operation makes this pretty clear. If Eigen::Array.sin() didn't exist, you could write this:
array.unaryExpr([](double x) -> double { return std::sin(x); }) to achieve exactly the same effect.
The binary and ternary versions take one or two more Eigen expressions as the second and third argument to the function. That's what I did above. The nullary version is explained in the documentation in its own chapter.
Use of auto
Eigen is correct to warn about auto but only in that you have to know what you do. It is important to realize that auto on an Eigen expression just keeps the expression around. It does not evaluate it into a vector or matrix.
This is fine and very useful if you want to compose a complex expression that would be hard to read when put in a single statement. In my code above, there are no temporary memory allocations and no floating point computations take place until the final expression is assigned to the matrix.
As long as the programmer knows that these are expressions and not final matrices, everything is fine.
I think the main take-away is that use of auto with Eigen should be limited to short-lived (as in: inside a single function) scalar expressions. Any coding style that uses auto for everything will quickly break or be hard to read with Eigen. But it can be used safely and make the code more readable in the process without sacrificing performance in the same way as evaluating into matrices would.
As for why I chose const auto& instead of auto or const auto: Mostly force of habit that is unrelated to the task at hand. I mostly do it for instances like this:
const Eigen::Vector& Foo::get_bar();
void quz(Foo& foo)
{
const auto& bar = foo.get_bar();
}
Here, bar will remain a reference whereas auto would create a copy. If the return value is changed, everything stays valid.
Eigen::Vector Foo::get_bar();
void quz(Foo& foo)
{
const auto& bar = foo.get_bar();
}
Now a copy is created anyway. But everything continues to work because assigning the return value to a const-reference extends the lifetime of the object. So this may look like a dangling pointer, but it is not.

using floating point arithmetic with Z3 C++ APIs

I am trying to solve a problem of nonlinear real numbers using Z3. I need the Z3 to generate multiple solutions.
In the problem domain, precision is not a critical issue; I need just one or two decimal digits after the decimal point. so, I need to set Z3 not to explore all the search space of real numbers to minimize the time to find multiple solutions.
I am trying to replace the real numbers with floating point numbers. I read the fpa example in the c_api.c file but I found it a little bit confusing for me.
for example, let me assume that I want to convert the reals in the following code:
config cfg;
cfg.set("auto_config", true);
context con(cfg);
expr x = con.real_const("x");
expr y = con.real_const("y");
solver sol(con);
sol.add(x*y > 10);
std::cout << sol.check() << "\n";
std::cout << sol.get_model() << "\n";
}
I tried the following code but it didn't work
config cfg;
cfg.set("auto_config", true);
context con(cfg);
expr sign = con.bv_const("sig", 1);
expr exp = con.bv_const("exp", 10);
expr sig = con.bv_const("sig", 10);
expr x = to_expr(con, Z3_mk_fpa_fp(con, sign, exp, sig));
expr y = to_expr(con, Z3_mk_fpa_fp(con, sign, exp, sig));
solver sol(con);
sol.add(x*y > 10);
std::cout << sol.check() << "\n";
and the output is:
Assertion failed: false, file c:\users\rehab\downloads\z3-master\z3-master\src\a
pi\c++\z3++.h, line 1199
My questions are:
Are there any detailed examples or code snippets about using fpa in C++ APIs? it is not clear to me how to convert the fpa example in the C API to C++ API.
What's wrong in the above code conversion?
I'm not sure if using floats is the best way to go for your problem. But sounds like you tried all other options and non-linearity is getting in your way. Note that even if you model your problem with floats, floating-point arithmetic is quite tricky and solver may have hard time finding satisfying models. Furthermore, solutions maybe way far off from actual results due to numerical instability.
Using C
Leaving all those aside, the correct way to code your query using the C api would be (assuming we use 32-bit single-precision floats):
#include <z3.h>
int main(void) {
Z3_config cfg = Z3_mk_config();
Z3_context ctx = Z3_mk_context(cfg);
Z3_solver s = Z3_mk_solver(ctx);
Z3_solver_inc_ref(ctx, s);
Z3_del_config(cfg);
Z3_sort float_sort = Z3_mk_fpa_sort(ctx, 8, 24);
Z3_symbol s_x = Z3_mk_string_symbol(ctx, "x");
Z3_symbol s_y = Z3_mk_string_symbol(ctx, "y");
Z3_ast x = Z3_mk_const(ctx, s_x, float_sort);
Z3_ast y = Z3_mk_const(ctx, s_y, float_sort);
Z3_symbol s_x_times_y = Z3_mk_string_symbol(ctx, "x_times_y");
Z3_ast x_times_y = Z3_mk_const(ctx, s_x_times_y, float_sort);
Z3_ast c1 = Z3_mk_eq(ctx, x_times_y, Z3_mk_fpa_mul(ctx, Z3_mk_fpa_rne(ctx), x, y));
Z3_ast c2 = Z3_mk_fpa_gt(ctx, x_times_y, Z3_mk_fpa_numeral_float(ctx, 10, float_sort));
Z3_solver_assert(ctx, s, c1);
Z3_solver_assert(ctx, s, c2);
Z3_lbool result = Z3_solver_check(ctx, s);
switch(result) {
case Z3_L_FALSE: printf("unsat\n");
break;
case Z3_L_UNDEF: printf("undef\n");
break;
case Z3_L_TRUE: { Z3_model m = Z3_solver_get_model(ctx, s);
if(m) Z3_model_inc_ref(ctx, m);
printf("sat\n%s\n", Z3_model_to_string(ctx, m));
break;
}
}
return 0;
}
When run, this prints:
sat
x_times_y -> (fp #b0 #xbe #b10110110110101010000010)
y -> (fp #b0 #xb5 #b00000000000000000000000)
x -> (fp #b0 #x88 #b10110110110101010000010)
These are single-precision floating point numbers; you can read about them in wikipedia for instance. In more conventional notation, they are:
x_times_y -> 1.5810592e19
y -> 1.8014399e16
x -> 877.6642
This is quite tricky to use, but what you have asked.
Using Python
I'd heartily recommend using the Python API to at least see what the solver is capable of before investing into such complicated C code. Here's how it would look in Python:
from z3 import *
x = FP('x', FPSort(8, 24))
y = FP('y', FPSort(8, 24))
s = Solver()
s.add(x*y > 10);
s.check()
print s.model()
When run, this prints:
[y = 1.32167303562164306640625,
x = 1.513233661651611328125*(2**121)]
Perhaps not what you expected, but it is a valid model indeed.
Using Haskell
Just to give you a taste of simplicity, here's how the same problem can be expressed using the Haskell bindings (It's just a mere one liner!)
Prelude Data.SBV> sat $ \x y -> fpIsPoint x &&& fpIsPoint y &&& x * y .> (10::SFloat)
Satisfiable. Model:
s0 = 5.1129496e28 :: Float
s1 = 6.6554557e9 :: Float
Summary
Note that Floating-point also has issues regarding NaN/Infinity values, so you might have to avoid those explicitly. (This is what the Haskell expression did by using the isFPPoint predicate. Coding it in Python or C would require more code, but is surely doable.)
It should be emphasized that literally any other binding to Z3 (Python, Haskell, Scala, what have you) will give you a better experience than what you'll get with C/C++/Java. (Even direct coding in SMTLib would be nicer.)
So, I heartily recommend using some higher-level interface (Python is a good one: It is easy to learn), and once you are confident with the model and how it works, you can then start coding the same in C if necessary.

C++ Trapezoidal Integration Function Returning Negative Numbers when it shouldn't

I am using the following function written in C++, whose purpose is to take the integral of one array of data (y) with respect to another (x)
// Define function to perform numerical integration by the trapezoidal rule
double trapz (double xptr[], double yptr[], int Npoints)
{
// The trapzDiagFile object and associated output file are how I monitor what data the for loop actually sees.
std::ofstream trapzDiagFile;
trapzDiagFile.open("trapzDiagFile.txt",std::ofstream::out | std::ofstream::trunc);
double buffer = 0.0;
for (int n = 0; n < (Npoints - 1); n++)
{
buffer += 0.5 * (yptr[n+1] + yptr[n]) * (xptr[n+1] - xptr[n]);
trapzDiagFile << xptr[n] << "," << yptr[n] << std::endl;
}
trapzDiagFile.close();
return buffer;
}
I validated this function for the simple case where x contains 100 uniformly spaced points from 0 to 1, and y = x^2, and it returned 0.33334, as it should.
But when I use it for a different data set, it returns -3.431, which makes absolutely no sense. If you look in the attached image file, the integral I am referring to is the area under the curve between the dashed vertical lines.
It's definitely a positive number.
Moreover, I used the native trapz command in MATLAB on the same set of numbers and that returned 1.4376.
In addition, I translated the above C++ trapz function into MATLAB, line for line as closely as possible, and again got 1.4376.
I feel like there's something C++ related I'm not seeing here. If it is relevant, I am using minGW-w64.
Apologies for the vagueness of this post. If I knew more about what kind of issue I am seeing, it would be easier to be concise about it.
Plot of the dataset for which the trapz function (my homemade C++ version) returns -3.431:
Please check the value of xptr[Npoints - 1]. It may be less than xptr[Npoints - 2], and was not included in the values that you output.

Compound Assignment (Multiply)

I recently learn the basic of C++. And i found something that i didn't get the idea. Here is the program that make me a little confuse.
#include <iostream>
using namespace std;
int main()
{
int m = 4, n;
n=++m*--m;
cout <<"m="<<m<<" and n="<<n<<"\n;
return 0;
}
And the output is m=4 and n=16.
I thought that
m=4, so ++m is 5, and --m will be 4,
then n= 5*4= 20.
Hence, the m=4 and n=20.
I think mine is false. So i need a help. Thank you.
The operands of * are unsequenced relative to each other. This means that not only may they be evaluated in any order; but if each operand contains multiple sub-steps, the sub-steps of one operand might be interleaved with those of the other operand.
An example of this might be (f() + g()) * (h() + i()) . The four functions could be called in any order -- it is not required that f and g are called together, etc.
Back to your example, the following two sub-steps are unsequenced relative to each other:
writing the new value to m, as part of ++m
reading m, as part of --m
When there are two unsequenced operations on the same variable (and at least one of them is a write), it is undefined behaviour which means anything can happen (including unexpected results).
This:
n=++m*--m;
is bad code. Replace it with something clear, such as:
n = (m + 1) * (m - 1);
The original code, for complicated reasons, may not do what you expect, so it's better not to write such code in the first place. If you want to know more about the nitty gritty details of why this is, see here: Undefined behavior and sequence points
++m means "increment m then use its value" The current call with have (m + 1) as value.
m-- means "use the value of m, then decrement it" The current call with have the original value of m, and subsequent calls will have (m - 1) as value
If that makes it any clearer for you, you can also rewrite it as:
int m = 4, n;
n = (m = (m + 1)) * (m = (m - 1));
I am pretty positive the operation occurs before the increment. That is why that is happening. If you break it down like this, it should work.
The answer should be 15 because 4 + 1 is 5 and 4 - 3 is 3, thus 5 * 3 is 15. See below
int main()
{
int m = 4, n;
int g;
n = (m+1) * (m-1);
std::cout << "m=" << m << " and n=" << n << "\n" ;
std::cin >> g;
return 0;
}

Solving a linear equation in one variable

What would be the most efficient algorithm to solve a linear equation in one variable given as a string input to a function? For example, for input string:
"x + 9 – 2 - 4 + x = – x + 5 – 1 + 3 – x"
The output should be 1.
I am considering using a stack and pushing each string token onto it as I encounter spaces in the string. If the input was in polish notation then it would have been easier to pop numbers off the stack to get to a result, but I am not sure what approach to take here.
It is an interview question.
Solving the linear equation is (I hope) extremely easy for you once you've worked out the coefficients a and b in the equation a * x + b = 0.
So, the difficult part of the problem is parsing the expression and "evaluating" it to find the coefficients. Your example expression is extremely simple, it uses only the operators unary -, binary -, binary +. And =, which you could handle specially.
It is not clear from the question whether the solution should also handle expressions involving binary * and /, or parentheses. I'm wondering whether the interview question is intended:
to make you write some simple code, or
to make you ask what the real scope of the problem is before you write anything.
Both are important skills :-)
It could even be that the question is intended:
to separate those with lots of experience writing parsers (who will solve it as fast as they can write/type) from those with none (who might struggle to solve it at all within a few minutes, at least without some hints).
Anyway, to allow for future more complicated requirements, there are two common approaches to parsing arithmetic expressions: recursive descent or Dijkstra's shunting-yard algorithm. You can look these up, and if you only need the simple expressions in version 1.0 then you can use a simplified form of Dijkstra's algorithm. Then once you've parsed the expression, you need to evaluate it: use values that are linear expressions in x and interpret = as an operator with lowest possible precedence that means "subtract". The result is a linear expression in x that is equal to 0.
If you don't need complicated expressions then you can evaluate that simple example pretty much directly from left-to-right once you've tokenised it[*]:
x
x + 9
// set the "we've found minus sign" bit to negate the first thing that follows
x + 7 // and clear the negative bit
x + 3
2 * x + 3
// set the "we've found the equals sign" bit to negate everything that follows
3 * x + 3
3 * x - 2
3 * x - 1
3 * x - 4
4 * x - 4
Finally, solve a * x + b = 0 as x = - b/a.
[*] example tokenisation code, in Python:
acc = None
for idx, ch in enumerate(input):
if ch in '1234567890':
if acc is None: acc = 0
acc = 10 * acc + int(ch)
continue
if acc != None:
yield acc
acc = None
if ch in '+-=x':
yield ch
elif ch == ' ':
pass
else:
raise ValueError('illegal character "%s" at %d' % (ch, idx))
Alternative example tokenisation code, also in Python, assuming there will always be spaces between tokens as in the example. This leaves token validation to the parser:
return input.split()
ok some simple psuedo code that you could use to solve this problem
function(stinrgToParse){
arrayoftokens = stringToParse.match(RegexMatching);
foreach(arrayoftokens as token)
{
//now step through the tokens and determine what they are
//and store the neccesary information.
}
//Use the above information to do the arithmetic.
//count the number of times a variable appears positive and negative
//do the arithmetic.
//add up the numbers both positive and negative.
//return the result.
}
The first thing is to parse the string, to identify the various tokens (numbers, variables and operators), so that an expression tree can be formed by giving operator proper precedences.
Regular expressions can help, but that's not the only method (grammar parsers like boost::spirit are good too, and you can even run your own: its all a "find and recourse").
The tree can then be manipulated reducing the nodes executing those operation that deals with constants and by grouping variables related operations, executing them accordingly.
This goes on recursively until you remain with a variable related node and a constant node.
At the point the solution is calculated trivially.
They are basically the same principles that leads to the production of an interpreter or a compiler.
Consider:
from operator import add, sub
def ab(expr):
a, b, op = 0, 0, add
for t in expr.split():
if t == '+': op = add
elif t == '-': op = sub
elif t == 'x': a = op(a, 1)
else : b = op(b, int(t))
return a, b
Given an expression like 1 + x - 2 - x... this converts it to a canonical form ax+b and returns a pair of coefficients (a,b).
Now, let's obtain the coefficients from both parts of the equation:
le, ri = equation.split('=')
a1, b1 = ab(le)
a2, b2 = ab(ri)
and finally solve the trivial equation a1*x + b1 = a2*x + b2:
x = (b2 - b1) / (a1 - a2)
Of course, this only solves this particular example, without operator precedence or parentheses. To support the latter you'll need a parser, presumable a recursive descent one, which would be simper to code by hand.