Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как лучше всего хранить коэффициенты? 
:(
    Опции темы
hello19
Дата 26.2.2012, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 13.7.2011

Репутация: нет
Всего: нет



Мне нужно работать с матрицей порядка 100 000. Она сильно разреженная, по этому хранить все коэффициенты - не вижу смысла. Стало быть нужно хранить только не нулевые элементы матрицы. Но вот как это сделать лучше всего, чтобы было задействовано как можно меньше памяти?
Элементы матрицы типа double
PM MAIL WWW   Вверх
feodorv
Дата 26.2.2012, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(hello19 @  26.2.2012,  12:58 Найти цитируемый пост)
как это сделать лучше всего, чтобы было задействовано как можно меньше памяти?

Хрантите 2 массива: один для double значений, другой для их индексов.
Код

struct
{
  size_t count;
  size_t reserved;
  double *values;
  unsigned int *indexes;
} spmatrix;

count означает число ненулевых элементов матрицы, reserved - число элементов, под которое выделена память (count <= reserved). Плюс подпрограмма бинарного поиска элемента с данным индексом. Плюс подпрограммы вставки/удаления элементов.

Гм. Только что дошло: у Вас матрица многомерная? Это немного более сложный случай...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
hello19
Дата 26.2.2012, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 42
Регистрация: 13.7.2011

Репутация: нет
Всего: нет



Нет, матрица обычная 100 000 * 100 000

Что-то не соображу как реализовать поиск элементов...
PM MAIL WWW   Вверх
feodorv
Дата 26.2.2012, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(hello19 @  26.2.2012,  13:58 Найти цитируемый пост)
Нет, матрица обычная 100 000 * 100 000

Если размер матрицы фиксирован, то её можно превратить в линейный список: [i][j] => [i*N+j], хотя 100 000 * 100 000 в int уже не влезают... Тогда можно хранить два набора индексов:
Код

struct
{
  size_t count;
  size_t reserved;
  double *values;
  unsigned int *x;
  unsigned int *y;
} spmatrix;


Цитата(hello19 @  26.2.2012,  13:58 Найти цитируемый пост)
Что-то не соображу как реализовать поиск элементов... 

Список индексов - отсортированный, поэтому можно воспользоваться бинарным поиском:
Код

BOOL spmatrixFind( spmatrix *m, unsigned int x, unsigned int y, unsigned int *pindex)
{
  BOOL result = FALSE;
  unsigned int lower, upper;
  int cmp;

  if( m->count == 0 )
    lower = 0;
  else
    for( lower = 0, upper = m->count-1; lower <= upper; )
    {
      unsigned int midpoint = (lower + upper) >> 1;

      if( m->x[midpoint] < x )
        cmp = -1;
      else if( m->x[midpoint] > x )
        cmp = 1;
      else if( m->y[midpoint] < y )
        cmp = -1;
      else if( m->y[midpoint] > y )
        cmp = 1;
      else /* cmp = 0; */
      {
    result = TRUE;
        lower = midpoint;
        break;
      }

      if( cmp > 0 )
        lower = midpoint + 1;
      else if( midpoint == 0 )
        break;
      else
        upper = midpoint - 1;
    }

  if( pindex != NULL ) *pindex = lower;
  return result;
}

Если элемент [x][y] не найден, значит его значение 0.0, иначе m->values[*pindex].

Добавлено @ 14:48
Аналогично пишется spmatrixAdd( m, x, y, value):
  • делаем spmatrixFind( m, x, y, &index)
  • если такой элемент найден, заменяете его значение на value (на этом всё)
  • если не найден, то тогда имеем индекс, куда нужно производить вставку (чтобы сохранить отсортированность матричных индексов)
  • 1. проверяем, есть ли свободная память в списках (m->count < m->reserved); если нет, то увеличиваем значение для reserved и перезаказываем память на все три списка (m->values, m->x, m->y) (или заказываем память, если reserved был нулевой)
  • 2. сдвигаем списки с [index] до [count-1] включительно на одну позицию вправо (освобождаем место в позиции index)
  • 3. помещаем значания x, y, value в освободившуюся позицию index
  • 4. count увеличиваем на 1


Это сообщение отредактировал(а) feodorv - 29.2.2012, 15:15


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
feodorv
Дата 26.2.2012, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Если нет желания возиться с отсортированным списком индексов, тогда можно в лоб сравнивать все пары m->x[i], m->y[i] с x, y. Но это потребует много времени...

Если же ненулевых значений мотрицы не так уж и мало (>10000), то можно воспользоваться (например) красно-чёрным деревом для хранения ненулевых значений матрицы, тогда каждый лист дерева будет содержать набор (x,y,value). Дерево удобнее тем, что при добавлении новых ненулевых элементов не нужно будет перезаказывать память (правда, и потребует больше памяти по сравнению со списками).

Это сообщение отредактировал(а) feodorv - 26.2.2012, 15:00


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
rumit7
Дата 26.2.2012, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: 6
Всего: 7



Цитата(hello19 @ 26.2.2012,  12:58)
Мне нужно работать с матрицей порядка 100 000. Она сильно разреженная, по этому хранить все коэффициенты - не вижу смысла...

Может быть вам будет интересно решение описанное здесь http://evgeny-lazin.blogspot.com/2011/06/blog-post.html
PM MAIL   Вверх
feodorv
Дата 26.2.2012, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(rumit7 @  26.2.2012,  14:55 Найти цитируемый пост)
Может быть вам будет интересно решение описанное здесь

Да, решение интересное (подобно можно организовать нечёткий поиск подстроки длинной не более 32 символов в строке произвольной длины). Но:
Цитата

массив фиксированной длины содержащий до 32-х элементов



--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
rumit7
Дата 26.2.2012, 15:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: 6
Всего: 7



Цитата(feodorv @ 26.2.2012,  15:04)
Да, решение интересное (подобно можно организовать нечёткий поиск подстроки длинной не более 32 символов в строке произвольной длины). Но:
Цитата

массив фиксированной длины содержащий до 32-х элементов

Что-то я не очень понимаю в чем проблема? std::bitset и разные другие готовые штучки уже не в моде?
PM MAIL   Вверх
Фантом
Дата 26.2.2012, 15:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: нет
Всего: 49



Технически, наверное, проще всего будет организовать массив 10^5 указателей (так что доступ по одной координате будет "прямым"), на которые повесить деревья (те же красно-черные или сразу B-), обеспечивающие поиск по второй координате. Скорость доступа по сравнению с чисто древесным вариантом будет в среднем в два раза больше, а одномерный массив из 10^5 указателей - это пустяк даже при 64-битной адресации. В принципе, если памяти не очень жалко, можно сделать аналогичную вещь, "сбросив" в линейный доступ еще и часть второй координаты (когда каждое дерево будет содержать не полную строку или столбец, а лишь некоторую часть).
PM   Вверх
volatile
Дата 26.2.2012, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Я бы первом делом попробовал на std::map, (или лучше на хеш.мап), что нибудь организовать.
на записи поставить иф. если нулевой коэф, просто не записывать в мап.
на чтении, обратное, если нет в мапе, возвращать 0.


Это сообщение отредактировал(а) volatile - 26.2.2012, 20:16
PM MAIL   Вверх
Earnest
Дата 27.2.2012, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Ну да, map (хэш-мап) с ключом pair <int, int>.


--------------------
...
PM   Вверх
azesmcar
Дата 27.2.2012, 11:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(volatile @  26.2.2012,  20:12 Найти цитируемый пост)
Я бы первом делом попробовал на std::map, (или лучше на хеш.мап), что нибудь организовать.


Цитата(hello19 @  26.2.2012,  12:58 Найти цитируемый пост)
Она сильно разреженная

Тут вопрос в том, насколько она разреженная?
Если там допустим половина элементов НЕ нулевые, то в итоге с map мы только теряем.
std::map - это +3 указателя для каждого НЕ нулевого элемента да еще плюс к нему сам индекс, а это немало, в итоге может выйти так, что расход будет больше, чем при обычной матрице, да еще и поиск становиться не константным.

Цитата(feodorv @  26.2.2012,  13:21 Найти цитируемый пост)
Хрантите 2 массива

В данном случае опять такие теряется константность поиска, но если хранить массив индексов отсортированным, то можно будет применить бинарный поиск.

Мне кажется данных мало для однозначного ответа.

hello19
Что для тебя важнее? Скорость нахождения элемента или размер расходуемой памяти, какой процент нулевых элементов ожидается в матрице?
Что предполагается делать с матрицей? Какие действия?
PM   Вверх
math64
Дата 29.2.2012, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Ещё зависит от того, где расположен ненулевые элементы.
Если ненулевые элементы находятся около главной диалогали - хранить по диагоналям полностью.
индекс диагонали - (x-y-minDiagonal), индекс на диагонали - max(x,y);
Код

struct matrix {
int size;
int minDiagonal;
vector<vector<double> > diagonals;
};

Если ненулевые элементы расположены блоками возле определеных координат
Код

struct matrix {
  struct submatix {
     int x, y, w, h;
    vector<vector<double> > data;
  };
  std::vector<submatrix> submatrices;
};


Добавлено через 12 минут и 50 секунд
При делении на блоки для поиска удобно, чтобы они были одного размера и выравнены по своему размеру:
Код

struct matrix10 {
double data[10][10];
};
struct matrix100 {
matrix10* data[10][10];
double get(int x, int y) { return matrix10* m = data[x/10][y/10]; return m?m->data[x%10][y%10]:0; }
};
struct matrix1000 {
matrix100* data[10][10];
double get(int x, int y) { return matrix100* m = data[x/100][y/100]; return m?m->get(x%100,y%100):0; }
};
struct matrix10000 {
matrix1000* data[10][10];
double get(int x, int y) { return matrix1000* m = data[x/1000][y/1000]; return m?m->get(x%1000,y%1000):0; }
};
struct matrix100000 {
matrix10000* data[10][10];
double get(int x, int y) { return matrix10000* m = data[x/10000][y/10000]; return m?m->get(x%10000,y%10000):0; }
};


PM   Вверх
baldina
Дата 29.2.2012, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.2062 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.