Интерфейсы

advertisement
Стандарт maCom:
Компоненты матричных алгоритмов
Стандарт maCom (Matrix Algorithms Components) описывает набор компонентов для разработки и использования обучаемых матричных алгоритмов. Стандарт находится в стадии
развития и может подвергаться изменениям.
Содержание
Введение ........................................................................................................................................2
Общие положения .....................................................................................................................2
Представление данных и алгоритмов ......................................................................................2
Состав компонентов ..................................................................................................................3
Примеры реализации и использования алгоритмов............................................................4
Реализация метода на C++ ........................................................................................................5
Реализация метода на Delphi ....................................................................................................6
Реализация библиотеки методов на C++ .................................................................................8
Использование алгоритма на C++............................................................................................9
Использование алгоритма на Delphi ......................................................................................10
Типы данных и интерфейсы ...................................................................................................10
Строка maString .......................................................................................................................10
Индекс maIndex ........................................................................................................................11
Код типа данных maType ........................................................................................................11
Интерфейсы..............................................................................................................................11
Интерфейс ячейки данных ImaCell ........................................................................................11
Интерфейсы списка ячеек ImaReadList и ImaList ................................................................12
Интерфейс списка ячеек ImaReadList ....................................................................................12
Интерфейс списка ячеек ImaList ............................................................................................13
Интерфейс многомерной матрицы ImaMatrix ......................................................................13
Интерфейс вещественной матрицы ImaDoubleMatrix .........................................................14
Интерфейс строковой матрицы ImaStringMatrix ..................................................................14
Интерфейс потока ввода-вывода ImaStream .........................................................................14
Алгоритмы и методы...............................................................................................................15
Интерфейс определителя метода ImaMethodDef..................................................................16
Спецификация описаний методов .........................................................................................17
Интерфейс метода ImaMethod ................................................................................................18
Интерфейс алгоритма ImaAlgorithm ......................................................................................19
Интерфейс управляющего ядра ImaKernel ...........................................................................20
Интерфейс библиотеки методов ImaLibrary .........................................................................21
Классы-оболочки C++ ..............................................................................................................21
Класс CmaIndex........................................................................................................................21
Класс CmaMatrix ......................................................................................................................22
Класс CmaList ..........................................................................................................................22
Класс CmaCell ..........................................................................................................................23
Класс CmaMethod ....................................................................................................................24
Класс CmaAlgorithm ................................................................................................................25
Класс CmaStream .....................................................................................................................25
Класс CmaKernel ......................................................................................................................25
Стандарт maCom: компоненты матричных алгоритмов
2
Введение
Общие положения
Область применения стандарта - разработка прикладного программного обеспечения для
интеллектуального анализа данных (data mining), распознавания, классификации и прогнозирования. На первом этапе развития стандарта приоритет отдается алгоритмам,
применяемым в технологии АКС (анализа клиентских сред).
Цель стандарта - унифицировать процессы создания и применения обучаемых алгоритмов
обработки многомерных матричных данных, обеспечить их повторное использование и
независимость от средств разработки, обеспечить эффективное накопление библиотек алгоритмов.
Технологической основой стандарта является компонентная объектная модель COM.
Стандарт описывает на языке IDL интерфейсы основных компонентов, необходимых для
разработки и использования матричных алгоритмов. Он описывает также классыоболочки (wrappers), упрощающие работу с компонентами в средах C++ и Delphi. Технология COM обеспечивает совместимость библиотек алгоритмов и прикладных программ,
разработанных в различных средах.
Функциональные возможности. Текущая версия стандарта описывает набор компонентов, позволяющих:
 реализовать обучаемые матричные алгоритмы;
 формировать и вызывать матричные алгоритмы;
 заполнять и считывать многомерные матрицы поэлементно;
 реализовать и использовать библиотеки матричных алгоритмов.
Основные принципы стандарта.
 Универсальность взятой за основу концепции алгоритма позволяет реализовать широкий класс преобразований матричных данных в рамках единого стандарта.
 Простота реализации матричных алгоритмов. Разработчик алгоритма реализует только
основные вычислительные функции алгоритма, делая минимум лишней работы.
 Простота использования матричных алгоритмов. Разработчик прикладной программы
формирует и запускает алгоритмы с помощью ясного лаконичного кода.
 Открытость алгоритмов. Общие операции, такие как просмотр, загрузка и сохранение,
производятся единообразно для всех алгоритмов, независимо от того, кем и когда они
(алгоритмы) разработаны. Создание новых общих операций не требует перекомпиляции старых алгоритмов.
 Документирование алгоритмов ведется по единому шаблону, начиная с этапа постановки технического задания по алгоритму.
Представление данных и алгоритмов
Основным типом хранилищ данных являются многомерные матрицы. Многомерная матрица данных характеризуется размерностью (числом координат) и размерами по каждой
из координат. Например, матрица 100×200 имеет размерность 2, размер 100 по координате
"строки" и размер 200 по координате "столбцы". Элементы матриц могут содержать значения различных типов, в том числе пустые. Матрицы могут быть разреженными
(эффективные структуры данных для представления разреженных матриц будут включены в следующую версию стандарта).
Основным типом вычислителей являются методы обработки матричных данных, или
просто методы. Метод - это преобразование данных, принимающее на входе некоторое
Стандарт maCom: компоненты матричных алгоритмов
3
количество матриц и выдающее на выходе некоторое количество матриц. «Некоторое количество» означает ни одной, одну или более одной. Такая общая структура вычислителя
принята во многих системах обработки матричных данных, например в MatLab. Однако в
maCom метод никогда не используется отдельно, а только в составе алгоритма, который
может объединять несколько взаимосвязанных методов. Это позволяет реализовать концепцию обучаемых (настраиваемых) алгоритмов преобразования информации.
Матричный алгоритм - это совокупность методов с общим списком параметров. Все методы алгоритма могут свободно считывать и записывать параметры алгоритма. Других
способов передачи информации между методами не предусмотрено. Допускаются алгоритмы, имеющие только один метод. Классические алгоритмы распознавания имеют два
метода: настройки и вычисления. Метод настройки формирует набор параметров на основе входной (обучающей) информации. Метод вычисления реализует основное
преобразование данных, используя настроенные значения параметров. В общем случае
алгоритм может иметь более двух методов, например для поэтапной настройки, для расширения состава обучающей выборки (дообучения), для оценивания качества настройки,
для настройки с применением процедуры кросс-проверки, и т.д.
Параметры алгоритмов, методы алгоритмов и матричные аргументы методов хранятся в
виде списков ячеек. Список ячеек - это универсальная структура данных, позволяющая
хранить значения произвольных типов: числа, строки, матрицы, методы, потоки. Ячейка
списка может также хранить еще один список. Это позволяет создавать деревья ячеек с
любым уровнем вложенности. Деревья используются для хранения параметров алгоритмов, которые в отдельных случаях образуют довольно сложный конгломерат данных.
Элементам списка можно приписывать символьные имена.
Любой объект maCom может быть сохранен в поток и считан из потока. Например, при
сохранении алгоритма происходит запись всего дерева параметров и всех методов, включая их матричные аргументы. Потоки имеют одинаковый интерфейс независимо от типа
носителя (файл, строка, окно, внешнее приложение, и т. д.).
Реализации методов объединяются в динамические библиотеки методов. Каждый метод
реализуется в виде отдельного объекта с очень простым интерфейсом, состоящим из
функций вычисления и инициализации метода. Библиотека методов предоставляет компонент, способный создавать экземпляры методов по указанному символьному имени
алгоритма. Процесс создания методов скрыт от пользователя и выполняется автоматически при создании алгоритма. Состав методов в алгоритме определяется разработчиком
библиотеки, а также порядком загрузки библиотек, поскольку одна библиотека может переопределять методы, описанные в другой библиотеке.
Состав компонентов
Стандарт описывает интерфейсы компонентов, с помощью которых можно создавать библиотеки матричных алгоритмов и использовать их в прикладных программах.
В компонентной объектной модели COM интерфейсом называется абстрактный базовый
класс, все функции которого виртуальные. Компонентом называется класс, наследующий
один или несколько интерфейсов, и реализующий все их функции. Работа с компонентом
производятся исключительно через указатель путем вызова интерфейсных функций. Данные, хранящиеся внутри компонента, не доступны для прямого использования. Это делает
компоненты более обособленными, чем при обычном объектно-ориентированном программировании. Появляется возможность модернизировать компоненты, просто заменяя
устаревшие компоненты новыми, поддерживающими прежние интерфейсы. Замена может
производиться на уровне бинарных файлов, без перекомпиляции остальных модулей.
Стандарт maCom: компоненты матричных алгоритмов
4
Стандарт maCom определяет следующие интерфейсы.
 Ячейка данных ImaCell предназначена для представления значений различных типов, как простых, так и объектных, включая матрицы, списки и потоки. Через ячейки
