Implementing the Bartels–Stewart algorithm in Eigen3? - linear-algebra

In the past when I've needed to solve the Sylvester equation, AX + XB = C, I've used scipy's function, solve_sylvester [1], which apparently works by using the Bartels-Stewart algorithm to get things into upper triangular form, and then solving the equation using lapack.
I now need to solve the equation using eigen. eigen provides an function, matrix_function_solve_triangular_sylvester [2], which seems by the documentation to be similar to the lapack function which scipy calls. I'm attempting to translate exactly scipy's implementation in eigen3, but in the end my value for X doesn't satisfy the equation. Here's my implementation:
#include <iostream>
#include <Eigen/Core>
#include <Eigen/Eigenvalues>
#include <unsupported/Eigen/MatrixFunctions>
int main()
{
Eigen::Matrix<double, 3, 3> A;
A << -17, -6, 0,
-15, 6, 14,
9, -12, 19;
Eigen::Matrix<double, 5, 5> B;
B << 5, -17, -12, 16, 11,
-4, 19, -1, 9, 13,
1, 3, 5, -5, 2,
8, -15, 5, 14, -12,
-2, -4, 13, -8, -17;
Eigen::Matrix<double, 3, 5> Q;
Q << 6, 5, -17, 12, 4,
-11, 15, 8, 1, 7,
15, -3, 9, -19, -10;
Eigen::RealSchur<Eigen::MatrixXd> SchurA(A);
Eigen::MatrixXd R = SchurA.matrixT();
Eigen::MatrixXd U = SchurA.matrixU();
Eigen::RealSchur<Eigen::MatrixXd> SchurB(B.transpose());
Eigen::MatrixXd S = SchurB.matrixT();
Eigen::MatrixXd V = SchurB.matrixU();
Eigen::MatrixXd F = (U.transpose() * Q) * V;
Eigen::MatrixXd Y =
Eigen::internal::matrix_function_solve_triangular_sylvester(R, S, F);
Eigen::MatrixXd X = (U * Y) * V.transpose();
Eigen::MatrixXd Q_calc = A * X + X * B;
std::cout << Q_calc - Q << std::endl;
// Should be all zeros, but instead getting:
// 421.868 193.032 -208.273 42.7449 -3.57527
//-1651.66 -390.314 2043.59 -1611.1 -1843.91
//-67.4093 207.414 1168.89 -1240.54 -1650.48
return EXIT_SUCCESS;
}
Any ideas what I'm doing wrong?
[1] https://github.com/scipy/scipy/blob/v0.15.1/scipy/linalg/_solvers.py#L23
[2] https://bitbucket.org/eigen/eigen/src/dbb0b1f3b07a261d01f43f8fb94e85ceede9fac7/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h?at=default#lines-274

