LAPack dpbsv returns 3 for positive definite matrix - swift

I am trying to use the LAPACK banded symmetric matrix solver dpbsv. I am testing the matrix:
4, 2, 0, 0, 0
2 4, 3, 0, 0
0, 3, 11, 7, 0
0, 0, 7, 11, 5
0, 0, 0, 5, 13
Mathematica tells me that this matrix is positive definite, with a determinate of 3684
I am using swift and have constructed the array
var a: [Double] = [ 0, 2, 3, 7, 5,
4, 4, 11, 11, 13]
var b: [Double] = [1, 2, 3, 4, 5]
And I am calling dpbsv as
var uplo = Int8("U".utf8.first!) // set to 'U'
var n = __CLPK_integer(5)
var kd = __CLPK_integer(1)
var ldab = kd + 1
var nrhs = __CLPK_integer(1)
var ldb = __CLPK_integer(5)
var info: __CLPK_integer = 0
dpbsv_(&uplo,
&n,
&kd,
&nrhs,
&a,
&ldab,
&b,
&ldb,
&info)
if info != 0 {
// here info is 3, indicating non-positive definite.
NSLog("error \(info)")
}
Any idea what the issue is here? Am I interpreting the parameters to dpbsv_ correctly? I've tried other matrices that Mathematica claims are pos-def with the same result.

So, apparently, what LAPACK documents as rows need to be coded as columns in swift. So, if the array is changed to
[ 0, 4,
2, 4,
3, 11,
7, 11,
5, 13]
everything works fine.

Related

Efficient replacement of x < i values in sparse array

How would I replace values less than 4 with 0 in this array without triggering a SparseEfficiencyWarning and without reducing its sparsity?
from scipy import sparse
x = sparse.csr_matrix(
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[0, 0, 0, 2, 5]])
x[x < 4] = 0
x.toarray() # verifies that this works
Note also that the sparsity between the initial version of x is 11 stored elements, which rises to 15 stored elements after doing the masking.
Manipulate the data array directly
from scipy import sparse
x = sparse.csr_matrix(
[[0, 1, 2, 3, 4],
[1, 2, 3, 4, 5],
[0, 0, 0, 2, 5]])
x.data[x.data < 4] = 0
>>> x.toarray()
array([[0, 0, 0, 0, 4],
[0, 0, 0, 4, 5],
[0, 0, 0, 0, 5]])
>>> x.data
array([0, 0, 0, 4, 0, 0, 0, 4, 5, 0, 5])
Note that the sparsity is unchanged and there are zero values unless you run x.eliminate_zeros().
x.eliminate_zeros()
>>> x.data
array([4, 4, 5, 5])
If for some reason you don't want to use a boolean mask & fancy indexing in numpy, you can loop over the array with numba:
import numba
#numba.jit(nopython=True)
def _set_array_less_than_to_zero(array, value):
for i in range(len(array)):
if array[i] < value:
array[i] = 0
This should also be faster than the numpy indexing by a fairly substantial degree.
array = np.arange(10)
_set_array_less_than_to_zero(array, 5)
>>> array
array([0, 0, 0, 0, 0, 5, 6, 7, 8, 9])

How to construct a sobel filter for kernel initialization in input layer for images of size 128x128x3?

This is my code for sobel filter:
def init_f(shape, dtype=None):
sobel_x = tf.constant([[-5, -4, 0, 4, 5], [-8, -10, 0, 10, 8], [-10, -20, 0, 20, 10], [-8, -10, 0, 10, 8], [-5, -4, 0, 4, 5]])
ker = np.zeros(shape, dtype)
ker_shape = tf.shape(ker)
kernel = tf.tile(sobel_x, ker_shape)//*Is this correct?*
return kernel
model.add(Conv2D(filters=30, kernel_size=(5,5), kernel_initializer=init_f, strides=(1,1), activation='relu'))
So far I have managed to do this.
But, this gives me error:
Shape must be rank 2 but is rank 4 for 'conv2d_17/Tile' (op: 'Tile') with input shapes: [5,5], [4].
Tensorflow Version: 2.1.0
You're close, but the args to tile don't appear to be correct. That is why you're getting the error "Shape must be rank 2 but is rank 4 for..." You're sobel_x must be a rank 4 tensor, so you need to add two more dimensions. I used reshape in this example.
from tensorflow import keras
import tensorflow as tf
import numpy
def kernelInitializer(shape, dtype=None):
print(shape)
sobel_x = tf.constant(
[
[-5, -4, 0, 4, 5],
[-8, -10, 0, 10, 8],
[-10, -20, 0, 20, 10],
[-8, -10, 0, 10, 8],
[-5, -4, 0, 4, 5]
], dtype=dtype )
#create the missing dims.
sobel_x = tf.reshape(sobel_x, (5, 5, 1, 1))
print(tf.shape(sobel_x))
#tile the last 2 axis to get the expected dims.
sobel_x = tf.tile(sobel_x, (1, 1, shape[-2],shape[-1]))
print(tf.shape(sobel_x))
return sobel_x
x1 = keras.layers.Input((128, 128, 3))
cvl = keras.layers.Conv2D(30, kernel_size=(5,5), kernel_initializer=kernelInitializer, strides=(2,2), activation='relu')
model = keras.Sequential();
model.add(x1)
model.add(cvl)
data = numpy.ones((1, 128, 128, 3))
data[:, 0:64, 0:64, :] = 0
pd = model.predict(data)
print(pd.shape)
d = pd[0, :, :, 0]
for row in d:
for col in row:
m = '0'
if col != 0:
m = 'X'
print(m, end="")
print("")
I looked at using expand_dims instead of reshape but there didn't appear any advantage. broadcast_to seems ideal, but you still have to add the dimensions, so I don't think it was better than tile.
Why 30 filters of the same filter though? Are they going to be changed afterwards?