осуществляется запись и считывание значений в элементах списков и матриц.
 Список ячеек ImaList предназначен для представления алгоритмов, методов и их параметров в виде иерархических структур - деревьев. Элементами списка являются
ячейки данных ImaCell. Интерфейс неизменяемого списка ImaReadList предоставляет
подмножество функций ImaList и предназначен для хранения внутренней структуры
методов и алгоритмов.
 Многомерная матрица ImaMatrix предназначена для хранения данных, представления входных и выходных данных в матричных алгоритмах. Конкретные виды матриц
предоставляют интерфейсы, наследующие ImaMatrix.
 Матричный алгоритм ImaAlgorithm - основной компонент, реализующий концепцию обучаемых алгоритмов обработки многомерных матричных данных. Алгоритм
состоит из набора методов ImaMethod с общим списком параметров ImaList.
 Метод алгоритма ImaMethod предназначен для хранения матричного вычислителя
вместе со своими входными и выходными матрицами-аргументами. Данный интерфейс представляет взгляд на метод с точки зрения его пользователя.
 Поток ввода-вывода ImaStream предназначен для унификации операций вводавывода, в частности, для отображения промежуточных результатов в виде таблиц и
графиков, а также для вывода отладочной информации о текущем состоянии вычислений в алгоритмах. Поток позволяет записывать и считывать данные простых типов, а
также матрицы, списки и ячейки. Все потоки имеют одинаковый интерфейс независимо от типа носителя.
 Управляющее ядро ImaKernel предназначено для управления загрузкой библиотек и
созданием алгоритмов. Оно инициализируется один раз в начале работы прикладной
программы и уничтожается при выходе из нее.
 Определитель метода ImaMethodDef предназначен для реализации метода. Классы с
этим интерфейсом предоставляют разработчики методов. Пользователю метода нет
необходимости вызывать функции данного интерфейса непосредственно.
 Библиотека алгоритмов ImaLibrary предназначена для объединения определителей
