I am trying to write a program that finds the inverse of an nxn matrix in Mathematica. I've been able to find matrices that don't find the inverse of the matrix but whose product has a determinant of 1, lol. Can you tell me where I went wrong?
m = Input["row"];
n = Input["column"];
mat = Table[Subscript[b, i, j], {i, m}, {j, n}];
mat2 = Table[Subscript[c, i, j], {i, m}, {j, n}];
For[i = 1, i <= m, i++,
For[j = 1, j <= n,
j++, {Subscript[c, i, i] = 1, Subscript[c, i, j] = 0,
Subscript[c, m, n] = 1}]];
For[i = 1, i <= m, i++,
For[j = 1, j <= n, j++,
Subscript[b, i, j] = RandomInteger[{1, 3}]]];
Print[mat // MatrixForm]
For[k = 1, k <= n - 1, k++,
For[l = k + 1, l <= n, l++,
If[Subscript[b, l, k] == 0, continue,
coe = Subscript[b, l, k]/Subscript[b, k, k];
For[t = k, t <= n, t++,
Subscript[b, l, t] = Subscript[b, l, t] - coe*Subscript[b, k, t];
Subscript[c, l, t] =
Subscript[c, l, t] - coe*Subscript[c, k, t]]]]];
For[i = 1, i <= m, i++,
coe2 = 1/Subscript[b, i, i];
For[j = 1, j <= n, j++,
Subscript[b, i, j] = Subscript[b, i, j]*coe2;
Subscript[c, i, j] = Subscript[c, i, j]*coe2]];
For[k = n - 1, k >= 1, k--,
For[l = n, l >= k + 1, l--,
If[Subscript[b, k, l] == 0, continue,
coe3 = Subscript[b, k, l]/Subscript[b, k, k];
For[t = k, t <= n, t++,
Subscript[b, t, l] = Subscript[b, t, l] - coe3*Subscript[b, t, k];
Subscript[c, t, l] =
Subscript[c, t, l] - coe3*Subscript[c, t, k]]]]];
Print[mat // MatrixForm];
Print[mat2 // MatrixForm];
Quit[];
This is not a complete answer. Just a work in progress.
For an nxn matrix you won't need m and n. Also, using Subscript makes the code difficult to read so I have replaced Subscript[b, i, j] with b[i, j] etc.
Clear[c, b, m, n, i, j, coe, coe2, coe3, k, l, t]
(* m = n = Input["n"]; *)
m = n = 5;
a = mat = Table[b[i, j], {i, m}, {j, n}];
mat2 = Table[c[i, j], {i, m}, {j, n}];
For[i = 1, i <= m, i++,
For[j = 1, j <= n, j++,
{c[i, i] = 1, c[i, j] = 0, c[m, n] = 1}]];
For[i = 1, i <= m, i++,
For[j = 1, j <= n, j++,
b[i, j] = RandomInteger[{1, 3}]]];
Print[mat // MatrixForm]
This is what you are aiming for: i.e. using RowReduce for the elimination, as per this post.
MatrixForm[inverse = RowReduce[Join[mat, mat2, 2]][[All, n + 1 ;;]]]
a.inverse == IdentityMatrix[n]
These matrices are not always invertible, e.g.
a = mat = {{1, 2, 3, 3, 3}, {1, 3, 1, 2, 1},
{2, 3, 3, 2, 3}, {3, 2, 1, 2, 1}, {3, 1, 3, 1, 3}};
So far unable to correct your code.
For[k = 1, k <= n - 1, k++,
For[l = k + 1, l <= n, l++,
If[b[l, k] != 0,
coe = b[l, k]/b[k, k];
For[t = k, t <= n, t++,
b[l, t] = b[l, t] - coe*b[k, t];
c[l, t] = c[l, t] - coe*c[k, t]]]]];
For[i = 1, i <= m, i++,
coe2 = 1/b[i, i];
For[j = 1, j <= n, j++,
b[i, j] = b[i, j]*coe2;
c[i, j] = c[i, j]*coe2]];
For[k = n - 1, k >= 1, k--,
For[l = n, l >= k + 1, l--,
If[b[k, l] != 0,
coe3 = b[k, l]/b[k, k];
For[t = k, t <= n, t++,
b[t, l] = b[t, l] - coe3*b[t, k];
c[t, l] = c[t, l] - coe3*c[t, k]]]]];
IdentityMatrix[n] == mat
MatrixForm[inverse = mat2]
a.inverse == IdentityMatrix[n]
Related
A vector V [0, n − 1] is a simple convex vector if a index j exists such that V [0] = V[1] = V[2] = ··· = V[j] and for each i > j, V[i] < V[i + 1]. Can you write pseudocode to solve this in O(log(n)) time complexity?
That's my solution, but I don't know if it works. I think it should but assuming for each i >= j, V[i] < V[i + 1]. I don't know if I have a wrong definition.
convex(A, l, r) {
m = floor((l + r) / 2);
if (A[m] == A[0] && A[m] != A[m + 1] {
return m;
}
if (A[m] == A[0]) {
return convex(A, m + 1, r);
}
else {
return convex(A, l, m - 1);
}
}
I had a code with nested for-loops
for a = 1:P
for i = 1:p
for j = 1:p
A(C(a, i), C(a, j)) = A(C(a, i), C(a, j)) + M(i, j);
end
end
end
I managed to ameliorate the time complexity
i = 1:p;
j = 1:p;
for a = 1:P
A(C(a, i), C(a, j)) = A(C(a, i), C(a, j)) + M(i, j);
end
However, I cannot use the same method for the last for loop because of array dimension errors. The constant P is also significantly larger than p, which makes the first for loop the most important to optimize.
How can I vectorise the last loop?
As an example of arbitrary values:
p = 2;
P = 5;
A = sparse(P+1, P+1); % A is a 6x6 matrix here. Sparse since we do not expect many non-zeros
C = [1 3; 3 5; 5 2; 2 4; 4 6]; % Pxp matrix with largest term = P+1
M = [3 6; 8 3]; % pxp matrix
The result of the for loop should be:
A(C(1, 1:2), C(1, 1:2)) += M(1:2, 1:2);
A(C(2, 1:2), C(2, 1:2)) += M(1:2, 1:2);
.
.
.
A(C(5, 1:2), C(5, 1:2)) += M(1:2, 1:2);
Here is a vectorized form:
[a, i, j] = ndgrid(1:P, 1:p, 1:p);
N = max(C(:));
ai = sub2ind([P, p], a, i);
aj = sub2ind([P, p], a, j);
ij = sub2ind([p, p], i, j);
A = sparse(C(ai), C(aj), M(ij), N, N);
However it may be less memory/processor efficient than the loop. As P is larger than p, You can only vectorize the outer loop:
A = sparse(N, N);
for i = 1:p
for j = 1:p
A = A + sparse(C(:, i), C(:, j), M(i, j), N, N);
end
end
Use accumarray if the computations should be applied on dense array:
A = 0;
for i = 1:p
for j = 1:p
A = A + accumarray(C(:, [i j]), M(i, j), [N, N]);
end
end
I am trying to create a Merge Sort using Wolfram Mathematica, but I am still getting this recursion error and I have no idea, where I made a misstake. I rewrite this code from Java, where it works just fine, so I guess it is some special thing for Wolfram. Do you have any idea, what could be wrong with my code?
Thanks a lot!
Heer is my code:
mergeSort[x_, left_, right_] :=
Module[{array = x, middle, n1, n2, L, R, i, j, k},
If[left < right,
middle = (left + right) / 2;
mergeSort[array, left, middle];
mergeSort[array, middle + 1, right];
n1 = middle - left + 1;
n2 = right - middle;
L = {};
R = {};
For[i = 1, i < n1, ++i,
L[[i]] = array[[left + 1]];
];
For[j = 1, j < n2, ++j,
R[[j]] = array[[middle + 1 + j]];
];
i = 0;
j = 0;
k = left;
While[i < n1 && j < n2,
If[L[[i]] <= R[[j]],
array[[k]] = L[[i]];
i++;
,
array[[k]] = R[[j]];
j++;
];
k++;
];
While[i < n1,
array[[k]] = L[[i]];
i++;
k++;
];
While[j < n2,
array[[k]] = R[[j]];
j++;
k++;
];
Return[array];
];
]
Here is my function call - mergeSort[{58, 3, 98}, 0, 3];
You have three main problems in your code.
The GfG code you are trying to adapt is passing the array arr by reference, so each recursion is operating on the same object. This doesn't ordinarily happen in Mathematica. I have added HoldFirst to pass array by reference. An alternative would be to simply leave array out of the function calls altogether and modify it directly as a global variable. E.g.
mergeSort[left_, right_] := Module[{},
If[left < right,
middle = Floor[(left + right)/2];
mergeSort[left, middle];
mergeSort[middle + 1, right];
...
Where the GfG code does int m = (l + r) / 2 the result is rounded down. This needs to be done explicitly in Mathematica: middle = Floor[(left + right)/2]. Otherwise you get infinite recursion.
The GfG code uses zero-based arrays. Mathematica uses one-based lists, so code such as for (int i = 0; i < n1; ++i) can be changed to For[i = 1, i <= n1, ++i, ...
You also had a typo from this line in the GfG code: L[i] = arr[l + i], and finally you do not need to use Return in Mathematica to return values at the end of a function.
Attributes[mergeSort] = HoldFirst;
mergeSort[array_Symbol, left_Integer, right_Integer] :=
Module[{middle, n1, n2, L, R, i, j, k},
If[left < right,
middle = Floor[(left + right)/2];
mergeSort[array, left, middle];
mergeSort[array, middle + 1, right];
n1 = middle - left + 1;
n2 = right - middle;
L = ConstantArray[Null, n1];
R = ConstantArray[Null, n2];
For[i = 1, i <= n1, ++i,
L[[i]] = array[[left + i - 1]];
];
For[j = 1, j <= n2, ++j,
R[[j]] = array[[middle + j]];
];
i = 1;
j = 1;
k = left;
While[i <= n1 && j <= n2,
If[L[[i]] <= R[[j]],
array[[k]] = L[[i]];
i++;
,
array[[k]] = R[[j]];
j++;
];
k++;
];
While[i <= n1,
array[[k]] = L[[i]];
i++;
k++;
];
While[j <= n2,
array[[k]] = R[[j]];
j++;
k++;
];
array
]
]
array = {58, 3, 98};
mergeSort[array, 1, Length[array]]
{3, 58, 98}
Note this has changed the contents of array.
array
{3, 58, 98}
Alternative Version
A version much more in the Mathematica idiom is this, by Wellin, Gaylord & Kamin.
merge[lis_List, {}] := lis
merge[{}, lis_List] := lis
merge[{a_, ra___}, {b_, rb___}] :=
If[a <= b,
Join[{a}, merge[{b}, {ra, rb}]],
Join[{b}, merge[{a, ra}, {rb}]]]
MergeSort[{}] := {}
MergeSort[{x_}] := {x}
MergeSort[lis_List] := Module[{div = Floor[Length[lis]/2]},
merge[MergeSort[Take[lis, div]], MergeSort[Drop[lis, div]]]]
MergeSort[{58, 3, 98}]
{3, 58, 98}
Im trying to find all the possible variations of a number in the form of:
'1_2_3_4' where _ is a number between 0 to 9.
I was wondering what is the best approach to this problem.
This seems like the simplest method:
static void printPerms()
{
int n = 1020304;
for (int i = 0; i <= 9; i++, n += 90000)
for (int j = 0; j <= 9; j++, n += 900)
for (int k = 0; k <= 9; k++, n += 10)
System.out.println(n);
}
Or even this, which has a lovely symmetry:
static void printPerms()
{
int n = 1020304;
for (int ni = n + 900000; n <= ni; n += 90000)
for (int nj = n + 9000; n <= nj; n += 900)
for (int nk = n + 90; n <= nk; n += 10)
System.out.println(n);
}
import java.util.*;
public class Solution {
public static void main(String[] args){
int[] fillable = {1,-1,2,-1,3,-1,4};
for(int i=0;i<=9;++i){
for(int j=0;j<=9;++j){
for(int k=0;k<=9;++k){
fillable[1] = i;
fillable[3] = j;
fillable[5] = k;
System.out.println(Arrays.toString(fillable));
}
}
}
}
}
OUTPUT:
[1, 0, 2, 0, 3, 0, 4]
[1, 0, 2, 0, 3, 1, 4]
[1, 0, 2, 0, 3, 2, 4]
[1, 0, 2, 0, 3, 3, 4]
[1, 0, 2, 0, 3, 4, 4]
[1, 0, 2, 0, 3, 5, 4]
[1, 0, 2, 0, 3, 6, 4]
.
.
.
.
Time Complexity: O(10^n) where n is no. of places to fill in. If 3 empty places if fixed, then it is O(1).
Space Complexity: O(1)
Note: There is no better way to do this. You have to go through each and every combination.
Python style, assuming ASCII code representation:
n= "1020304"
while True:
n[5]+= 1
if n[5] == ':':
n[5]= '0'
n[3]+= 1
if n[3] == ':':
n[3]= '0'
n[1]+= 1
if n[1] == ':'=
break
More specifically, I'm looking for an algorithm A that takes as its inputs
a sorted multiset M = {a1, a2, …, an } of non-negative integers;
an integer 0 ≤ k ≤ n = |M |;
a "visitor" callback V (taking a k-combination of M as input);
(optional) a sorted k-combination K of M (DEFAULT: the k-combination {a1, a2, …, ak }).
The algorithm will then visit, in lexicographic order, all the k-combinations of M, starting with K, and apply the callback V to each.
For example, if M = {0, 0, 1, 2}, k = 2, and K = {0, 1}, then executing A(M, k, V, K ) will result in the application of the visitor callback V to each of the k-combinations {0, 1}, {0, 2}, {1, 2}, in this order.
A critical requirement is that the algorithm be non-recursive.
Less critical is the precise ordering in which the k-combinations are visited, so long as the ordering is consistent. For example, colexicographic order would be fine as well. The reason for this requirement is to be able to visit all k-combinations by running the algorithm in batches.
In case there are any ambiguities in my terminology, in the remainder of this post I give some definitions that I hope will clarify matters.
A multiset is like a set, except that repetitions are allowed. For example, M = {0, 0, 1, 2} is a multiset of size 4. For this question I'm interested only in finite multisets. Also, for this question I assume that the elements of the multiset are all non-negative integers.
Define a k-combination of a multiset M as any sub-multiset of M of size k. E.g. the 2-combinations of M = {0, 0, 1, 2} are {0, 0}, {0, 1}, {0, 2}, and {1, 2}.
As with sets, the ordering of a multiset's elements does not matter. (e.g. M can also be represented as {2, 0, 1, 0}, or {1, 2, 0, 0}, etc.) but we can define a canonical representation of the multiset as the one in which the elements (here assumed to be non-negative integers) are in ascending order. In this case, any collection of k-combinations of a multiset can itself be ordered lexicographically by the canonical representations of its members. (The sequence of all 2-combinations of M given earlier exhibits such an ordering.)
UPDATE: below I've translated rici's elegant algorithm from C++ to JavaScript as faithfully as I could, and put a simple wrapper around it to conform to the question's specs and notation.
function A(M, k, V, K) {
if (K === undefined) K = M.slice(0, k);
var less_than = function (a, b) { return a < b; };
function next_comb(first, last,
/* first_value */ _, last_value,
comp) {
if (comp === undefined) comp = less_than;
// 1. Find the rightmost value which could be advanced, if any
var p = last;
while (p != first && ! comp(K[p - 1], M[--last_value])) --p;
if (p == first) return false;
// 2. Find the smallest value which is greater than the selected value
for (--p; comp(K[p], M[last_value - 1]); --last_value) ;
// 3. Overwrite the suffix of the subset with the lexicographically
// smallest sequence starting with the new value
while (p !== last) K[p++] = M[last_value++];
return true;
}
while (true) {
V(K);
if (!next_comb(0, k, 0, M.length)) break;
}
}
Demo:
function print_it (K) { console.log(K); }
A([0, 0, 0, 0, 1, 1, 1, 2, 2, 3], 8, print_it);
// [0, 0, 0, 0, 1, 1, 1, 2]
// [0, 0, 0, 0, 1, 1, 1, 3]
// [0, 0, 0, 0, 1, 1, 2, 2]
// [0, 0, 0, 0, 1, 1, 2, 3]
// [0, 0, 0, 0, 1, 2, 2, 3]
// [0, 0, 0, 1, 1, 1, 2, 2]
// [0, 0, 0, 1, 1, 1, 2, 3]
// [0, 0, 0, 1, 1, 2, 2, 3]
// [0, 0, 1, 1, 1, 2, 2, 3]
A([0, 0, 0, 0, 1, 1, 1, 2, 2, 3], 8, print_it, [0, 0, 0, 0, 1, 2, 2, 3]);
// [0, 0, 0, 0, 1, 2, 2, 3]
// [0, 0, 0, 1, 1, 1, 2, 2]
// [0, 0, 0, 1, 1, 1, 2, 3]
// [0, 0, 0, 1, 1, 2, 2, 3]
// [0, 0, 1, 1, 1, 2, 2, 3]
This, of course, is not production-ready code. In particular, I've omitted all error-checking for the sake of readability. Furthermore, an implementation for production will probably structure things differently. (E.g. the option to specify the comparator used by next_combination's becomes superfluous here.) My main aim was to keep the ideas behind the original algorithm as clear as possible in a piece of functioning code.
I checked the relevant sections of TAoCP, but this problem is at most an exercise there. The basic idea is the same as Algorithm L: try to "increment" the least significant positions first, filling the positions after the successful increment to have their least allowed values.
Here's some Python that might work but is crying out for better data structures.
def increment(M, K):
M = list(M) # copy them
K = list(K)
for x in K: # compute the difference
M.remove(x)
for i in range(len(K) - 1, -1, -1):
candidates = [x for x in M if x > K[i]]
if len(candidates) < len(K) - i:
M.append(K[i])
continue
candidates.sort()
K[i:] = candidates[:len(K) - i]
return K
return None
def demo():
M = [0, 0, 1, 1, 2, 2, 3, 3]
K = [0, 0, 1]
while K is not None:
print(K)
K = increment(M, K)
In iterative programming, to make combinations of K size you would need K for loops. First we remove the repetitions from the sorted input, then we create an array that represents the for..loop indices. While the indices array doesn't overflow we keep generating combinations.
The adder function simulates the pregression of counters in a stacked for loop. There is a little bit of room for improvement in the below implementation.
N = size of the distinct input
K = pick size
i = 0 To K - 1
for(var v_{i0} = i_{0}; v_{i} < N - (K - (i + 1)); v_{i}++) {
...
for(var v_{iK-1} = i_{K-1}; v_{iK-1} < N - (K - (i + 1)); v_{iK-1}++) {
combo = [ array[v_{i0}] ... array[v_{iK-1}] ];
}
...
}
Here's the working source code in JavaScript
function adder(arr, max) {
var k = arr.length;
var n = max;
var carry = false;
var i;
do {
for(i = k - 1; i >= 0; i--) {
arr[i]++;
if(arr[i] < n - (k - (i + 1))) {
break;
}
carry = true;
}
if(carry === true && i < 0) {
return false; // overflow;
}
if(carry === false) {
return true;
}
carry = false;
for(i = i + 1; i < k; i++) {
arr[i] = arr[i - 1] + 1;
if(arr[i] >= n - (k - (i + 1))) {
carry = true;
}
}
} while(carry === true);
return true;
}
function nchoosekUniq(arr, k, cb) {
// make the array a distinct set
var set = new Set();
for(var i=0; i < arr.length; i++) { set.add(arr[i]); }
arr = [];
set.forEach(function(v) { arr.push(v); });
//
var n = arr.length;
// create index array
var iArr = Array(k);
for(var i=0; i < k; i++) { iArr[i] = i; }
// find unique combinations;
do {
var combo = [];
for(var i=0; i < iArr.length; i++) {
combo.push(arr[iArr[i]]);
}
cb(combo);
} while(adder(iArr, n) === true);
}
var arr = [0, 0, 1, 2];
var k = 2;
nchoosekUniq(arr, k, function(set) {
var s="";
set.forEach(function(v) { s+=v; });
console.log(s);
}); // 01, 02, 12