Inverting a ZZ_p matrix in NTL - linear-algebra

I am trying to generate a random binary matrix and its inverse mod q where q is a power of 2. Sometimes when the determinant of my matrix is invertible modulo q (so the matrix over Z_q is invertible), I am getting the error "InvMod:inverse undefined Aborted (core dumped)" and other times the inverse is computed. What am I doing incorrectly?
#include <iostream>
//NTL files
#include <NTL/ZZ_p.h>
#include <NTL/vec_vec_ZZ_p.h>
#include <NTL/LLL.h>
#include <NTL/matrix.h>
#include <NTL/vector.h>
#include <NTL/tools.h>
#include <NTL/ZZ.h>
#include <NTL/vec_vec_ZZ.h>
using namespace std;
using namespace NTL;
int main(){//task generate a random matrix S with 0/1 entries stored as a ZZ_p matrix, then generate a random, invertible S
int nn = 8;
ZZ n = ZZ(nn);
ZZ N = ZZ(0);
ZZ q; power2(q, 4);
ZZ_p::init(q);
mat_ZZ S; S.SetDims(nn,nn);
for(int i = 0; i<nn; i++){
for(int j = 0; j<nn; j++){
S[i][j] = RandomBits_ZZ(1);
}
}
mat_ZZ_p S1; S1.SetDims(nn,nn);//copy to ZZ_P
mat_ZZ_p R; R.SetDims(nn,nn);//will set to inverse if
cout<<"The random matrix is S = "<<endl; //print S
for(int i = 0; i<nn; i++){
for(int j=0; j<n;j++){
cout<<S[i][j]<<", ";
} cout<<endl;
}
ZZ d; determinant(d,S); ZZ_p d1; conv(d1, d % q);
if(GCD(q,d) == 1){//convert to mod q datatype
for(int i = 0; i<nn; i++){
for(int j = 0; j<nn; j++){
conv(S1[i][j], S[i][j]);
}
}
//let's invert the matrix and print it!
cout<<"The random matrix is R = "<<endl; //print R
R = inv(S1); //mul(R,R,S1);
for(int i = 0; i<nn; i++){
for(int j=0; j<n;j++){
cout<<R[i][j]<<", ";
} cout<<endl;
}
}
cout<<endl<<"det of S is "<<d<<" and this mod q is "<<d1<<endl;
cout<<"Our modulus is "<< q <<endl;
return 0;
}

If the determinant is invertable mod q this only means that there exists an inverse matrix. But the algorithm that computes this matrix can still come to a point where it would need to calculate the inverse of an element that don't has one.
You don't have this problem if q is prime.
By the way, here is a simplified version of your code.
#include <iostream>
//NTL files
#include <NTL/mat_ZZ_p.h>
using namespace std;
using namespace NTL;
int main()
{//task generate a random matrix S with 0/1 entries stored as a ZZ_p matrix, then generate a random, invertible S
int nn = 8;
ZZ q;
power2(q, 4);
ZZ_p::init(q);
mat_ZZ_p S;
S.SetDims(nn, nn);
for(int i = 0; i < nn; i++)
{
for(int j = 0; j < nn; j++)
{
S[i][j] = conv<ZZ_p>(RandomBits_ZZ(1));
}
}
mat_ZZ_p R;
R.SetDims(nn, nn);//will set to inverse if
cout << "The random matrix is S = " << endl << S;
ZZ_p d;
determinant(d, S);
cout << endl << "det(S) = " << d << endl;
cout << "q = " << q << endl;
if(GCD(conv<ZZ>(d), q) == 1)
{
// let's invert the matrix and print it!
R = inv(S);
cout << "The random matrix is R = " << R << endl;
}
return 0;
}

Related

Compare vector to an input number and count numbers in vector that is greater