методов в динамическую библиотеку - DLL. Пользователю алгоритмов нет необходимости вызывать функции данного интерфейса непосредственно, так как он управляет
загрузкой библиотек с помощью ImaKernel.
Примеры реализации и использования алгоритмов
В данном разделе приводятся исходные коды на С++ и Delphi, демонстрирующие порядок
реализации и использования алгоритмов обработки матричных данных на примере алгоритма наименьших квадратов LSM.
Алгоритм LSM имеет метод настройки Tune и метод вычисления Calc. Стандарт maCom
требует, чтобы все методы сообщали управляющему ядру свою спецификацию - строковое описание структуры входных и выходных данных:
Tune St|F, St|{goal} ->
Calc Sc|F -> Sc|{y}
В данном случае спецификация означает следующее. Метод настройки Tune имеет два
обязательных входных аргумента размером StF и St1 и ни одного выходного. Метод
вычисления Сalc имеет входную матрицу размером ScF и выходной вектор размером
Стандарт maCom: компоненты матричных алгоритмов
5
Sc1. Все размеры, имеющие одинаковое обозначение, должны совпадать. Например, в
матрицах St|F и Sc|F должно совпадать число столбцов.
Спецификация накладывает ограничения на размерности и размеры матричных аргументов, но ничего не говорит об их семантике. В данном случае следовало бы добавить, что
St - длина обучающей выборки, Sc - длина рабочей выборки, F - число базисных признаков, goal - целевой признак, y - результат аппроксимации целевого признака.
Предполагается также, что алгоритм LSM хранит матричный параметр под именем coeff,
содержащий настроенные коэффициенты линейной комбинации.
В примере используются классы-оболочки, скрывающие технические детали COMпрограммирования. Каждому из перечисленных выше интерфейсов соответствует классоболочка, за исключением ImaLibrary и ImaMethodDef, которым соответствуют классыкомпоненты, непосредственно реализуемые разработчиком библиотеки. Более подробно
классы-оболочки описаны в заключительной части настоящего документа.
Реализация метода на C++
Классы-оболочки C++ переопределяют операции преобразования типов, присваивания,
индексирования, и некоторые другие, чтобы сделать работу с матрицами, списками, ячейками и потоками привычной и естественной для программиста.
Наиболее быстрый способ реализации метода - вывести его путем наследования из классаполуфабриката CmaStdMethodDef, описанного в заголовочном файле maComBase.h. Следующий код показывает реализацию метода вычисления для алгоритма наименьших
квадратов.
// Метод вычисления в алгоритме наименьших квадратов
class CLsmCalc : public CmaStdMethodDef {
public:
CLsmCalc () {}
MA_INTERFUNC Description (maString* descr);
MA_INTERFUNC Init (ImaList*param, ImaList*input, ImaList*output);
MA_INTERFUNC CalcDef ();
MA_INTERFUNC maCalcCellDef (int argno, maIndex index, ImaCell* cell);
private:
// ячейки матриц-аргументов
CmaCell m_Sc_F, m_Sc_y, m_Coeff;
};
// Функция возвращает спецификацию метода
HRESULT CLsmCalc::Description (maString* descr) {
descr = L"Calc Sc|F -> Sc|{y}";
return NOERROR;
}
// Функция инициализации метода
HRESULT CLsmCalc::Init (ImaList*param, ImaList*input, ImaList*output) {
CmaList Param = param;
CmaReadList Input = input;
CmaReadList Output = output;
// ячейки матриц-аргументов запоминаются во время инициализации метода,
// что повышает эффективность доступа к матрицам во время выполнения
m_Sc_F = Input[L"Sc|F"];
m_Sc_y = Output[L"Sc|{y}"];
m_Coeff = Param[L"coeff"];
return NOERROR;
}
Стандарт maCom: компоненты матричных алгоритмов
6
// Вычисление выходной матрицы целиком
HRESULT CLsmCalc::CalcDef () {
// получение параметров и аргументов
CmaMatrix A = m_Sc_F;
CmaMatrix y = m_Sc_y;
CmaMatrix coeff = m_Coeff;
// собственно вычисление
int nSc = A.Size(0); // число строк матрицы A=Sc|F
int nF = A.Size(1); // число столбцов матрицы A=Sc|F
for (int i=0; i<nSc; i++) {
double sum = 0.0;
// вычисление линейной комбинации
for (int j=0; j<nF; j++)
sum += A[i][j] * coeff[j];
y[i] = sum;
}
return NOERROR;
}
// Вычисление одной ячейки выходной матрицы
HRESULT CLsmCalc::CalcCellDef (int argno, maIndex index, ImaCell* cell) {
// получение параметров и аргументов
CmaMatrix A = m_Sc_F;
CmaMatrix y = m_Sc_y;
CmaMatrix coeff = m_Coeff;
// собственно вычисление
int i = index->idx[0];
int nF = A.Size(1);
double sum = 0.0;
for (int j=0; j<nF; j++)
sum += A[i][j] * coeff[j];
// запись результата в ячейку
if (cell)
cell->put_AsDouble (sum);
else
y[i] = sum;
return NOERROR;
}
Реализация метода на Delphi
Классы-оболочки Delphi определяют свойства, в том числе индексированные и свойства
по умолчанию, чтобы сделать работу с матрицами, списками и ячейками привычной и
естественной для программиста. Поскольку в Delphi нельзя, как в C++, переопределить
операции присваивания и приведения типа, для доступа к элементам матриц и списков
приходится использовать свойства AsDouble, AsString, AsMatrix, и т. д.
Наиболее быстрый способ реализации метода - вывести его путем наследования из заранее заготовленного стандартного класса TStdMethodDef. Следующий код показывает
реализацию метода вычисления для алгоритма наименьших квадратов.
// Класс-реализация метода LSM.Calc
type
TLsmCalc= class (TStdMethodDef)
private
m_Sc_F, m_Sc_y, m_Coeff: TmaCell;
Стандарт maCom: компоненты матричных алгоритмов
public
function
function
function
function
end;
7
GetDescription (descr: maString): HRESULT;
Init (aparam, ainput, aoutput: ImaList): HRESULT;
CalcDef:HRESULT;
CalcCellDef (argno:integer; index:maIndex, cell:ImaCell): HRESULT;
// Структура метода
function TLsmCalc.GetDescription(descr: maString): HRESULT;
begin
descr:= 'Calc Sc|F -> Sc|{y}';
result:= S_OK;
end;
// Установка списков
function TLsmCalc.Init(aparam, ainput, aoutput: ImaList);
var Param, Input, Output: TmaList;
begin
Param.List := param;
Input.List := input;
Output.List := output;
// ячейки матриц-аргументов запоминаются во время инициализации метода,
// что повышает эффективность доступа к матрицам во время выполнения
m_Sc_F := Input['Sc|F'];
m_Sc_y := Input['Sc|{y}'];
m_Coeff := Param['coeff'];
result:=S_OK;
end;
// Вычисление выходной матрицы целиком
function TLsmCalc.CalcDef: HRESULT;
var
A, y, coeff: TmaMatrix;
nSc, nF, i, j: integer;
sum: real;
begin
// получение параметров и аргументов
A:= m_Sc_F.AsMatrix;
y:= m_Sc_y.AsMatrix;
coeff:= m_Coeff.AsMatrix;
// собственно вычисление
nSc:= A.Size[0];
nF:= A.Size[1];
for i:=0 to nSc-1 do begin
sum:=0;
for j:=0 to nF-1 do
sum:= sum + A[i][j].AsDouble * coeff[j].AsDouble;
y[i].AsDouble:= sum;
end;
result:=S_OK;
end;
// Вычисление одной ячейки выходной матрицы
Стандарт maCom: компоненты матричных алгоритмов
8
function TLsmCalc.CalcCellDef
(argno: integer; index: maIndex, cell: ImaCell): HRESULT;
var
A, y, coeff: TmaMatrix;
nF, i, j:integer;
sum: real;
begin
// получение параметров и аргументов
A:= m_Sc_F.AsMatrix;
y:= m_Sc_y.AsMatrix;
coeff:= m_Coeff.AsMatrix;
..// собственно вычисление
..i:= index.idx[0];
..nF:= A.Size[1];
..sum:= 0;
for j:=0 to nF-1 do
sum:= sum + A[i][j].AsDouble * coeff[j].AsDouble;
// запись результата в ячейку
if cell<>nil then
cell.SetDouble (sum)
else
y[i].AsDouble:= sum;
result:= S_OK;
end;
Реализация библиотеки методов на C++
Реализация библиотеки требует выполнения следующих шагов:
1. Создание нового проекта динамической библиотеки.
2. Реализация методов (см. предыдущий параграф).
3. Определение класса библиотеки, наследуемого от CmaStdLibrary.
4. Реализация в этом классе единственной функции CreateMethodDef.
5. Включение в функцию CreateMethodDef кода для создания экземпляра каждого из методов, определяемых данной библиотекой.
6. Определение GUID класса библиотеки, сгенерированного утилитой guidgen.exe.
7. Определение фабрики класса и экспортируемых функций DLL. Рекомендуется использовать для этого макросы MA_LIBLIST_BEGIN, MA_LIBRARY, MA_LIBLIST_END.
Макрос MA_LIBRARY имеет 4 аргумента: CLSID класса библиотеки; имя класса библиотеки;
текстовая строка, по которой библиотеку можно найти в реестре; и комментарий, также
заносимый в реестр. Макросы MA_LIBLIST_BEGIN и MA_LIBLIST_END служат ограничителями списка библиотек, определяемых в данной DLL.
Добавление метода в уже существующую библиотеку возможно при наличии исходного
кода и требует выполнения только шагов 2 и 5.
Ниже приводится исходный код, реализующий библиотеку CExampleLib, способную создавать методы Tune и Calc для алгоритма LSM.
#include "maComBase.h"
// классы CmaStdLibrary и CmaStdMethodDef
#include "maComClasses.h" // классы-оболочки
// GUID класса библиотеки, сгенерированный утилитой guidgen.exe
DEFINE_GUID (CLSID_CExampleLib,
Стандарт maCom: компоненты матричных алгоритмов
{0x12121212, 0x1212, 0x1212,
{0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12}});
9
// макросы для определения фабрики класса и экспортируемых функций
MA_LIBLIST_BEGIN
MA_LIBRARY (CLSID_CExampleLib, CExampleLib, "maComExample.ExampleLib", "")
MA_LIBLIST_END
// Класс библиотеки
class CExampleLib : public CmaStdLibrary<CLSID_CExampleLib> {
public:
CExampleLib () {}
// Основная функция библиотеки - создание методов
MA_INTERFUNC CreateMethodDef
(maString aname, int methodno, ImaMethodDef* method) {
HRESULT res = S_OK;
method = 0;
if (wcsicmp(aname, L"LSM")==0) {
switch (methodno) {
case 0: *method = new CLsmTune; break;
case 1: *method = new CLsmCalc; break;
default: res = MA_ERR_METHODUNDEF; break;
}
}
if (method==0 && res==S_OK)
res = E_NOMEMORY;
return res;
}
};
Использование алгоритма на C++
В типичном случае использование алгоритма строится по следующей схеме.
1. Создаётся экземпляр алгоритма.
2. Создаются входные и выходные матрицы метода.
3. Созданные матрицы присваиваются аргументам метода(-ов).
4. Заполняются входные матрицы метода.
5. Вызывается функция выполнения метода.
6. Считываются результаты выполнения метода.
Шаги 1 и 2 можно менять местами. Шаги 3 и 4 также можно менять местами.
Ниже представлен код формирования и вызова метода Tune алгоритма LSM.
// создание ядра и загрузка библиотеки
CmaKernel Kernel;
Kernel.LoadLibraryByFilename ("maExampleLib.dll");
// создание экземпляра алгоритма
CmaAlgorithm A("LSM",Kernel);
// создание матриц данных
CmaIndex sz;
CmaMatrix F(MA_DOUBLE, sz[168][7]);
CmaMatrix g(MA_DOUBLE, sz[168][7]);
// загрузка матриц данных из потока текстового файла
Стандарт maCom: компоненты матричных алгоритмов
10
CmaStream istr(MA_FILE_READ | MA_FILE_TEXT, L"data.txt");
istr >> F >> g;
// формирование аргументов и выполнение метода
CmaMethod Tune = A.Method(L"Tune");
Tune.Input(L"St|F") = F;
Tune.Input(L"St|{goal}") = g;
Tune.Calc();
// считывание результата настройки
double approx_err = A.Param (L"Result")[L"err"];
Использование алгоритма на Delphi
Формирование и вызов метода в Delphi производится так же, как и в C++. Ниже представлена Delphi-версия того же участка кода, формирующего метод Tune алгоритма LSM.
var A: TmaAlgorithm;
Tune: TmaMethod;
F, g: TmaMatrix;
IStr: TmaStream;
// создание экземпляра алгоритма
A:= TmaAlgorithm.Create ('LSM', Kernel);
// создание матриц данных
F:= TmaMatirx.Create (MA_DOUBLE, [168,7]);
g:= TmaMatrix.Create (MA_DOUBLE, [168,1]);
// загрузка матриц данных из потока текстового файла
IStr:= TmaStream.Create (MA_FILE_READ+MA_FILE_TEXT, 'data.txt');
IStr.Read(F).Read(g);
// формирование аргументов и выполнение метода
Tune:= A.Method ('Tune');
Tune.Input('St|F').AsMatrix:= F;
Tune.Input('St|{goal}').AsMatrix:= g;
Tune.Calc();
// считывание результата настройки
approx_err:= A.Param['Result']['err'].AsDouble;
Типы данных и интерфейсы
Строка maString
Тип maString предназначен для передачи строк через интерфейсные функции и является
указателем на строку Unicode, завершающуюся нулевым символом.
typedef const wchar_t* maString;
При передаче строк соблюдаются два основных правила:
 Если строка передаётся как maString, то она является входным аргументом, создается и
