w4nderlust wrote:
> That's the way i'm working right now.
> Really not right now, because i discovered a bug in the single thread
> version and i'm correcting it at this time. Can you help me about it?
> The problem is this: if the result matrix is a vector 1xn or nx1 the
> final c.transpose() gives a segmentation fault. I really can't
> understand why.
> You can easly reproduce the problem addint a true as third parameter
> to the function (it calculates only the diagonal values and returns it
> in a colum vector).
> Like:
> A = sprand(400, 400, 0.02);
> B = sprand(400, 400, 0.02);
> Z= fl_spcompose(A, B, true);
>
> I attach the code
>
I really have no idea what your code is trying to do, but trying to
decypt what you've written and rewriting, I'd suggest the attached
instead.. I suspect the code doesn't do what you want however as the
matrix A is only checked at elements where the matrix B is non zero.
D.
#include <octave/oct.h>
#include <octave/parse.h>
#define HELP " -- Loadable Function: C = fl_spcompose (A, B)\n -- Loadable Function: C = fl_spcompose (A, B, LOCK)\n -- Loadable Function: C = fl_spcompose (A, B, T)\n -- Loadable Function: C = fl_spcompose (A, B, T, S)\n -- Loadable Function: C = fl_spcompose (A, B, LOCK, T)\n\nReturns the T-Norm / S-Norm composition as basic inference mechanism of Fuzzy\nLogic. By default, it calculates the max-min composition.\n\nA and B must be matrices with conformant dimensions as in matrix product.\n\nWhen true, the boolean LOCK option forces to calculate the diagonal results\nonly and returns it as a column vector.\n\nThe arguments T and S allows you to specify a custom T-Norm and S-Norm function\nrespectively. They can be:\n - 'min': use the minimum function (default for T-Norm);\n - 'pro': use the product function;\n - 'max': use the maximum function (default for S-Norm);\n - 'sum': use the sum function;\n - function_handle: a user-defined function (at most 2 arguments).\n\nNote that only the predefined functions are calculated rapidly and in\nmultithread mode. Using a user-defined function as T-Norm and/or S-Norm\nwill result in a long time calculation. \n\n\n\n\n"
#define MIN_ARG 2
#define MAX_ARG 4
#define STR_MINNORM "min"
#define STR_PRONORM "pro"
#define STR_MAXNORM "max"
#define STR_SUMNORM "sum"
#define ERR_INVALIDFUNC "fl_spcompose: the specified T-Norm or S-Norm function is invalid!\nPlease read help for details"
#define ERR_ARG "fl_spcompose: invalid arguments number!\n"
#define ERR_MATRIXSIZE "fl_spcompose: incompatible matrices dimensions\n"
#define ERR_MATRIXTYPE "fl_spcompose: the first two argument must be matrices\n"
#define ERR_LOCKOPTION "fl_spcompose: the lock_option must be 0 or 1\n"
// Functions prototype declaration
double (*calc_tnorm)(double,double);
double (*calc_snorm)(double,double);
double func_min(double first, double second);
double func_prod(double first, double second);
double func_max(double first, double second);
double func_sum(double first, double second);
double func_custom_tnorm(double first, double second);
double func_custom_snorm(double first, double second);
int checkFunction(octave_function *func);
int assignFunction(octave_value arg, int tnorm);
// T-Norm and S-Norm function pointers
octave_function *tnorm;
octave_function *snorm;
/* Main function - Check the arguments and call the compose method */
DEFUN_DLD (fl_spcompose, args, nargout, HELP)
{
int numargs = args.length(); // Arguments number
// Set the lock_option to default value (0)
bool lockoption = false;
// Set the T-Norm and S-Norm function pointer to default value
// (Minimum and Maximum)
calc_tnorm = func_min;
calc_snorm = func_max;
// Check if the argument number is correct
if(numargs < MIN_ARG || numargs > MAX_ARG)
{
error(ERR_ARG);
return octave_value_list();
}
// Check if the first two arguments are matrices
if(!args(0).is_matrix_type() || !args(1).is_matrix_type())
{
error(ERR_MATRIXTYPE);
return octave_value_list();
}
// Analyze the third argument (can be the lockoption, a custom T-Norm
// or a default string for T-Norm)
if(numargs > 2)
{
// Check if the third argument is the lockoption.
if(args(2).is_bool_scalar())
lockoption = args(2).bool_value ();
// Check if the third argument is a function
else if(args(2).is_function_handle())
{
// Check if the custom T-Norm function has at most two arguments
if(!checkFunction (args(2).function_value()))
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
else
{
// Set the custom T-Norm and force single thread mode
tnorm = args(2).function_value();
calc_tnorm = func_custom_tnorm;
}
}
// Check if the third argument is a string and try to
//assign a default T-Norm
else if(!((args(2).is_sq_string() || args(2).is_dq_string())
&& assignFunction(args(2),1)))
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
}
// Analyze the fourth argument (can be a custom T-Norm, a
// default string for T-Norm or a custom S-Norm)
if(numargs > 3)
{
// Check if the fourth argument is a function
if(args(3).is_function_handle())
{
if(lockoption)
{
// Check if the custom T-Norm function has at most
// two arguments
if(!checkFunction(args(3).function_value()))
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
else
{
// Set the custom T-Norm and force single thread mode
tnorm = args(3).function_value();
calc_tnorm = func_custom_tnorm;
}
}
else
{
// Check if the custom S-Norm function has at most two arguments
if (!checkFunction(args(3).function_value()))
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
else
{
// Set the custom S-Norm and force single thread mode
snorm = args(3).function_value();
calc_snorm = func_custom_snorm;
}
}
}
// Check if the fourth argument is a string (could be a default T-Norm)
else if (args(3).is_sq_string() || args(3).is_dq_string())
{
if (lockoption)
{
if (!assignFunction(args(3),1))
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
}
else
{
if (!assignFunction(args(3),0))
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
}
}
else
{
error(ERR_INVALIDFUNC);
return octave_value_list();
}
}
// Get the input matrices
// Create constat versions of the input matrices to
// prevent them to be filled by zeros on reading
const SparseMatrix constA = args(0).sparse_matrix_value();
const SparseMatrix constB = args(1).sparse_matrix_value();
// Get the dimensions of matrices
octave_idx_type rowsA,rowsB,colsA,colsB,nnzA,nnzB;
rowsA = constA.dims()(0);
colsA = constA.dims()(1);
nnzA = constA.nnz();
rowsB = constB.dims()(0);
colsB = constB.dims()(1);
nnzB = constB.nnz();
// Check if the dimensions are compatible
if(colsA != rowsB)
{
error(ERR_MATRIXSIZE);
return octave_value_list();
}
// Declare variables for the T-Norm and S-Norm values
double snorm_val;
double tnorm_val;
if (lockoption)
{
ColumnVector C (rowsA);
// Start the matrix composition
// Calculate the composition for the specified rows
// (between 0 and rowsA)
for (int i = 0; i < rowsA; i++)
{
snorm_val = calc_tnorm(constA(i,0), constB(0,i));
// From b.cidx(i) to b.cidx(i+1)-1 there are all the
// nonzero elements of the column j of b (constB actually)
for (int k = constB.cidx(i); k <= (constB.cidx(i+1)-1); k++)
{
// b.ridx(k) is the row index of the actual nonzero
// element in b (constB actually) so it is also the
// column index of the element in a (constA actually)
tnorm_val = calc_tnorm(constA(i, constB.ridx(k)),
constB.data(k));
snorm_val = calc_snorm(snorm_val, tnorm_val);
}
C (i) = snorm_val;
}
return octave_value (C);
}
else
{
// Count the number of non-zero elements first. This should be
// relatively low cost
octave_idx_type nnzC = 0;
for (octave_idx_type i = 0; i < rowsA; i++)
{
for(octave_idx_type j = 0; j < colsB; j++)
{
if (constB.cidx(j) != constB.cidx(j+1))
nnzC++;
else
{
for (octave_idx_type k = constB.cidx(j);
k < constB.cidx(j+1); k++)
{
if (constA(i, constB.ridx(k)) != 0)
{
nnzC++;
break;
}
}
}
}
}
// Sets proper matrix dimension
SparseMatrix C(colsB, rowsA, nnzC);
// Start the matrix composition
// Initialize the number of nonzero elemnts in sparse matrix c
int nel = 0;
C.xcidx(0) = 0;
// Calculate the composition for the specified rows
// (between 0 and rowsA)
for (int i = 0; i < rowsA; i++)
{
for(int j = 0; j < colsB; j = j++)
{
snorm_val = calc_tnorm(constA(i,0), constB(0,j));
// From b.cidx(j) to b.cidx(j+1)-1 there are all the
// nonzero elements of the column j of b (constB actually)
for (int k = constB.cidx(j); k < constB.cidx(j+1); k++)
{
// b.ridx(k) is the row index of the actual nonzero
// element in b (constB actually) so it is also the
// column index of the element in a (constA actually)
tnorm_val = calc_tnorm(constA(i, constB.ridx(k)),
constB.data(k));
snorm_val = calc_snorm(snorm_val, tnorm_val);
}
if (snorm_val != 0)
{
// Equivalent to c(i, j) = snorm_val;
C.xridx(nel) = j;
C.xdata(nel++) = snorm_val;
}
}
C.xcidx(i+1) = nel;
}
// Compress the result sparse matrix because it is initialized
// with a number of nonzero element probably greater than the real one
C.maybe_compress();
octave_stdout << "OK\n";
// Return the result sparse matrix (it's trasposed because we
// have been working on the rows of its transpose
return octave_value(C.transpose());
}
}
/* Calculate the minimum between the two values */
double func_min(double first, double second)
{
if(first < second)
return first;
else
return second;
}
/* Calculate the product between the two values */
double func_prod(double first, double second)
{
return first*second;
}
/* Calculate the Maximum between the two values */
double func_max(double first, double second)
{
if(first > second)
return first;
else
return second;
}
/* Calculate the sum between the two values */
double func_sum(double first, double second)
{
return first+second;
}
/* Calculate a custom T-Norm between the two values */
double func_custom_tnorm(double first, double second)
{
octave_value_list fargs;
fargs(0) = octave_value(first);
fargs(1) = octave_value(second);
return feval(tnorm,fargs)(0).double_value();
}
/* Calculate a custom S-Norm between the two values */
double func_custom_snorm(double first, double second)
{
octave_value_list fargs;
fargs(0) = octave_value(first);
fargs(1) = octave_value(second);
return feval(snorm,fargs)(0).double_value();
}
/* Returns 1 if an octave_function FUNC has at most 2 arguments. */
int checkFunction(octave_function *func)
{
octave_value_list testArgs;
testArgs(0) = 1;
testArgs(1) = 2;
feval(func,testArgs);
if(error_state)
return 0;
else
return 1;
}
/* Assign a default function or T-Norm or S-Norm.
If tnorm = 0 the function will be assigned as S-Norm, else the function will be assigned as T-Norm.
Returns 0 if it fails*/
int assignFunction(octave_value arg, int tnorm)
{
int res = 1;
if(arg.string_value() == STR_PRONORM)
if(tnorm)
calc_tnorm = func_prod;
else
calc_snorm = func_prod;
else if (arg.string_value() == STR_MAXNORM)
if(tnorm)
calc_tnorm = func_max;
else
calc_snorm = func_max;
else if (arg.string_value() == STR_SUMNORM)
if(tnorm)
calc_tnorm = func_sum;
else
calc_snorm = func_sum;
else if(!(arg.string_value() == STR_MINNORM))
res = 0;
return res;
}
------------------------------------------------------------------------------
Gaining the trust of online customers is vital for the success of any company
that requires sensitive data to be transmitted over the Web. Learn how to
best implement a security strategy that keeps consumers' information secure
and instills the confidence they need to proceed with transactions.
http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________
Octave-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/octave-dev