//How do I count numbers in the input vector that is greater and lesser than input number X?
#include <iostream>
#include
#include
using namespace std;
int main()
{
int i, size;
float verdi = 0;
vector<float> minvektor;
cout << "input vectorsize " << endl;
cin >> size;
cout << "Input vector-numbers, use enten space or enter to space/divide numbers. " << endl;
for (i = 0; i < size; i++)
{
cin >> verdi;
minvektor.push_back(verdi);
}
for (i = 0; i < size; i++)
{
cout << minvektor[i] << " ";
}
// -------------------------------------------------
cout << "\ninput number X to compare to vector: " << endl;
float X;
cin >> X;
//count numbers in a vector that is greater than X
//output ex: 5 numbers in a vector that is greater than number X
}

Dealing with NA values using Rcpp

I'm testing a piece of my code, which is shown below:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix testOutMat(const int& ncols, const int& nrows, const NumericVector& col_prob){
//Store row and column positions
NumericVector col_pos = no_init(nrows);
NumericVector row_pos = no_init(nrows);
int row_val;
int nz_counter=0;
for(int j=0; j<ncols; ++j){
for(int i=0; i<nrows; ++i){
row_val = R::rbinom(1,col_prob[j]);
Rcout << "i,j: " << i << "," << j << std::endl;
Rcout << "val: " << row_val << std::endl;
if(row_val==1){ //if (i,j)th entry is a 1, save location
row_pos[i] = i;
col_pos[i] = j;
nz_counter += 1;
} else{ //assign as NA
row_pos[i] = NA_REAL;
col_pos[i] = NA_REAL;
}
Rcout << "row_pos[i]: " << row_pos[i] << std::endl;
Rcout << "col_pos[i]: " << col_pos[i] << std::endl;
Rcout << "num non-zeros: " << nz_counter << std::endl;
}
}
NumericMatrix out = no_init(nz_counter,2);
Rcout << "Printing output matrix" << std::endl;
for(int i=0; i<nz_counter; ++i){
if(!Rcpp::NumericVector::is_na(row_pos[i])){
out(i,0) = row_pos[i];
out(i,1) = col_pos[i];
}
Rcout << "row_pos[i]: " << row_pos[i] << std::endl;
Rcout << "col_pos[i]: " << col_pos[i] << std::endl;
}
return out;
}
/*** R
set.seed(1)
res <- testOutMat(ncols=5,nrows=5,col_prob = runif(20, 0.1, 0.2))
*/
From the output, I have that the entries (i,j)={(0,0),(3,1)} are non-zero, so that res should be a 2x2 matrix with 0 0 in the first row and 3 1 in the second. However, I get something very different:
[,1] [,2]
[1,] 64 1024
[2,] 1 4
I suspect that this is due to how I'm handling NAs. The overall goal of the function is to generate the row and column indices for non-zero elements (generated by the call to rbinom).
I've tried debugging this for some time now and I can't seem to get a fix.
The problem here is that you're writing over row_pos and col_pos over and over again (ncols times) without any kind of keeping track of the prior result. That, coupled with your no_init() use, is what's causing the end result you see. We can change your code just a bit to ensure that row_pos and col_pos don't get overwritten:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerMatrix testOutMat(const int ncols, const int nrows,
const NumericVector& col_prob) {
IntegerMatrix binomial_deviates(nrows, ncols);
IntegerVector row_positions;
IntegerVector col_positions;
int nz_counter = 0;
for ( int j = 0; j < ncols; ++j ) {
binomial_deviates(_, j) = rbinom(nrows, 1, col_prob[j]);
for ( int i = 0; i < nrows; ++i ) {
if ( binomial_deviates(i, j) == 1 ) {
row_positions.push_back(i);
col_positions.push_back(j);
nz_counter += 1;
}
}
}
IntegerMatrix out(nz_counter, 2);
for ( int i = 0; i < nz_counter; ++i ) {
out(i, 0) = row_positions[i];
out(i, 1) = col_positions[i];
}
return out;
}
/*** R
set.seed(1)
res <- testOutMat(ncols=5,nrows=5,col_prob = runif(20, 0.1, 0.2))
*/
Result:
> set.seed(1)
> res <- testOutMat(ncols=5,nrows=5,col_prob = runif(20, 0.1, 0.2))
> res
[,1] [,2]
[1,] 0 0
[2,] 3 1