удаляется вне интерфейсной функции, и функция не имеет права её модифицировать.
 Если строка передаётся как maString*, то она является выходным аргументом, создается и удаляется внутри интерфейсной функции, и клиент не имеет права её
модифицировать. Следующий вызов любой интерфейсной функции может изменить
расположенную по данному указателю строку.
Стандарт maCom: компоненты матричных алгоритмов
11
Индекс maIndex
Тип maIndex предназначен для задания координат ячеек в многомерных матрицах и списках. Реализован как массив целых чисел, нулевой элемент которого содержит размерность
(длину) индекса. Нумерация по каждой координате начинается с нуля.
typedef int* maIndex;
Эквивалентный способ реализации - через структуру:
typedef struct {
int count;
int [size_is(count)] idx[];
} *maIndex;
Код типа данных maType
Тип maType перечисляет допустимые типы данных в ячейках:
typedef unsigned long maType;
Определены следующие константы типа maType:
константа
MA_EMPTY
MA_BOOLEAN
MA_LONG
MA_DOUBLE
MA_STRING
MA_COMPONENT
MA_READLIST
MA_LIST
MA_ALGORITHM
MA_METHOD
MA_STREAM
MA_MATRIX
MA_DMATRIX
значение
0
1<<0
1<<1
1<<2
1<<3
1<<4
1<<5 + MA_COMPONENT
1<<6 + MA_READLIST
1<<7 + MA_READLIST
1<<8 + MA_READLIST
1<<9 + MA_COMPONENT
1<<10 + MA_COMPONENT
1<<11 + MA_MATRIX
тип данных
Пустое значение
Логическое значение 0/1
Длинное целое число
Вещественное число двойной точности
Строка
Компонент
Список ячеек
Список ячеек
Алгоритм
Метод алгоритма
Поток ввода-вывода
Многомерная матрица
Многомерная матрица вещественных чисел
Интерфейсы
При передаче интерфейсов соблюдаются два основных правила:
 Если интерфейс ImaX передаётся через указатель ImaX*, то он является входным аргументом, создается и удаляется клиентом (вне интерфейсной функции), которая
имеет право только вызывать функции интерфейса ImaX. В частности, она может захватить интерфейс, увеличив число ссылок с помощью функции AddRef.
 Если интерфейс ImaX передаётся через указатель на указатель ImaX**, то он является
выходным аргументом. Предыдущее значение указателя ImaX** затирается, и для него
не вызывается Release, даже если это был указатель на существующий интерфейс.
Клиент должен заботиться о том, чтобы передаваемый по ссылке указатель был заранее освобождён. При возвращении интерфейса число ссылок на него увеличивается с
помощью AddRef. По окончании использования клиент обязан освободить полученный интерфейс с помощью функции Release.
Интерфейс ячейки данных ImaCell
Ячейка данных способна хранить значение любого типа, как простого, так и объектного.
Ячейки используются при записи и чтении данных в матрицах. Из ячеек составляются
списки параметров.
Стандарт maCom: компоненты матричных алгоритмов
12
Ниже перечислены функции интерфейса ImaCell.
[propget] HRESULT Type ([out,retval] maType* type)
Функция возвращает тип значения ячейки.
[propget] HRESULT AsDouble ([out,retval] double* value)
[propput] HRESULT AsDouble ([in] double value)
[propget] HRESULT AsString ([out,retval,string] maString* value)
[propput] HRESULT AsString ([in,string] maString value)
[propget] HRESULT AsMatrix ([out,retval] ImaMatrix** value)
[propput] HRESULT AsMatrix ([in] ImaMatrix* value)
[propget] HRESULT AsList ([out,retval] ImaList** value)
[propput] HRESULT AsList ([in] ImaList* value)
[propget] HRESULT AsStream ([out,retval] ImaStream** value)
[propput] HRESULT AsStream ([in] ImaStream* value)
Функции считывают и записывают значения ячейки соответствующего типа. При записи и
считывании интерфейса у него увеличивается число ссылок.
HRESULT Copy ([in] ImaCell* cell)
Функция копирует значение ячейки из ячейки cell.
HRESULT IsEmpty ()
Функция проверяет, является ли ячейка пустой. Возвращает коды MA_TRUE или
MA_FALSE.
HRESULT Clear ()
Функция устанавливает пустое значение ячейки. Если ячейка содержала указатель на интерфейс, для него вызывается Release.
Интерфейсы списка ячеек ImaReadList и ImaList
Список ячеек - это универсальная структура данных, позволяющая хранить алгоритмы,
деревья параметров и методы со всеми их входными и выходными аргументами. Элементами списка являются ячейки данных ImaCell. Элементы списка доступны как по
номерам, так и по именам. Элемент может иметь или не иметь имя. Элементы одного
списка не могут иметь одинаковых имён. Элемент списка может хранить ещё один список, образуя тем самым дерево ячеек.
Для представления списков предусмотрены два интерфейса. Интерфейс ImaReadList
предоставляет доступ к ячейкам списка по именам и по номерам, но не позволяет модифицировать список. Интерфейс ImaList наследует все функции ImaReadList и
дополнительно определяет функции добавления ячеек и очистки списка.
Интерфейс списка ячеек ImaReadList
[propget] HRESULT Size ([out,retval] int* size)
Функция возвращает размер (количество элементов) списка.
HRESULT GetCell ([in] int cellno, [out,retval] ImaCell** cell)
Функция возвращает ячейку списка с порядковым номером cellno. Ячейки нумеруются
от 0 до (size-1), где size - размер списка, выдаваемый функцией Size. Если ячейка не существует, в cell записывается нулевой указатель и возвращается код ошибки
MA_ERR_NOTFOUND.
Стандарт maCom: компоненты матричных алгоритмов
13
HRESULT FindCellno ([in] maString name, [out,retval] int* cellno)
Функция ищет в списке ячейку с именем name и записывает номер найденной ячейки в
cellno. Если ячейка не найдена, в cellno записывается (-1) и возвращается код ошибки
MA_ERR_NOTFOUND.
HRESULT FindCell ([in,string] maString name, [out,retval] ImaCell** cell)
Функция совмещает в себе FindCellno и GetCell. Она возвращает в cell указатель на
найденную ячейку. Если ячейка не существует, в cell записывается нулевой указатель и
возвращается код ошибки MA_ERR_NOTFOUND.
HRESULT GetName ([in] int cellno, [out,retval,string] maString* name)
Функция возвращает имя ячейки с заданным номером. Если ячейка не имеет имени, в
name записывается нулевой указатель. Если ячейка не существует, возвращается код
ошибки MA_ERR_NOTFOUND.
Интерфейс списка ячеек ImaList
HRESULT AddCellno ([in,string] maString name, [out,retval] int* cellno)
Функция добавляет в конец списка ячейку с именем name и пустым значением. Номер новой ячейки записывается в cellno. Если ячейка с указанным именем уже существует,
возвращается код ошибки MA_ERR_REPNAME.
HRESULT AddCell ([in,string] maString name, [out,retval] ImaCell** cell)
Функция совмещает в себе AddCellno и GetCell. Она возвращает в cell указатель на созданную ячейку. Если ячейка с указанным именем уже существует, в cell записывается
нулевой указатель и возвращается код ошибки MA_ERR_REPNAME.
HRESULT FindCreateCellno ([in,string] maString name,
[out,retval] int* cellno)
Функция ищет в списке ячейку с именем name. Если такая ячейка не найдена, то функция
создаёт новую ячейку, присваивает ей пустое значение и добавляет в конец списка. Номер
найденной или созданной ячейки записывается в cellno.
HRESULT FindCreateCell ([in,string] maString name,
[out,retval] ImaCell** cell)
Функция совмещает в себе FindCreateCellno и GetCell. Она возвращает в cell указатель на
найденную или созданную ячейку.
HRESULT CreateCells ([in] int cellno)
Функция добавляет в конец списка необходимое количество ячеек, чтобы номер последней ячейки был равен cellno. Если ячейка с таким номером уже есть в списке, функция
ничего не добавляет. Все добавленные ячейки не имеют имени и содержат пустое значение.
HRESULT Clear ()
Функция очищает список, обнуляет размерность.
Интерфейс многомерной матрицы ImaMatrix
Матрицы могут реализовываться с помощью различных компонентов, поддерживающих
интерфейс ImaMatrix.
[propget] HRESULT Dim ([out,retval] int* dim)
Функция возвращает размерность матрицы.
Стандарт maCom: компоненты матричных алгоритмов
14
[propget] HRESULT Size ([in] int dimno, [out,retval] int* size)
Функция возвращает размер матрицы по координате dimno. Координата может принимать
значения от 0 до (dim-1), где dim - размерность матрицы, выдаваемая Dim.
HRESULT Cell ([in] maIndex index, [out] ImaCell* cell)
HRESULT Cell ([in] maIndex index, [in] ImaCell* cell)
Функции чтения и записи ячейки матрицы.
[propget] HRESULT AsDouble ([in] maIndex index, [out,retval] double* value)
[propput] HRESULT AsDouble ([in] maIndex index, [in] double value)
Функции чтения и записи числового значения ячейки матрицы. Если матрица не является
числовой, выполняется необходимое преобразование данных.
[propget] HRESULT AsString ([in] maIndex index,
[out,retval,string] maString* val)
[propput] HRESULT AsString ([in] maIndex index,
[in,string] maString value)
Функции чтения и записи строкового значения ячейки матрицы. Если матрица не является
строковой, выполняется необходимое преобразование данных.
HRESULT Clear ()
Функция очищает матрицу, обнуляет размерность.
Интерфейс вещественной матрицы ImaDoubleMatrix
Вещественная матрица поддерживает интерфейс ImaDoubleMatrix, который наследуется
от ImaMatrix.
HRESULT CreateDouble ([in] maIndex sizes)
Функция создаёт числовую матрицу заданной размерности и размеров. Если матрица уже
содержит данные, то они уничтожаются.
Интерфейс строковой матрицы ImaStringMatrix
Строковая матрица поддерживает интерфейс ImaStringMatrix, который наследуется от
ImaMatrix.
HRESULT CreateString ([in] maIndex sizes)
Функция создаёт строковую матрицу заданной размерности и размеров. Если матрица уже
содержит данные, то они уничтожаются.
Интерфейс потока ввода-вывода ImaStream
Все потоки, независимо от их типа, имеют одинаковый интерфейс. Типами потоков являются: файлы, буферы в оперативной памяти, окна, таблицы, графики, внешние
приложения. Потоки используются для сохранения, загрузки и визуализации промежуточных результатов, отладочных данных и окончательных результатов.
Потоки реализуются различными компонентами с интерфейсом ImaStream. Поток может
поддерживать или не поддерживать различные операции записи и чтения в зависимости
от типа потока. Тип потока задается в момент создания потока, и определяется классом
компонента, который реализует интерфейс ImaStream.
Потоки различных типов отличаются следующими параметрами:
 направленность: запись / чтение;
 формат данных: бинарный / текстовый;