Your A and B matrices have non-real eigenvalues, therefore their RealSchur decomposition will be non-triangular (only "quasi-triangular", i.e., it contains a 2x2 block on the diagonal). If you compile without -DNDEBUG, you should get an assertion like this:
../eigen/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h:277: MatrixType Eigen::internal::matrix_function_solve_triangular_sylvester(const MatrixType&, const MatrixType&, const MatrixType&) [with MatrixType = Eigen::Matrix<double, -1, -1>]: Assertion `A.isUpperTriangular()' failed.
I don't know, if there is a Sylvester-solver which also handles quasi-triangular matrices, but the easiest solution using Eigen methods would be to use the ComplexSchur decomposition (also use adjoint() instead of transpose() -- and don't transpose B):
Eigen::ComplexSchur<Eigen::MatrixXd> SchurA(A);
Eigen::MatrixXcd R = SchurA.matrixT();
Eigen::MatrixXcd U = SchurA.matrixU();
Eigen::ComplexSchur<Eigen::MatrixXd> SchurB(B);
Eigen::MatrixXcd S = SchurB.matrixT();
Eigen::MatrixXcd V = SchurB.matrixU();
Eigen::MatrixXcd F = (U.adjoint() * Q) * V;
Eigen::MatrixXcd Y =
Eigen::internal::matrix_function_solve_triangular_sylvester(R, S, F);
Eigen::MatrixXcd X = (U * Y) * V.adjoint();
Eigen::MatrixXcd Q_calc = A * X + X * B;
I think X should always be real, so you can replace the last two lines by
Eigen::MatrixXd X = ((U * Y) * V.adjoint()).real();
Eigen::MatrixXd Q_calc = A * X + X * B;

#chtz is correct; this is due to the Schurr decomposition matrix being quasi-triangular rather than triangular. The eigen solver you are using cannot deal with such matrices. However, chtz is wrong in that there are Sylvester solvers that can deal with quasi-triangular solvers. For example lapack's trsyl can deal with quasi-triangular matrices. This is what is called by scipy, which explains why the OP's scipy implementation worked fine.

Related

Most common term in a vector - PARI/GP

I feel like I'm being really stupid here as I would have thought there's a simple command already in Pari, or it should be a simple thing to write up, but I simply cannot figure this out.
Given a vector, say V, which will have duplicate entries, how can one determine what the most common entry is?
For example, say we have:
V = [ 0, 1, 2, 2, 3, 4, 6, 8, 8, 8 ]
I want something which would return the value 8.
I'm aware of things like vecsearch, but I can't see how that can be tweaked to make this work?
Very closely related to this, I want this result to return the most common non-zero entry, and some vectors I look at will have 0 as the most common entry. Eg: V = [ 0, 0, 0, 0, 3, 3, 5 ]. So whatever I execute here I would like to return 3.
I tried writing up something which would remove all zero terms, but again struggled.
The thing I have tried in particular is:
rem( v ) = {
my( c );
while( c = vecsearch( v, 0 ); #c, v = vecextract( v, "^c" ) ); v
}
but vecextract doesn't seem to like this set up.
If you can ensure all the elements are within the some fixed range then it is enough just to do the counting sorting with PARI/GP code like this:
counts_for(v: t_VEC, lower: t_INT, upper: t_INT) = {
my(counts = vector(1+upper-lower));
for(i=1, #v, counts[1+v[i]-lower]++);
vector(#counts, i, [i-1, counts[i]])
};
V1 = [0, 1, 2, 2, 3, 4, 6, 8, 8, 8];
vecsort(counts_for(V1, 0, 8), [2], 4)[1][1]
> 8
V2 = [0, 0, 0, 0, 3, 3, 5];
vecsort(counts_for(V2, 0, 5), [2], 4)[1][1]
> 0
You also can implement the following short-cut for the sake of convenience:
counts_for1(v: t_VEC) = {
counts_for(v, vecmin(v), vecmax(v))
};
most_frequent(v: t_VEC) = {
my(counts=counts_for1(v));
vecsort(counts, [2], 4)[1][1]
};
most_frequent(V1)
> 8
most_frequent(V2)
> 0
The function matreduce provides this in a more general setting: applied to a vector of objects, it returns a 2-column matrix whose first column contains the distinct objects and the second their multiplicity in the vector. (The function has a more general form that takes the union of multisets.)
most_frequent(v) = my(M = matreduce(v), [n] = matsize(M)); M[n, 1];
most_frequent_non0(v) =
{ my(M = matreduce(v), [n] = matsize(M), x = M[n, 1]);
if (x == 0, M[n - 1, 1], x);
}
? most_frequent([ 0, 1, 2, 2, 3, 4, 6, 8, 8, 8 ])
%1 = 8
? most_frequent([x, x, Mod(1,3), [], [], []])
%2 = []
? most_frequent_non0([ 0, 0, 0, 0, 3, 3, 5 ])
%3 = 5
? most_frequent_non0([x, x, Mod(1,3), [], [], []])
%4 = x
The first function will error out if fed an empty vector, and the second one if there are no non-zero entries. The second function tests for "0" using the x == 0 test (and we famously have [] == 0 in GP); for a more rigorous semantic, use x === 0 in the function definition.

Next number in the sequence || General approach

how can I find the next number in this sequence ,
1, 4, 7, 8, 13, 12, 9 , ?
How to check , given any sequence of numbers , feasible or not. Any general theory or approach is very much welcomed .
One method is to go to the Online Encyclopedia of Integer Sequences and enter your list of at least six or eight numbers into the box and see if that happens to be a known sequence. For your example this doesn't find a known sequence.
If that doesn't work then you can try Mathematica's FindFormula
p=FindFormula[{1, 4, 7, 8, 13, 12, 9}];
and then
p[1] returns 1, p[2] returns 4, p[3] returns 7... and p[8] returns 106, etc.
You can read the documentation on FindFormula and you can look at the formula p by using InputForm[p] where #1 represents a variable in the function p.
In general I think this is rarely going to produce the result that you are looking for.
seq = FindSequenceFunction[{1, 4, 7, 8, 13, 12, 9}, n]
(48 - 74 n - 14 n^2 + 11 n^3 - n^4)/(3 (-13 + 3 n))
Checking the 7th number
n = 7;
seq
9
The next number is a fraction, apparently
n = 8;
seq
32/11
Show[Plot[seq, {n, 1, 10}],
ListPlot[Table[seq, {n, 1, 10}]],
PlotRange -> {{0, 10}, {-20, 30}}, AxesOrigin -> {0, 0}]

Cryptarithmetic Multiplication Prolog

I have the grasp of the idea of crypt arithmetic and addition but I cannot figure out how to do a multiplication crypt arithmetic problem. It's simply TWO*SIX=TWELVE or something along those lines without the middle additional part of the multiplication problem given. I couldn't find anything online and I already found some constraints for the problem but nothing to leads me to some answers. Not sure where to ask this and thought this would be the best place.
I want to know how to solve a multiplication crypt arithmetic problem.
I already concluded:
T W O
* S I X
_________________
T W E L V E
T \= 0 which also means S \= 0
T is 1-6
E is (O*X) mod 10
O or X cannot be 0 or 1 since E has to be different and 0 or 1 gives the same value
as either O or X.
EDIT: I was using the generate and test method
solve(T,W,O,S,I,X,E,L,V) :-
X = [T,W,O,S,I,X,E,L,V],
Digits = [0,1,2,3,4,5,6,7,8,9],
assign_digits(X, Digits),
T > 0,
S > 0,
100*T + 10*W + O * 100*S + 10*I + X =:=
100000*T + 10000*W + 1000*E + 100*L + 10*V + E,
write(X).
select(X, [X|R], R).
select(X, [Y|Xs], [Y|Ys]):- select(X, Xs, Ys).
assign_digits([], _List).
assign_digits([D|Ds], List):-
select(D, List, NewList),
assign_digits(Ds, NewList).
Trivially to do with constraint logic programming. For example, in ECLiPSe Prolog:
:- lib(ic).
puzzle(Vars) :-
[T,W,O,S,I,X,E,L,V] = Vars,
Vars :: 0..9,
alldifferent(Vars),
T #> 0, S #> 0,
(100*T + 10*W + O) * (100*S + 10*I + X) #=
100000*T + 10000*W + 1000*E + 100*L + 10*V + E,
labeling(Vars).
First solution:
[eclipse]: puzzle([T,W,O,S,I,X,E,L,V]).
T = 1
W = 6
O = 5
S = 9
I = 7
X = 2
E = 0
L = 3
V = 8
Yes (0.01s cpu, solution 1, maybe more) ?
There are 3 different solutions:
[eclipse]: puzzle([T,W,O,S,I,X,E,L,V]), writeln([T,W,O,S,I,X,E,L,V]), fail.
[1, 6, 5, 9, 7, 2, 0, 3, 8]
[2, 1, 8, 9, 6, 5, 0, 3, 7]
[3, 4, 5, 9, 8, 6, 0, 1, 7]
No (0.02s cpu)
Update - translation to SWI Prolog:
:- use_module(library(clpfd)).
puzzle(Vars) :-
[T,W,O,S,I,X,E,L,V] = Vars,
Vars ins 0..9,
all_different(Vars),
T #> 0, S #> 0,
(100*T + 10*W + O) * (100*S + 10*I + X) #=
100000*T + 10000*W + 1000*E + 100*L + 10*V + E,
label(Vars).
More general and no-CLP solution:
number_to_digits(Number,List) :-
length(List,Len),
ntb(0,Len,Number,List).
ntb(N,_,N,[]).
ntb(C,E,N,[D|L]) :-
NE is E-1,
V is C + D*10^NE,
ntb(V,NE,N,L).
crypto(In1, In2, Out) :-
term_variables([In1, In2, Out], Vars),
permutation([0,1,2,3,4,5,6,7,8,9], Perm),
append(_, Vars, Perm),
number_to_digits(N1, In1),
number_to_digits(N2, In2),
number_to_digits(N3, Out),
N3 is N1 * N2.
It is quite inefficient and definetly this problem should be solved using CLP like #Sergey did, but maybe someone will be interested in possible solutions without CLP.
Input and output:
?- crypto([T,W,O], [S,I,X], [T,W,E,L,V,E]).
T = 0,
W = 5,
O = 7,
S = 9,
I = 6,
X = 2,
E = 4,
L = 8,
V = 3;
(...)
(57 * 962 = 54834).

unknown recursive method, must find how it runs

This was a past exam question and I have no idea what it does! Please can someone run through it.
public static int befuddle(int n){
if(n <= 1){
return n;
}else{
return befuddle(n - 1) * befuddle(n - 2) + 1;
}
}
this is computing the sequence: 0, 1, 1, 2, 3, 7, 22, 155, ...
Which can be expressed using this formula:
when dealing with numerical sequences, a great resources is The Online Encyclopedia of Integer Sequences!, a quick search there shows a similar sequence to yours but with:
giving the following sequence: 0, 0, 1, 1, 2, 3, 7, 22, 155, ...
you can find more about it here
public static is the type of member function it is. I'm assuming this is part of a class? The static keyword allows you to use it without creating an instance of the class.
Plug in a value of 'n' and step through it. For instance, if n = 1, then the function returns 1. If n = 0 -> 0; n = -100 -> -100.
If n = 2, the else branch is triggered and befuddled is called with 1 and 0. So n = 2 returns 0*1 + 1 = 1.
Do the same thing for n = 3, etc. (calls n = 2 -> 1, and n = 1 -> 1, so n=3 -> 1*1+1 = 2.)

How do I write an Euler function in Mathematica?

I programmed a Euler function but misread the instructions, so now I have to make a new one, but I can't figure it out.
I have made the following automatic Euler function.
f[x_, y_] := -x y^2;
x0 = 0;
y0 = 2;
xend = 2;
steps = 20;
h = (xend - x0)/steps // N;
x = x0;
y = y0;
eulerlist = {{x, y}};
For[i = 1, i <= steps, y = f[x, y]*h + y;
x = x + h;
eulerlist = Append[eulerlist, {x, y}];
i++
]
Print[eulerlist]
But it just generates the list I have specified.
I would like to have a Euler function which is able to generate this form:
Euler[y, 2, -x y^2, {x, 0, 2}, 20]
I don't seem to get any further.
It is not clear what you are asking, but if what you want is to be able to input
Euler[y, 2, -x y^2, {x, 0, 2}, 20]
and get
{{0,2},{0.1,2.},{0.2,1.96},{0.3,1.88317},{0.4,1.77678},{0.5,1.6505},{0.6,1.51429},{0.7,1.37671},{0.8,1.24404},{0.9,1.12023},{1.,1.00728},{1.1,0.905822},{1.2,0.815565},{1.3,0.735748},{1.4,0.665376},{1.5,0.603394},{1.6,0.548781},{1.7,0.500596},{1.8,0.457994},{1.9,0.420238},{2.,0.386684}}
Then you need to write a function definition like this:
Euler[y0_, f_, {x0_, xend_}, steps_Integer?Positive] := (* body *)
Notice the underscores to denote patterns, the := to denote delayed evaluation and the pattern specification Integer?Positive.
As for the body of the function -- oh my goodness could you have picked a less Mathematica-style approach? Perhaps not. Procedural loops and Append are almost never the best way to do anything in Mathematica.
Here is a better solution.
Euler[y_, y0_, f_, {x_, x0_, xend_}, steps_Integer?Positive] :=
With[{h = N[(xend - x0)/steps], ff = Function[{x, y}, f]},
NestList[{#[[1]] + h, ff[#[[1]], #[[2]]]*h + #[[2]]} &, {x0, y0},
steps]]
Euler[y, 2, -x y^2, {x, 0, 2}, 20]
{{0, 2}, {0.1, 2.}, {0.2, 1.96}, {0.3, 1.88317}, {0.4,
1.77678}, {0.5, 1.6505}, {0.6, 1.51429}, {0.7, 1.37671}, {0.8,
1.24404}, {0.9, 1.12023}, {1., 1.00728}, {1.1, 0.905822}, {1.2,
0.815565}, {1.3, 0.735748}, {1.4, 0.665376}, {1.5, 0.603394}, {1.6,
0.548781}, {1.7, 0.500596}, {1.8, 0.457994}, {1.9, 0.420238}, {2.,
0.386684}}
If you want something that outputs Euler[y, 2, -x y^2, {x, 0, 2}, 20], then typing it into the notebook is the quickest method.

Resources