Strange behavior when incrementally sampling using RcppArmadillo::sample

I'm trying to implement some draws using a polya urn scheme using Rcpp. Basically, I have a matrix I'm drawing from, and a 2nd matrix with weights proportional to the probabilities. After each draw, I need to increase the weight of whichever cell I drew.
I was running into some indexing errors which lead me to examine the sampling more generally, and I found that my weight matrix was getting modified by RcppArmadillo::sample. Two questions (1) is this behavior that I should have expected or is this a bug which I should report somewhere? (2) Any ideas on current work-around? Here's a reproducible example:
#include <RcppArmadilloExtensions/sample.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp ;
// [[Rcpp::export]]
void sampler(int N, int inc, NumericMatrix& weight_matrix, int reps) {
IntegerVector wm_tmp = seq_along(weight_matrix);
Rcout << "Initial weight_matrix:\n" << weight_matrix << "\n";
int x_ind;
for(int i = 0; i < reps; ++i) {
x_ind = RcppArmadillo::sample(wm_tmp, 1, true, weight_matrix)(0) - 1;
Rcout << "Weight matrix after sample: (rep = " << i << ")\n" << weight_matrix << "\n";
Rcout << "x_ind: " << x_ind << "\n";
// get indices
weight_matrix[x_ind] = weight_matrix[x_ind] + inc;
Rcout << "Add increment of " << inc << " to weight_matrix:\n" << weight_matrix << "\n";
}
}
//
// // [[Rcpp::export]]
// IntegerVector seq_cpp(IntegerMatrix x) {
// IntegerVector tmp = seq_along(x);
// IntegerVector ret = RcppArmadillo::sample(tmp, 2, true);
// return ret;
// }
/*** R
weight_matrix <- matrix(1, 5, 2)
sampler(5, 1, weight_matrix, 3)
weight_matrix <- matrix(1, 5, 2)
sampler(5, 0, weight_matrix, 3)
*/
Thanks!
That is known and documented behaviour.
You could do
i) Use Rcpp::clone() to create a distinct copy of your SEXP (ie NumericMatrix).
ii) Use an Armadillo matrix instead and pass as const arma::mat & m.
There are architectural reasons having to do with the way R organizes its data structure which mean that we cannot give you fast access (no copies!) and also protect against writes.

Prim's algorithm won't compute