Стандарт maCom: компоненты матричных алгоритмов

15
носитель данных: файл / буфер / приложение.
HRESULT Open ()
HRESULT Close ()
Функции открывают и закрывают поток соответственно. Использовать эти функции не
обязательно. Однако для некоторых типов потоков (например, файлов) имеет смысл открыть поток один раз перед многократным обращением к функциям ввода-вывода, а по
завершении работы закрыть поток. Тогда поток не будет открываться и закрываться при
чтении/записи каждой порции данных, что повысит эффективность операции.
HRESULT Flush ()
Функция принудительно выводит в поток содержимое внутреннего буфера (если таковой
определён для данного типа потоков).
HRESULT WriteStr ([in,string] maString str)
Функция выводит строку в текстовый поток, вместо завершающего нуля выводится символ перевода строки. Если поток не открыт, то он открывается, и по завершении вывода
закрывается.
HRESULT ReadStr ([out,retval,string] maString* str)
Функция считывает строку из текстового потока, символ перевода строки не считывается.
Если поток не открыт, то он открывается, и по завершении ввода закрывается.
HRESULT WriteBlock ([in] void* ptr, [in] int length)
HRESULT ReadBlock ([in] void* ptr, [in] int length)
Функции записи и чтения блока заданной длины. Только для бинарных потоков. Если поток не открыт, то он открывается, и по завершении ввода/вывода закрывается.
HRESULT WriteCell ([in] ImaCell* cell)
HRESULT ReadCell ([out] ImaCell* cell)
Функции записи и чтения ячейки. Если поток не открыт, то он открывается, и по завершении ввода/вывода закрывается.
HRESULT WriteMatrix ([in] ImaMatrix* matrix)
HRESULT ReadMatrix ([out] ImaMatrix* matrix)
Функции записи и чтения матрицы. Если поток не открыт, то он открывается, и по завершении ввода/вывода закрывается.
HRESULT WriteList ([in] ImaList* list)
HRESULT ReadList ([out] ImaList* list)
Функции записи и чтения списка. Если поток не открыт, то он открывается, и по завершении ввода/вывода закрывается.
Алгоритмы и методы
Стандарт maCom определяет ключевые понятия алгоритма и метода следующим образом.
Метод - это преобразование данных, которое принимает на входе некоторое количество
входных аргументов и записывает результат в выходные аргументы. Аргументами являются многомерные матрицы.
Алгоритм - это совокупность методов с общим списком параметров. Методы алгоритма
могут свободно считывать и записывать параметры алгоритма. Алгоритм хранится в виде
дерева (списка списков), включающего поддерево параметров Param и по одному подде-
Стандарт maCom: компоненты матричных алгоритмов
16
реву для каждого метода. Поддерево метода состоит из двух списков - списка входных
аргументов и списка выходных аргументов.
Типичная структура алгоритма иллюстрируется следующей таблицей:
Имя элемента списка
Param
Debug
coeff
Tune
Input
St|F
St|{goal}
Output
Calc
Input
Sc|F
Output
Sc|{y}
Назначение элемента списка
поддерево параметров
параметр Debug - поток вывода отладочной информации
параметр с именем coeff
метод настройки (в общем случае имя метода произвольно)
список входных аргументов
двумерная матрица1
вектор-столбец
список выходных аргументов (в данном случае пуст)
метод настройки (в общем случае имя метода произвольно)
список входных аргументов
двумерная матрица
список выходных аргументов
вектор-столбец
Алгоритм реализуется компонентом с интерфейсами ImaReadList и ImaAlgorithm. Метод
реализуется компонентом с интерфейсами ImaReadList и ImaMethod. Аргументами методов являются многомерные матрицы с интерфейсом ImaMatrix.
Интерфейс определителя метода ImaMethodDef
Для упрощения разработки методов вычислительные функции метода вынесены в отдельный интерфейс определителя метода ImaMethodDef. Разработчику метода достаточно
реализовать класс с единственным (не считая IUnknown) интерфейсом ImaMethodDef, и
больше не заботиться об инициализации и сохранении целостности поддерева метода,
проверках аргументов на соответствие размеров и размерностей, и прочих мелочах.
Реализация методов в виде отдельных классов с предельно упрощенным интерфейсом
изолирует методы друг от друга и от алгоритмов. Метод может считывать и записывать
значения любых параметров алгоритма, но не имеет доступа к аргументам других методов
данного алгоритма. Кроме того, метод не имеет права записывать данные во входные матрицы и считывать данные из выходных матриц.
[propget] HRESULT Description ([out,retval,string] maString* descr)
Функция выдает описание метода, устанавливающее количество аргументов, их размеры
и размерности. Посредством этой функции разработчик метода сообщает информацию о
структуре метода. Синтаксис строки descr подробно рассматривается далее.
HRESULT Init
([in] ImaList* param, [in] ImaList* input, [in] ImaList* output)
Функция вызывается один раз при создании поддерева метода в алгоритме. Она запоминает списки параметров, входных и выходных аргументов метода (в частности, это может
быть сделано путем инициализации классов-оболочек). Она также может создать и инициализировать некоторые параметры алгоритма.
Рекомендуется при реализации функции Init запомнить во внутренних переменных класса
указатели на ячейки, представляющие аргументы метода. Это несколько повысит эффек1
Имена аргументов берутся из структурного описания метода.
Стандарт maCom: компоненты матричных алгоритмов
17
тивность обращения к матрицам-аргументам в функции CalcCellDef, особенно, если для
этого используются символьные имена. Отметим также, что в функции Init некорректно
пытаться получить интерфейс матрицы ImaMatrix, хранящейся в ячейке аргумента, так как
на этапе вызова Init значения аргументов, скорее всего, ещё не заданы.
HRESULT CalcDef ()
Функция выполняет метод, полностью вычисляет все выходные аргументы метода и, при
необходимости, изменяет параметры алгоритма. Функция использует списки параметров,
входных и выходных аргументов, установленные функцией Init.
HRESULT CalcCellDef
([in] int argno, [in] maIndex index, [out] ImaCell *cell)
Функция вычисляет значение единственной ячейки с индексом index в выходном аргументе argno. Нумерация аргументов начинается с нуля. Если указатель cell нулевой, то
вычисленное значение записывается в соответствующую ячейку argno-го выходного аргумента. Если указатель cell ненулевой, то вычисленное значение записывается в ячейку
cell, и не записывается в выходной аргумент. Функция использует списки параметров,
входных и выходных аргументов, установленные функцией maInit.
Функции CalcDef и CalcCellDef обязаны выполнять одно и то же преобразование данных.
Такое дублирование имеет целью повысить эффективность вычислений в системах построения алгоритмических композиций, поддерживающих концепцию вычислимых
(не хранимых) данных.
Спецификация описаний методов
Строка, возвращаемая функцией maMethodDef::Description, содержит формальное описание структуры метода. В ней указывается имя метода, количество входных и выходных
матриц-аргументов, имена и размерности аргументов, а также вводятся ограничения на
размеры аргументов.
Описание метода выполняет несколько важных функций:
 автоматизирует проверку аргументов на соответствие размерностей и размеров, освобождает разработчика метода от выполнения этих проверок;
 автоматизирует создание дерева алгоритма, обеспечивает защиту от модификации
