0

I am trying to use LIBSVM to perform binary-class machine learning (two classes only) using C on Eclipse. Before I started using my training data, I tried running a simple XOR problem to see if my LIBSVM application could predict the correct output value (which is a supposed to be +1).

However, after I built my project, I got errors such as undefined reference to '_Heap_Begin' , undefined reference to '_Heap_Limit' and undefined reference to '__reset_hardware'.

I added the svm.h file to the 'include' folder and svm_train.c and svm.cpp files to the 'src' folder and I already #include 'svm.h' in my source files, which is the instruction I followed from the README file in LIBSVM. I followed all the instructions from the README file, which states "You need to #include "svm.h" in your C/C++ source files and link your program with `svm.cpp'."

What am I doing wrong here?

File svm.h

#ifndef _LIBSVM_H
#define _LIBSVM_H

#define LIBSVM_VERSION 322

#ifdef __cplusplus
extern "C" {
#endif

extern int libsvm_version;

struct svm_node
{
    int index;
    double value;
};

struct svm_problem
{
    int l;
    double *y;
    struct svm_node **x;
};

enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR }; /* svm_type */
enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED };  /* kernel_type */

struct svm_parameter
{
    int svm_type;
    int kernel_type;
    int degree;    /* For poly */
    double gamma;  /* For poly/rbf/sigmoid */
    double coef0;  /* For poly/sigmoid */

    /* These are for training only */
    double cache_size; /* In MB */
    double eps;        /* Stopping criteria */
    double C;          /* For C_SVC, EPSILON_SVR and NU_SVR */
    int nr_weight;     /* For C_SVC */
    int *weight_label; /* For C_SVC */
    double* weight;    /* For C_SVC */
    double nu;         /* For NU_SVC, ONE_CLASS, and NU_SVR */
    double p;          /* For EPSILON_SVR */
    int shrinking;     /* Use the shrinking heuristics */
    int probability;   /* Do probability estimates */
};

//
// svm_model
//
struct svm_model
{
    struct svm_parameter param;  /* Parameter */
    int nr_class;                /* Number of classes, = 2 in regression/one class svm */
    int l;                       /* Total #SV */
    struct svm_node **SV;        /* SVs (SV[l]) */
    double **sv_coef;            /* Coefficients for SVs in decision functions (sv_coef[k-1][l]) */
    double *rho;                 /* Constants in decision functions (rho[k*(k-1)/2]) */
    double *probA;               /* Pariwise probability information */
    double *probB;
    int *sv_indices;             /* sv_indices[0, ..., nSV-1] are values in [1, ..., num_traning_data] to indicate SVs in the training set */

    /* For classification only */

    int *label;  /* Label of each class (label[k]) */
    int *nSV;    /* Number of SVs for each class (nSV[k]) */
                 /* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
    /* XXX */
    int free_sv; /* 1 if svm_model is created by svm_load_model*/
                 /* 0 if svm_model is created by svm_train */
};

struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);

int svm_save_model(const char *model_file_name, const struct svm_model *model);
struct svm_model *svm_load_model(const char *model_file_name);

int svm_get_svm_type(const struct svm_model *model);
int svm_get_nr_class(const struct svm_model *model);
void svm_get_labels(const struct svm_model *model, int *label);
void svm_get_sv_indices(const struct svm_model *model, int *sv_indices);
int svm_get_nr_sv(const struct svm_model *model);
double svm_get_svr_probability(const struct svm_model *model);

double svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);
double svm_predict(const struct svm_model *model, const struct svm_node *x);
double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);

void svm_free_model_content(struct svm_model *model_ptr);
void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);
void svm_destroy_param(struct svm_parameter *param);

const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
int svm_check_probability_model(const struct svm_model *model);

void svm_set_print_string_function(void (*print_func)(const char *));

#ifdef __cplusplus
}
#endif

#endif /* _LIBSVM_H */

File svm_train.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "svm.h"

#define Malloc(type,n) (type *)malloc((n)*sizeof(type))

struct svm_parameter param;     // Set by parse_command_line
struct svm_problem prob;        // Set by read_problem
struct svm_model *model;
struct svm_node *x_space;
struct svm_node ** x;
struct svm_node *testnode;

