I'm trying to do the following in CUSP:
A=[
1,1,0,0;
2,2,2,0;
0,3,3,3;
0,0,4,4];
B=[1,1,1,1]';
disp(mldivide(A,B));
which is
X=[0.9167,0.0833,-0.5000,0.7500]
On the other hand I get a strange answer from CUSP
#include <cusp/dia_matrix.h>
#include <cusp/krylov/cg.h>
#include <cusp/print.h>
int main()
{
cusp::dia_matrix<int,float,cusp::host_memory> A(4,4,10,3);
A.diagonal_offsets[0] = -1;
A.diagonal_offsets[1] = 0;
A.diagonal_offsets[2] = 1;
for (int i = 0;i <3;i++)
{
for (int q = 0 ;q < A.num_cols;q++)
{
A.values(q,i)=q+1;
}
}
//copy
cusp::dia_matrix<int,float,cusp::device_memory> AA = A;
cusp::array1d<float,cusp::device_memory> BB(A.num_rows,1);
cusp::array1d<float,cusp::device_memory> XX(A.num_rows,0);
cusp::print(AA);
cusp::print(XX);
cusp::print(BB);
cusp::krylov::cg(AA,XX,BB);\
cusp::print(XX);
return 0;
}
The result looks like
sparse matrix <4, 4> with 10 entries
0 0 1
0 1 1
1 0 2
1 1 2
1 2 2
2 1 3
2 2 3
2 3 3
3 2 4
3 3 4
array1d <4>
0
0
0
0
array1d <4>
1
1
1
1
array1d <4>
-39.9938
-53.436
87.9025
-30.1429
The last one doesn't look quite right. Anybody know what I'm doing wrong? Am I using the code wrong or are we supposed to have a really good guessed solution + use a preconditioner?
The conjugate gradient method is only valid for use in symmetric positive definite matrices. Your matrix isn't symmetric. That is why it isn't (and cannot) producing a valid solution. Either use an appropriate, well conditioned SPD matrix, or use a different numerical method.
Related
I want to extract linear combinations from matrices but by performing combinations in modulus.
Let us consider the calculation modulus 5, we then have the following for the addition:
+ | 0 1 2 3 4
--+-----------
0 | 0 1 2 3 4
1 | 1 2 3 4 0
2 | 2 3 4 0 1
3 | 3 4 0 1 2
4 | 4 0 1 2 3
and this table for the multiplication:
* | 0 1 2 3 4
--+-----------
0 | 0 0 0 0 0
1 | 0 1 2 3 4
2 | 0 2 4 1 3
3 | 0 3 1 4 2
4 | 0 4 3 2 1
So let us take an example:
Let us consider the following matrix:
E = 2 1 3 2 0
4 3 0 1 1
Then we can obtain the triangulation matrix by applying a LU decomposition (https://en.wikipedia.org/wiki/LU_decomposition) (or a Gaussian Elimination), which is the following:
T = 1 0 0 0 0
2 1 0 0 0
and finally, the matrix that I want to extract, which is the one storing the linear combinations:
CL = 3 2 3 0 3
0 1 1 3 4
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
So basically, the algorithm should work as follows:
Input: a matrix E with n rows and m columns, and p, a prime number.
* We perform a Gaussian elimination/LU decomposition to obtain the lower-triangulation matrix T.
But all the calculus are done modulo 'p'.
Output: T (with the same size as E, n rows m columns).
CL (with a size m rows, m columns),
which is basically the identity matrix on which we
applied all the modifications that were performed on E to obtain T.
Alright, so now we have the context, let me explain the problem.
I started to do it using the Armadillo library (http://arma.sourceforge.net/), but I did not find any solution on the library to perform the calculus on a mathematical Field p. I easily found the LU method to obtain the lower-triangle matrix, but the calculations are performed in the real.
#include <iostream>
#include <armadillo>
using namespace arma;
using namespace std;
int main(int argc,char** argv)
{
mat A = mat({{2,1,3,2,0},{4,3,0,1,1}});
mat L, U, P;
lu(L, U, P, A);
cout << L << endl;
return 0;
}
With the following, you obtain the lower-triangle matrix 'L' but in the real calculus. Thus you obtain:
T' = 1 0
1/2 1
Is there any technique to perform the computation in a modulus way?
EDIT The Armadillo library is not able to do it. I developed my own LU decomposition in modulus but there is still a bug there. I asked a new question here Linear Combination C++ in modulus, hoping to solve it.
First of all: drop the using namespaces, code can become completely unreadable if you do that.
I haven't used Armadillo yet. But I have looked at the documentation, and it seems templated to me.
Now things are getting a bit wild. The type you use, arma::mat seems to be a typedef on arma::Mat<double>.
The high-level function arma::lu isn't properly documented. It obviously does an LU-decomposition, but I don't know if the function is templated. If it is, i.e., you cannot just call it with double mats but also other types, you might have a shot using a custom type representing the field (since 5 is prime, otherwise you'd be completely lost) of calculations modulo 5. Meaning you write a class, let's call it IntMod5 and define all required operators for this class, meaning all operators that IntMod5 uses. For example, you'd need to define operator/(), e.g. by making a table of inverses of 4 of the 5 elements of the field (0 has none), i.e. 1->1, 2->3, 3->2, 4->4, and define
IntMod5 operator/(const IntMod5& o) const
{
return IntMod5((this->value*inverse(o.value))%5);
}
This is just one example, you likely need to define all arithmetic operators, binary and unary, and possibly more such as comparison (LU decomposition might use finding good pivot elements). If you're lucky and the library is written in a way that it works for any field, not just floating point, you have a chance.
Before you go through all the work, you should use a trivial class simply wrapping double and check if arma::Mat or arma::lu do any type checks blocking you out.
If either of these fails, you'll likely have to write your own LU decomposition modulo 5 or find another library that supports it.
I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.
Problem
I need to compute a function of an array of integers. For every three-element subset (or triplet) of the array, I need to compute the term floor((sum of triplet)/(product of triplet)). Then I need to return the sum of all such terms.
Example
Input (length; array):
5
1 2 1 7 3
Output:
6
Explanation
The following triplets exist in the given array:
1 2 1
1 2 7
1 2 3
1 1 7
1 1 3
1 7 3
2 1 7
2 1 3
2 7 3
1 7 3
Considering these triplets from the sample input:
1 2 1 contributes 2, because floor((1+2+1)/(1*2*1)) = floor(4/2) = 2
1 2 3 contributes 1
1 1 7 contributes 1
1 1 3 contributes 1
2 1 3 contributes 1
All other triplets contribute 0 to the sum.
Hence the answer is (2+1+1+1+1)=6.
My Solution
What I tried is complexity O(n^3). Code is given below:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long t,n[300005],sum=0,mul=1,i,j,k,res=0;
cin >> t;
for(i=0;i<t;i++)
cin >>n[i];
for(i=0;i<t-2;i++)
for(j=i+1;j<t-1;j++)
for(k=j+1;k<t;k++)
{
sum = n[i]+n[j]+n[k];
mul = n[i]*n[j]*n[k];
res += floor(sum/mul);
}
cout << res << endl;
return 0;
}
Is there any hint of better optimization?
While still O(n^3), you could save some operations by caching the redundant calculations between n[i] and n[j] as you iterate over n[k].
For example:
long sum_ij,mul_ij;
for(i=0;i<t-2;i++) {
for(j=i+1;j<t-1;j++) {
sum_ij = n[i]+n[j];
mul_ij = n[i]*n[j];
for(k=j+1;k<t;k++)
{
sum = sum_ij+n[k];
mul = mul_ij*n[k];
res += floor(sum/mul);
}
}
}
So I have to fill in a square matrix recursively. For size N=5, it should be:
1 1 1 1 1
1 2 2 2 1
1 2 3 2 1
1 2 2 2 1
1 1 1 1 1
but my program shows:
1 1 1 1 1
1 2 2 2 1
1 2 3 3 1
1 2 2 2 1
1 1 1 1 1
void llenar5 (int** mat, int n, int f=0, int c=0,int k=2)
{
if (f<n)
{
if (c<n)
{
if (f==0 ||c==0||f==n-1||c==n-1)
{
*(*(mat+f)+c)=1;
llenar5(mat,n,f,c+1,k); //move to the right
}
else if (f==k-1 ||c==k-1||f==n-k||c==n-k)
{
*(*(mat+f)+c)=k;
llenar5(mat,n,f,c+1,k++);
}
}
llenar5(mat,n,f+1,c,k);
}
}
I am creating a matrix in dynamic memory, and I tried calling the function llenar5(mat,n,f+1,c+1,k+1) to jump a column and row while incrementing the values.
void llenar5 (int** mat, int n, int f=0, int c=0,int k=1)
{
if (f<n)
{
if (c<n)
{
if (f==k-1 ||c==k-1||f==n-k||c==n-k)
{
*(*(mat+f)+c)=k;
llenar5(mat,n,f,c+1,k+1);
}
llenar5(mat,n,f,c+1,k);
}
llenar5(mat,n,f+1,c,k);
}
}
I think it will help if you, temporarily, consider a matrix with 0-based numbers. For example, your initial matrix would look instead something like this:
0 0 0 0 0
0 1 1 1 0
0 1 2 1 0
0 1 1 1 0
0 0 0 0 0
If you inspect this matrix, you should quickly observe a fundamental property of this matrix. The value of each cell is the minimum distance from the cell to its closest horizontal or vertical edge.
So, for cell at coordinates (x,y), with the matrix of size w (width) and h (height), the value of each cell is:
min(x, y, (w-1-x), (h-1-y))
Where the min() function is a classical minimum function, that computes the minimum value of its arguments.
Then, it should be obvious that going from a 0-based matrix to a 1-based matrix you should simply add 1 to the result.
So, in conclusion your code should be trivially simple:
Loop over all the x and y coordinates.
Set the value of the corresponding cell based on the above formula.
Your code seems to be unnecessarily complicated. All that recursion is completely unneeded. This can be done using a single pass over their entire matrix, top to bottom, left to right. You don't need to know the values of adjacent cells, to compute the value in the next cell.
When the following program is fead the following input (reading from cin):
1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1
The output is surprising:
1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1
#include<iostream>
using namespace std;
int main()
{
int arey[3][3];
int i,j;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cin>>arey[j][i];
}
}
arey[0][0]=1;
arey[3][3]=1;
i=0,j=0;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cout<<arey[j][i];
}
}
return 0;
}
Can someone explain what I should change to get the same output as the input?
Is the matrix 3x3 or 4x4?
you created 3x3 but the loops run for 4 elements and you also update [3][3]
Basically your indexes overflow and you overwrite a different cell in the matrix.
Update: cheecked your input, use: int arey[4][4];
Arrays use 0 based indices, so the valid range of indices for your
int arey[3][3];
are 0 <= i < 3 and 0 <= j < 3
So you need to change the condition in your for loops to be strictly < instead of <=
I really don't think I understand your question, but this is wrong:
int arey[3][3];
...
for(j=0;j<=3;j++) // <= invalid
...
array[3][3]=1; // out of bounds
arey is a 3*3 array. You can't access arey[3][?], that's out of bounds. The only valid indices are 0..2.
Once you've written past the bounds of your array, your program behavior becomes undefined.