поддеревьев методов после создания алгоритма, освобождает разработчика метода от
выполнения необходимых для этого инициализаций;
 обеспечивает минимальную самодокументированность методов, предоставляя актуальную информацию о структуре их аргументов.
Синтаксис строки описания метода в форме Бэкуса-Наура2:
ОписаниеМетода ::= ИмяМетода СписокВходов -> СписокВыходов [; Комментарий]
СписокВходов ::= Аргумент,...,Аргумент
СписокВыходов ::= Аргумент,...,Аргумент
Аргумент
::= [?] [ИмяАргумента=] Координата | ... | Координата
Координата
::= ИмяРазмерности
Координата
::= {ИмяЭлемента,...,[?]ИмяЭлемента,...,ИмяЭлемента}
Имя метода - это произвольный идентификатор, не содержащий пробелов.
Списки входных и выходных аргументов могут состоять из любого числа элементов, в
том числе они могут быть пустыми. Разделитель -> опускать нельзя.
Знак ::= обозначает определение элемента. Многоточие обозначает повторение элемента любое число раз.
Необязательные элементы заключаются в квадратные скобки [ ].
2
Стандарт maCom: компоненты матричных алгоритмов
18
Если описание аргумента начинается знаком вопроса, то аргумент может быть опущен.
При реализации функций вычисления CalcDef и CalcCellDef следует учитывать, что в
этом случае аргумент метода представляется нулевым указателем на ImaMatrix.
Далее в описании аргумента может следовать имя и знак равенства. Если они не указаны,
то имя аргумента по умолчанию совпадает с описанием аргумента, и может содержать
спецсимволы { , } |.
Каждый аргумент описывается перечислением координат многомерной матрицы. Число
координат равно размерности матрицы. Символ вертикальной черты служит разделителем
координат. Координата может описываться двумя способами: идентификатором или списком элементов.
Если координата матрицы задана идентификатором, то размер матрицы по данной координате может быть любым. Однако если в описании какой-либо матрицы в любом из
методов данного алгоритма встречается координата с таким же именем, то размеры матриц по соответствующим координатам обязаны совпадать.
Если размерность задана списком идентификаторов в фигурных скобках, то размер матрицы по данной координате должен быть равен числу элементов в списке. Если в списке
есть элемент, перед которым стоит символ вопроса ?, то этот элемент и все последующие
за ним необязательны. В этом случае размер матрицы может варьироваться в пределах от
числа обязательных элементов до полного числа элементов в списке.
Строка описания может содержать концевой комментарий, отделяемый от неё символом
точки с запятой. Комментарий может иметь произвольную длину и содержать произвольные символы, включая табуляции и переводы строки. С помощью комментария
разработчик метода может включить в исходный код краткие пояснения к некоторым
элементам описания.
Пример.
Описание методов настройки и вычисления для алгоритма наименьших квадратов могло
бы выглядеть следующим образом:
HRESULT CLsmTune:: Description (maString* descr) {
*descr = "Tune St|F, St|{goal} ->;\n"
"St - обучающая выборка;\n"
"F - набор признаков;\n"
"goal - целевой признак.\n"
return S_OK;
}
HRESULT CLsmCalc::Description (maString* descr) {
*descr = "Calc Sc|F -> Sc|{y};\n"
"Sc - рабочая выборка;\n"
"F - набор признаков;\n"
"y - результат аппроксимации.\n"
return S_OK;
}
Здесь описаны два метода алгоритма наименьших квадратом LSM. Метод настройки
CLsmTune имеет два обязательных входных аргумента размером StF и St1 и ни одного
выходного. Метод вычисления CLsmСalc имеет входную матрицу размером ScF и выходной вектор размером Sc1.
Интерфейс метода ImaMethod
Интерфейс ImaMethod предназначен для использования методов, в отличие от интерфейса
ImaMethodDef, служащего для упрощения их реализации. Класс метода поддерживает ин-
Стандарт maCom: компоненты матричных алгоритмов
19
терфейсы ImaReadList и ImaMethod. Внутри себя он хранит указатель на интерфейс
ImaMethodDef.
[propget] HRESULT MethodDef ([out,retval] ImaMethodDef** mdef)
[propput] HRESULT MethodDef ([in] ImaMethodDef* mdef)
Функции служат для получения и установки соответственно указателя на интерфейс
определителя метода. Функция установки [propput] создаёт дерево метода. Если она вызывается повторно, то старое дерево уничтожается и заменяется новым. При этом
указатели на матрицы аргументов, ранее полученные для старого дерева с помощью
функций Input и Output, перестают быть связанными с методом.
[propget] HRESULT Param ([out,retval] ImaList** param)
Функция служит для получения списка параметров метода. Список параметров
устанавливается во время создания поддерева метода и далее предполагается
неизменным.
[propget] HRESULT Input ([in] int argno, [out,retval] ImaMatrix** arg)
[propput] HRESULT Input ([in] int argno, [in] ImaMatrix* arg)
Функции служат соответственно для получения и установки argno-го входного аргумента
метода.
[propget] HRESULT Output ([in] int argno, [out,retval] ImaMatrix** arg)
[propput] HRESULT Output ([in] int argno, [in] ImaMatrix* arg)
Функции служат соответственно для получения и установки argno-го выходного аргумента метода.
HRESULT Calc ()
Функция выполняет метод путем вызова функции CalcDef определителя метода.
HRESULT CalcCell ([in] int argno, [in] maIndex index, [out] ImaCell *cell)
Функция вычисляет значение единственной ячейки в выходном аргументе метода путем
вызова функции CalcCellDef определителя метода. Смысл аргументов тот же, что и для
функции CalcCellDef.
Интерфейс алгоритма ImaAlgorithm
Алгоритм - это совокупность методов с общим списком параметров. Класс алгоритма
поддерживает интерфейс списка ImaReadList, а также интерфейс ImaAlgorithm, функции
которого перечислены ниже.
HRESULT SetMethod ([in,string] maString name, [in] ImaMethodDef* mdef)
Функция создает и добавляет в алгоритм новый метод с именем name и определителем
mdef. Если метод с таким именем уже существует в алгоритме, он заменяется новым. При
создании алгоритма с помощью функции управляющего ядра CreateAlgorithm все методы
создаются ядром автоматически.
[propget] HRESULT Method ([in,string] maString name,
[out,retval] ImaMethod** method)
Функция возвращает метод алгоритма по имени метода.
[propget] HRESULT Description ([out,retval,string] maString* descr)
Функция выдает строку с описанием всех методов алгоритма.
Стандарт maCom: компоненты матричных алгоритмов
20
HRESULT VerifyMethod ([in] int cellno)
HRESULT VerifyMethodByName ([in,string] maString name)
Функции проверяют правильность формирования всех аргументов метода, в том числе
соответствие размеров и размерностей матриц данных. Проверяется также соответствие
размеров с аргументами других сформированных методов данного алгоритма. Метод считается сформированным, если заданы все его обязательные аргументы. Функцию
VerifyMethod следует вызывать после формирования метода, но перед первым обращением к функциям Calc или CalcCell данного метода. Проверка осуществляется в
соответствии с описаниями всех методов данного алгоритма. В случае обнаружения ошибок функция проверки записывает соответствующие сообщения в отладочный поток
алгоритма и возвращает MA_ERR_VERIFY. Если метод сформирован неправильно, то результат его выполнения непредсказуем, так как функции метода Calc и CalcCell не
обязаны проверять свои аргументы.
HRESULT Verify ()
Функция проверяет правильность формирования всех аргументов во всех методах. Проверка сводится к вызову VerifyMethod для каждого метода алгоритма. В случае
обнаружения ошибок хотя бы в одном из методов функция записывает соответствующие
сообщения в отладочный поток алгоритма и возвращает MA_ERR_VERIFY.
Интерфейс управляющего ядра ImaKernel
Ядро управляет загрузкой библиотек алгоритмов, созданием алгоритмов и поздним связыванием методов с алгоритмами.
Ядро позволяет загрузить любое количество библиотек. Каждая библиотека предоставляет
компонент с интерфейсом ImaLibrary, способный создавать определители методов - компоненты с интерфейсом ImaMethodDef.
Ядро позволяет создать алгоритм с заданным именем. При этом создаются все методы
данного алгоритма. Для создания методов ядро просматривает список всех загруженных
библиотек и для каждой библиотеки вызывает функцию CreateMethod столько раз, сколько методов определяет данная библиотека для алгоритма с указанным именем.
Библиотеки, обрабатываемые позже, могут добавлять или переопределять методы, созданные предыдущими библиотеками. Поэтому последовательность загрузки библиотек
может повлиять на состав и порядок следования методов в алгоритме. Однако чаще всего
все методы одного алгоритма определяются в какой-то одной библиотеке.
Ядро предоставляет также возможность определять и переопределять поток вывода отладочной информации, по умолчанию наследуемый всеми создаваемыми алгоритмами.
Управляющее ядро поддерживает интерфейс ImaKernel со следующими функциями.
HRESULT LoadLibraryByName ([in,string] maString clsname)
HRESULT LoadLibraryByClsid ([in,string] maString clsid)
HRESULT LoadLibraryByFilename ([in,string] maString filename)
Функции загружают библиотеку алгоритмов - компонент с интерфейсом ImaLibrary, реализующий определённое количество методов.
В зависимости от выбранной функции библиотека ищется, соответственно по имени класса библиотеки clsname, по строковому представлению идентификатора класса библиотеки
clsid, или по имени DLL-файла библиотеки filename.
В первом и во втором случаях класс библиотеки должен быть предварительно зарегистрирован в реестре. В третьем случае регистрация не обязательна, что позволяет
приложениям иметь свои собственные локальные библиотеки алгоритмов.
Стандарт maCom: компоненты матричных алгоритмов
21
HRESULT CreateAlgorithm ([in,string] maString name,
[out,retval] ImaAlgorithm** algor)
Функция создает алгоритм с именем name и помещает указатель на интерфейс созданного
алгоритма в algor. Создается дерево алгоритма, содержащее поддерево параметров
"Param" и поддеревья для каждого из методов алгоритма с пустыми аргументами.
[propput] HRESULT DebugStream ([in] ImaStream* debug)
Функция устанавливает отладочный поток вывода по умолчанию. При создании алгоритмов этот поток будет автоматически заноситься в параметр "Debug".
[propget] HRESULT DebugStream ([out,retval] ImaStream** debug)
Функция возвращает отладочный поток вывода.
Интерфейс библиотеки методов ImaLibrary
Библиотека методов представляет собой компонент, способный создавать методы алгоритмов по заданному символьному имени алгоритма. Обычно библиотека строится в виде
отдельной DLL, которая предоставляет единственный компонент с интерфейсом ImaLibrary, реализованный в полном соответствии с канонами COM, то есть имеющий
собственную фабрику класса и регистрирующийся в реестре.
Методы библиотеки представляют собой компоненты с интерфейсом ImaMethodDef, но не
имеют собственных фабрик, идентификаторов CLSID и не регистрируются в реестре. Роль
фабрики методов берет на себя функция библиотеки CreateMethodDef.
HRESULT CreateMethodDef ([in,string] maString aname, [in] int methodno,
[out,retval] ImaMethodDef* method)
Функция создает экземпляр метода по символьному имени алгоритма aname и номеру метода methodno. Методы нумеруются от 0 до N-1, где N - количество методов, которое
определяет данная библиотека для данного алгоритма. По запросу N-го метода библиотека записывает в method нулевой указатель и возвращает код ошибки
MA_ERR_METHODUNDEF.
Номера методов в библиотеке могут отличаться от номеров методов в структуре алгоритма, так как в общем случае несколько библиотек могут создавать методы для данного
алгоритма, и итоговая нумерация методов внутри алгоритма будет зависеть от очередности загрузки библиотек. По этой причине для получения доступа к конкретному методу
алгоритма следует пользоваться символьными именами методов.
Классы-оболочки C++
Классы-оболочки (wrappers) предоставляют удобный объектно-ориентированный интерфейс для работы с основными компонентами. Они скрывают специфику COM за
обычными классами языка C++.
Классы-оболочки очень компактны, обычно они имеют размер одного или двух указателей. Поэтому в функциях можно возвращать сами классы-оболочки, а не ссылки на них,
не сильно проигрывая в эффективности.
Класс CmaIndex
Класс переопределяет оператор [ ] и преобразование к типу maIndex, чтобы сократить код
формирования и передачи индекса.
CmaIndex& CmaIndex::operator[] (long i);
CmaIndex::operator maIndex ();
Стандарт maCom: компоненты матричных алгоритмов
22
Преобразование к типу maIndex сбрасывает формирование индекса в исходное состояние,
поэтому одним и тем же индексом можно пользоваться многократно.
Пример.
Создание числовых матриц заданной размерности и размеров.
CmaIndex sz;
IA->CreateDouble (sz[20][200]);
IB->CreateDouble (sz[20][200][4]);
При создании индекса можно явно указать размерность, иначе выбирается фиксированная
по умолчанию размерность (достаточно большая, например 5):
CmaIndex sz(3);
IB->CreateDouble (sz[20][200][4]);
Класс CmaMatrix
Класс наследует от CmaIndex способ формирования индекса для доступа к элементам
матрицы. Он также переопределяет операторы преобразования типов и присваивания,
чтобы сократить код записи и считывания значений в ячейках матрицы.
CmaMatrix& CmaMatrix::operator[] (long i);
CmaMatrix& CmaMatrix::operator[] (maIndex idx);
CmaMatrix::operator double ();
CmaMatrix::operator maString ();
double CmaMatrix::operator= (double rvalue);
maString CmaMatrix::operator= (maString rvalue);
Объекты класса CmaMatrix создаются в следующих ситуациях, для каждой из которых
предусмотрен отдельный конструктор.
7. Создание нового экземпляра матрицы для хранения промежуточных данных или для
последующего сохранения в списке ячеек. Создается компонент и интерфейс.
CmaMatrix (maType, maIndex sizes);
8. Получение доступа к матрице, заданной своим интерфейсом.
CmaMatrix (ImaMatrix *matrix);
9. Получение доступа к матрице, хранящейся в ячейке. Создается только интерфейс.
CmaMatrix (CmaCell &cell);
Пример.
Создание и заполнение двумерной числовой матрицы.
CmaIndex sz;
CmaMatrix X(MA_DMATRIX, sz[168][7]);
for (int i=0; i<X.Size(0); i++)
for (int j=0; j<X.Size(1); j++)
X[i][j] = double(i+j);
Класс CmaList
Класс переопределяет оператор [ ], чтобы сократить код обращения к ячейкам списка. Несуществующие ячейки добавляются в список автоматически.
CmaCell& CmaList::operator[] (long i);
CmaCell& CmaList::operator[] (maString i);
Чтобы обращаться к существующим ячейкам списка без возможности автоматического
добавления, следует использовать функции GetCell и FindCell. Если ячейка не найдена,
эти функции возвращают нулевой указатель:
CmaCell* CmaList::GetCell (long i);
Стандарт maCom: компоненты матричных алгоритмов
23
CmaCell* CmaList::FindCell (maString i);
Оператор присваивания позволяет связать класс-оболочку с конкретным интерфейсом,
при этом предыдущий интерфейс освобождается, а у нового интерфейса увеличивается
число ссылок:
ImaList* CmaCell::operator= (ImaList* list);
Объекты класса CmaList создаются в следующих ситуациях, для каждой из которых
предусмотрен отдельный конструктор.
1. Создание нового пустого списка (с нулевым указателем на интерфейс).
CmaList ();
2. Получение доступа к списку, заданному своим интерфейсом.
CmaList (ImaList *list);
3. Получение доступа к списку, хранящемуся в ячейке. Если ячейка не является списком,
то в ней создаётся новый пустой список, а старое содержимое затирается.
CmaList (CmaCell &cell);
Класс CmaCell
Класс переопределяет оператор [ ], чтобы сократить код обращения к спискам, хранящимся в ячейках. Если ячейка не является списком, то новый список создается и заносится в
ячейку, затирая её прежнее значение. Несуществующие элементы добавляются в список
автоматически.
CmaCell& CmaCell::operator[] (long i);
CmaCell& CmaCell::operator[] (maString i);
Класс переопределяет операторы преобразования типов и присваивания, чтобы сократить
код записи и считывания значений в ячейках.
CmaCell::operator double ();
CmaCell::operator maString ();
double CmaCell::operator= (double rvalue);
maString CmaCell::operator= (maString rvalue);
В классе определяется перегруженная функция Default, которая задает стандартное значение, возвращаемое операторами преобразования типа, если ячейка пуста.
CmaCell& CmaCell::Default (double rvalue);
CmaCell& CmaCell::Default (maString rvalue);
Функцию Default можно вызвать один раз для какой угодно ячейки, чтобы установить
значение по умолчанию для всех последующих ячеек. Её также можно вызывать для каждой конкретной ячейки непосредственно перед выполнением преобразования типа
(см. пример). Функция Default реализуется через статические члены, однако сама не является статической, поскольку возвращает ссылку на *this.
private:
static double CmaCell::default_double;
static maString CmaCell::default_string;
Для объектных типов переопределяются только операции присваивания. Для создания
объекта (матрицы, списка, метода или потока) по ячейке необходимо воспользоваться
конструктором соответствующего объекта с аргументом CmaCell&.
CmaMatrix& CmaCell::operator= (CmaMatrix& rvalue);
CmaList& CmaCell::operator= (CmaList& rvalue);
CmaStream& CmaCell::operator= (CmaStream& rvalue);
Объекты класса CmaCell создаются в следующих ситуациях, для каждой из которых
предусмотрен отдельный конструктор.
Стандарт maCom: компоненты матричных алгоритмов
24
1. Создание новой пустой ячейки, например, для записи/считывания значений из матриц.
CmaCell ();
2. Получение доступа к ячейке, заданной своим интерфейсом.
CmaCell (ImaCell *cell);
3. Создание копии ячейки. Если ячейка cell хранит объект, то увеличивается число ссылок на него.
CmaCell (CmaCell &cell);
Объекты классов CmaList и CmaCell позволяют сократить код записи и считывания значений в деревьях параметров. Операторы [ ] автоматически создают недостающие списки и
ячейки, позволяя конструировать дерево параметров путём обращения к несуществующим
элементам.
Пример.
Считывание и запись параметров.
CmaList Param = MethodTune.Param();
double alpha = Param["coeff"][0].Default(0.0);
double beta = Param["coeff"][1].Default(1.0);
CmaMatrix weight = Param["weight"];
int n = weight.Size(0);
for (int i=0; i<n; i++)
Param["circle"][i]["x"] = cos(2*PI*i/double(n));
Param["circle"][i]["y"] = sin(2*PI*i/double(n));
}
Класс CmaMethod
Класс CmaMethod является потомком CmaList, наследуя от него операторы [ ], присваивания и преобразования типов.
Объекты класса CmaMethod создаются в следующих ситуациях, для каждой из которых
предусмотрен отдельный конструктор.
1. Получение доступа к методу, хранящемуся в ячейке.
CmaMethod (CmaCell &cell);
2. Получение доступа к методу, заданному своим интерфейсом.
CmaMethod (ImaMethod *method);
Для доступа к параметрам алгоритма предусмотрена перегруженная функция Param:
CmaList Param ();
CmaCell Param (maString name);
CmaCell Param (int cellno);
Для доступа к входным аргументам предусмотрена перегруженная функция Input:
CmaList Input ();
CmaCell Input (maString name);
CmaCell Input (int cellno);
Для доступа к выходным аргументам предусмотрена перегруженная функция Output:
CmaList Output ();
CmaCell Output (maString name);
CmaCell Output (int cellno);
Для выполнения метода предусмотрены функции Calc и CalcCell:
void Calc ();
void CalcCell (int cellno, CmaIndex& index, CmaCell& cell);
Стандарт maCom: компоненты матричных алгоритмов
25
Класс CmaAlgorithm
Класс CmaAlgorithm является потомком CmaList, наследуя от него операторы [ ], присваивания и преобразования типов. При создании объекта CmaAlgorithm указывается имя
алгоритма, под которым он был зарегистрирован в управляющем ядре. Отметим, что это
имя является именем семейства алгоритмов, но не именем конкретного экземпляра алгоритма. По имени алгоритма однозначно определяется состав его методов. Можно создать
сколько угодно экземпляров алгоритмов из данного семейства.
Конструктор CmaAlgorithm скрывает вызов функции управляющего ядра CreateAlgorithm.
При создании алгоритма создается дерево алгоритма, поддерево параметров и все методы
алгоритма вместе со своими поддеревьями.
CmaAlgorithm (maString name, ImaKernel* kernel);
Для доступа к параметрам алгоритма предусмотрена перегруженная функция Param:
CmaList Param ();
CmaCell Param (maString name);
CmaCell Param (int cellno);
Для доступа к методам алгоритма предусмотрена функция Method:
CmaMethod Method (maString name);
Класс CmaStream
Класс CmaStream переопределяет операторы потокового вывода, чтобы сократить код сохранения данных (аналогично переопределяются операторы потокового ввода):
CmaStream& CmaStream::operator<< (double data);
CmaStream& CmaStream::operator<< (maString data);
CmaStream& CmaStream::operator<< (CmaCell &data);
CmaStream& CmaStream::operator<< (CmaList &data);
CmaStream& CmaStream::operator<< (CmaMatrix &data);
При создании потока с помощью битовой маски type указываются типы потока
(ввод/вывод, текстовый/бинарный, файл/буфер/приложение) и задается расположение потока location (имя файла, строка запуска приложения):
CmaStream (maType type, maString location);
Класс CmaKernel
Класс CmaKernel позволяет сократить код создания ядра, определяя единственный конструктор без параметров.
Класс CmaKernel определяет функции загрузки библиотеки:
int CmaKernel::LoadLibraryByName (maString clsname)
int CmaKernel::LoadLibraryByClsid (maString clsid)
int CmaKernel::LoadLibraryByFilename (maString filename)
Класс CmaKernel определяет функции для установки и выдачи отладочного потока:
CmaStream CmaKernel::GetDefaultStream ();
CmaStream& CmaKernel::SetDefaultStream (CmaStream stream);
Download