I made a prim's algorithm but whenever i try to use the code it give me the same matrix back. In general it isn't minimizing. Can anyone check the code and let me know why it isn't minimizing my matrix
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <list>
#include <cstdlib>
#include <iomanip>
#include <limits.h>
int minKey(int n,int key[], bool mst[])
{
// Initialize min value
int min = INT_MAX, min_index;
for (int i = 0; i < n; i++)
if (mst[i] == false && key[i] < min)
min = key[i], min_index = i;
return min_index;
}
void print(int n,int **matrix)
{
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++) // print the matrix
{
cout << setw(2) << matrix[i][j] << " ";
}
cout << endl;
}
}
int **gen_random_graph(int n)
{
srand(time(0));
int **adj_matrix = new int*[n];
for(int i = 0; i < n; i++)
{
for (int j = i; j < n; j++) //generating a N x N matrix based on the # of vertex input
{
adj_matrix[i] = new int[n];
}
}
for(int u = 0; u < n; u++)
{
for (int v = u; v < n; v++) //decide whether it has an edge or not
{
bool edgeOrNot = rand() % 2;
adj_matrix[u][v] = adj_matrix[v][u] = edgeOrNot;
cout << u << " " << v << " " << adj_matrix[u][v] << endl;
if(adj_matrix[u][v] == true)
{
adj_matrix[v][u] = true;
if(u == v) //We can't have i = j in an undirected graph
{
adj_matrix[u][v] = -1;
}
cout << u << " " << v << " " << adj_matrix[u][v] << endl;
}
else
{
adj_matrix[v][u] = adj_matrix[u][v] = -1;
cout << u << " " << v << " " << adj_matrix[u][v] << "else" << endl;
}
}
}
for(int i = 0; i < n; i++)
{
for(int j = i; j < n; j++) //create the N x N with edges and sets the weight between the edge randomly
{
if(adj_matrix[i][j] == true)
{
int weight = rand() % 10 + 1;
adj_matrix[i][j] = adj_matrix[j][i] = weight;
cout << " ( " << i << "," << j << " ) " << "weight: " << adj_matrix[i][j] << endl;
}
}
}
print(n,adj_matrix);
return (adj_matrix);
}
void solve_mst_prim_matrix(int n, int **matrix)
{
int parent[n]; // Array to store constructed MST
int key[n]; // Key values used to pick minimum weight edge in cut
bool mstSet[n]; // To represent set of vertices not yet included in MST
// Initialize all keys as INFINITE
for (int i = 0; i < n; i++)
{
key[i] = INT_MAX, mstSet[i] = false;
}
// Always include first 1st vertex in MST.
key[0] = 0; // Make key 0 so that this vertex is picked as first vertex
parent[0] = -1; // First node is always root of MST
// The MST will have n vertices
for (int count = 0; count < n-1; count++)
{
// Pick the minimum key vertex from the set of vertices
// not yet included in MST
int u = minKey(n,key, mstSet);
// Add the picked vertex to the MST Set
mstSet[u] = true;
// Update key value and parent index of the adjacent vertices of
// the picked vertex. Consider only those vertices which are not yet
// included in MST
for (int v = 0; v < n; v++)
// matrix[u][v] is non zero only for adjacent vertices of m
// mstSet[v] is false for vertices not yet included in MST
// Update the key only if matrix[u][v] is smaller than key[v]
if (matrix[u][v] && mstSet[v] == false && matrix[u][v] < key[v])
parent[v] = u, key[v] = matrix[u][v];
}
cout << endl;
print(n,matrix);
}
int main()
{
int N;
cout << "Enter number of vertices" << endl;
cin >> N;
int **matrix = gen_random_graph(N);
solve_mst_prim_matrix(N, matrix);
return 0;
}
Correct me if I'm wrong, but after reading your code, you did not even change any value of **matrix in your solve_mst_prim_matrix function. So it basically prints the same thing..

Converting 1d vector into 2d vector

#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<double> > DV; //2d vector
std::vector<double>temp(8,0.0); //1d vector
temp[0] = 1;
temp[1] = 2;
temp[2] = 3;
temp[3] = 4;
temp[4] = 5;
temp[5] = 6;
temp[6] = 7;
temp[7] = 8;
DV.resize(3, temp);
for (int i = 0; i < DV.size(); i++)
{
for (int j = 0; j < DV.size(); j++)
{
std::cout << DV[i][j];
}
}
std::cin.get();
}
The convertion actually works but it does not give the expected the result. The output should be:
1 2 3
4 5 6
7 8
and it outputs:
123123123
Thanks in advance
I'm not aware of a method to automagically turn a 1D vector into a 2D one. It's not too hard to do manually, though...
typedef std::vector<std::vector<double>> DoubleVector2D;
DoubleVector2D boxed(size_t cols, std::vector<double> values) {
DoubleVector2D result;
for (std::size_t i = 0; i < values.size(); ++i) {
if (i % cols == 0) result.resize(result.size() + 1);
result[i / cols].push_back(values[i]);
}
return result;
}
With that done, you can call boxed(3, temp) to get back a vector of vectors of doubles. At that point, you just have to loop over them.
for (auto row : DV) {
for (auto value : row) {
std::cout << value << ' ';
}
std::cout << "\n";
}
If you're stuck without decent C++11 support, you may need to use counters or iterators.
for (int row = 0; row < DV.size(); ++row) {
for (int col = 0; col < DV[i].size(); ++col) {
std::cout << DV[row][col] << ' ';
}
std::cout << '\n';
}
Change this lines
for (int i = 0; i < DV.size(); i++){
for (int j = 0; j < DV.size(); j++){
std::cout << DV[i][j] << ", ";
}
std::cout << std::endl;
}
Your issue is how you are printing your values to the standard output.

Resources