I am trying to write a program that will use backtracking to create a Sudoku solver. I have been able to create a black Sudoku grid and I can check to see if a move is a valid move. My program works fine until there are more than one choice of numbers for a square.
Problem: Will you look at my Solve method and see how I could modify it to backtrack, change the answer and move forward again. I gave the names of all of my other methods above and every one of those work.
Example input:
int board[ROWS][COLS] = {
{ 6, 0, 3, 0, 2, 0, 0, 9, 0 },
{ 0, 0, 0, 0, 5, 0, 0, 8, 0 },
{ 0, 2, 0, 4, 0, 7, 0, 0, 1 },
{ 0, 0, 6, 0, 1, 4, 3, 0, 0 },
{ 0, 0, 0, 0, 8, 0, 0, 5, 6 },
{ 0, 4, 0, 6, 0, 3, 2, 0, 0 },
{ 8, 0, 0, 2, 0, 0, 0, 0, 7 },
{ 0, 1, 0, 0, 7, 5, 8, 0, 0 },
{ 0, 3, 0, 0, 0, 6, 1, 0, 5 }
};
bool sudokuBoard::emptyCell(int i, int j);
bool sudokuBoard::isValidCol(int i, int j, int number);
bool sudokuBoard::isValidRow(int i, int j, int number);
bool sudokuBoard::isValidSquare(int i, int j, int number);
bool sudokuBoard::validMove(int i, int j, int number);
void sudokuBoard::solvePuzzle(int row, int col) {
for (int i = 1; i < 10; i++) {
if (validMove(row, col, i)) {
board[row][col] = i;
showBoard();
}
}
if (row < 8 && col < 8) {
if (col < 8) {
solvePuzzle(row, col + 1);
}
else {
col = 0;
solvePuzzle(row + 1, col);
}
}
}
Example current output:
6 5 3| 1 2 8| 4 9 0|
0 0 0| 0 5 0| 0 8 0|
0 2 0| 4 0 7| 0 0 1|
--------------------------------
0 0 6| 0 1 4| 3 0 0|
0 0 0| 0 8 0| 0 5 6|
0 4 0| 6 0 3| 2 0 0|
--------------------------------
8 0 0| 2 0 0| 0 0 7|
0 1 0| 0 7 5| 8 0 0|
0 3 0| 0 0 6| 1 0 5|
my program stops at the last 0 of the first row since there is no solution unless that previous 4 changes to a 7, the program terminates.
Backtracking can be hard to wrap your mind around the first time so we will take this step by step starting with some pseudocode of about what you have now :
while(puzzlenotsolved)
{
foreach row
{
findEmptySquare
{
findValidMove(1-9)
}
}
}
This of course gets stuck once no valid move can be found for a square because of a previously chosen value.
To counter this we need to return false when we run out of valid moves in a square, we also need to unassign our guess to make the square empty again. We then need to resume looping in the previous square where we left off.
So our find valid move function (Solve puzzle in your case) could look something like this :
bool findValidMove
{
if(noEmptySquare) {return true;} //important bit
findEmptySquare()
for (1-9)
{ if (isvalidMove )
{
assignMoveToSquare
}
if (findValidMove) {return true} //important bit
unassignMoveFromSquare
}
return false; //no values valid in this square, a previous square has a wrong value
}
Now this is considered a brute force approach, and can be optimized, but for your question lets get backtracking working and you can worry about speed optimizations later if you wish.
Note the two places I commented as important bits, the first is a signifier that there are no empty squares left. Since your program only assigns valid moves the puzzle should be complete and correct here, so the program returns true. This is the base case, In general recursive functions need a base case.
The second important bit is where the function recursively calls itself. Take note that it is still within the loop, so when a call returns false, it will resume looping in a previous call. Each call stacks onto the other like in this example except our example returns back into a loop.
Notice that the cell does not get unassigned until after the recursive function returns, this allows you to not worry about adding 1 to your rows and columns as you mentioned in your comment. All you have to do is have a reliable findEmptySquare method and recursion takes care of the rest.
Your showBoard(); method will be invaluable for debugging, i'd say put it right after assignMoveToSquare
Hopefully this helps, you are really close so I think it will. If you have further questions feel free to comment on this and I'll try to get to you when I have time.
This is what solved it for me. Thank you for all your help.
bool sudokuBoard::solvePuzzle() {
int row, col;
if (emptyCell(row, col) == false) {
return true;
}
for (int i = 1; i < 10; i++) {
cout << "Trying " << i << " in spot [" << row << "][" << col << "]" << endl;
if (validMove(row, col, i)) {
board[row][col] = i;
showBoard();
if (solvePuzzle()) {
return true;
}
board[row][col] = 0;
}
}
return false;
}
Related
I was implementing a basic version of the flood fill algorithm when I ran into this doubt.
When should you color the present cell (i.e. do image[sr][sc] = newColor) before the recursive calls or after the recursive calls? Why is there a difference between the two approaches? When the current cell is colored before the recursive calls works but if I change the order then it gives segmentation error.
Here's the code:
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
if(image.size()<=0 || image[sr][sc] == newColor) return image;
int rows = image.size(),cols=image[sr].size();
int temp = image[sr][sc];
image[sr][sc] = newColor;
//check up
if((sr-1)>=0 && image[sr-1][sc] == temp){
image = floodFill(image,sr-1,sc,newColor);
}
//check left
if((sc-1)>=0 && image[sr][sc-1] == temp){
image = floodFill(image,sr,sc-1,newColor);
}
//check right
if((sc+1)<cols && image[sr][sc+1] == temp){
image = floodFill(image,sr,sc+1,newColor);
}
//check down
if((sr+1)<rows && image[sr+1][sc] == temp){
image = floodFill(image,sr+1,sc,newColor);
}
//if i put the image[sr][sc] = newColor; here it give seg error
return image;
}
This code appears to modify image in-place by reference, so there's no need to return it -- in fact, it's a bad idea to do so. Writing the cell to the new color after the recursive call won't work because the child call's base case-related tests of image[sr+N][sc] == temp and image[sr][sc] == newColor will be wrong -- the parent call plans to color the cell but since it has't gotten around to it, it's revisited, giving an infinite loop as it spawns more child calls.
Here's my suggestion in a runnable example you can adapt to your use case:
#include <iostream>
#include <vector>
void floodFill(
std::vector <std::vector<int> > &image,
int r,
int c,
int newColor,
int oldColor
) {
if (
r < 0 ||
c < 0 ||
r >= (int)image.size() ||
c >= (int)image[r].size() ||
image[r][c] == newColor ||
image[r][c] != oldColor
) {
return;
}
image[r][c] = newColor;
floodFill(image, r - 1, c, newColor, oldColor);
floodFill(image, r, c - 1, newColor, oldColor);
floodFill(image, r, c + 1, newColor, oldColor);
floodFill(image, r + 1, c, newColor, oldColor);
}
void printMatrix(std::vector<std::vector<int> > &img) {
for (auto row : img) {
for (int cell : row) {
std::cout << cell << " ";
}
std::cout << "\n";
}
}
int main() {
std::vector<std::vector<int> > img{
{0, 2, 2, 1, 1, 1,},
{0, 0, 0, 1, 0, 1,},
{1, 1, 0, 1, 0, 1,},
{0, 1, 0, 1, 1, 1,},
{1, 0, 0, 0, 0, 0,},
{0, 0, 0, 2, 1, 0,},
};
printMatrix(img);
std::cout << "\n";
floodFill(img, 2, 2, 1, img[2][2]);
printMatrix(img);
return 0;
}
Output:
0 2 2 1 1 1
0 0 0 1 0 1
1 1 0 1 0 1
0 1 0 1 1 1
1 0 0 0 0 0
0 0 0 2 1 0
1 2 2 1 1 1
1 1 1 1 0 1
1 1 1 1 0 1
0 1 1 1 1 1
1 1 1 1 1 1
1 1 1 2 1 1
As you can see, you can remove a lot of repetition by making one base case check at the start of the recursive call. This adds an extra call relative to checking conditions in branches, but that's probably a premature optimization.
If I have a table of vertexes represented by:
a b c d
e f g h
i j k l
m n o p
How can I get the adjacencies of a node as indexes, if the indexes for this table is as follows:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
For example, node "a" should result: 1, 4, 5. node "f" results in 0, 1, 2, 4, 6, 8, 9, 10.
How can this be expanded to a table of any size? This is a 4x4, what about a 10x10? 3x4?
Can this be found with code? c++ preferred.
So far I tried: Since it's a 4x4 I tried subtracting 4 and adding 4 from the index of the node in question. However, this does not work for every node, especially the edge and corner nodes.
Here, every node is connected to 8-directional way. So we will try to get grid number of 8 adjacent cells.
// starting from upper left corner for a cell
int dr[8] = {-1, -1, -1, 0, 1, 1, 1, 0}; // 8 direction row
int dc[8] = {-1, 0, 1, 1, 1, 0, -1, -1}; // 8 direction column
int n = 20;
int m = 30;
int r = 1, c = 1; // position of 'f' is (1, 1)
for(int i = 0; i < 8; i++) {
int adjr = r + dr[i];
int adjc = c + dc[i];
if (adjr < 0 || adjr >= n || adjc < 0 || adjc >= m) continue; // check for invalid cells
cout << adjr << " " << adjc << endl; // {row, column} which is connected
}
Outputs:
0 0
0 1
0 2
1 2
2 2
2 1
2 0
1 0
These cells are connected to (1,1).
Given an integer array A of size N, find minimum sum of K non-neighboring entries (entries cant be adjacent to one another, for example, if K was 2, you cant add A[2], A[3] and call it minimum sum, even if it was, because those are adjacent/neighboring to one another), example:
A[] = {355, 46, 203, 140, 28}, k = 2, result would be 74 (46 + 28)
A[] = {9, 4, 0, 9, 14, 7, 1}, k = 3, result would be 10 (9 + 0 + 1)
The problem is somewhat similar to House Robber on leetcode, except instead of finding maximum sum of non-adjacent entries, we are tasked to find the minimum sum and with constraint K entries.
From my prespective, this is clearly a dynamic programming problem, so i tried to break down the problem recursively and implemented something like this:
#include <vector>
#include <iostream>
using namespace std;
int minimal_k(vector<int>& nums, int i, int k)
{
if (i == 0) return nums[0];
if (i < 0 || !k) return 0;
return min(minimal_k(nums, i - 2, k - 1) + nums[i], minimal_k(nums, i - 1, k));
}
int main()
{
// example above
vector<int> nums{9, 4, 0, 9, 14, 7, 1};
cout << minimal_k(nums, nums.size() - 1, 3);
// output is 4, wrong answer
}
This was my attempt at the solution, I have played around a lot with this but no luck, so what would be a solution to this problem?
This line:
if (i < 0 || !k) return 0;
If k is 0, you should probably return return 0. But if i < 0 or if the effective length of the array is less than k, you probably need to return a VERY LARGE value such that the summed result goes higher than any valid solution.
In my solution, I have the recursion return INT_MAX as a long long when recursing into an invalid subset or when k exceeds the remaining length.
And as with any of these dynamic programming and recursion problems, a cache of results so that you don't repeat the same recursive search will help out a bunch. This will speed things up by several orders of magnitude for very large input sets.
Here's my solution.
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
// the "cache" is a map from offset to another map
// that tracks k to a final result.
typedef unordered_map<size_t, unordered_map<size_t, long long>> CACHE_MAP;
bool get_cache_result(const CACHE_MAP& cache, size_t offset, size_t k, long long& result);
void insert_into_cache(CACHE_MAP& cache, size_t offset, size_t k, long long result);
long long minimal_k_impl(const vector<int>& nums, size_t offset, size_t k, CACHE_MAP& cache)
{
long long result = INT_MAX;
size_t len = nums.size();
if (k == 0)
{
return 0;
}
if (offset >= len)
{
return INT_MAX; // exceeded array boundary, return INT_MAX
}
size_t effective_length = len - offset;
// If we have more k than remaining elements, return INT_MAX to indicate
// that this recursion is invalid
// you might be able to reduce to checking (effective_length/2+1 < k)
if ( (effective_length < k) || ((effective_length == k) && (k != 1)) )
{
return INT_MAX;
}
if (get_cache_result(cache, offset, k, result))
{
return result;
}
long long sum1 = nums[offset] + minimal_k_impl(nums, offset + 2, k - 1, cache);
long long sum2 = minimal_k_impl(nums, offset + 1, k, cache);
result = std::min(sum1, sum2);
insert_into_cache(cache, offset, k, result);
return result;
}
long long minimal_k(const vector<int>& nums, size_t k)
{
CACHE_MAP cache;
return minimal_k_impl(nums, 0, k, cache);
}
bool get_cache_result(const CACHE_MAP& cache, size_t offset, size_t k, long long& result)
{
// effectively this code does this:
// result = cache[offset][k]
bool ret = false;
auto itor1 = cache.find(offset);
if (itor1 != cache.end())
{
auto& inner_map = itor1->second;
auto itor2 = inner_map.find(k);
if (itor2 != inner_map.end())
{
ret = true;
result = itor2->second;
}
}
return ret;
}
void insert_into_cache(CACHE_MAP& cache, size_t offset, size_t k, long long result)
{
cache[offset][k] = result;
}
int main()
{
vector<int> nums1{ 355, 46, 203, 140, 28 };
vector<int> nums2{ 9, 4, 0, 9, 14, 7, 1 };
vector<int> nums3{8,6,7,5,3,0,9,5,5,5,1,2,9,-10};
long long result = minimal_k(nums1, 2);
std::cout << result << std::endl;
result = minimal_k(nums2, 3);
std::cout << result << std::endl;
result = minimal_k(nums3, 3);
std::cout << result << std::endl;
return 0;
}
It is core sorting related problem. To find sum of minimum k non adjacent elements requires minimum value elements to bring next to each other by sorting. Let's see this sorting approach,
Given input array = [9, 4, 0, 9, 14, 7, 1] and k = 3
Create another array which contains elements of input array with indexes as showed below,
[9, 0], [4, 1], [0, 2], [9, 3], [14, 4], [7, 5], [1, 6]
then sort this array.
Motive behind this element and index array is, after sorting information of index of each element will not be lost.
One more array is required to keep record of used indexes, so initial view of information after sorting is as showed below,
Element and Index array
..............................
| 0 | 1 | 4 | 7 | 9 | 9 | 14 |
..............................
2 6 1 5 3 0 4 <-- Index
Used index record array
..............................
| 0 | 0 | 0 | 0 | 0 | 0 | 0 |
..............................
0 1 2 3 4 5 6 <-- Index
In used index record array 0 (false) means element at this index is not included yet in minimum sum.
Front element of sorted array is minimum value element and we include it for minimum sum and update used index record array to indicate that this element is used, as showed below,
font element is 0 at index 2 and due to this set 1(true) at index 2 of used index record array showed below,
min sum = 0
Used index record array
..............................
| 0 | 0 | 1 | 0 | 0 | 0 | 0 |
..............................
0 1 2 3 4 5 6
iterate to next element in sorted array and as you can see above it is 1 and have index 6. To include 1 in minimum sum we have to find, is left or right adjacent element of 1 already used or not, so 1 has index 6 and it is last element in input array it means we only have to check if value of index 5 is already used or not, and this can be done by looking at used index record array, and as showed above usedIndexRerocd[5] = 0 so 1 can be considered for minimum sum. After using 1, state updated to following,
min sum = 0 + 1
Used index record array
..............................
| 0 | 0 | 1 | 0 | 0 | 0 | 1 |
..............................
0 1 2 3 4 5 6
than iterate to next element which is 4 at index 1 but this can not be considered because element at index 0 is already used, same happen with elements 7, 9 because these are at index 5, 3 respectively and adjacent to used elements.
Finally iterating to 9 at index = 0 and by looking at used index record array usedIndexRecordArray[1] = 0 and that's why 9 can be included in minimum sum and final state reached to following,
min sum = 0 + 1 + 9
Used index record array
..............................
| 1 | 0 | 1 | 0 | 0 | 0 | 1 |
..............................
0 1 2 3 4 5 6
Finally minimum sum = 10,
One of the Worst case scenario when input array is already sorted then at least 2*k - 1 elements have to be iterated to find minimum sum of non adjacent k elements as showed below
input array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and k = 4 then following highlighted elements shall be considered for minimum sum,
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Note: You have to include all input validation, like one of the validation is, if you want to find minimum sum of k non adjacent elements then input should have at least 2*k - 1 elements. I am not including these validations because i am aware of all input constraints of problem.
#include <iostream>
#include <vector>
#include <algorithm>
using std::cout;
long minSumOfNonAdjacentKEntries(std::size_t k, const std::vector<int>& arr){
if(arr.size() < 2){
return 0;
}
std::vector<std::pair<int, std::size_t>> numIndexArr;
numIndexArr.reserve(arr.size());
for(std::size_t i = 0, arrSize = arr.size(); i < arrSize; ++i){
numIndexArr.emplace_back(arr[i], i);
}
std::sort(numIndexArr.begin(), numIndexArr.end(), [](const std::pair<int, std::size_t>& a,
const std::pair<int, std::size_t>& b){return a.first < b.first;});
long minSum = numIndexArr.front().first;
std::size_t elementCount = 1;
std::size_t lastIndex = arr.size() - 1;
std::vector<bool> usedIndexRecord(arr.size(), false);
usedIndexRecord[numIndexArr.front().second] = true;
for(std::vector<std::pair<int, std::size_t>>::const_iterator it = numIndexArr.cbegin() + 1,
endIt = numIndexArr.cend(); elementCount < k && endIt != it; ++it){
bool leftAdjacentElementUsed = (0 == it->second) ? false : usedIndexRecord[it->second - 1];
bool rightAdjacentElementUsed = (lastIndex == it->second) ? false : usedIndexRecord[it->second + 1];
if(!leftAdjacentElementUsed && !rightAdjacentElementUsed){
minSum += it->first;
++elementCount;
usedIndexRecord[it->second] = true;
}
}
return minSum;
}
int main(){
cout<< "k = 2, [355, 46, 203, 140, 28], min sum = "<< minSumOfNonAdjacentKEntries(2, {355, 46, 203, 140, 28})
<< '\n';
cout<< "k = 3, [9, 4, 0, 9, 14, 7, 1], min sum = "<< minSumOfNonAdjacentKEntries(3, {9, 4, 0, 9, 14, 7, 1})
<< '\n';
}
Output:
k = 2, [355, 46, 203, 140, 28], min sum = 74
k = 3, [9, 4, 0, 9, 14, 7, 1], min sum = 10
I found a bug in my code and can't figuring out the error. I tried debugging by showing the output of each variable step by step but I can't find my error. Here is what I have and what I want to do:
I have a matrix A:
0000
0101
1010
1111
And I have a matrix B:
10000
21000
30100
41100
20010
21010
40110
41110
30001
41001
30101
41101
40011
41011
40111
41111
The matrix B has 16 rows and 5 coloumns. The matrix A has 4 rows and 4 coloumns. Now I declare a matrix C that has 4 rows and 16 coloumns.
What I want to do is to calculate the inner product of each row from B with a corresponding row from A. With corresponding I mean that the first coloumn of B shoud define the row from A that I want to multiply. So the B matrix has in fact also four-dimensional vectors and the first element corresponds to the row of A. One could say this first coloumn of B is an index for choosing the row of A. Because C++ start counting by zero I substract one for my index. Here is my code:
std::vector< std::vector<int> > C(4, std::vector<int>(16));
std::vector<int> index(4);
std::vector<int> vectorA(4);
std::vector<int> vectorB(4);
for( int y = 0; y < 16; y++)
{
for(int i=0; i<4; ++i){
vectorA[i] = A[ B[y][0]-1 ][i];
}
for( int x = 1; x < 4; x++)
{
vectorB[x -1] = B[y][x];
}
C[ B[y][0] -1][index[ B[y][0] -1] ] = inner_product(vectorA.begin(), vectorA.end(), vectorB.begin(), 0);
index[B[y][0]-1] += 1;
}
This results in my matrix C:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
2 2 3 1 2 1 2 2 3 0 0 0 0 0 0 0
The first two rows are correct but row three and four are false.
The correct solution has to be (maybe except of ordering in row 3 and 4):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
4 3 3 2 3 2 3 2 2 0 0 0 0 0 0 0
Where is my problem? Please help, it drives me crazy :( I tried showing each variable by step but can't find why is it false.
Thanks and greetings.
I have to agree with the other comments: Your code is kind of confusing. You should really simplify the access of vectors by index.
First simple thing you should do is to change the first column of B to be zero-based. All stuff in C++ is zero-based. Adopt it. Do not start adjusting it in your code by substracting one. (This does not gain much simplicity, but is is symptomatic for your code.)
Another source of confusion is that you use the first column of B as an index into A. This might be an implication from the problem you'd like to solve, but it makes things unclear: first column of B has a totally different meaning, always code in a way that objects are seperated by their meaning.
For me the most confusing thing is, that I really do not get what you're up to. With inner product you mean dot product, right? You have 2 sets of vectors you want to calculate the dot product of. This should result in a set of scalars, a 1D vector not a 2D matrix. You do some special stuff with this index vector, which makes the result being a 2D matrix. But you haven't explained the purpose/system behind it. Why do you need a vector for index, not just a scalar??
Vector index is the most ugly/complex part of your code. Without having a clue what you are up to, I would still guess that you find out what is going wrong when you start printing out the full vector index on every iteration and check if it is changing the way you expect.
I don't know what's the rationale behind OP choices, so I can't properly comment the design of code provided, but for what I can understand there are some mistakes with the example input too.
Given A and B matrices as presented, the inner product of the lower rows of A with the corresponding in B is always 0:
B[1] { 2, 1, 0, 0, 0 },
row "2" or A[1] is { 0, 1, 0, 1 } <- B[4] { 2, 0, 0, 1, 0 },
B[5] { 2, 1, 0, 1, 0 },
The same for the succesive row. Only if swapped, the expected output can be obtained and so I did in my code.
vectorA and vectorB and the corresponding copy loops aren't really neccessary and probably are the cause of the wrong output:
for( int x = 1; x < 4; x++)
{ // ^^^^^ this should be <= to reach the last element
vectorB[x -1] = B[y][x];
}
My code, with the updated input and the direct use of A and B is:
#include <iostream>
#include <vector>
#include <numeric>
using vec_t = std::vector<int>; // I assume a C++11 compliant compiler
using mat_t = std::vector<vec_t>;
using std::cout;
int main() {
mat_t A{
{ 0, 0, 0, 0 },
{ 1, 0, 1, 0 }, // <-- those lines are swapped
{ 0, 1, 0, 1 }, // <--
{ 1, 1, 1, 1 }
};
mat_t B{
{ 1, 0, 0, 0, 0 },
{ 2, 1, 0, 0, 0 },
{ 3, 0, 1, 0, 0 },
{ 4, 1, 1, 0, 0 },
{ 2, 0, 0, 1, 0 },
{ 2, 1, 0, 1, 0 },
{ 4, 0, 1, 1, 0 },
{ 4, 1, 1, 1, 0 },
{ 3, 0, 0, 0, 1 },
{ 4, 1, 0, 0, 1 },
{ 3, 0, 1, 0, 1 },
{ 4, 1, 1, 0, 1 },
{ 4, 0, 0, 1, 1 },
{ 4, 1, 0, 1, 1 },
{ 4, 0, 1, 1, 1 },
{ 4, 1, 1, 1, 1 }
};
mat_t C(4, vec_t(16));
vec_t pos(4);
for ( int i = 0; i < 16; ++i )
{
int row = B[i][0] - 1;
int col = pos[row];
int prod = std::inner_product( A[row].begin(), A[row].end(),
++(B[i].begin()), 0 );
// ^^^ skip the first element
C[row][col] = prod;
if ( prod )
++pos[row];
}
for ( auto & r : C )
{
for ( int x : r ) {
cout << ' ' << x;
}
cout << '\n';
}
return 0;
}
The output is:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
2 2 3 2 3 2 3 3 4 0 0 0 0 0 0 0
I don't know if the ordering of the last row is as expected, but it mimics the logic of OP's code.
I am using Microsoft Visual Studio 2008 on a Windows 7 x64. I am trying to solve the following linear system Ax=b by using csparse, where A is positive definite.
| 1 0 0 1 |
A = | 0 3 1 0 |
| 0 1 2 1 |
| 1 0 1 2 |
| 1 |
b = | 1 |
| 1 |
| 1 |
I have used the following codes
int Ncols = 4, Nrows = 4, nnz = 10;
int cols[] = {0, 3, 1, 2, 1, 2, 3, 0, 2, 3};
int rows[] = {0, 0, 1, 1, 2, 2, 2, 3, 3, 3};
double vals[] = {1, 1, 3, 1, 1, 2, 1, 1, 1, 2};
cs *Operator = cs_spalloc(Ncols,Nrows,nnz,1,1);
int j;
for(j = 0; j < nnz; j++)
{
Operator->i[j] = rows[j];
Operator->p[j] = cols[j];
Operator->x[j] = vals[j];
Operator->nz++;
}
for(j = 0; j < nnz; j++)
cout << Operator->i[j] << " " << Operator->p[j] << " " << Operator->x[j] << endl;
Operator = cs_compress(Operator);
for(j = 0; j < nnz; j++)
cout << Operator->i[j] << " " << Operator->p[j] << " " << Operator->x[j] << endl;
// Right hand side
double b[] = {1, 1, 1, 1};
// Solving Ax = b
int status = cs_cholsol(0, Operator, &b[0]); // status = 0 means error.
In order to make sure that I have created the sparse variable correctly, I tried to print out the rows and columns index as well as their values to the console before and after cs_compress. The following is the result of this print-out.
Before:
0 0 1
0 3 1
1 1 3
1 2 1
2 1 1
2 2 2
2 3 1
3 0 1
3 2 1
3 3 2
After:
0 0 1
3 2 1
1 4 3
2 7 1
1 10 1
2 -6076574517017313795 2
3 -6076574518398440533 1
0 -76843842582893653 1
2 0 1
3 0 2
Because of the trash values that can be observed above after calling cs_compress, the solution of Ax=b does not match with the one that I have calculated with MATLAB. MATLAB results in the following solution.
| 2.0000 |
x = | 0.0000 |
| 1.0000 |
|-1.0000 |
Interestingly, I don't have this problem for the following codes which solve Ax=b, where A is a 3×3 identity matrix.
int Ncols = 3, Nrows = 3, nnz = Nrows;
cs *Operator = cs_spalloc(Ncols,Nrows,nnz,1,1);
int j;
for(j = 0; j < nnz; j++) {
Operator->i[j] = j;
Operator->p[j] = j;
Operator->x[j] = 1.0;
Operator->nz++;
}
Operator = cs_compress(Operator);
double b[] = {1, 2, 3};
int status = cs_cholsol(0, Operator, &b[0]); // status = 1 means no error.
Could someone please help me fix the problem that I have with cs_compress?
Having never worked with csparse before, I skimmed the source code.
When you call cs_spalloc() to create Operator, you are creating a triplet (indicated by setting the last parameter to 1). But, after the call to cs_copmress(), the result is no longer a triplet (you can detect this by checking the result and see that Operator->n is now -1 after compression). So, it is an error to traverse the matrix as if it were.
You can use the cs_print() API to print your sparse matrix.
As an aside, your code leaks memory, since the compressed matrix is a new allocation, and the original uncompressed matrix was not freed by cs_compress().