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
Octave-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to