Skip to content

Commit ced09d3

Browse files
committed
Bundle LIBLINEAR 2.47.
1 parent a22a4d3 commit ced09d3

File tree

3 files changed

+113
-114
lines changed

3 files changed

+113
-114
lines changed

src/liblinear/COPYRIGHT

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
Copyright (c) 2007-2023 The LIBLINEAR Project.
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without
6+
modification, are permitted provided that the following conditions
7+
are met:
8+
9+
1. Redistributions of source code must retain the above copyright
10+
notice, this list of conditions and the following disclaimer.
11+
12+
2. Redistributions in binary form must reproduce the above copyright
13+
notice, this list of conditions and the following disclaimer in the
14+
documentation and/or other materials provided with the distribution.
15+
16+
3. Neither name of copyright holders nor the names of its contributors
17+
may be used to endorse or promote products derived from this software
18+
without specific prior written permission.
19+
20+
21+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22+
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
25+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

src/liblinear/linear.cpp

Lines changed: 81 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -2155,75 +2155,59 @@ static int solve_l1r_lr(const problem *prob_col, const parameter *param, double
21552155
return newton_iter;
21562156
}
21572157

2158-
struct heap {
2159-
enum HEAP_TYPE { MIN, MAX };
2160-
int _size;
2161-
HEAP_TYPE _type;
2162-
feature_node* a;
2158+
static int compare_feature_node(const void *a, const void *b)
2159+
{
2160+
double a_value = (*(feature_node *)a).value;
2161+
double b_value = (*(feature_node *)b).value;
2162+
int a_index = (*(feature_node *)a).index;
2163+
int b_index = (*(feature_node *)b).index;
21632164

2164-
heap(int max_size, HEAP_TYPE type)
2165-
{
2166-
_size = 0;
2167-
a = new feature_node[max_size];
2168-
_type = type;
2169-
}
2170-
~heap()
2171-
{
2172-
delete [] a;
2173-
}
2174-
bool cmp(const feature_node& left, const feature_node& right)
2175-
{
2176-
if(_type == MIN)
2177-
return left.value > right.value;
2178-
else
2179-
return left.value < right.value;
2180-
}
2181-
int size()
2182-
{
2183-
return _size;
2184-
}
2185-
void push(feature_node node)
2165+
if(a_value < b_value)
2166+
return -1;
2167+
else if(a_value == b_value)
21862168
{
2187-
a[_size] = node;
2188-
_size++;
2189-
int i = _size-1;
2190-
while(i)
2191-
{
2192-
int p = (i-1)/2;
2193-
if(cmp(a[p], a[i]))
2194-
{
2195-
swap(a[i], a[p]);
2196-
i = p;
2197-
}
2198-
else
2199-
break;
2200-
}
2169+
if(a_index < b_index)
2170+
return -1;
2171+
else if(a_index == b_index)
2172+
return 0;
22012173
}
2202-
void pop()
2203-
{
2204-
_size--;
2205-
a[0] = a[_size];
2206-
int i = 0;
2207-
while(i*2+1 < _size)
2174+
return 1;
2175+
}
2176+
2177+
// elements before the returned index are < pivot, while those after are >= pivot
2178+
static int partition(feature_node *nodes, int low, int high)
2179+
{
2180+
int i;
2181+
int index;
2182+
2183+
swap(nodes[low + rand()%(high-low+1)], nodes[high]); // select and move pivot to the end
2184+
2185+
index = low;
2186+
for(i = low; i < high; i++)
2187+
if (compare_feature_node(&nodes[i], &nodes[high]) == -1)
22082188
{
2209-
int l = i*2+1;
2210-
int r = i*2+2;
2211-
if(r < _size && cmp(a[l], a[r]))
2212-
l = r;
2213-
if(cmp(a[i], a[l]))
2214-
{
2215-
swap(a[i], a[l]);
2216-
i = l;
2217-
}
2218-
else
2219-
break;
2189+
swap(nodes[index], nodes[i]);
2190+
index++;
22202191
}
2221-
}
2222-
feature_node top()
2223-
{
2224-
return a[0];
2225-
}
2226-
};
2192+
2193+
swap(nodes[high], nodes[index]);
2194+
return index;
2195+
}
2196+
2197+
// rearrange nodes so that nodes[:k] contains nodes with the k smallest values.
2198+
static void quick_select_min_k(feature_node *nodes, int low, int high, int k)
2199+
{
2200+
int pivot;
2201+
if(low == high)
2202+
return;
2203+
pivot = partition(nodes, low, high);
2204+
if(pivot == k)
2205+
return;
2206+
else if(k-1 < pivot)
2207+
return quick_select_min_k(nodes, low, pivot-1, k);
2208+
else
2209+
return quick_select_min_k(nodes, pivot+1, high, k);
2210+
}
22272211

22282212
// A two-level coordinate descent algorithm for
22292213
// a scaled one-class SVM dual problem
@@ -2262,11 +2246,12 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
22622246
int max_iter = 1000;
22632247
int active_size = l;
22642248

2265-
double negGmax; // max { -grad(f)_i | alpha_i < 1 }
2266-
double negGmin; // min { -grad(f)_i | alpha_i > 0 }
2267-
2268-
int *most_violating_i = new int[l];
2269-
int *most_violating_j = new int[l];
2249+
double negGmax; // max { -grad(f)_i | i in Iup }
2250+
double negGmin; // min { -grad(f)_i | i in Ilow }
2251+
// Iup = { i | alpha_i < 1 }, Ilow = { i | alpha_i > 0 }
2252+
feature_node *max_negG_of_Iup = new feature_node[l];
2253+
feature_node *min_negG_of_Ilow = new feature_node[l];
2254+
feature_node node;
22702255