MiniZinc Geocode not printing all solutions to CSP with "all" solutions enabled

The Issue
With solve minimize I only get one solution, even though there are multiple optimal solutions. I have enabled printout of multiple solutions in the solver configurations. The other optimal solutions are found with solve satisfy, along with non-optimal solutions.
Possible causes
Could it be that the cardinality function card() ranks by enum value where size of two sets are equal? In other words that card(A, B) > card(B, C)? If so, do I have to switch the representation of my vertices?
The Program
I am creating a MiniZinc program for finding the minimum vertex cover of a given graph. The graph in this example is this:
With Minimal Vertex Cover solutions being:
[{A, B, C, E}, {A, B, E, F}, {A, C, D, E}, {B, C, D, E}, {B, C, D, F}, {B, D, E, F}]. My code only outputs {A, B, C, E}.
Data file:
VERTEX = {A, B, C, D, E, F};
edges = [|1, 0, 1, 0, 0, 0, 0, 0, 0
|1, 1, 0, 1, 1, 0, 0, 0, 0
|0, 1, 0, 0, 0, 1, 1, 0, 0
|0, 0, 1, 1, 0, 0, 0, 1, 0
|0, 0, 0, 0, 1, 1, 0, 1, 1
|0, 0, 0, 0, 0, 0, 1, 0, 1|];
Solver program:
% Vertices in graph
enum VERTEX;
% Edges between vertices
array[VERTEX, int] of int: edges;
int: num_edges = (length(edges) div card(VERTEX));
% Set of vertices to find
var set of VERTEX: span;
% Number of vertices connected to edge resulting from span
array[1..num_edges] of var 0..num_edges: conn;
% All edges must be connected with at least one vertex from span
constraint forall(i in 1..num_edges)
(conn[i] >= 1);
% The number of connections to each edge is the number of vertices
% in span with a connection to that edge
constraint forall(i in 1..num_edges)
(conn[i] = sum([edges[vert,i]| vert in span]));
% Minimize the number of vertices in span
solve minimize card(span);
solve minimize only show one optimal solution (in some cases, intermediate values might also be shown).
If you want all optimal solutions you must use solve satisfy and add the constraint with the optimal value:
constraint card(span) = 4;
Then the model outputs all the 6 optimal solutions:
card(cpan): 4
span: {A, B, C, E}
conn: [2, 2, 1, 1, 2, 2, 1, 1, 1]
----------
card(cpan): 4
span: {B, C, D, F}
conn: [1, 2, 1, 2, 1, 1, 2, 1, 1]
----------
card(cpan): 4
span: {A, C, D, E}
conn: [1, 1, 2, 1, 1, 2, 1, 2, 1]
----------
card(cpan): 4
span: {B, C, D, E}
conn: [1, 2, 1, 2, 2, 2, 1, 2, 1]
----------
card(cpan): 4
span: {A, B, E, F}
conn: [2, 1, 1, 1, 2, 1, 1, 1, 2]
----------
card(cpan): 4
span: {B, D, E, F}
conn: [1, 1, 1, 2, 2, 1, 1, 2, 2]
----------
==========
Note: I added the output section to show all the values:
output [
"card(cpan): \(card(span))\n",
"span: \(span)\n",
"conn: \(conn)"
];
An alternative solution is to use OptiMathSAT (v. 1.6.3).
When asking for all solutions in optimization mode, the solver returns all solutions (with respect to the output variables) with the same optimal value.
Example:
~$ mzn2fzn test.mzn test.dzn # your instance
~$ optimathsat -input=fzn -opt.fzn.all_solutions=True < test.fzn
% allsat model
span = {2, 4, 5, 6};
conn = array1d(1..9, [1, 1, 1, 2, 2, 1, 1, 2, 2]);
----------
% allsat model
span = {1, 3, 4, 5};
conn = array1d(1..9, [1, 1, 2, 1, 1, 2, 1, 2, 1]);
----------
% allsat model
span = {1, 2, 3, 5};
conn = array1d(1..9, [2, 2, 1, 1, 2, 2, 1, 1, 1]);
----------
% allsat model
span = {1, 2, 5, 6};
conn = array1d(1..9, [2, 1, 1, 1, 2, 1, 1, 1, 2]);
----------
% allsat model
span = {2, 3, 4, 5};
conn = array1d(1..9, [1, 2, 1, 2, 2, 2, 1, 2, 1]);
----------
% allsat model
span = {2, 3, 4, 6};
conn = array1d(1..9, [1, 2, 1, 2, 1, 1, 2, 1, 1]);
----------
=========
The main advantage wrt. the approach presented in the accepted answer is that OptiMathSAT is incremental, meaning that the tool searches for other solutions without being restarted, so that it can re-use any useful information that has been previously generated to speed-up the search (e.g. theory lemmas). [CAVEAT: this may not be relevant for small instances; also, other MiniZinc solvers may still be faster depending on the input problem]
Note: please notice that OptiMathSAT does not print the labels of each VERTEX, because the mzn2fzn compiler removes these labels when compiling the file. However, the mapping among numbers and labels should be obvious.
Disclosure: I am one of the developers of this tool.

