Sparse Vectors
|
In that page, methods and functions related to sparse vectors are detailed. Sparse vectors consist of row numbers and values. In order to have efficient algorithms, row numbers are always sorted in ascending order.
// sparse vector of doubles Vector<double, VectSparse> V;
Vector constructors | |
Vector operators | |
GetM | returns the number of elements in the vector |
GetLength | returns the number of elements in the vector |
GetSize | returns the number of elements in the vector |
GetMemorySize | returns the memory used to store the vector in bytes |
GetIndex | returns a pointer to the row numbers |
GetData | returns a pointer to the values |
GetDataConst | returns a pointer to the values |
GetDataVoid | returns a pointer to the values |
GetDataConstVoid | returns a pointer to the values |
Clear | removes all elements of the vector |
Reallocate | changes the size of vector (removes previous elements) |
Resize | changes the size of vector (keeps previous elements) |
SetData | sets the pointer to the array contained in the vector |
Nullify | clears the vector without releasing memory |
Index | access to row number |
Value | access to value |
Get | modification of V(i) |
Val | modification of V(i) if the non-zero entry exists |
Copy | copies a vector |
Assemble | sorts row numbers |
GetDataSize | returns the number of elements in the vector |
Zero | sets all elements to zero |
Fill | sets all elements to a given value |
FillRand | fills randomly the vector |
AddInteraction | adds a coefficient to the vector |
AddInteractionRow | adds coefficients to the vector |
RemoveSmallEntry | removes small values of the vector |
GetNormInf | returns highest absolute value |
GetNormInfIndex | returns the index of the highest absolute value |
displays the vector | |
Write | writes the vector in binary format |
Read | reads the vector in binary format |
WriteText | writes the vector in text format |
ReadText | reads the vector in text format |
Mlt | multiplies the elements of the vector by a scalar |
Add | adds two vectors |
Copy | copies one vector into another one |
Swap | exchanges two vectors |
DotProd | scalar product between two vectors |
DotProdConj | scalar product between two vectors, first vector being conjugated |
Conjugate | conjugates a vector |
GetMaxAbsIndex | returns index where highest absolute value is reached |
Norm1 | returns 1-norm of a vector |
Norm2 | returns 2-norm of a vector |
GatherSparseEntry | fills a sparse vector with a dense one |
ScatterSparseEntry | fills a dense vector with a sparse one |
GatherSparseEntryZero | fills a sparse vector with a dense one, the dense vector is zeroed. |
Vector(); Vector(const Vector& X ); Vector(int n);
// default constructor -> empty vector Vector<int, VectSparse> U; cout << "Number of elements " << U.GetM() << endl; // It should return 0 // then you can use Reallocate to change the number of non-zero entries U.Reallocate(3); // you need to initialize row numbers (in ascending order) U.Index(0) = 0; U.Index(1) = 4; U.Index(2) = 14; // for values, you can use Fill U.Fill(); // copy constructor (V -> U) Vector<int, VectSparse> V = U; // constructor specifying the number of non-zero entries Vector<double, VectSparse> W(2); // W is not initialized, you have to fill it W.Fill(1.0); // and row numbers as well W.Index(0) = 7; W.Index(1) = 4; // if you forgot to sort numbers, call Assemble W.Assemble();
Reallocate
Assemble
Index
Fill
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
T operator () const; Vector& operator =(const Vector& ); Vector& operator *=(const T0& alpha);
The access operator () can be used to retrieve the value of V at index i. If the index i does not correspond to a non-zero entry, it will return 0. This operator cannot be used to modify the vector, use Get instead. Contrary to dense vectors, operators +, -, * and / cannot be used with sparse vectors.
Vector<double, VectSparse> V; // use of Get to insert non-zero entry. V.Get(2) = 1.5; V.Get(5) = -1.0; // you can display value of V at row i // V(4) should return 0 (zero entry) cout << "V(4) = " << V(4) << endl; // but V(2) should return 1.5 cout << "V(2) = " << V(2) << endl; // everything is fine, and 'val' is equal to 0. double val = V(20); Vector<double, VectSparse> W; // use of operator = to copy contents of vector V W = V; // multiplication by a scalar W *= 1.5;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
T& Get(int i);
This function can be used to modify (or insert) a non-zero entry in the sparse vector. This function should be used in replacement of operator () when the user wants to modify the sparse vector.
Vector<double, VectSparse> V; // use of Get to insert non-zero entry V.Get(2) = 1.5; V.Get(5) = -1.0; // you can display value of V at row i // V(4) should return 0 (zero entry) cout << "V(4) = " << V(4) << endl; // but V(2) should return 1.5 cout << "V(2) = " << V(2) << endl; // warning: a non-zero entry V(20) will be created here: double val = V.Get(20);
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
int GetM() const; int GetLength() const; int GetSize() const; int GetDataSize() const;
All those methods are identic and return the number of non-zero entries contained in the vector.
Vector<float, VectSparse> V(3); cout << "Number of elements of V " << V.GetM() << endl; V.Reallocate(5); cout << "Number of elements of V " << V.GetSize() << endl;
Class Vector_Base
Vector.hxx
Vector.cxx
size_t GetMemorySize() const;
This method returns the memory used by a vector in bytes (by using sizeof function). It will work only if the vector stores non-pointers objects or types, i.e. objects that do not store dynamic arrays.
Vector<float, VectSparse> V(3); cout << "Memory used to store V = " << V.GetMemorySize() << " bytes " << endl; Vector<Vector<double>, VectSparse> W(5); W(0).Reallocate(10); W(1).Reallocate(5); // Here GetMemorySize would not take into account the dynamic allocations that // occured in the elements of W, it will only display the memory used to store usual attributes cout << "Minimal memory used to store W = " << W.GetMemorySize() << " bytes " << endl;
Class Vector_Base
Vector.hxx
Vector.cxx
int* GetIndex();
This method is used to retrieve the pointer to the row numbers and should be used in conjunction with method GetData.
Vector<double, VectSparse> V; V(3) = -3.5; V(1) = 1.3; int* index = V.GetIndex(); // you can use index as a normal C array cout << "row number 1 : " << index[0] << endl;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
T* GetData() const; const T* GetDataConst() const; void* GetDataVoid() const; const void* GetDataConstVoid() const;
Those methods are useful to retrieve the pointer to the values. In practice, you can use those methods in order to interface fortran subroutines or to realize some low level operations. But in this last case, you have to be careful, because debugging operations will be more tedious.
Vector<double, VectSparse>; V; V(3) = -3.5; V(1) = 1.3; double* data = V.GetData(); // you can use data as a normal C array // here the sum of elements is computed double sum = 0; for (int i = 0; i < V.GetM(); i++) sum += data[i]; // this would be equivalent and safer to write sum = 0; for (int i = 0; i < V.GetM(); i++) sum += V.Value(i); // if you want to call a fortran subroutine daxpy Vector<double, VectSparse> X(3), Y(3); double coef = 2.0; // in this case, X is constant int m = X.GetM(); int n = Y.GetM(); daxpy_(&coef, &m, X.GetDataConst(), X.GetIndex(), &n, Y.GetData(), Y.GetIndex()); // for complex numbers, conversion to void* is needed : Vector<complex<double>, VectSparse> Xc(3), Yc(3); complex<double> beta(1,1); zaxpy(reinterpret_cast<const void*>(beta), >m, Xc.GetDataConstVoid(), Xc.GetIndex(), >n, Yc.GetDataVoid(), Yc.GetIndex());
GetIndex
Value
SetData
Nullify
Class Vector_Base
Vector.hxx
Vector.cxx
void Clear();
This method removes all the non-zero entries of the vector. After calling this method, the vector is equal to 0 (and does not contain non-zero entries) .
Vector<double, VectSparse> V; V(2) = 1.5; // clears vector V V.Clear();
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Reallocate(int);
This method changes the number of non-zero entries contained in the vector, but removes previous values. For sparse vectors, this may be a better solution to use methods AddInteraction, AddInteractionRow or Get.
Vector<long double, VectSparse> V; V.Get(1) = 1.5; V.Get(5) = -1.0; // resizes vector V V.Reallocate(20); // you need to initialize all new values V.Fill(1.0); // and row numbers as well for (int k = 0; k < 20; k++) V.Index(k) = 2*k+3;
Resize
AddInteraction
AddInteractionRow
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Resize(int);
This method changes the size of the vector, and keeps previous elements. For sparse vectors, this may be a better solution to use methods AddInteraction, AddInteractionRow or Get.
Vector<long double, VectSparse> V; V.AddInteraction(3, 1.4); V.AddInteraction(7, -1.5; // resizes vector V V.Resize(4); // you need to initialize new elements if there are new // here two new elements V.Index(2) = 0; V.Value(2) = 0.8; V.Index(3) = 6; V.Value(3) = -0.7; // Assemble should be called to sort row numbers V.Assemble();
AddInteraction
AddInteractionRow
Reallocate
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void SetData(int, T*, int*); void SetData(Vector<T>, Vector<int>);
This method sets the row numbers and values. This method should be used carefully, and generally in conjunction with method Nullify.
// for example, you can construct the sparse vector // with two arrays row and values IVect row(2); Vector<double> values(2); row(0) = 4; values(0) = 1.5; row(1) = 1; values(1) = -0.5; Vector<double, VectSparse> U; // and provide those arrays with SetData U.SetData(values, row); // but here, the row numbers are not sorted U.Assemble();
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Nullify();
This method clears the vector without releasing memory. This method should be used carefully, and generally in conjunction with method SetData. You can look at the example shown in the explanation of method SetData.
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
int Index(int) const; int& Index(int);
This method gives a direct access to a non-zero entry
Vector<double, VectSparse> V(3); // you can use Index and Value to modify sparse vector V.Index(0) = 1; // row number of first non-zero entry V.Value(0) = 0.7; // value of first non-zero entry V.Index(1) = 5; // row number of first non-zero entry V.Value(1) = -0.7; V.Index(2) = 7; V.Value(2) = 1.2; // we display non-zero entries for (int k = 0; k < V.GetM(); k++) cout << "Interaction at row " << V.Index(k) << " value : " << V.Value(k) << endl;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
T Value(int) const; T& Value(int);
This method gives a direct access to a non-zero entry
Vector<double, VectSparse> V(3); // you can use Index and Value to modify sparse vector V.Index(0) = 1; // row number of first non-zero entry V.Value(0) = 0.7; // value of first non-zero entry V.Index(1) = 5; // row number of first non-zero entry V.Value(1) = -0.7; V.Index(2) = 7; V.Value(2) = 1.2; // we display non-zero entries for (int k = 0; k < V.GetM(); k++) cout << "Interaction at row " << V.Index(k) << " value : " << V.Value(k) << endl;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
T Val(int) const; T& Val(int);
This method returns access to V(i), if there is a non-zero entry at this position, otherwise an exception is raised.
Vector<double, VectSparse> V; // you can set non-zero entries with Get V.Get(3) = 1.5; V.Get(1) = -0.7; V.Get(7) = 1.3; // V would be equal to [0, -0.7, 0, 1.5, 0, 0, 0, 1.3] // you can modify values already present V.Val(3) = 2.8; V.Val(7) = 1.7; // V would be equal to [0, -0.7, 0, 2.8, 0, 0, 0, 1.7] // next line would raise an exception V.Val(2) = 0.4;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Copy(const Vector<T>&);
This method copies a vector into the current vector.
// copy of a vector V Vector<double, VectSparse> V(2), W; V.Index(0) = 1; V.Index(1) = 3; V.FillRand(); W.Copy(V); // this is equivalent to use operator = W = V;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Assemble();
This method sorts row numbers, and adds values if there are two same row numbers. You don't need to call this method if you are using the access operator () or methods AddInteraction.
Vector<double, VectSparse> V(3); V.Index(0) = 2; V.Value(0) = 0.3; V.Index(1) = 0; V.Value(1) = -0.5; V.Index(2) = 2; V.Value(2) = 1.2; // here the row numbers given by using Index are not sorted V.Assemble(); // V should be equal to [0 -0.5, 2 1.5] cout << "V = " << V << endl;
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Zero();
This method fills memory of 0. All non-zero entries have their values set to 0. This is useful in order to keep the same profile for the vector, and initialize it to 0, before adding new interactions. Since the sparsity pattern is conserved, there is no insertion of non-zero entries, therefore the strategy is more efficient
Vector<double, VectSparse> V; // we add two interactions V.AddInteraction(5, 1.3); V.AddInteraction(2, -10); // now we want to keep the same profile but with null values V.Zero(); // V should be equal to [2 0.0, 5 0.0] cout << "V = " << V << endl; // after you can add coefficients in that profile // so that you are more efficient (no insertion) V.AddInteraction(2, 3.0);
Class Vector<T, Vect_Full>
Vector.hxx
Vector.cxx
void Fill(); void Fill(const T0& );
This method sets values of non-zero entries with 0, 1, 2, etc or with a given value. Row numbers are not affected.
Vector<double> V(4); // row numbers V.Index(0) = 2; V.Index(1) = 4; V.Index(2) = 6; V.Index(3) = 7; // for values, we call fill V.Fill(); // V should contain [2 0.0, 4 1.0, 6 2.0, 7 3.0] // you can specify the coefficient for all values V.Fill(2); // V should contain [2 2.0, 4 2.0, 6 2.0, 7 2.0]
Class Vector<T, Vect_Full>
Vector.hxx
Vector.cxx
void FillRand();
This method sets values of non-zero entries randomly. Row numbers are not affected.
Vector<double> V(4); // row numbers V.Index(0) = 2; V.Index(1) = 4; V.Index(2) = 6; V.Index(3) = 7; // for values, we ask random values V.FillRand(); // V should contain [2 r0, 4 r1, 6 r2, 7 r3] // where r0, r1, r2 and r3 are random numbers
Class Vector<T, Vect_Full>
Vector.hxx
Vector.cxx
void AddInteraction(int, T);
This method adds/inserts a coefficient to the sparse vector. If the entry doesn't exist, it is inserted at the correct position, so that row numbers stay sorted in ascending order.
// empty vector Vector<double, VectSparse> V; // a non-zero entry is created by using AddInteraction V.AddInteraction(3, 2.5); // if the non-zero entry exists, the coefficient is added V.AddInteraction(3, -1.0); // V is now equal to 3 1.5 cout << "V = " << endl; // if you want to set the value, you can use operator () V(3) = -0.8; // V is now equal to 3 -0.8
Vector operators
AddInteractionRow
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void AddInteractionRow(Vector<int>, Vector<T>);
This method adds/inserts coefficients to the sparse vector. If there is no entry, it is inserted at the correct position, so that row numbers stay sorted in ascending order.
// empty vector Vector<double, VectSparse> V; // non-zero entries are created by using AddInteractionRow IVect row(2); Vector<double> value(2); row(0) = 6; value(0) = 1.3; row(1) = 3; value(1) = -0.8; V.AddInteractionRow(row, value); // V is now equal to [3 -0.8, 6 1.3] cout << "V = " << endl;
Vector operators
AddInteraction
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void RemoveSmallEntry(T epsilon);
This method removes non-zero entries whose values are below epsilon.
// empty vector Vector<double, VectSparse> V; V(1) = 1e-3; V(4) = 0.2; V(5) = -1.3; V(7) = -1e-4; V.RemoveSmallEntry(0.1); // V should be equal to [0, 0, 0, 0, 0.2, -1.3, 0, 0]
Vector operators
AddInteraction
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
T GetNormInf(); int GetNormInfIndex();
GetNormInf
returns the highest absolute value (modulus for complex numbers) whereas GetNormInfIndex
returns the row number where this maximum is reached. This returns the row number and not the index.
Vector<double, VectSparse> > V; V(0) = 1; V(3) = -2.2; V(4) = 0.5; int imax = V.GetNormInf(); // should return 2.2 int irow = V.GetNormInfIndex(); // should return 3 cout << "maximum reached at row " << irow << endl;
Class Vector<T, Vect_Full>
SparseVector.hxx
SparseVector.cxx
void Print() const;
This method displays the vector with 1-index convention for row numbers.
Vector<double, VectSparse> V; V.AddInteraction(5, -1.0); V.AddInteraction(2, 1.5); V.Print(); // should display 3 1.5 \n 6 -1.0
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Write(string) const; void Write(ofstream&) const;
This method writes the vector on a file/stream in binary format. The file will contain the number of non-zero entries, the list of row numbers, and then the list of values.
Vector<double, VectSparse> V; V(1) = 1.0; V(3) = 0.5; // you can write directly in a file V.Write("vector.dat"); // or open a stream with other datas ofstream file_out("vector.dat"); int my_info = 3; file_out.write(reinterpret_cast<char*>(&my_info), sizeof(int)); V.Write(file_out); file_out.close();
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void Read(string); void Read(istream&);
This method reads the vector from a file/stream in binary format. The file will contain the number of non-zero entries, the list of row numbers, and then the list of values.
Vector<double, VectSparse> V; // you can read directly on a file V.Read("vector.dat"); // or read from a stream ifstream file_in("vector.dat"); int my_info; file_in.read(reinterpret_cast<char*>(&my_info), sizeof(int)); V.Read(file_in); file_in.close();
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void WriteText(string) const; void WriteText(ofstream&) const;
This method writes the vector on a file/stream in text format. The file will contain the list of non-zero entries, each line of the file will contain a row number and a value. The 1-index convention is used for row numbers.
Vector<double, VectSparse> V; V.AddInteraction(6, 3.1); V.AddInteraction(2, -1.3); // you can write directly in a file V.WriteText("vector.dat"); // or open a stream with other datas ofstream file_out("vector.dat"); int my_info = 3; file_out << my_info << '\n'; V.WriteText(file_out); file_out.close();
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void ReadText(string); void ReadText(istream&);
This method reads the vector on a file/stream in text format. The used format is detailed above in the explanation of the method WriteText.
Vector<double, VectSparse> V; // you can read directly on a file V.ReadText("vector.dat"); // or read from a stream ifstream file_in("vector.dat"); int my_info; file_in >> my_info; V.ReadText(file_in); file_in.close();
Class Vector<T, VectSparse>
SparseVector.hxx
SparseVector.cxx
void GatherSparseEntry(const Vector& X, Vector& Y); void GatherSparseEntryZero(Vector& X, Vector& Y); void ScatterSparseEntry(const Vector& X, Vector& Y);
The function GatherSparseEntry fills the sparse vector Y with values of X. The profile of the sparse vector is not modified, already existing non-zero entry are overwritten with values contained in Y. The function GatherSparseEntryZero does the same job as GatherSparseEntry and zeroes the corresponding entries of Y. The function ScatterSparseEntry fills the dense vector Y with non-zero entries of the sparse vector X : Y(i) = X(i) for all i corresponding to a non-zero entry of X. Other entries of Y (that do not correspond to non-zero entries of X) are not modified. ScatterSparseEntry is the reciprocal function of GatherSparseEntry.
// sparse vector Vector<double, VectSparse> Vsp; Vsp.Get(1) = 4.0; Vsp.Get(4) = -1.5; Vsp.Get(7) = 0.3; // dense vector Vector<double> Y(10); Y.Fill(); // Y = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) // sets Vsp(i) = Y(i) only for non-zero entries of Vsp GatherSparseEntry(Y, Vsp); // result should be Vsp = (1, 1) (4, 4) (7, 7) // fills Vsp, and zeros values of Y GatherSparseEntryZero(Y, Vsp); // Y should be equal to (0, 0, 2, 3, 0, 5, 6, 0, 8, 9) // test for ScatterSparseEntry Vsp.Get(1) = 4.0; Vsp.Get(4) = -1.5; Vsp.Get(7) = 0.3; ScatterSparseEntry(Vsp, Y); // Y should be equal to (0, 4.0, 2, 3, -1.5, 5, 6, 0.3, 8, 9)