22712256
int n = (int)(nu*l); // # of alpha's at upper bound
22722257
for(i=0; i<n; i++)
@@ -2328,9 +2313,8 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
23282313
}
23292314

23302315
max_inner_iter = max(active_size/10, 1);
2331-
struct heap min_heap = heap(max_inner_iter, heap::MIN);
2332-
struct heap max_heap = heap(max_inner_iter, heap::MAX);
2333-
struct feature_node node;
2316+
int len_Iup = 0;
2317+
int len_Ilow = 0;
23342318
for(s=0; s<active_size; s++)
23352319
{
23362320
i = index[s];
@@ -2339,44 +2323,28 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
23392323

23402324
if (alpha[i] < 1)
23412325
{
2342-
if (min_heap.size() < max_inner_iter)
2343-
min_heap.push(node);
2344-
else if (min_heap.top().value < node.value)
2345-
{
2346-
min_heap.pop();
2347-
min_heap.push(node);
2348-
}
2326+
max_negG_of_Iup[len_Iup] = node;
2327+
len_Iup++;
23492328
}
23502329

23512330
if (alpha[i] > 0)
23522331
{
2353-
if (max_heap.size() < max_inner_iter)
2354-
max_heap.push(node);
2355-
else if (max_heap.top().value > node.value)
2356-
{
2357-
max_heap.pop();
2358-
max_heap.push(node);
2359-
}
2332+
min_negG_of_Ilow[len_Ilow] = node;
2333+
len_Ilow++;
23602334
}
23612335
}
2362-
max_inner_iter = min(min_heap.size(), max_heap.size());
2363-
while (max_heap.size() > max_inner_iter)
2364-
max_heap.pop();
2365-
while (min_heap.size() > max_inner_iter)
2366-
min_heap.pop();
2336+
max_inner_iter = min(max_inner_iter, min(len_Iup, len_Ilow));
23672337

2368-
for (s=max_inner_iter-1; s>=0; s--)
2369-
{
2370-
most_violating_i[s] = min_heap.top().index;
2371-
most_violating_j[s] = max_heap.top().index;
2372-
min_heap.pop();
2373-
max_heap.pop();
2374-
}
2338+
quick_select_min_k(max_negG_of_Iup, 0, len_Iup-1, len_Iup-max_inner_iter);
2339+
qsort(&(max_negG_of_Iup[len_Iup-max_inner_iter]), max_inner_iter, sizeof(struct feature_node), compare_feature_node);
2340+
2341+
quick_select_min_k(min_negG_of_Ilow, 0, len_Ilow-1, max_inner_iter);
2342+
qsort(min_negG_of_Ilow, max_inner_iter, sizeof(struct feature_node), compare_feature_node);
23752343

23762344
for (s=0; s<max_inner_iter; s++)
23772345
{
2378-
i = most_violating_i[s];
2379-
j = most_violating_j[s];
2346+
i = max_negG_of_Iup[len_Iup-s-1].index;
2347+
j = min_negG_of_Ilow[s].index;
23802348

23812349
if ((alpha[i] == 0 && alpha[j] == 0) ||
23822350
(alpha[i] == 1 && alpha[j] == 1))
@@ -2484,15 +2452,14 @@ static int solve_oneclass_svm(const problem *prob, const parameter *param, doubl
24842452
*rho = sum_free/nr_free;
24852453
else
24862454
*rho = (ub + lb)/2;
2487-
24882455
info("rho = %lf\n", *rho);
24892456

24902457
delete [] QD;
24912458
delete [] G;
24922459
delete [] index;
24932460
delete [] alpha;
2494-
delete [] most_violating_i;
2495-
delete [] most_violating_j;
2461+
delete [] max_negG_of_Iup;
2462+
delete [] min_negG_of_Ilow;
24962463

24972464
return iter;
24982465
}
@@ -3678,10 +3645,10 @@ double get_decfun_rho(const struct model *model_)
36783645

36793646
void free_model_content(struct model *model_ptr)
36803647
{
3681-
if(model_ptr->w != NULL)
3682-
free(model_ptr->w);
3683-
if(model_ptr->label != NULL)
3684-
free(model_ptr->label);
3648+
free(model_ptr->w);
3649+
model_ptr->w = NULL;
3650+
free(model_ptr->label);
3651+
model_ptr->label = NULL;
36853652
}
36863653

36873654
void free_and_destroy_model(struct model **model_ptr_ptr)
@@ -3691,17 +3658,18 @@ void free_and_destroy_model(struct model **model_ptr_ptr)
36913658
{
36923659
free_model_content(model_ptr);
36933660
free(model_ptr);
3661+
*model_ptr_ptr = NULL;
36943662
}
36953663
}
36963664

36973665
void destroy_param(parameter* param)
36983666
{
3699-
if(param->weight_label != NULL)
3700-
free(param->weight_label);
3701-
if(param->weight != NULL)
3702-
free(param->weight);
3703-
if(param->init_sol != NULL)
3704-
free(param->init_sol);
3667+
free(param->weight_label);
3668+
param->weight_label = NULL;
3669+
free(param->weight);
3670+
param->weight = NULL;
3671+
free(param->init_sol);
3672+
param->init_sol = NULL;
37053673
}
37063674

37073675
const char *check_parameter(const problem *prob, const parameter *param)

src/liblinear/linear.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef _LIBLINEAR_H
22
#define _LIBLINEAR_H
33

4-
#define LIBLINEAR_VERSION 245
4+
#define LIBLINEAR_VERSION 247
55

66
#ifdef __cplusplus
77
extern "C" {

0 commit comments

Comments
 (0)