Python quicksort only sorting first half

I'm taking Princeton's algorithms-divide-conquer course - 3rd week, and trying to implement the quicksort.
Here's my current implementation with some tests ready to run:
import unittest
def quicksort(x):
if len(x) <= 1:
return x
pivot = x[0]
xLeft, xRight = partition(x)
print(xLeft, xRight)
quicksort(xLeft)
quicksort(xRight)
return x
def partition(x):
j = 0
print('partition', x)
for i in range(0, len(x)):
if x[i] < x[0]:
n = x[j + 1]
x[j + 1] = x[i]
x[i] = n
j += 1
p = x[0]
x[0] = x[j]
x[j] = p
return x[:j + 1], x[j + 1:]
class Test(unittest.TestCase):
def test_partition_pivot_first(self):
arrays = [
[3, 1, 2, 5],
[3, 8, 2, 5, 1, 4, 7, 6],
[10, 100, 3, 4, 2, 101]
]
expected = [
[[2, 1, 3], [5]],
[[1, 2, 3], [5, 8, 4, 7, 6]],
[[2, 3, 4, 10], [100, 101]]
]
for i in range(0, len(arrays)):
xLeft, xRight = partition(arrays[i])
self.assertEqual(xLeft, expected[i][0])
self.assertEqual(xRight, expected[i][1])
def test_quicksort(self):
arrays = [
[1, 2, 3, 4, 5, 6],
[3, 5, 6, 10, 2, 4]
]
expected = [
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 6, 10]
]
for i in range(0, len(arrays)):
arr = arrays[i]
quicksort(arr)
self.assertEqual(arr, expected[i])
if __name__ == "__main__":
unittest.main()
so for array = [3, 5, 6, 10, 2, 4] I get [2, 3, 6, 10, 5, 4] as a result... I can't figure what's wrong with my code. It partitions just fine, but the results are off...
Can anyone chip in? :) Thank you!
it's actually so minor problem that you'd be laughing
the problem resides with quicksort function
the correct one is:
def quicksort(x):
if len(x) <= 1:
return x
pivot = x[0]
xLeft, xRight = partition(x)
print(xLeft, xRight)
quicksort(xLeft)
quicksort(xRight)
x=xLeft+xRight #this one!
return x
what happens is python created a new object out of these xleft and xright they were never an in place-sort
so this is one solution(which is not in place)
the other one is to pass the list,the start_index,end_index
and do it in place
well done fella!
edit:
and actually if you'd print xleft and xright you'd see it performed perfectly:)

Matrix dimensions must agree, Index exceeds matrix dimensions

I have the following code for positioning some subplots:
fig = figure;
fig.Units = 'centimeters';
fig.Position(3:4) = [25 25];
plotPositions = [ 3, 21, 7, 7;
12, 21, 7, 7;
];
nPlots=length(plotPositions); % shorthand variable for convenience
hAx=zeros(nPlots,1); % preallocate array for axes/subplot handles
for i = 1:length(plotPositions)
plotHandle = subplot(3, 2, i);
plotHandle.Units = 'centimeters';
plotHandle.Position = plotPositions(i,:);
hAx(i)=subplot(3, 2, i);
axis(hAx(i),[ -300 300 0 150]); %
end
If I use
plotPositions = [ 3, 21, 7, 7;
12, 21, 7, 7;
3, 12, 7, 7;
12, 12, 7, 7;
3, 3, 7, 7;
12, 3, 7, 7];
it works, but if use
plotPositions = [ 3, 21, 7, 7;
12, 21, 7, 7;
];
it does not work, and I'm getting the error:
Matrix dimensions must agree.
Index exceeds matrix dimensions.
What's going on?
You shouldn't be using the function length but instead the function size(...,1) to count the rows of plotPositions. length is actually max(size(vec)), which is 6 (number of rows, correctly) in the "working" case, and 4 (number of columns) in the non-working one.
Thus, in the 2nd case you're actually trying to access "nonexistent" rows, so MATLAB complains....