void main(void)
{
    param.svm_type = C_SVC;
    param.kernel_type = RBF;
    param.degree = 3;
    param.gamma = 0.5;
    param.coef0 = 0;
    param.nu = 0.5;
    param.cache_size = 100;
    param.C = 1;
    param.eps = 1e-3;
    param.p = 0.1;
    param.shrinking = 1;
    param.probability = 0;
    param.nr_weight = 0;
    param.weight_label = NULL;
    param.weight = NULL;


    // Problem definition-------------------------------------------------------------
    prob.l = 4;

    // x values matrix of xor values (training data)
    double matrix[prob.l][2];
    matrix[0][0] = 1;
    matrix[0][1] = 1;

    matrix[1][0] = 1;
    matrix[1][1] = 0;

    matrix[2][0] = 0;
    matrix[2][1] = 1;

    matrix[3][0] = 0;
    matrix[3][1] = 0;

    // This part i do not understand
    struct svm_node** x = (struct svm_node * *)malloc((prob.l)*sizeof(struct svm_node *));

    // Trying to assign from matrix to svm_node training examples
    for (int row = 0; row <prob.l; row++)
    {
        struct svm_node* x_space = Malloc(struct svm_node, 3);
        for (int col = 0; col < 2; col++)
        {
            x_space[col].index = col;
            x_space[col].value = matrix[row][col];
        }
        x_space[2].index = -1;  // Each row of properties should be terminated with a -1 according to the readme
        x[row] = x_space;
    }

    prob.x = x;

    // Y values
    prob.y = (double *)malloc((prob.l)*sizeof(double));
    prob.y[0] = -1;
    prob.y[1] = 1;
    prob.y[2] = 1;
    prob.y[3] = -1;

    // Train model---------------------------------------------------------------------
    struct svm_model *model = svm_train(&prob, &param);

    // Test model----------------------------------------------------------------------
    struct svm_node* testnode = (struct svm_node *) malloc((3)*sizeof(struct svm_node));
    testnode[0].index = 0;
    testnode[0].value = 1;
    testnode[1].index = 1;
    testnode[1].value = 0;
    testnode[2].index = -1;

    double retval = svm_predict(model, testnode);

    svm_destroy_param(&param);
    free(prob.y);
    free(prob.x);
    free(x_space);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ryan Jaya
  • 3
  • 1
  • You need to link the library and included necessary header file. Because it's not able to find the reference that's why it complaints. – danglingpointer Aug 24 '17 at 07:45
  • @LethalProgrammer how do I link the library to my program? I already added it into my source codes and the functions in my "svm_train.c" are in the "svm.cpp" file. Could you please explain? – Ryan Jaya Aug 24 '17 at 08:26
  • Go through this question this will help you to know, how to link the library but in eclipse, you need to add the library path and include header file location at properties. https://stackoverflow.com/questions/6016815/how-to-include-needed-c-library-using-gcc – danglingpointer Aug 24 '17 at 08:47
  • @LethalProgrammer I read the question which you sent me, but I still do not understand how I should link my svm.cpp file with my program. And I do not understand what you mean by "add the library path". Could you please explain it to me step-by-step? Thank you! – Ryan Jaya Aug 24 '17 at 14:06

1 Answers1

0

Those undefined symbols don't seem related to SVMs, but to your toolchain. There must be a standard library of your development environment that you don't link (that we can't guess since we don't know the platform you are developing for).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bartoli
  • 173
  • 8
  • But the error only occurs when I added in the svm-train.c and svm.cpp files. When I removed both those files, there were no more errors and I was able to build the rest of my project (which has nothing to do with LIBSVM). Does the errors have anything to do with the Heap memory or is it because I did not link the scm.cpp file properly? – Ryan Jaya Aug 24 '17 at 13:59
  • You have all svm code in your project. As you can see, none of those symbols are in the sources. Maybe the cpp extension of the file triggers different compiler options than the rest of your C files? – bartoli Aug 24 '17 at 15:50
  • I see. But how do I solve this issue? I am not sure how to link my cpp file with the rest of my C program. – Ryan Jaya Aug 25 '17 at 05:38